Skip to content

Commit

Permalink
Merge branch 'master' into spectrum
Browse files Browse the repository at this point in the history
  • Loading branch information
v923z authored Sep 14, 2024
2 parents 30c7f4f + 45f23eb commit 00897b9
Show file tree
Hide file tree
Showing 23 changed files with 305 additions and 120 deletions.
20 changes: 11 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ on:

jobs:
micropython:
continue-on-error: true
strategy:
matrix:
os:
Expand All @@ -28,10 +29,10 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Set up Python 3.10
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.12"

- name: Install requirements
run: |
Expand All @@ -44,10 +45,10 @@ jobs:
gcc --version
python3 --version
- name: Checkout ulab
uses: actions/checkout@v1
uses: actions/checkout@v4

- name: Checkout micropython repo
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: micropython/micropython
path: micropython
Expand All @@ -56,6 +57,7 @@ jobs:
run: ./build.sh ${{ matrix.dims }}

circuitpython:
continue-on-error: true
strategy:
matrix:
os:
Expand All @@ -68,18 +70,18 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Set up Python 3.10
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.12"

- name: Versions
run: |
gcc --version
python3 --version
- name: Checkout ulab
uses: actions/checkout@v1
uses: actions/checkout@v4

- name: Install requirements
run: |
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ulab

