Code Monkey home page Code Monkey logo

micropython-ulab's People

Contributors

callumjhays avatar ciscorn avatar crazyhackelkorn avatar deqingsun avatar derfies avatar dpgeorge avatar felixnumworks avatar gadgetoid avatar haydens3 avatar hugonumworks avatar jepler avatar jetpax avatar jimmo avatar jonathanhogg avatar jsimonrichard avatar kbsriram avatar mdaeron avatar mouryarahul avatar nickovs avatar qqice avatar rcolistete avatar robertoroos avatar t-ikegami avatar tannewt avatar tekktrik avatar teuler avatar ubiqio avatar v923z avatar vikas-udupa avatar wired8 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

micropython-ulab's Issues

ulab assumes that floats are boxed: MICROPY_OBJ_REPR_A or B

ulab is assuming that MicroPython is built with MICROPY_OBJ_REPR_A or MICROPY_OBJ_REPR_B, which store floats as boxed objects instead of as immediate values like smallints. In the code below, the float object is assumed to be boxed:

typedef struct _mp_obj_float_t {
mp_obj_base_t base;
mp_float_t value;
} mp_obj_float_t;
mp_obj_float_t ulab_version = {{&mp_type_float}, ULAB_VERSION};

Feature request: clip()

Feature request: an equivalent to numpy’s clip() function. Sure, same operation can be done in a couple lines of Python, but the speed of occurring entirely in ulab space would be a big plus. Thanks.

multiple definition ulab_ndarray_type

Great work!

I want to add your ulab to MaixPy as a submodule, and I come across two problems,

  • variable multiple defined, maybe should change to extern const mp_obj_type_t ulab_ndarray_type;

const mp_obj_type_t ulab_ndarray_type;

const mp_obj_type_t ulab_ndarray_type = {
{ &mp_type_type },
.name = MP_QSTR_ndarray,
.print = ndarray_print,
.make_new = ndarray_make_new,
.subscr = ndarray_subscr,
.getiter = ndarray_getiter,
.unary_op = ndarray_unary_op,
.binary_op = ndarray_binary_op,
.locals_dict = (mp_obj_dict_t*)&ulab_ndarray_locals_dict,
};

  • maybe should include py/obj.h in header files like fft.h

indexing by boolean list is slow

Trying to optimize an inner loop, I've tried to limit the computations by indexing an array with a boolean list. unfortunately, it take waaaay more time for each iteration.
example code on circuitpython :

import ulab
import time

a = ulab.ones(1000)
b = [False]*1000
b[5:10] = [True]*5

start = time.monotonic_ns()
a = a * 2
print('time for a*2           : ', time.monotonic_ns() - start )

start = time.monotonic_ns()
a[5:10] = a[5:10] * 2
print('time for a[5:10]*2     : ', time.monotonic_ns() - start )


start = time.monotonic_ns()
a[b] = a[b] * 2
print('time for a[b] = a[b]*2 :', time.monotonic_ns() - start )

output (timing in ns) :

time for a*2           :  423000
time for a[5:10]*2     :  123000
time for a[b] = a[b]*2 : 4745000

I am testing with : Adafruit CircuitPython 5.0.0-37-geebe76997 on 2020-03-09; Adafruit Monster M4SK with samd51j19

Crash (wrong argument types not handled?)

Use Ctrl-D to exit, Ctrl-E for paste mode
>>> import ulab
>>> ulab.dot(ulab.zeros(3), 0)
Segmentation fault

I've encountered a number of these; I think it's where both arguments need to be ndarrays, but it's not caught as an exception but leads to segmentation fault / hardfault instead. Do you want them reported separately as I encounter them? (this is the only one I wrote down so far)

Support for matrix multiplication operator

Micropython now supports the PEP 465 syntax for using @ as an infix binary operator for matrix multiplication (following the merge of micropython/micropython#4947). Classes implemented in C will get their binary_op method called with the MP_BINARY_OP_MAT_MULTIPLY operator code when the user does this. It would be great if ulab supported this syntax in the same way that numpy does, since it makes code much more concise and readable, as well as making numpy code more directly portable.

Wish list

This is the place, where suggestions related to new functions/functionality and the like should be brought up.

Issue with np.mean

This is a great package, and I was working through the examples provided in the documentation. I had some trouble replicating the np.mean function. (See output below). I am working on the SF6 hardware on Microptyhon v1.12-43-g54a2584de-dirty using ulab version 0.263

import ulab as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print('a: \n', a)

a:
array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0]], dtype=float)

print('sum, flat array: ', np.sum(a))

sum, flat array: 45.0

print('mean, horizontal: ', np.mean(a, axis=1))

mean, horizontal: array([2048.00048828125, 5.387879937997763e-315, 0.0], dtype=float)

print('std, vertical: ', np.std(a, axis=0))

std, vertical: array([7.191838266139812, 5.314304082212256e-315, 0.0], dtype=float)

Subscripting 2-D array returns an array not a single value

When subscripting a 1-D array with an integer a single value is returned but when subscripting a 2-D array with two integers the result is a 1x1 array containing the value. For example:

>>> a = np.array(range(6))
>>> a[4]
4.0
>>> b = np.array(range(6)).reshape((2,3))
>>> b[1,1]
array([4.0], dtype=float)
>>> _.shape()
(1, 1)

Note that in numpy the behaviour of subscripting is simple: dimensions that are indexed with a single value are removed from the result while dimensions that are indexed with a slice or which are not index at all (i.e. there are fewer indices than dimensions) remain. Thus when indexing an array b with 2 dimensions b[0,0] returns a single value, b[0,0:1] returns a 1-D result containing that single value and b[0:1,0:1] returns a 2-D array containing that value. Ideally ulab should do the same.

