Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

incomplete implementation of qr decomposition #371

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e3bf07c
Lowercase MP macros
tannewt Apr 23, 2021
9a3c32a
incomplete implementation of qr decomposition
v923z Apr 23, 2021
cba8873
revert to upper case macro, so that the circuitpython test passes
v923z Apr 23, 2021
f375359
fix small glitch in optimize
v923z Apr 26, 2021
64d53aa
Merge pull request #374 from v923z/optimize-fix
v923z Apr 26, 2021
bd3b030
add circuitpython compilation section to README
v923z Apr 27, 2021
c79a993
Update README.md
v923z Apr 27, 2021
0924daa
Update README.md
v923z Apr 27, 2021
ecae9e8
Merge pull request #375 from v923z/readme
v923z Apr 27, 2021
3b2d7dd
Merge pull request #370 from adafruit/lowercase_macros
v923z Apr 27, 2021
e01f805
add ESP32 cmake instructions to readme
v923z Apr 28, 2021
16af741
add build script for ESP32 cmake
v923z Apr 28, 2021
9464cb7
refer to build script in readme
v923z Apr 28, 2021
6e0b9bb
Merge pull request #376 from v923z/readme
v923z Apr 28, 2021
ab60c5c
implemented solve_triangular function in numpy.linalg module along wi…
vikas-udupa Apr 29, 2021
3e63c8e
implemented solve_triangular and syncing with original repo
vikas-udupa Apr 29, 2021
f9b0e43
corrections to solve_triangular, moved solve_triangular to scipy.lina…
vikas-udupa May 5, 2021
ba6409a
corrected date in ulab-change-log
vikas-udupa May 5, 2021
e52fa96
removed redundant function pointers, added copyright note
vikas-udupa May 5, 2021
a61cd88
Merge pull request #377 from RoboticExplorationLab/master
v923z May 7, 2021
1c02726
fix circuitpython CI
v923z May 7, 2021
df2c994
add docs for solve_triangular
v923z May 9, 2021
3c39995
Merge pull request #380 from v923z/solve-docs
v923z May 9, 2021
43d7de1
update docs
v923z May 9, 2021
5f1d4f5
Merge pull request #381 from v923z/doc-fix
v923z May 9, 2021
ebdff02
build-cp.sh: Drop unneeded workaround.
jepler May 10, 2021
24f0001
qr works now with square matrices
v923z May 10, 2021
1d05843
requirements_cp_dev: Update with requirements from circuitpython
jepler May 10, 2021
9b082fc
Build on changes to build scripts or requirements
jepler May 10, 2021
6b20ae8
ignore an error in upstream circuitpython
jepler May 10, 2021
7616e44
Merge pull request #383 from jepler/fix-cp-build
jepler May 10, 2021
d8f6b7b
fix uppercase macro
v923z May 10, 2021
3141d2a
add tricks chapter
v923z May 11, 2021
17cef6a
Merge pull request #384 from v923z/tricks
v923z May 11, 2021
f80be5f
finish incomplete example snippet
v923z May 11, 2021
7271c13
Merge pull request #385 from v923z/trick-fix
v923z May 11, 2021
0c1ac71
incomplete implementation of qr decomposition
v923z Apr 23, 2021
456b41b
revert to upper case macro, so that the circuitpython test passes
v923z Apr 23, 2021
d628d01
qr works now with square matrices
v923z May 10, 2021
4e0c665
fix uppercase macro
v923z May 10, 2021
e07a10d
Merge branch 'qr' of github.com:v923z/micropython-ulab into qr
v923z May 11, 2021
a84db8f
fix transposition glitch in linalg.qr
v923z Jun 17, 2021
47a0b3c
implement mode keyword argument
v923z Jun 19, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
- 'code/**'
- 'tests/**'
- '.github/workflows/**'
- 'build*.sh'
- 'requirements*.txt'
release:
types: [published]
check_suite:
Expand Down
107 changes: 102 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ The `float` implementation of `micropython` (`float`, or `double`) is automatica
1. [Benchmarks](#benchmarks)
1. [Firmware](#firmware)
1. [UNIX](#unix-port)
2. [STM-based boards](#stm-based-boards)
3. [ESP32-based boards](#esp32-based-boards)
4. [RP2-based boards](#rp2-based-boards)
1. [STM-based boards](#stm-based-boards)
1. [ESP32-based boards](#esp32-based-boards)
1. [RP2-based boards](#rp2-based-boards)
1. [Compiling for CircuitPython](#compiling-for-circuitpython)
3. [Issues, contributing, and testing](#issues-contributing-and-testing)
1. [Testing](#testing)

Expand Down Expand Up @@ -82,7 +83,7 @@ Representative numbers on performance can be found under [ulab samples](https://

# Firmware

## Compiled
## Compiled

Compiled firmware for many hardware platforms can be downloaded from Roberto Colistete's
gitlab repository: for the [pyboard](https://gitlab.com/rcolistete/micropython-samples/-/tree/master/Pyboard/Firmware/), and
Expand Down Expand Up @@ -171,7 +172,57 @@ In case you got stuck somewhere in the process, a bit more detailed instructions

### ESP32-based boards

The firmware can be compiled either by downloading and running the [build script](https://github.com/v923z/micropython-ulab/blob/master/build/esp32.sh), or following the steps below:
Firmware for `Espressif` boards can be built in two different ways. These are discussed in the next two paragraphs. A solution for issues with the firmware size is outlined in the [last paragraph](#what-to-do-if-the-firmware-is-too-large) in this section.

#### Compiling with cmake

Beginning with version 1.15, `micropython` switched to `cmake` on the ESP32 port. If your operating system supports `CMake > 3.12`, you can either simply download, and run the single [build script](https://github.com/v923z/micropython-ulab/blob/master/build/esp32-cmake.sh), or follow the step in this section. Otherwise, you should skip to the [next one](#compiling-with-make), where the old, `make`-based approach is discussed.

In case you encounter difficulties during the build process, you can consult the (general instructions for the ESP32)[https://github.com/micropython/micropython/tree/master/ports/esp32#micropython-port-to-the-esp32].

Frist, clone the `ulab`, the `micropython`, as well as the `espressif` repositories:

```bash
export BUILD_DIR=$(pwd)

git clone https://github.com/v923z/micropython-ulab.git ulab
git clone https://github.com/micropython/micropython.git

cd $BUILD_DIR/micropython/

git clone -b v4.0.2 --recursive https://github.com/espressif/esp-idf.git

```

Then install the `ESP-IDF` tools:

```bash
cd esp-idf
./install.sh
. ./export.sh
```

Next, build the `micropython` cross-compiler, and the `ESP` sub-modules:

```bash
cd $BUILD_DIR/micropython/mpy-cross
make
cd $BUILD_DIR/micropython/ports/esp32
make submodules
```
At this point, all requirements are installed and built. We can now compile the firmware with `ulab`. In `$BUILD_DIR/micropython/ports/esp32` create a `makefile` with the following content:

```bash
BOARD = GENERIC
USER_C_MODULES = $(BUILD_DIR)/ulab/code/micropython.cmake

include Makefile
```
You specify with the `BOARD` variable, what you want to compile for, a generic board, or `TINYPICO`, etc. Still in `$BUILD_DIR/micropython/ports/esp32`, you can now run `make`.

#### Compiling with make

If your operating system does not support a recent enough version of `CMake`, you have to stay with `micropython` version 1.14. The firmware can be compiled either by downloading and running the [build script](https://github.com/v923z/micropython-ulab/blob/master/build/esp32.sh), or following the steps below:

First, clone `ulab` with

Expand Down Expand Up @@ -273,6 +324,29 @@ If it compiles without error, you can plug in your ESP32 via USB and then flash
```bash
make erase && make deploy
```

#### What to do, if the firmware is too large?

When selecting `BOARD=TINYPICO`, the firmware is built but fails to deploy, because it is too large for the standard partitions. We can rectify the problem by creating a new partition table. In order to do so, in `$BUILD_DIR/micropython/ports/esp32/`, copy the following 8 lines to a file named `partitions_ulab.cvs`:

```
# Notes: the offset of the partition table itself is set in
# $ESPIDF/components/partition_table/Kconfig.projbuild and the
# offset of the factory/ota_0 partition is set in makeimg.py
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 0x200000,
vfs, data, fat, 0x220000, 0x180000,
```
This expands the `factory` partition by 128 kB, and reduces the size of `vfs` by the same amount. Having defined the new partition table, we should extend `sdkconfig.board` by adding the following two lines:

```
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_ulab.csv"
```
This file can be found in `$BUILD_DIR/micropython/ports/esp32/boards/TINYPICO/`. Finally, run `make clean`, and `make`. The new firmware contains the modified partition table, and should fit on the microcontroller.

### RP2-based boards

RP2 firmware can be compiled either by downloading and running the single [build script](https://github.com/v923z/micropython-ulab/blob/master/build/rp2.sh), or executing the commands below.
Expand Down Expand Up @@ -316,6 +390,29 @@ make USER_C_MODULE=/path/to/ulab/code/micropython.cmake

If `micropython` and `ulab` were in the same folder on the computer, you can set `USER_C_MODULES=../../../ulab/code/micropython.cmake`. The compiled firmware will be placed in `micropython/ports/rp2/build`.

# Compiling for CircuitPython

[Adafruit Industries](www.adafruit.com) always include a relatively recent version of `ulab` in their nightly builds. However, if you really need the bleeding edge, you can easily compile the firmware from the source. Simply clone `circuitpython`, and move the commit pointer to the latest version of `ulab` (`ulab` will automatically be cloned with `circuitpython`):

```bash
git clone https://github.com/adafruit/circuitpython.git

cd circuitpyton/extmod/ulab

# update ulab here
git checkout master
git pull
```
You might have to check, whether the `CIRCUITPY_ULAB` variable is set to `1` for the port that you want to compile for. You find this piece of information in the `make` fragment:

```bash
circuitpython/ports/port_of_your_choice/mpconfigport.mk
```
After this, you would run `make` with the single `BOARD` argument, e.g.:

```bash
make BOARD=mini_sam_m4
```

# Issues, contributing, and testing

Expand Down
4 changes: 1 addition & 3 deletions build-cp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ HERE="$(dirname -- "$(readlinkf_posix -- "${0}")" )"
rm -rf circuitpython/extmod/ulab; ln -s "$HERE" circuitpython/extmod/ulab
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
# Work around circuitpython#3990
make -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' build/genhdr/qstrdefs.generated.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'
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'

for dir in "circuitpy" "common"
do
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ make -C micropython/ports/unix -j${NPROC} axtls
make -C micropython/ports/unix -j${NPROC} USER_C_MODULES="${HERE}" DEBUG=1 STRIP=: MICROPY_PY_FFI=0 MICROPY_PY_BTREE=0


for dir in "numpy" "common" "utils"
for dir in "numpy" "scipy" "common" "utils"
do
if ! env MICROPY_MICROPYTHON=micropython/ports/unix/micropython ./run-tests -d tests/"$dir"; then
for exp in *.exp; do
Expand Down
28 changes: 28 additions & 0 deletions build/esp32-cmake.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

export BUILD_DIR=$(pwd)

git clone https://github.com/v923z/micropython-ulab.git ulab
git clone https://github.com/micropython/micropython.git

cd $BUILD_DIR/micropython/

git clone -b v4.0.2 --recursive https://github.com/espressif/esp-idf.git

```bash
cd esp-idf
./install.sh
. ./export.sh

cd $BUILD_DIR/micropython/mpy-cross
make
cd $BUILD_DIR/micropython/ports/esp32
make submodules


echo "BOARD = GENERIC" > $BUILD_DIR/micropython/ports/esp32/makefile
echo "USER_C_MODULES = \$(BUILD_DIR)/ulab/code/micropython.cmake" >> $BUILD_DIR/micropython/ports/esp32/makefile

cd $BUILD_DIR/micropython/ports/esp32

make
1 change: 1 addition & 0 deletions code/micropython.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
USERMODULES_DIR := $(USERMOD_DIR)

# Add all C files to SRC_USERMOD.
SRC_USERMOD += $(USERMODULES_DIR)/scipy/linalg/linalg.c
SRC_USERMOD += $(USERMODULES_DIR)/scipy/optimize/optimize.c
SRC_USERMOD += $(USERMODULES_DIR)/scipy/signal/signal.c
SRC_USERMOD += $(USERMODULES_DIR)/scipy/special/special.c
Expand Down
38 changes: 19 additions & 19 deletions code/ndarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,10 @@ size_t *ndarray_shape_vector(size_t a, size_t b, size_t c, size_t d) {
}

bool ndarray_object_is_array_like(mp_obj_t o_in) {
if(MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type) ||
MP_OBJ_IS_TYPE(o_in, &mp_type_tuple) ||
MP_OBJ_IS_TYPE(o_in, &mp_type_list) ||
MP_OBJ_IS_TYPE(o_in, &mp_type_range)) {
if(mp_obj_is_type(o_in, &ulab_ndarray_type) ||
mp_obj_is_type(o_in, &mp_type_tuple) ||
mp_obj_is_type(o_in, &mp_type_list) ||
mp_obj_is_type(o_in, &mp_type_range)) {
return true;
}
return false;
Expand Down Expand Up @@ -420,13 +420,13 @@ mp_obj_t ndarray_dtype_make_new(const mp_obj_type_t *type, size_t n_args, size_t
dtype_obj_t *dtype = m_new_obj(dtype_obj_t);
dtype->base.type = &ulab_dtype_type;

if(MP_OBJ_IS_TYPE(args[0], &ulab_ndarray_type)) {
if(mp_obj_is_type(args[0], &ulab_ndarray_type)) {
// return the dtype of the array
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0]);
dtype->dtype = ndarray->dtype;
} else {
uint8_t _dtype;
if(MP_OBJ_IS_INT(_args[0].u_obj)) {
if(mp_obj_is_int(_args[0].u_obj)) {
_dtype = mp_obj_get_int(_args[0].u_obj);
if((_dtype != NDARRAY_BOOL) && (_dtype != NDARRAY_UINT8)
&& (_dtype != NDARRAY_INT8) && (_dtype != NDARRAY_UINT16)
Expand Down Expand Up @@ -466,7 +466,7 @@ mp_obj_t ndarray_dtype(mp_obj_t self_in) {
// this is the cheap implementation of tbe dtype
mp_obj_t ndarray_dtype(mp_obj_t self_in) {
uint8_t dtype;
if(MP_OBJ_IS_TYPE(self_in, &ulab_ndarray_type)) {
if(mp_obj_is_type(self_in, &ulab_ndarray_type)) {
ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in);
dtype = self->dtype;
} else { // we assume here that the input is a single character
Expand Down Expand Up @@ -908,7 +908,7 @@ STATIC uint8_t ndarray_init_helper(size_t n_args, const mp_obj_t *pos_args, mp_m

uint8_t _dtype;
#if ULAB_HAS_DTYPE_OBJECT
if(MP_OBJ_IS_TYPE(args[1].u_obj, &ulab_dtype_type)) {
if(mp_obj_is_type(args[1].u_obj, &ulab_dtype_type)) {
dtype_obj_t *dtype = MP_OBJ_TO_PTR(args[1].u_obj);
_dtype = dtype->dtype;
} else { // this must be an integer defined as a class constant (ulba.uint8 etc.)
Expand All @@ -923,7 +923,7 @@ STATIC uint8_t ndarray_init_helper(size_t n_args, const mp_obj_t *pos_args, mp_m
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)) {
if(mp_obj_is_type(args[0], &ulab_ndarray_type)) {
ndarray_obj_t *source = MP_OBJ_TO_PTR(args[0]);
if(dtype == source->dtype) {
return ndarray_copy_view(source);
Expand Down Expand Up @@ -1151,9 +1151,9 @@ static size_t slice_length(mp_bound_slice_t slice) {

static mp_bound_slice_t generate_slice(mp_int_t n, mp_obj_t index) {
mp_bound_slice_t slice;
if(MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
if(mp_obj_is_type(index, &mp_type_slice)) {
mp_obj_slice_indices(index, n, &slice);
} else if(MP_OBJ_IS_INT(index)) {
} else if(mp_obj_is_int(index)) {
mp_int_t _index = mp_obj_get_int(index);
if(_index < 0) {
_index += n;
Expand Down Expand Up @@ -1185,7 +1185,7 @@ static ndarray_obj_t *ndarray_view_from_slices(ndarray_obj_t *ndarray, mp_obj_tu
}
int32_t offset = 0;
for(uint8_t i=0; i < tuple->len; i++) {
if(MP_OBJ_IS_INT(tuple->items[i])) {
if(mp_obj_is_int(tuple->items[i])) {
// if item is an int, the dimension will first be reduced ...
ndim--;
int32_t k = mp_obj_get_int(tuple->items[i]);
Expand Down Expand Up @@ -1411,7 +1411,7 @@ static mp_obj_t ndarray_assign_from_boolean_index(ndarray_obj_t *ndarray, ndarra
}

static mp_obj_t ndarray_get_slice(ndarray_obj_t *ndarray, mp_obj_t index, ndarray_obj_t *values) {
if(MP_OBJ_IS_TYPE(index, &ulab_ndarray_type)) {
if(mp_obj_is_type(index, &ulab_ndarray_type)) {
ndarray_obj_t *nindex = MP_OBJ_TO_PTR(index);
if((nindex->ndim > 1) || (nindex->boolean == false)) {
mp_raise_NotImplementedError(translate("operation is implemented for 1D Boolean arrays only"));
Expand All @@ -1422,9 +1422,9 @@ static mp_obj_t ndarray_get_slice(ndarray_obj_t *ndarray, mp_obj_t index, ndarra
ndarray_assign_from_boolean_index(ndarray, index, values);
}
}
if(MP_OBJ_IS_TYPE(index, &mp_type_tuple) || MP_OBJ_IS_INT(index) || MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
if(mp_obj_is_type(index, &mp_type_tuple) || mp_obj_is_int(index) || mp_obj_is_type(index, &mp_type_slice)) {
mp_obj_tuple_t *tuple;
if(MP_OBJ_IS_TYPE(index, &mp_type_tuple)) {
if(mp_obj_is_type(index, &mp_type_tuple)) {
tuple = MP_OBJ_TO_PTR(index);
if(tuple->len > ndarray->ndim) {
mp_raise_msg(&mp_type_IndexError, translate("too many indices"));
Expand Down Expand Up @@ -1676,7 +1676,7 @@ ndarray_obj_t *ndarray_from_mp_obj(mp_obj_t obj) {
// creates an ndarray from a micropython int or float
// if the input is an ndarray, it is returned
ndarray_obj_t *ndarray;
if(MP_OBJ_IS_INT(obj)) {
if(mp_obj_is_int(obj)) {
int32_t ivalue = mp_obj_get_int(obj);
if((ivalue >= 0) && (ivalue < 256)) {
ndarray = ndarray_new_linear_array(1, NDARRAY_UINT8);
Expand Down Expand Up @@ -1704,7 +1704,7 @@ ndarray_obj_t *ndarray_from_mp_obj(mp_obj_t obj) {
ndarray = ndarray_new_linear_array(1, NDARRAY_FLOAT);
mp_float_t *array = (mp_float_t *)ndarray->array;
array[0] = (mp_float_t)fvalue;
} else if(MP_OBJ_IS_TYPE(obj, &ulab_ndarray_type)){
} else if(mp_obj_is_type(obj, &ulab_ndarray_type)){
return obj;
} else {
mp_raise_TypeError(translate("wrong operand type"));
Expand Down Expand Up @@ -2013,7 +2013,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(ndarray_transpose_obj, ndarray_transpose);
#if NDARRAY_HAS_RESHAPE
mp_obj_t ndarray_reshape(mp_obj_t oin, mp_obj_t _shape) {
ndarray_obj_t *source = MP_OBJ_TO_PTR(oin);
if(!MP_OBJ_IS_TYPE(_shape, &mp_type_tuple)) {
if(!mp_obj_is_type(_shape, &mp_type_tuple)) {
mp_raise_TypeError(translate("shape must be a tuple"));
}

Expand Down Expand Up @@ -2050,7 +2050,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(ndarray_reshape_obj, ndarray_reshape);
#if ULAB_NUMPY_HAS_NDINFO
mp_obj_t ndarray_info(mp_obj_t obj_in) {
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(obj_in);
if(!MP_OBJ_IS_TYPE(ndarray, &ulab_ndarray_type)) {
if(!mp_obj_is_type(ndarray, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("function is defined for ndarrays only"));
}
mp_printf(MP_PYTHON_PRINTER, "class: ndarray\n");
Expand Down
5 changes: 1 addition & 4 deletions code/ndarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ typedef struct _mp_obj_slice_t {
#define MP_ERROR_TEXT(x) x
#endif

#if CIRCUITPY
#define mp_obj_is_bool(o) (MP_OBJ_IS_TYPE((o), &mp_type_bool))
#define mp_obj_is_int(x) (MP_OBJ_IS_INT((x)))
#else
#if !CIRCUITPY
#define translate(x) MP_ERROR_TEXT(x)
#endif

Expand Down
Loading