[![Documentation Status](https://readthedocs.org/projects/micropython-ulab-robert/badge/?version=latest)](https://micropython-ulab-robert.readthedocs.io/en/latest/?badge=latest)
[![Documentation Status](https://readthedocs.org/projects/micropython-ulab/badge/?version=latest)](https://micropython-ulab.readthedocs.io/en/latest/index.html)

`ulab` is a `numpy`-like array manipulation library for [micropython](http://micropython.org/) and [CircuitPython](https://circuitpython.org/).
The module is written in C, defines compact containers (`ndarray`s) for numerical data of one to four
Expand Down Expand Up @@ -47,7 +47,7 @@ the `imag`, and `real` properties are automatically included.

## `numpy` and `scipy` functions

In addition, `ulab` includes [universal functions](https://micropython-ulab.readthedocs.io/en/latest/numpy-universal.html), [many `numpy` functions](https://micropython-ulab.readthedocs.io/en/latest/numpy-functions.html), and functions from the [`numpy.fft`](https://micropython-ulab.readthedocs.io/en/latest/numpy-fft.html), [`numpy.linalg`](https://micropython-ulab.readthedocs.io/en/latest/numpy-linalg.html), [`scipy.linalg`](https://micropython-ulab.readthedocs.io/en/latest/scipy-linalg.html), [`scipy.optimize`](https://micropython-ulab.readthedocs.io/en/latest/scipy-optimize.html), [`scipy.signal`](https://micropython-ulab.readthedocs.io/en/latest/scipy-signal.html), and [`scipy.special`](https://micropython-ulab.readthedocs.io/en/latest/scipy-special.html) modules. A complete list of available routines can be found under [micropython-ulab](https://micropython-ulab.readthedocs.io/en/latest).
In addition, `ulab` includes [universal functions](https://micropython-ulab.readthedocs.io/en/latest/numpy-universal.html), [many `numpy` functions](https://micropython-ulab.readthedocs.io/en/latest/numpy-functions.html), and functions from the [`numpy.fft`](https://micropython-ulab.readthedocs.io/en/latest/numpy-fft.html), [`numpy.linalg`](https://micropython-ulab.readthedocs.io/en/latest/numpy-linalg.html), [`numpy.random`](https://micropython-ulab.readthedocs.io/en/latest/numpy-random.html), [`scipy.linalg`](https://micropython-ulab.readthedocs.io/en/latest/scipy-linalg.html), [`scipy.optimize`](https://micropython-ulab.readthedocs.io/en/latest/scipy-optimize.html), [`scipy.signal`](https://micropython-ulab.readthedocs.io/en/latest/scipy-signal.html), and [`scipy.special`](https://micropython-ulab.readthedocs.io/en/latest/scipy-special.html) modules. A complete list of available routines can be found under [micropython-ulab](https://micropython-ulab.readthedocs.io/en/latest).

## `ulab` utilities

Expand Down Expand Up @@ -112,7 +112,6 @@ of the user manual.
1. `MaixPy` https://github.com/sipeed/MaixPy
1. `OpenMV` https://github.com/openmv/openmv
1. `pimoroni-pico` https://github.com/pimoroni/pimoroni-pico
3. `pycom` https://pycom.io/

## Compiling

Expand Down
3 changes: 1 addition & 2 deletions build-cp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ HERE="$(dirname -- "$(readlinkf_posix -- "${0}")" )"
rm -rf circuitpython/extmod/ulab; ln -s "$HERE" circuitpython/extmod/ulab
dims=${1-2}
make -C circuitpython/mpy-cross -j$NPROC
sed -e '/MICROPY_PY_UHASHLIB/s/1/0/' < circuitpython/ports/unix/mpconfigport.h > circuitpython/ports/unix/mpconfigport_ulab.h
make -k -C circuitpython/ports/unix -j$NPROC DEBUG=1 MICROPY_PY_FFI=0 MICROPY_PY_BTREE=0 MICROPY_SSL_AXTLS=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-DMP_CONFIGFILE=\"<mpconfigport_ulab.h>\" -Wno-tautological-constant-out-of-range-compare -Wno-unknown-pragmas -DULAB_MAX_DIMS=$dims" BUILD=build-$dims PROG=micropython-$dims
make -k -C circuitpython/ports/unix -j$NPROC DEBUG=1 MICROPY_PY_FFI=0 MICROPY_PY_BTREE=0 MICROPY_SSL_AXTLS=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-Wno-tautological-constant-out-of-range-compare -Wno-unknown-pragmas -DULAB_MAX_DIMS=$dims" BUILD=build-$dims PROG=micropython-$dims

# bash test-common.sh "${dims}" "circuitpython/ports/unix/micropython-$dims"

Expand Down
53 changes: 25 additions & 28 deletions code/ndarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2019-2022 Zoltán Vörös
* Copyright (c) 2019-2024 Zoltán Vörös
* 2020 Jeff Epler for Adafruit Industries
* 2020 Taku Fukada
*/
Expand Down Expand Up @@ -509,8 +509,9 @@ static size_t multiply_size(size_t a, size_t b) {
return result;
}

ndarray_obj_t *ndarray_new_ndarray(uint8_t ndim, size_t *shape, int32_t *strides, uint8_t dtype) {
ndarray_obj_t *ndarray_new_ndarray(uint8_t ndim, size_t *shape, int32_t *strides, uint8_t dtype, uint8_t *buffer) {
// Creates the base ndarray with shape, and initialises the values to straight 0s
// optionally, values can be supplied via the last argument
ndarray_obj_t *ndarray = m_new_obj(ndarray_obj_t);
ndarray->base.type = &ulab_ndarray_type;
ndarray->dtype = dtype == NDARRAY_BOOL ? NDARRAY_UINT8 : dtype;
Expand All @@ -536,9 +537,13 @@ ndarray_obj_t *ndarray_new_ndarray(uint8_t ndim, size_t *shape, int32_t *strides

// if the length is 0, still allocate a single item, so that contractions can be handled
size_t len = multiply_size(ndarray->itemsize, MAX(1, ndarray->len));
uint8_t *array = m_new0(byte, len);
// this should set all elements to 0, irrespective of the of the dtype (all bits are zero)
// we could, perhaps, leave this step out, and initialise the array only, when needed
uint8_t *array;
array = buffer;
if(array == NULL) {
// this should set all elements to 0, irrespective of the of the dtype (all bits are zero)
// we could, perhaps, leave this step out, and initialise the array only, when needed
array = m_new0(byte, len);
}
ndarray->array = array;
ndarray->origin = array;
return ndarray;
Expand All @@ -547,24 +552,20 @@ ndarray_obj_t *ndarray_new_ndarray(uint8_t ndim, size_t *shape, int32_t *strides
ndarray_obj_t *ndarray_new_dense_ndarray(uint8_t ndim, size_t *shape, uint8_t dtype) {
// creates a dense array, i.e., one, where the strides are derived directly from the shapes
// the function should work in the general n-dimensional case
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
strides[ULAB_MAX_DIMS-1] = (int32_t)ulab_binary_get_size(dtype);
for(size_t i=ULAB_MAX_DIMS; i > 1; i--) {
strides[i-2] = strides[i-1] * MAX(1, shape[i-1]);
}
return ndarray_new_ndarray(ndim, shape, strides, dtype);
// int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
// strides[ULAB_MAX_DIMS - 1] = (int32_t)ulab_binary_get_size(dtype);
// for(size_t i = ULAB_MAX_DIMS; i > 1; i--) {
// strides[i-2] = strides[i-1] * MAX(1, shape[i-1]);
// }
return ndarray_new_ndarray(ndim, shape, NULL, dtype, NULL);
}

ndarray_obj_t *ndarray_new_ndarray_from_tuple(mp_obj_tuple_t *_shape, uint8_t dtype) {
// creates a dense array from a tuple
// the function should work in the general n-dimensional case
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
for(size_t i = 0; i < ULAB_MAX_DIMS; i++) {
if(i >= _shape->len) {
shape[ULAB_MAX_DIMS - 1 - i] = 0;
} else {
shape[ULAB_MAX_DIMS - 1 - i] = mp_obj_get_int(_shape->items[i]);
}
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
for(size_t i = 0; i < _shape->len; i++) {
shape[ULAB_MAX_DIMS - 1 - i] = mp_obj_get_int(_shape->items[_shape->len - 1 - i]);
}
return ndarray_new_dense_ndarray(_shape->len, shape, dtype);
}
Expand Down Expand Up @@ -654,7 +655,7 @@ ndarray_obj_t *ndarray_copy_view(ndarray_obj_t *source) {
if(source->boolean) {
dtype = NDARRAY_BOOL;
}
ndarray_obj_t *ndarray = ndarray_new_ndarray(source->ndim, source->shape, strides, dtype);
ndarray_obj_t *ndarray = ndarray_new_ndarray(source->ndim, source->shape, strides, dtype, NULL);
ndarray_copy_array(source, ndarray, 0);
return ndarray;
}
Expand Down Expand Up @@ -921,7 +922,7 @@ ndarray_obj_t *ndarray_from_iterable(mp_obj_t obj, uint8_t dtype) {
return ndarray;
}

STATIC uint8_t ndarray_init_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static uint8_t ndarray_init_helper(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_ROM_NONE } },
{ MP_QSTR_dtype, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_INT(NDARRAY_FLOAT) } },
Expand All @@ -944,7 +945,7 @@ STATIC uint8_t ndarray_init_helper(size_t n_args, const mp_obj_t *pos_args, mp_m
return _dtype;
}

STATIC mp_obj_t ndarray_make_new_core(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args, mp_map_t *kw_args) {
static mp_obj_t ndarray_make_new_core(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args, mp_map_t *kw_args) {
uint8_t dtype = ndarray_init_helper(n_args, args, kw_args);

if(mp_obj_is_type(args[0], &ulab_ndarray_type)) {
Expand Down Expand Up @@ -1888,7 +1889,7 @@ mp_obj_t ndarray_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
#if ULAB_SUPPORTS_COMPLEX
if(self->dtype == NDARRAY_COMPLEX) {
int32_t *strides = strides_from_shape(self->shape, NDARRAY_FLOAT);
ndarray_obj_t *target = ndarray_new_ndarray(self->ndim, self->shape, strides, NDARRAY_FLOAT);
ndarray_obj_t *target = ndarray_new_ndarray(self->ndim, self->shape, strides, NDARRAY_FLOAT, NULL);
ndarray = MP_OBJ_TO_PTR(carray_abs(self, target));
} else {
#endif
Expand Down Expand Up @@ -2021,7 +2022,7 @@ mp_obj_t ndarray_reshape_core(mp_obj_t oin, mp_obj_t _shape, bool inplace) {
mp_obj_t *items = m_new(mp_obj_t, 1);
items[0] = _shape;
shape = mp_obj_new_tuple(1, items);
} else {
} else { // at this point it's certain that _shape is a tuple
shape = MP_OBJ_TO_PTR(_shape);
}

Expand Down Expand Up @@ -2072,11 +2073,7 @@ mp_obj_t ndarray_reshape_core(mp_obj_t oin, mp_obj_t _shape, bool inplace) {
if(inplace) {
mp_raise_ValueError(MP_ERROR_TEXT("cannot assign new shape"));
}
if(mp_obj_is_type(_shape, &mp_type_tuple)) {
ndarray = ndarray_new_ndarray_from_tuple(shape, source->dtype);
} else {
ndarray = ndarray_new_linear_array(source->len, source->dtype);
}
ndarray = ndarray_new_dense_ndarray(shape->len, new_shape, source->dtype);
ndarray_copy_array(source, ndarray, 0);
}
return MP_OBJ_FROM_PTR(ndarray);
Expand Down
2 changes: 1 addition & 1 deletion code/ndarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ int32_t *ndarray_contract_strides(ndarray_obj_t *, uint8_t );
ndarray_obj_t *ndarray_from_iterable(mp_obj_t , uint8_t );
ndarray_obj_t *ndarray_new_dense_ndarray(uint8_t , size_t *, uint8_t );
ndarray_obj_t *ndarray_new_ndarray_from_tuple(mp_obj_tuple_t *, uint8_t );
ndarray_obj_t *ndarray_new_ndarray(uint8_t , size_t *, int32_t *, uint8_t );
ndarray_obj_t *ndarray_new_ndarray(uint8_t , size_t *, int32_t *, uint8_t , uint8_t *);
ndarray_obj_t *ndarray_new_linear_array(size_t , uint8_t );
ndarray_obj_t *ndarray_new_view(ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t );
bool ndarray_is_dense(ndarray_obj_t *);
Expand Down
4 changes: 2 additions & 2 deletions code/numpy/approx.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ ULAB_DEFINE_FLOAT_CONST(approx_trapz_dx, MICROPY_FLOAT_CONST(1.0), 0x3f800000UL,
//| ...
//|

STATIC mp_obj_t approx_interp(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static mp_obj_t approx_interp(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_ROM_NONE } },
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE } },
Expand Down Expand Up @@ -151,7 +151,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(approx_interp_obj, 2, approx_interp);
//| ...
//|

STATIC mp_obj_t approx_trapz(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static mp_obj_t approx_trapz(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_ROM_NONE } },
{ MP_QSTR_x, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE } },
Expand Down
10 changes: 7 additions & 3 deletions code/numpy/carray/carray.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@

#if ULAB_SUPPORTS_COMPLEX

//| import builtins
//|
//| import ulab.numpy

//| def real(val):
//| def real(val: ulab.numpy.ndarray) -> ulab.numpy.ndarray:
//| """
//| Return the real part of the complex argument, which can be
//| either an ndarray, or a scalar."""
Expand All @@ -54,7 +56,7 @@ mp_obj_t carray_real(mp_obj_t _source) {

MP_DEFINE_CONST_FUN_OBJ_1(carray_real_obj, carray_real);

//| def imag(val):
//| def imag(val: ulab.numpy.ndarray) -> ulab.numpy.ndarray:
//| """
//| Return the imaginary part of the complex argument, which can be
//| either an ndarray, or a scalar."""
Expand Down Expand Up @@ -82,7 +84,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(carray_imag_obj, carray_imag);

#if ULAB_NUMPY_HAS_CONJUGATE

//| def conjugate(val):
//| def conjugate(
//| val: builtins.complex | ulab.numpy.ndarray
//| ) -> builtins.complex | ulab.numpy.ndarray:
//| """
//| Return the conjugate of the complex argument, which can be
//| either an ndarray, or a scalar."""
Expand Down
Loading

0 comments on commit 00897b9

Please sign in to comment.