Note that if the design for N-dimensional arrays discussed in #13 is implemented then this will clearly require the implementation of a more generic subscripting system anyway.

undefined reference to `roundf'

I had been download the latest verison ulab,when make it, it showed the error information as follow:

LINK build-PYBV11/firmware.elf
build-PYBV11/code/vectorise.o: In function vectorise_around': vectorise.c:(.text.vectorise_around+0x76): undefined reference to roundf'
Makefile:597: recipe for target 'build-PYBV11/firmware.elf' failed
make: *** [build-PYBV11/firmware.elf] Error 1

How to solve this issue,Thanks!

building in CircuitPython

This is amazing! I've been trying to build ulab in CircuitPython, which I should be able to do as CP is a fork of micropython, but I've been having a lot of trouble. I'm seeing a lot of issues with shadowed declarations and comparison between signed and unsigned integers. When I attempt to make the board in the appropriate port using:

make BOARD=pybadge USER_C_MODULES=../../../ulab all

I get the following error:

Including User C Module from ../../../ulab/code
QSTR updated
FREEZE ../../frozen/circuitpython-stage/pybadge
../../../ulab/code/ndarray.c: In function 'ndarray_print_row':
../../../ulab/code/ndarray.c:81:20: error: declaration of 'i' shadows a previous local [-Werror=shadow]
for(size_t i=1; i<3; i++) {
^
../../../ulab/code/ndarray.c:66:12: note: shadowed declaration is here
size_t i;
^
../../../ulab/code/ndarray.c: In function 'ndarray_make_new':
../../../ulab/code/ndarray.c:168:30: error: passing argument 2 of 'mp_arg_check_num' makes pointer from integer without a cast [-Werror=int-conversion]
mp_arg_check_num(n_args, n_kw, 1, 2, true);
^~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:80:6: note: expected 'mp_map_t * {aka struct _mp_map_t *}' but argument is of type 'size_t {aka unsigned int}'
void mp_arg_check_num(size_t n_args, mp_map_t *kw_args, size_t n_args_min, size_t n_args_max, bool takes_kw);
^~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:176:29: error: passing argument 1 of 'mp_raise_ValueError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_ValueError("first argument must be an iterable");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:153:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_ValueError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:191:25: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
if(len2 != MP_OBJ_SMALL_INT_VALUE(len_in)) {
^~
../../../ulab/code/ndarray.c:192:41: error: passing argument 1 of 'mp_raise_ValueError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_ValueError("iterables are not of the same length");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:153:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_ValueError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c: In function 'true_length':
../../../ulab/code/ndarray.c:234:13: error: implicit declaration of function 'mp_obj_is_type'; did you mean 'mp_obj_is_true'? [-Werror=implicit-function-declaration]
if(!mp_obj_is_type(item, &mp_type_bool)) {
^~~~~~~~~~~~~~
mp_obj_is_true
../../../ulab/code/ndarray.c:234:13: error: nested extern declaration of 'mp_obj_is_type' [-Werror=nested-externs]
../../../ulab/code/ndarray.c: In function 'generate_slice':
../../../ulab/code/ndarray.c:251:15: error: implicit declaration of function 'mp_obj_is_int'; did you mean 'mp_obj_list_init'? [-Werror=implicit-function-declaration]
} else if(mp_obj_is_int(index)) {
^~~~~~~~~~~~~
mp_obj_list_init
../../../ulab/code/ndarray.c:251:15: error: nested extern declaration of 'mp_obj_is_int' [-Werror=nested-externs]
../../../ulab/code/ndarray.c:256:20: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
if((_index >= n) || (_index < 0)) {
^~
../../../ulab/code/ndarray.c:257:47: error: passing argument 2 of 'mp_raise_msg' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_msg(&mp_type_IndexError, "index is out of bounds");
^~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:151:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg);
^~~~~~~~~~~~
../../../ulab/code/ndarray.c:263:43: error: passing argument 2 of 'mp_raise_msg' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_msg(&mp_type_IndexError, "indices must be integers, slices, or Boolean lists");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:151:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg);
^~~~~~~~~~~~
../../../ulab/code/ndarray.c: In function 'insert_slice_list':
../../../ulab/code/ndarray.c:293:33: error: passing argument 1 of 'mp_raise_ValueError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_ValueError("could not broadast input array from shape");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:153:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_ValueError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:355:27: error: declaration of 'cindex' shadows a previous local [-Werror=shadow]
size_t j = 0, cindex = 0;
^~~~~~
../../../ulab/code/ndarray.c:296:12: note: shadowed declaration is here
size_t cindex, rindex;
^~~~~~
../../../ulab/code/ndarray.c: In function 'iterate_slice_list':
../../../ulab/code/ndarray.c:380:43: error: passing argument 2 of 'mp_raise_msg' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_msg(&mp_type_IndexError, "empty index range");
^~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:151:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg);
^~~~~~~~~~~~
../../../ulab/code/ndarray.c:441:27: error: declaration of 'cindex' shadows a previous local [-Werror=shadow]
size_t j = 0, cindex = 0;
^~~~~~
../../../ulab/code/ndarray.c:390:12: note: shadowed declaration is here
size_t cindex, rindex;
^~~~~~
../../../ulab/code/ndarray.c: In function 'ndarray_get_slice':
../../../ulab/code/ndarray.c:498:47: error: passing argument 2 of 'mp_raise_msg' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_msg(&mp_type_IndexError, "too many indices");
^~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:151:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg);
^~~~~~~~~~~~
../../../ulab/code/ndarray.c:506:51: error: passing argument 2 of 'mp_raise_msg' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_msg(&mp_type_IndexError, "indices must be integers, slices, or Boolean lists");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:151:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg);
^~~~~~~~~~~~
../../../ulab/code/ndarray.c: In function 'ndarray_subscr':
../../../ulab/code/ndarray.c:547:33: error: passing argument 1 of 'mp_raise_ValueError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_ValueError("right hand side must be an ndarray, or a scalar");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:153:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_ValueError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c: In function 'ndarray_flatten':
../../../ulab/code/ndarray.c:658:29: error: passing argument 1 of 'mp_raise_ValueError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_ValueError("flattening order must be either 'C', or 'F'");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:153:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_ValueError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c: In function 'ndarray_binary_op':
../../../ulab/code/ndarray.c:723:33: error: passing argument 1 of 'mp_raise_ValueError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_ValueError("operands could not be broadcast together");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:153:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_ValueError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:826:40: error: passing argument 1 of 'mp_raise_TypeError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_TypeError("wrong input type");
^~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:155:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_TypeError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:834:28: error: passing argument 1 of 'mp_raise_TypeError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_TypeError("wrong operand type on the right hand side");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:155:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_TypeError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c: In function 'ndarray_unary_op':
../../../ulab/code/ndarray.c:852:37: error: passing argument 1 of 'mp_raise_ValueError' from incompatible pointer type [-Werror=incompatible-pointer-types]
mp_raise_ValueError("operation is not supported for given type");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../../ulab/code/ndarray.c:15:0:
../../py/runtime.h:153:15: note: expected 'const compressed_string_t * {aka const struct *}' but argument is of type 'const char *'
NORETURN void mp_raise_ValueError(const compressed_string_t *msg);
^~~~~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:865:26: error: declaration of 'array' shadows a previous local [-Werror=shadow]
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:868:25: error: declaration of 'array' shadows a previous local [-Werror=shadow]
int8_t *array = (int8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:871:27: error: declaration of 'array' shadows a previous local [-Werror=shadow]
uint16_t *array = (uint16_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:874:26: error: declaration of 'array' shadows a previous local [-Werror=shadow]
int16_t *array = (int16_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:877:29: error: declaration of 'array' shadows a previous local [-Werror=shadow]
mp_float_t *array = (mp_float_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:892:25: error: declaration of 'array' shadows a previous local [-Werror=shadow]
int8_t *array = (int8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:897:26: error: declaration of 'array' shadows a previous local [-Werror=shadow]
int16_t *array = (int16_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:902:29: error: declaration of 'array' shadows a previous local [-Werror=shadow]
mp_float_t *array = (mp_float_t *)ndarray->array->items;
^~~~~
../../../ulab/code/ndarray.c:857:22: note: shadowed declaration is here
uint8_t *array = (uint8_t *)ndarray->array->items;
^~~~~
cc1: all warnings being treated as errors
make: *** [build-pybadge/code/ndarray.o] Error 1

Compiling for Nucleo-L476RG

Some changes had to be made to compile ulab into MicroPython v1.12-93 for the Nucleo-L476RG. After the following changes were made, everything seems to work well. NOTE: I'm new to building custom C modules for MicroPython, and these problems may have been caused by my doing something (or many somethings) incorrectly.

  • mp_const_none_obj, mp_const_true_obj, and mp_const_false_obj were unrecognized. Replacing macros such as MP_ROM_PTR(&mp_const_none_obj) with corresponding macros MP_ROM_NONE, MP_ROM_TRUE, and MP_ROM_FALSE allowed successful compilation.

  • As I intend to compile other external C code as well as ulab, it is appropriate to place the ulab directory one level under the main external C code directory, which I've placed inside the root MicroPython directory (is that a faux pas?). The ulab source files are then only found if moved from the ulab/code subdirectory to the main ulab directory. A workaround which seems to work is to move micropython.mk to the main ulab directory, leave the source files in ulab/code, and edit micropython.mk to specify the location of the source and header files as follows:

USERMODULES_DIR := $(USERMOD_DIR)

# Add all C files to SRC_USERMOD.
SRC_USERMOD += $(USERMODULES_DIR)/code/ndarray.c
SRC_USERMOD += $(USERMODULES_DIR)/code/linalg.c
SRC_USERMOD += $(USERMODULES_DIR)/code/vectorise.c
SRC_USERMOD += $(USERMODULES_DIR)/code/poly.c
SRC_USERMOD += $(USERMODULES_DIR)/code/fft.c
SRC_USERMOD += $(USERMODULES_DIR)/code/numerical.c
SRC_USERMOD += $(USERMODULES_DIR)/code/ulab.c

# We can add our module folder to include paths if needed
# This is not actually needed in this example.
CFLAGS_USERMOD += -I$(USERMODULES_DIR)/code

Instructions from the ulab README as well as the MicroPython external C modules page were used to duct tape this solution together. I suspect that the directory problems are my own doing, but I'm not sure about the compiler not recognizing mp_const_none_obj, etc.

Happy to supply more details, diffs, patches, or whatever...as soon as I've gone and learned how to generate them correctly.

Indexing by Boolean List seems to malfunction

I'm not sure if I'm doing any mistake, but indexing using boolean list is not working as expected. See below the result:

MicroPython v1.12-167-gf020eac6a-dirty on 2020-03-06; PYBD-SF6W with STM32F767IIK
Type "help()" for more information.

import ulab as np
a = np.array(range(9), dtype=np.float)
print("a:\t", a)
a: array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], dtype=float)
print("a < 5:\t", a[a < 5])
a < 5: array([], dtype=float)

Is there any workaround? Thanks for your suggestions.

ndarray from image ?

How can I create an ndarray of shape (w, h, c) from a C array of pixels (uint8_t) ? I can create 1D arrays by implementing getiter and unary_op, do I need to return an iter as the items of the first iter and so on ?

Can't create 2d np.arrays with only 1 element

np.array([[1,2]]) should return a two dimensional array with only one element. Accessing said array with array[0] should return [1,2] and it should be passable to arguments such as argsort() which takes in an ndarray. I have not been able to create such an array with ulab. Using reshape() doesn't affect the issue.

Examples:

ulab
import ulab as np
arr = [[1,2]]
arr2 = np.array(arr)
arr2[0]
1.0

numpy
import numpy as np
arr = [[1,2]]
arr2 = np.array(arr)
arr2[0]
Out[1]: array([1, 2])

No need to define MODULE_ULAB_ENABLED in mpconfigport.h

Since the micropython.mk file has added the following line

CFLAGS_EXTRA = -DMODULE_ULAB_ENABLED=1

There's no need to add #define MODULE_ULAB_ENABLED (1) in the mpconfigport.h.Or it would make redefined errors while compiling code.

Incorrect results from ulab.dot() in ESP32

When running ulab on the ESP32 the dot product function ulab.dot() yields erroneous results when the inputs are non-square. For instance:

>>> import ulab as np
>>> aa = np.array(range(6)).reshape((2,3))
>>> bb = np.array(range(6)).reshape((3,2))
>>> np.dot(aa,bb)
array([[2.0, 3.0],
         [8.0, 15.0]], dtype=float)
>>> np.dot(bb,aa)
array([[3.0, 4.0, 0.0],
         [9.0, 14.0, 0.0],
         [0.0, 0.0, 0.0]], dtype=float)

While regular binary operators seem to work fine the dot product function behaves very erratically. The fact that it seems to work correctly for square arrays suggest that the problem is likely some transposition of the dimension lengths.

Issue with dot on PYBD_SF6

I am having an issue running np.dot(). I am running on PYBD-SF6 using version 0.26.5. It appears that a row matrix times a square matrix works fine. However, when I use dot with a square matrix times a column matrix, the results aren't as expected. It appears to only provide the first element in the expected result (14,32,50)

`MicroPython v1.12-92-gd89ed3e62-dirty on 2020-01-26; PYBD-SF6W with STM32F767IIK
Type "help()" for more information.

import ulab as np
print('you are running ulab version', np.version)
you are running ulab version 0.26.5
a = np.array(([1,2,3],[4,5,6],[7,8,9]))
b = np.array(([1,2,3]))
b.transpose()
c = np.dot(a,b)
c
array([14.0, 0.0, 0.0], dtype=float)

`

Ambiguity in Comparison operators

I was trying to implement numpy.linalg.norm in the pythonic way, e.g., L0-norm, and got this when doing:
>>> a
array([1.2, 0.0, -1.3, 0.25, 1.45, -0.35, 2.0], dtype=float)
>>> a != 0.
True
>>> a[a != 0.]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: too many indices
I see that there isn't any mention of != comparision in the documenation. Is this intensional?

At the moment, I'm achieving L0-norm in two steps:
>>> a = array([1.2, 0.0, -1.3, 0.25, 1.45, -0.35, 2.0], dtype=float)
>>> sum([a < 0.]) + sum([a > 0.])

@v923z Do you suggest some efficient way?

Behaviour of transpose() and reshape() are incompatible with numpy

In numpy, ndarray.transpose() returns a view of the original array and ndarray.reshape() returns a view when possible and otherwise they returns a new array. In both cases the array object passed in as the argument is left unaffected. The current ulab behaviour is to reshape the argument that was passed and return the modified original.

The code for both of these functions will naturally get reworked with the new N-dimensional arrays and views, so this GitHub issue is more a spec for the new code than a plea for fixing the old code.

FWIW, in the code I started writing for ndarray the "if possible" test for reshape was simple and dumb: reshape used a view if and only if the input array or view had never been sliced or transposed (which implies that the stride on each dimension is the product of the lengths of all the more deeply nested dimensions). In practice I just kept a flag that was set on creation of new arrays but cleared for new slice or transposes views. Views created by subscripting using only integer indices copied the flag from the parent. In practice this meant that there are some cases that could have used a view but ended up copying because the code to check those cases seemed unnecessarily complex for Micropython.

Certain malfuction in numerical.sort function

I'm not sure, is this happening only in my testing! I'm running test on:

MicroPython v1.12-326-g8fff0b0ac on 2020-04-01; PYBD-SF6W with STM32F767IIK

The numerical.sort function is corrupting a certain element in the matrix:
>>> a
array([[6.058420993051577, 2.018588295338188, 6.307303740008193, 6.743567296659661], [3.760399477657426, 1.501626760992716, 1.020398368879967, 1.903483081086812], [5.20075447514754, 0.7655233559988428, 0.2730999062713479, 5.448723074844875], [3.666587663986214, 0.5528238825462162, 7.759826840359533, 9.887756673795574], [3.228270818725618, 1.784248212712498, 5.302361277197747, 6.772730290987155]], dtype=float)
>>> ulab.numerical.sort(a, axis=0)
array([[3.228270818725618, 0.5528238825462162, 0.2730999062713479, 1.903483081086812], [4.550686286587561e-314, 0.7655233559988428, 1.020398368879967, 5.448723074844875], [3.666587663986214, 1.501626760992716, 5.302361277197747, 6.743567296659661], [3.760399477657426, 1.784248212712498, 6.307303740008193, 6.772730290987155], [5.20075447514754, 2.018588295338188, 7.759826840359533, 9.887756673795574]], dtype=float)

Observe that the two elements of zero column has changed abruptly. However, this does happen when axis=1:
>>> ulab.numerical.sort(a, axis=1)
array([[2.018588295338188, 6.058420993051577, 6.307303740008193, 6.743567296659661], [1.020398368879967, 1.501626760992716, 1.903483081086812, 3.760399477657426], [0.2730999062713479, 0.7655233559988428, 5.20075447514754, 5.448723074844875], [0.5528238825462162, 3.666587663986214, 7.759826840359533, 9.887756673795574], [1.784248212712498, 3.228270818725618, 5.302361277197747, 6.772730290987155]], dtype=float)

Can you also verify at your end?

CNN extend for Numpy-like interface

Hi, Glad to find this repo.
Numpy is the base of science analysis in python. So micropython-ulab is a meaningful repo.

And now CNN is very prevent everywhere. So we wrote Planer, Powerful Light Artificial NEuRon. It is a CNN framework based on pure Numpy-like interface (with out any kernel code, just use reshape, transpose, concadinate, dot, and + - * /). I think it can run on with ulab as backend (with no modify or little modify).

I will buy a micropython board to have a try, if I encounter any problem, could you give a support?

Apparent C-syntax compiling errors

I'm attempting to compile ulab for the PYBD_SF6 from a Mac running macOS 10.13.4.

  • I cloned the 0.24 release of micropython-ulab and the current version of micropython.
  • I ran make in micropython/mpy-cross
  • I ran make BOARD=PYBD_SF6 CROSS_COMPILE=/usr/local/bin/arm-none-eabi- in micropython/ports/stm32, which successfully compiled the "normal" firmware for SF6.
  • But when I instead run make BOARD=PYBD_SF6 CROSS_COMPILE=/usr/local/bin/arm-none-eabi- USER_C_MODULES=../../../ulab all, compilation fails with the error messages below.

Am I doing something wrong here? I'm not an experienced firmware compiler.

CC ../../../ulab/code/ndarray.c
../../../ulab/code/ndarray.c: In function 'ndarray_init_helper':
../../../ulab/code/ndarray.c:157:11: error: 'MP_QSTR_dtype' undeclared (first use in this function); did you mean 'MP_QSTR_type'?
         { MP_QSTR_dtype, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NDARRAY_FLOAT } },
           ^~~~~~~~~~~~~
           MP_QSTR_type
../../../ulab/code/ndarray.c:157:11: note: each undeclared identifier is reported only once for each function it appears in
../../../ulab/code/ndarray.c: In function 'ndarray_flatten':
../../../ulab/code/ndarray.c:648:11: error: 'MP_QSTR_order' undeclared (first use in this function); did you mean 'MP_QSTR_ord'?
         { MP_QSTR_order, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_C)} },
           ^~~~~~~~~~~~~
           MP_QSTR_ord
../../../ulab/code/ndarray.c:648:11: error: initialization of 'short unsigned int' from 'const mp_arg_t *' {aka 'const struct _mp_arg_t *'} makes integer from pointer without a cast [-Werror=int-conversion]
../../../ulab/code/ndarray.c:648:11: note: (near initialization for 'allowed_args[0].qst')
../../../ulab/code/ndarray.c:648:11: error: initializer element is not constant
../../../ulab/code/ndarray.c:648:11: note: (near initialization for 'allowed_args[0].qst')
In file included from ../../py/mpstate.h:35,
                 from ../../py/runtime.h:29,
                 from ../../../ulab/code/ndarray.c:15:
../../../ulab/code/ndarray.c:648:81: error: 'MP_QSTR_C' undeclared (first use in this function); did you mean 'MP_QSTR_r'?
         { MP_QSTR_order, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_C)} },
                                                                                 ^~~~~~~~~
../../py/obj.h:92:56: note: in definition of macro 'MP_OBJ_NEW_QSTR'
 #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))
                                                        ^~~
../../../ulab/code/ndarray.c:648:69: note: in expansion of macro 'MP_ROM_QSTR'
         { MP_QSTR_order, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_C)} },
                                                                     ^~~~~~~~~~~
../../py/obj.h:92:30: error: initializer element is not constant
 #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))
                              ^
../../py/obj.h:248:24: note: in expansion of macro 'MP_OBJ_NEW_QSTR'
 #define MP_ROM_QSTR(q) MP_OBJ_NEW_QSTR(q)
                        ^~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:648:69: note: in expansion of macro 'MP_ROM_QSTR'
         { MP_QSTR_order, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_C)} },
                                                                     ^~~~~~~~~~~
../../py/obj.h:92:30: note: (near initialization for 'allowed_args[0].defval.u_rom_obj')
 #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2))
                              ^
../../py/obj.h:248:24: note: in expansion of macro 'MP_OBJ_NEW_QSTR'
 #define MP_ROM_QSTR(q) MP_OBJ_NEW_QSTR(q)
                        ^~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:648:69: note: in expansion of macro 'MP_ROM_QSTR'
         { MP_QSTR_order, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_C)} },
                                                                     ^~~~~~~~~~~
cc1: all warnings being treated as errors
make: *** [build-PYBD_SF6/code/ndarray.o] Error 1

ulab std method for matrix

Symptom:
ulab.std() sometimes produce nan in the result
ulab version 0.25

Reproduce:
import ulab as np
a = np.array([[109.5894, 117.2053, 69.3245],
[109.5894, 117.1788, 69.3245],
[109.596, 117.1854, 69.3245],
[109.596, 117.1854, 69.3245],
[109.5894, 117.1722, 69.31788],
[109.5894, 117.1921, 69.31788],
[109.5894, 117.1854, 69.31788],
[109.596, 117.1656, 69.31788],
[109.596, 117.1589, 69.31126],
[109.596, 117.1788, 69.30463],
[109.596, 117.1656, 69.29801],
[109.596, 117.1391, 69.29801],
[109.5894, 117.1656, 69.29801],
[109.5828, 117.1523, 69.29801],
[109.5762, 117.1391, 69.29139],
[109.5695, 117.1457, 69.29139],
[109.5762, 117.1457, 69.29139],
[109.5762, 117.1258, 69.28477],
[109.5695, 117.1192, 69.28477],
[109.5695, 117.0861, 69.28477],
[109.5695, 117.0728, 69.27814],
[109.5695, 117.0728, 69.27814],
[109.5695, 117.0861, 69.28477],
[109.5629, 117.0861, 69.29139],
[109.5695, 117.1059, 69.29139],
[109.5695, 117.1126, 69.28477],
[109.5762, 117.1059, 69.28477],
[109.5828, 117.1258, 69.29139],
[109.5762, 117.1457, 69.29139],
[109.5762, 117.1324, 69.29139],
[109.5762, 117.1192, 69.28477],
[109.5762, 117.1192, 69.28477],
[109.5695, 117.1391, 69.28477],
[109.5695, 117.1059, 69.28477],
[109.5762, 117.1457, 69.28477],
[109.5828, 117.1258, 69.28477],
[109.5828, 117.0993, 69.28477],
[109.5828, 117.1457, 69.28477],
[109.5828, 117.1523, 69.29139],
[109.5894, 117.0993, 69.28477],
[109.5828, 117.1059, 69.27814],
[109.5762, 117.1457, 69.27814],
[109.5695, 117.1126, 69.27814],
[109.5695, 117.1192, 69.27814],
[109.5695, 117.1457, 69.28477],
[109.5695, 117.1324, 69.29139],
[109.5695, 117.1192, 69.28477],
[109.5762, 117.1523, 69.29139],
[109.5695, 117.1722, 69.29801],
[109.5695, 117.1523, 69.29801],
[109.5629, 117.1391, 69.29801],
[109.5695, 117.1722, 69.30463],
[109.5762, 117.1391, 69.31126],
[109.5762, 117.0927, 69.30463],
[109.5695, 117.1391, 69.30463],
[109.5695, 117.0927, 69.30463],
[109.5629, 117.053, 69.30463],
[109.5629, 117.0795, 69.30463],
[109.5563, 117.0728, 69.30463],
[109.5497, 117.0265, 69.29801],
[109.5497, 117.0066, 69.29139],
[109.5497, 117.0199, 69.29139],
[109.5497, 116.9868, 69.29139],
[109.5497, 116.9603, 69.29139],
[109.5497, 116.9801, 69.29801],
[109.5497, 116.9603, 69.29801],
[109.543, 116.9404, 69.29139],
[109.543, 116.9338, 69.28477],
[109.5364, 116.9536, 69.28477],
[109.543, 116.9536, 69.29139],
[109.543, 116.9603, 69.29139],
[109.5364, 116.947, 69.29139],
[109.5298, 116.9669, 69.29139],
[109.5298, 116.9801, 69.29139],
[109.5232, 116.947, 69.29139],
[109.5298, 116.9735, 69.29139],
[109.5232, 117.0066, 69.28477],
[109.5165, 117.0, 69.27814],
[109.5099, 116.9868, 69.27152],
[109.5099, 117.0132, 69.27152],
[109.5099, 117.0199, 69.27152],
[109.5099, 116.9735, 69.27152],
[109.5033, 117.0132, 69.2649],
[109.4967, 117.0662, 69.25828],
[109.4967, 117.0265, 69.25828],
[109.4967, 117.0397, 69.25828],
[109.5033, 117.0728, 69.25166],
[109.4967, 117.053, 69.25166],
[109.4967, 117.0, 69.24503],
[109.4967, 117.0331, 69.23841],
[109.4901, 117.0662, 69.23841],
[109.4967, 117.0464, 69.23841],
[109.4901, 117.0728, 69.23841],
[109.4901, 117.0993, 69.23841],
[109.4901, 117.0662, 69.23841],
[109.4967, 117.0199, 69.23841],
[109.4901, 117.053, 69.23841],
[109.4901, 117.053, 69.23841],
[109.4901, 117.0199, 69.23841],
[109.4834, 117.0596, 69.23841]])

print(np.std(a,axis=0))
Result:
array([nan, nan, nan], dtype=float)

Expected result:
array([0.03424415, 0.07198399, 0.02212126], dtype=float)

Certain inconsistency in numerical.argsort function

@v923z I'm not sure if this is intentional?

MicroPython v1.12-337-g312c69949 on 2020-04-06; PYBD-SF6W with STM32F767IIK
Type "help()" for more information.
>>> import ulab as np
>>> np.__version__
'0.41.0'
>>> a = np.array([[4,5,6],[1,2,3],[7,8,9]])
>>> np.numerical.argsort(a, axis=0)
array([[1, 1, 1],
         [0, 0, 0],
         [2, 2, 2]], dtype=uint16)
>>> a
array([[4.0, 5.0, 6.0],
         [1.0, 2.0, 3.0],
         [7.0, 8.0, 9.0]], dtype=float)
>>> np.numerical.argsort(a, axis=None)
array([3, 4, 5, 0, 1, 2, 6, 7, 8], dtype=uint16)
>>> a
array([4.0, 5.0, 6.0, 1.0, 2.0, 3.0, 7.0, 8.0, 9.0], dtype=float)

whereas the documentation of ULAB mentions: "Since during the sorting, only the indices are shuffled, argsort does not modify the input array...". The original array is flattened when axis=None. The Numpy behaves as the documentation of ULAB mentions.

Bug in ulab.linalg.dot function

@v923z linalg.dot seems to have a certain bug:

MicroPython v1.12-368-gbd63c26dd on 2020-04-13; PYBD-SF6W with STM32F767IIK
Type "help()" for more information.
>>> ulab.__version__
'0.41.2'

>>> A
array([[1.0, 2.0],
         [3.0, 4.0]], dtype=float)
>>> B
array([[1.0, 2.0, 3.0, 4.0],
         [5.0, 6.0, 7.0, 8.0]], dtype=float)
>>> ulab.linalg.dot(A,B)
array([[11.0, 23.0, 14.0, 30.0],
         [17.0, 37.0, 20.0, 44.0]], dtype=float)

whereas the correct result from Numpy is:

np.dot(A,B)
array([[11, 14, 17, 20],
       [23, 30, 37, 44]])

Seems that it has something to do with way the elements are stored in the array!
Can you reproduce the same at your end?

let ndarrays be on the right hand side of binary operators

At the moment, ndarrays must be on the left hand side of a binary operator. Thus

a = np.array([1, 2, 3])
a + 1

works, but

a = np.array([1, 2, 3])
1 + a

fails. A solution involves the implementation of the REVERSE operators in binary_op in ndarray.c

platform support?

Is this generic C code that could easily build and run on linux, mac, windows?
Or does it only work on microcontrollers? (which ones?)

Added to OpenMV

Hi, I just wanted to say that Ibrahim added your code to the OpenMV Cam.

Thanks!

(Yes, I know this is not the best way to contact you).

Epsilon double promotion warning/error.

MICROPY_FLOAT_IMPL_FLOAT turns on -Wdouble-promotion and -fsingle-precision-constant which causes epsilon literal to be float and an implicit conversion from 'float' to 'double' (to match fabs) warning/error. Maybe fabsf should be used instead...

QSTR not updated
CC ../../extmod/ulab/code/linalg.c
../../extmod/ulab/code/linalg.c: In function 'linalg_invert_matrix':
../../extmod/ulab/code/linalg.c:127:32: error: implicit conversion from 'float' to 'double' to match other operand of binary expression [-Werror=double-promotion]
         if(fabs(data[m*(N+1)]) < epsilon) {
                                ^
../../extmod/ulab/code/linalg.c: In function 'linalg_det':
../../extmod/ulab/code/linalg.c:310:35: error: implicit conversion from 'float' to 'double' to match other operand of binary expression [-Werror=double-promotion]
         if(fabs(tmp[m*(in->n+1)]) < epsilon) {
                                   ^
../../extmod/ulab/code/linalg.c: In function 'linalg_eig':
../../extmod/ulab/code/linalg.c:349:24: error: implicit conversion from 'float' to 'double' to match other operand of binary expression [-Werror=double-promotion]
             if(epsilon < fabs(array[m*in->n + n] - array[n*in->n + m])) {
                        ^
cc1: all warnings being treated as errors

Feature requests

If you find that you would need a numpy function that is not implemented in ulab, please, open a new issue for each function you want to have implemented. This issue is locked, and cannot be appended to.

Array shapes where one dimension is length 1 not properly represented

Currently ulab fails to properly displays arrays where the length of one of the dimensions is 1. Furthermore it incorrectly represents the shape of arrays with only one dimension.

To see this consider the following code for regular Python and numpy:

>>> import numpy as np
>>> aa = np.array(range(3))
>>> aa, aa.shape
(array([0, 1, 2]), (3,))
>>> bb = np.array(range(3)).reshape((1,3))
>>> bb, bb.shape
(array([[0, 1, 2]]), (1, 3))
>>> cc = np.array(range(3)).reshape((3,1))
>>> cc, cc.shape
(array([[0],
       [1],
       [2]]), (3, 1))

Compare this with the equivalent code in Micropython with ulab:

>>> import ulab as np
>>> aa = np.array(range(3))
>>> aa, aa.shape()
(array([0.0, 1.0, 2.0], dtype=float), (1, 3))
>>> bb = np.array(range(3)).reshape((1,3))
>>> bb, bb.shape()
(array([0.0, 1.0, 2.0], dtype=float), (1, 3))
>>> cc = np.array(range(3)).reshape((3,1))
>>> cc, cc.shape()
(array([0.0, 1.0, 2.0], dtype=float), (3, 1))

In the aa case the shape is misrepresented as being two dimensional even though it is printed as one dimensional. In the bb and cc cases the shape is correctly displayed but the array is printed as if it were one dimensional.

Two dimensional arrays where the length of both dimensions is greater than one are printed correctly and have the shape correctly represented.

ndarrays are not modifiable

I've been playing around with ulab and it's awesome, but I've run into some issues because I can't modify the elements of an ndarray.

For example:

>>> a = 100 * np.linspace(0,10,num=1024)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported types for __mul__: 'int', 'ndarray'

and

>>> for i in range(len(b)):
... b[i] = i
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: index is out of range

By the way, THANK YOU for making this module. I'm still getting my bearings with mpy and usermods, but your documentation has been very helpful. Hopefully soon I'll have some time to add some of these features in myself.

EDIT: I just tried >>> a = np.linspace(0,10,num=1024) * 100 and it worked, so that's a solid workaround!

Out of curiosity about using CMSIS library

@v923z Hi, I was wondering if there exists already optimized Math and DSP library for ARM uController and found that there is one provided by ARM itself called CMSIS, I guess you may be aware of it. I see that Micropython does use the only device driver part from CMSIS library from ST in the port stm32. I was wondering will it be possible to include CMSIS DSP library into ULAB, e.g. using arm_math.h and others? I'm not sure about the Licencing thing though!

argmin/argmax of iterable: results differ from ndarray and numpy

>>> ulab.numerical.argmax([[1,2],[4,3]])
1
>>> ulab.numerical.argmin([[1,2],[4,3]])
0

but

>>> ulab.numerical.argmin(ulab.array([[1,2],[4,3]]))
0
>>> ulab.numerical.argmax(ulab.array([[1,2],[4,3]]))
2

and

>>> numpy.argmin([[1,2],[4,3]])
0
>>> numpy.argmax([[1,2],[4,3]])
2

Missing .T transpose property

In numpy the transpose of an array x can be accessed using the property x.T. This is a widely used feature that should be supported.

It should be noted in numpy the T property points to the same underlying value set, with the array stride values and dimensions reversed. Unless ulab changes to track the array strides for all dimensions this may be difficult to replicate.

Minor inconsistency in accessed the one element from ndarray

I'm not sure if this is intentional:
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a[1,1]
array([5.0], dtype=float)
>>> a[1][1]
5.0
why in the first case we get an array while in second case a numeric value? In numpy, both result into a numeric value rather in array container.

Compilation errors for unix port on macOS

I am able to compile micropython+ulab for the PYBD_SF6 but not for unix.

My batch script is the following:

mkdir build
cd build

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

cd micropython
git submodule update --init

cd mpy-cross/
make

cd ../ports/stm32
echo '#define MODULE_ULAB_ENABLED (1)' | cat >> mpconfigport.h
make BOARD=PYBD_SF6 CROSS_COMPILE=/usr/local/bin/arm-none-eabi- USER_C_MODULES=../../../ulab all

cd ../unix
echo '#define MODULE_ULAB_ENABLED (1)' | cat >> mpconfigport.h
make USER_C_MODULES=../../../ulab all

When running the above code, I get a functional PUBD_SF6 firmware but the unix make results in 3 -Wparentheses-equality errors in ulab/code/ndarray.c:

CC ../../../ulab/code/ndarray.c
../../../ulab/code/ndarray.c:583:20: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
    if((ndarray->m == 1)) {
        ~~~~~~~~~~~^~~~
../../../ulab/code/ndarray.c:583:20: note: remove extraneous parentheses around the comparison to silence this warning
    if((ndarray->m == 1)) {
       ~           ^   ~
../../../ulab/code/ndarray.c:583:20: note: use '=' to turn this equality comparison into an assignment
    if((ndarray->m == 1)) {
                   ^~
                   =
../../../ulab/code/ndarray.c:891:39: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
            if((self->array->typecode == NDARRAY_INT8)) {
                ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:891:39: note: remove extraneous parentheses around the comparison to silence this warning
            if((self->array->typecode == NDARRAY_INT8)) {
               ~                      ^              ~
../../../ulab/code/ndarray.c:891:39: note: use '=' to turn this equality comparison into an assignment
            if((self->array->typecode == NDARRAY_INT8)) {
                                      ^~
                                      =
../../../ulab/code/ndarray.c:896:46: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
            } else if((self->array->typecode == NDARRAY_INT16)) {
                       ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
../../../ulab/code/ndarray.c:896:46: note: remove extraneous parentheses around the comparison to silence this warning
            } else if((self->array->typecode == NDARRAY_INT16)) {
                      ~                      ^               ~
../../../ulab/code/ndarray.c:896:46: note: use '=' to turn this equality comparison into an assignment
            } else if((self->array->typecode == NDARRAY_INT16)) {
                                             ^~
                                             =
3 errors generated.
make: *** [build/code/ndarray.o] Error 1

If I add -Wno-parentheses-equality to the CFLAGS in micropython/ports/unix/Makefile, I get different errors, in ulab/code/linalg.c this time:

CC ../../../ulab/code/ndarray.c
CC ../../../ulab/code/linalg.c
../../../ulab/code/linalg.c:127:12: error: using integer absolute value function 'abs' when argument is of floating point type [-Werror,-Wabsolute-value]
        if(abs(data[m*(N+1)]) < epsilon) {
           ^
../../../ulab/code/linalg.c:127:12: note: use function 'fabs' instead
        if(abs(data[m*(N+1)]) < epsilon) {
           ^~~
           fabs
../../../ulab/code/linalg.c:310:12: error: using integer absolute value function 'abs' when argument is of floating point type [-Werror,-Wabsolute-value]
        if(abs(tmp[m*(in->n+1)]) < epsilon) {
           ^
../../../ulab/code/linalg.c:310:12: note: use function 'fabs' instead
        if(abs(tmp[m*(in->n+1)]) < epsilon) {
           ^~~
           fabs
../../../ulab/code/linalg.c:349:26: error: using integer absolute value function 'abs' when argument is of floating point type [-Werror,-Wabsolute-value]
            if(epsilon < abs(array[m*in->n + n] - array[n*in->n + m])) {
                         ^
../../../ulab/code/linalg.c:349:26: note: use function 'fabs' instead
            if(epsilon < abs(array[m*in->n + n] - array[n*in->n + m])) {
                         ^~~
                         fabs
3 errors generated.
make: *** [build/code/linalg.o] Error 1

I suspect this might be due to some quirk of the macOS C compiler, but that's not much more than a random guess.

Is there anything obvious that I'm doing wrong?

.transpose() missing

I recently updated to version 0.32.0 and notices that the .transpose() function was not available.
`

a = np.zeros((5,3))
a.shape
(5, 3)
a.transpose
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'ndarray' object has no attribute 'transpose'
a.transpose()
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'ndarray' object has no attribute 'transpose'
`

Slicing difference vs numpy

It seems that too few elements are in the result.

>>> np.array([0,1,2,3,4])[::2]
array([0, 2, 4])

vs

>>> ulab.array([0,1,2,3,4])[::2]
array([0.0, 2.0], dtype=float)

Let me know if you'd like me to look into this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.