Browse Source

added numerical module to ulab

pull/8/head
Zoltán Vörös 5 years ago
parent
commit
7d769da4f5
  1. 692
      docs/ulab.ipynb
  2. 1
      ulab/micropython.mk
  3. 6
      ulab/ndarray.c
  4. 6
      ulab/ndarray.h
  5. 149
      ulab/numerical.c
  6. 19
      ulab/numerical.h
  7. 22
      ulab/ulab.c

692
docs/ulab.ipynb

@ -11,7 +11,17 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"ulab is a C module for micropython. The main aim is to implement a small subset of numpy. We chose those functions and methods that might be useful in the context of a microcontroller. This means low-level data processing. "
"ulab is a C module for micropython. The aim was to implement a small subset of numpy. We chose those functions and methods that might be useful in the context of a microcontroller. This means low-level data processing of linear and matrix data.\n",
"\n",
"The main points of ulab are \n",
"\n",
"- compact, iterable and slicable container of numerical data in 1, and 2 dimensions (arrays and matrices). In addition, these containers support all the relevant unary and binary operators (e.g., `len`, `bool`, ==, +, *, etc.)\n",
"- vectorised computations on micropython iterables and numerical arrays/matrices\n",
"- basic linear algebra routines (like matrix inversion, matrix reshaping, and transposition)\n",
"- polynomial first to numerical data\n",
"- fast Fourier transforms\n",
"\n",
"Each section of the implementation part kicks out with a short discussion on what can be done with the module, and what are the tripping points at the C level. I hope that these musings can be used as a starting point for further discussion on the code. Then come the contents of the header and C files of the particular module. "
]
},
{
@ -225,6 +235,69 @@
"**NOTE: with a little bit of extra effort, mp_obj_array_t can be replaced by a single void array. We should, perhaps, consider the pros and cons of that. One patent advantage is that we could get rid of the verbatim copy of array_new function in ndarray.c.**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Most of the functions in ndarray.c are internal (i.e., not exposed to the python interpreter). Exception to this rule are the `shape`, `size`, and `rawsize` functions. This latter on is not standard in numpy, and is meant to return the total number of bytes used by the container. Since the RAM of a microcontroller is limited, I deemed this to be a reasonable addition for optimisation purposes. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Initialisation\n",
"\n",
"An ndarray can be initialised by passing an iterable (linear arrays), or an iterable of iterables (matrices) into the constructor as"
]
},
{
"cell_type": "code",
"execution_count": 205,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-07T19:42:05.874414Z",
"start_time": "2019-08-07T19:42:05.853846Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ndarray([1.0, 2.0, 3.0, 4.0])\n",
"\n",
"ndarray([[1.0, 2.0, 3.0, 4.0],\n",
"\t [2.0, 3.0, 4.0, 5.0]])\n",
"\n",
"ndarray([[0.0, 1.0, 2.0, ..., 7.0, 8.0, 9.0],\n",
"\t [0.0, 1.0, 2.0, ..., 7.0, 8.0, 9.0]])\n",
"\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython\n",
"\n",
"from ulab import ndarray\n",
"\n",
"a = ndarray([1, 2, 3, 4])\n",
"print(a)\n",
"a = ndarray([[1, 2, 3, 4], [2, 3, 4, 5]])\n",
"print(a)\n",
"a = ndarray([range(10), range(10)])\n",
"print(a)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In addition, the constructor can take a keyword argument, dtype, that will force type conversion."
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -234,11 +307,11 @@
},
{
"cell_type": "code",
"execution_count": 118,
"execution_count": 198,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-07T16:45:07.715837Z",
"start_time": "2019-08-07T16:45:07.708734Z"
"end_time": "2019-08-07T19:13:59.067813Z",
"start_time": "2019-08-07T19:13:59.049895Z"
}
},
"outputs": [
@ -246,7 +319,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"written 1505 bytes to ndarray.h\n"
"written 1490 bytes to ndarray.h\n"
]
}
],
@ -292,11 +365,11 @@
"*/\n",
"\n",
"void ndarray_print_row(const mp_print_t *, mp_obj_array_t *, size_t , size_t );\n",
"void ulab_ndarray_print(const mp_print_t *, mp_obj_t , mp_print_kind_t );\n",
"void ndarray_print(const mp_print_t *, mp_obj_t , mp_print_kind_t );\n",
"void assign_elements(mp_obj_array_t *, mp_obj_t , uint8_t , size_t *);\n",
"ndarray_obj_t *create_new_ndarray(size_t , size_t , uint8_t );\n",
"mp_obj_t ulab_ndarray_copy(mp_obj_t );\n",
"mp_obj_t ulab_ndarray_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *);\n",
"mp_obj_t ndarray_copy(mp_obj_t );\n",
"mp_obj_t ndarray_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *);\n",
"\n",
"mp_obj_t ndarray_shape(mp_obj_t );\n",
"mp_obj_t ndarray_size(mp_obj_t , mp_obj_t );\n",
@ -314,11 +387,11 @@
},
{
"cell_type": "code",
"execution_count": 105,
"execution_count": 199,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-07T16:38:44.272360Z",
"start_time": "2019-08-07T16:38:44.260534Z"
"end_time": "2019-08-07T19:14:32.169261Z",
"start_time": "2019-08-07T19:14:32.149002Z"
}
},
"outputs": [
@ -326,7 +399,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"written 8066 bytes to ndarray.c\n"
"written 8051 bytes to ndarray.c\n"
]
}
],
@ -386,10 +459,10 @@
" mp_print_str(print, \"]\");\n",
"}\n",
"\n",
"void ulab_ndarray_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n",
"void ndarray_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {\n",
" (void)kind;\n",
" ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in);\n",
" mp_print_str(print, \"ndarray(\");\t\n",
" mp_print_str(print, \"ndarray(\");\n",
" if((self->m == 1) || (self->n == 1)) {\n",
" ndarray_print_row(print, self->data, 0, self->data->len);\n",
" } else {\n",
@ -429,7 +502,7 @@
" return ndarray;\n",
"}\n",
"\n",
"mp_obj_t ulab_ndarray_copy(mp_obj_t self_in) {\n",
"mp_obj_t ndarray_copy(mp_obj_t self_in) {\n",
" // returns a verbatim (shape and typecode) copy of self_in\n",
" ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in);\n",
" ndarray_obj_t *out = create_new_ndarray(self->m, self->n, self->data->typecode);\n",
@ -438,7 +511,7 @@
" return MP_OBJ_FROM_PTR(out);\n",
"}\n",
"\n",
"mp_obj_t ulab_ndarray_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {\n",
"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) {\n",
" mp_arg_check_num(n_args, n_kw, 1, 3, true);\n",
" \n",
" size_t len1, len2=0, i=0;\n",
@ -539,7 +612,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Linear algebra"
"# Linear algebra\n",
"\n",
"This module contains very basic matrix operators, such as transposing, reshaping, and inverting. The actual inversion is factored out into a helper function, so that the routine can be re-used in other modules. Also note that inversion is based on the notion of a *small number* (epsilon). During the computation of the inverse, a number is treated as 0, if its absolute value is smaller than epsilon. This precaution is required, otherwise, one might run into singular matrices. "
]
},
{
@ -748,8 +823,51 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The following module implements the common mathematical functions for scalars, ndarrays (linear or matrix), and iterables. If the input argument is a scalar, a scalar is returned (i.e., for such arguments, these functions are identical to the functions in the `math` module), while for ndarrays, and iterables, the return value is an ndarray. \n",
"## General comments"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following module implements the common mathematical functions for scalars, ndarrays (linear or matrix), and iterables. If the input argument is a scalar, a scalar is returned (i.e., for such arguments, these functions are identical to the functions in the `math` module), while for ndarrays, and iterables, the return value is an ndarray. "
]
},
{
"cell_type": "code",
"execution_count": 208,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-07T19:44:50.983799Z",
"start_time": "2019-08-07T19:44:50.965600Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ndarray([1.0, 2.718281745910645, 7.389056205749512, 20.08553695678711, 54.59814834594727])\n",
"\n",
"7.38905609893065\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython\n",
"\n",
"import ulab\n",
"\n",
"print(ulab.exp(range(5)))\n",
"print(ulab.exp(2.0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that ndarrays are linear arrays in memory, even if the `shape` of the ndarray is a matrix. This means that we can treat both cases in a *single* loop."
]
},
@ -872,7 +990,7 @@
" }\n",
"/* if(MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type)) {\n",
" ndarray_obj_t *o = MP_OBJ_TO_PTR(o_in);\n",
" ndarray_obj_t *array = create_new_ndarray(o->m, o->n, NDARRAY_FLOAT);\n",
" ndarray_obj_t *nd_array = create_new_ndarray(o->m, o->n, NDARRAY_FLOAT);\n",
" }*/\n",
" if(MP_OBJ_IS_TYPE(o_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(o_in, &mp_type_list) || \n",
" MP_OBJ_IS_TYPE(o_in, &mp_type_range)) {\n",
@ -1088,6 +1206,263 @@
"#include \"fft.h\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Numerical\n",
"\n",
"This section contains miscellaneous functions that did not fit in the other submodules. These include `linspace`, `logspace`, `min/max`, `argmin/argmax`, `sum`, `mean`, `std`, and `clip`. These latter functions work with iterables, or ndarrays. When the ndarray is two-dimensional, an `axis` keyword can be supplied, in which case, the function returns a vector, otherwise a scalar."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)"
]
},
{
"cell_type": "code",
"execution_count": 249,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-08T05:24:24.356757Z",
"start_time": "2019-08-08T05:24:24.335597Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ndarray([0.0, 1.0, 2.0, ..., 8.0, 9.0, 10.0])\n",
"\n",
"6.0\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython\n",
"\n",
"import ulab\n",
"\n",
"print(ulab.linspace(0, 10, 11))\n",
"print(ulab.sum([1, 2, 3]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## numerical.h"
]
},
{
"cell_type": "code",
"execution_count": 267,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-08T19:01:22.049275Z",
"start_time": "2019-08-08T19:01:22.027294Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"written 359 bytes to numerical.h\n"
]
}
],
"source": [
"%%ccode numerical.h\n",
"\n",
"#ifndef _NUMERICAL_\n",
"#define _NUMERICAL_\n",
"\n",
"#include \"ndarray.h\"\n",
"\n",
"mp_obj_t numerical_linspace(mp_obj_t , mp_obj_t , mp_obj_t );\n",
"mp_obj_t numerical_sum(mp_obj_t , mp_obj_t );\n",
"\n",
"#endif"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## numerical.c"
]
},
{
"cell_type": "code",
"execution_count": 275,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-08T19:05:43.361531Z",
"start_time": "2019-08-08T19:05:43.352973Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"written 5865 bytes to numerical.c\n"
]
}
],
"source": [
"%%ccode numerical.c\n",
"\n",
"#include <math.h>\n",
"#include \"py/runtime.h\"\n",
"#include \"numerical.h\"\n",
"\n",
"typedef struct {\n",
" uint8_t uint8;\n",
" int8_t int8;\n",
" uint16_t uint16;\n",
" int16_t int16;\n",
" float float1, float2; // we need two floats, so that the standard deviation can be calculated\n",
"} numerical_results;\n",
"\n",
"numerical_results n_results;\n",
"\n",
"mp_obj_t numerical_linspace(mp_obj_t _start, mp_obj_t _stop, mp_obj_t _len) {\n",
" // TODO: accept keyword argument endpoint=True\n",
" mp_int_t len = mp_obj_get_int_truncated(_len);\n",
" if(len < 2) {\n",
" mp_raise_ValueError(\"number of points must be at least 2\");\n",
" }\n",
" mp_float_t value, step;\n",
" value = mp_obj_get_float(_start);\n",
" step = (mp_obj_get_float(_stop)-value)/(len-1);\n",
" ndarray_obj_t *nd_array = create_new_ndarray(1, len, NDARRAY_FLOAT);\n",
" for(size_t i=0; i < len; i++, value += step) {\n",
" mp_binary_set_val_array('f', nd_array->data->items, i, mp_obj_new_float(value));\n",
" }\n",
" return MP_OBJ_FROM_PTR(nd_array);\n",
"}\n",
"void clear_results(void) {\n",
" n_results.uint8 = 0;\n",
" n_results.int8 = 0;\n",
" n_results.uint16 = 0;\n",
" n_results.int16 = 0;\n",
" n_results.float1 = n_results.float2 = 0.0;\n",
"}\n",
"\n",
"void sum_matrix(void *data, size_t start, size_t stop, size_t stride, unsigned char type) {\n",
" clear_results();\n",
" for(size_t i=start; i < stop; i+= stride) {\n",
" switch(type) {\n",
" case NDARRAY_UINT8:\n",
" n_results.uint8 += ((uint8_t *)data)[i];\n",
" break;\n",
" case NDARRAY_INT8:\n",
" n_results.int8 += ((int8_t *)data)[i];\n",
" break;\n",
" case NDARRAY_UINT16:\n",
" n_results.uint16 += ((uint16_t *)data)[i];\n",
" break;\n",
" case NDARRAY_INT16:\n",
" n_results.int16 += ((int16_t *)data)[i];\n",
" break;\n",
" case NDARRAY_FLOAT:\n",
" n_results.float1 += ((float *)data)[i];\n",
" }\n",
" }\n",
"}\n",
"\n",
"mp_obj_t numerical_sum(mp_obj_t o_in, mp_obj_t axis) {\n",
" // TODO: deal with keyword argument\n",
" if(MP_OBJ_IS_TYPE(o_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(o_in, &mp_type_list) || \n",
" MP_OBJ_IS_TYPE(o_in, &mp_type_range)) {\n",
" mp_float_t _sum = 0.0;\n",
" mp_obj_iter_buf_t iter_buf;\n",
" mp_obj_t item, iterable = mp_getiter(o_in, &iter_buf);\n",
" while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {\n",
" _sum += mp_obj_get_float(item);\n",
" }\n",
" return mp_obj_new_float(_sum);\n",
" } else if(MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type)) {\n",
" ndarray_obj_t *o = MP_OBJ_TO_PTR(o_in);\n",
" if((o->m == 1) || (o->n == 1)) {\n",
" sum_matrix(o->data->items, 1, o->data->len, 1, o->data->typecode);\n",
" if(o->data->typecode == NDARRAY_UINT8) {\n",
" return mp_obj_new_int(n_results.uint8);\n",
" } else if(o->data->typecode == NDARRAY_INT8) {\n",
" return mp_obj_new_int(n_results.int8);\n",
" } else if(o->data->typecode == NDARRAY_UINT16) {\n",
" return mp_obj_new_int(n_results.uint16);\n",
" } else if(o->data->typecode == NDARRAY_INT16) {\n",
" return mp_obj_new_int(n_results.int16);\n",
" } else {\n",
" return mp_obj_new_float(n_results.float1);\n",
" }\n",
" } else {\n",
" size_t m = (mp_obj_get_int(axis) == 1) ? 1 : o->m;\n",
" size_t n = (mp_obj_get_int(axis) == 1) ? o->n : 1;\n",
" ndarray_obj_t *out = create_new_ndarray(m, n, o->data->typecode);\n",
" \n",
" if(m == 1) { // sum vertically\n",
" for(size_t i=0; i < n; i++) {\n",
" sum_matrix(o->data->items, i, o->data->len, m, o->data->typecode);\n",
" switch(o->data->typecode) {\n",
" case NDARRAY_UINT8:\n",
" *(uint8_t *)out->data->items[i] = n_results.uint8;\n",
" break;\n",
" case NDARRAY_INT8:\n",
" *(int8_t *)out->data->items[i] = n_results.int8;\n",
" break;\n",
" case NDARRAY_UINT16:\n",
" *(uint16_t *)out->data->items[i] = n_results.uint16;\n",
" break;\n",
" case NDARRAY_INT16:\n",
" *(int16_t *)out->data->items[i] = n_results.int16;\n",
" break;\n",
" case NDARRAY_FLOAT:\n",
" *(float_t *)out->data->items[i] = n_results.float1;\n",
" break;\n",
" }\n",
" }\n",
" } else { // sum horizontally\n",
" for(size_t i=0; i < m; i++) {\n",
" sum_matrix(o->data->items, i*n, o->data->len, n, o->data->typecode);\n",
" switch(o->data->typecode) {\n",
" case NDARRAY_UINT8:\n",
" *(uint8_t *)out->data->items[i] = n_results.uint8;\n",
" break;\n",
" case NDARRAY_INT8:\n",
" *(int8_t *)out->data->items[i] = n_results.int8;\n",
" break;\n",
" case NDARRAY_UINT16:\n",
" *(uint16_t *)out->data->items[i] = n_results.uint16;\n",
" break;\n",
" case NDARRAY_INT16:\n",
" *(int16_t *)out->data->items[i] = n_results.int16;\n",
" break;\n",
" case NDARRAY_FLOAT:\n",
" *(float_t *)out->data->items[i] = n_results.float1;\n",
" break;\n",
" }\n",
" } \n",
" }\n",
" }\n",
" } else {\n",
" mp_raise_TypeError(\"input must be tuple, list, range, or ndarray\");\n",
" }\n",
" return mp_const_none;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -1104,11 +1479,11 @@
},
{
"cell_type": "code",
"execution_count": 195,
"execution_count": 265,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-07T18:49:46.336179Z",
"start_time": "2019-08-07T18:49:46.321868Z"
"end_time": "2019-08-08T19:01:02.138430Z",
"start_time": "2019-08-08T19:01:02.129451Z"
}
},
"outputs": [
@ -1116,7 +1491,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"written 5923 bytes to ulab.c\n"
"written 6163 bytes to ulab.c\n"
]
}
],
@ -1135,7 +1510,9 @@
"#include \"ndarray.h\"\n",
"#include \"linalg.h\"\n",
"#include \"vectorise.h\"\n",
"#include \"numerical.h\"\n",
"\n",
"#define ULAB__VERSION 1.0\n",
"\n",
"MP_DEFINE_CONST_FUN_OBJ_1(ndarray_shape_obj, ndarray_shape);\n",
"MP_DEFINE_CONST_FUN_OBJ_2(ndarray_size_obj, ndarray_size);\n",
@ -1143,6 +1520,7 @@
"\n",
"MP_DEFINE_CONST_FUN_OBJ_1(linalg_transpose_obj, linalg_transpose);\n",
"MP_DEFINE_CONST_FUN_OBJ_2(linalg_reshape_obj, linalg_reshape);\n",
"MP_DEFINE_CONST_FUN_OBJ_1(linalg_inv_obj, linalg_inv);\n",
"\n",
"MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acos_obj, vectorise_acos);\n",
"MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acosh_obj, vectorise_acosh);\n",
@ -1168,6 +1546,10 @@
"MP_DEFINE_CONST_FUN_OBJ_1(vectorise_tan_obj, vectorise_tan);\n",
"MP_DEFINE_CONST_FUN_OBJ_1(vectorise_tanh_obj, vectorise_tanh);\n",
"\n",
"MP_DEFINE_CONST_FUN_OBJ_3(numerical_linspace_obj, numerical_linspace);\n",
"MP_DEFINE_CONST_FUN_OBJ_2(numerical_sum_obj, numerical_sum);\n",
"\n",
"\n",
"STATIC const mp_rom_map_elem_t ulab_ndarray_locals_dict_table[] = {\n",
" { MP_ROM_QSTR(MP_QSTR_shape), MP_ROM_PTR(&ndarray_shape_obj) },\n",
" { MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&ndarray_size_obj) },\n",
@ -1189,17 +1571,15 @@
"const mp_obj_type_t ulab_ndarray_type = {\n",
" { &mp_type_type },\n",
" .name = MP_QSTR_ndarray,\n",
" .print = ulab_ndarray_print,\n",
" .make_new = ulab_ndarray_make_new,\n",
"// .unary_op = ulab_ndarray_unary_op,\n",
" .print = ndarray_print,\n",
" .make_new = ndarray_make_new,\n",
"// .unary_op = ndarray_unary_op,\n",
"// .subscr = ndarray_subscr,\n",
"// .getiter = ndarray_iterator_new,\n",
"// .binary_op = ulab_ndarray_binary_op,\n",
"// .binary_op = ndarray_binary_op,\n",
" .locals_dict = (mp_obj_dict_t*)&ulab_ndarray_locals_dict,\n",
"};\n",
"\n",
"MP_DEFINE_CONST_FUN_OBJ_1(linalg_inv_obj, linalg_inv);\n",
"\n",
"STATIC const mp_map_elem_t ulab_globals_table[] = {\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ulab) },\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR_ndarray), (mp_obj_t)&ulab_ndarray_type },\n",
@ -1226,8 +1606,9 @@
" { MP_OBJ_NEW_QSTR(MP_QSTR_sinh), (mp_obj_t)&vectorise_sinh_obj },\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&vectorise_sqrt_obj },\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR_tan), (mp_obj_t)&vectorise_tan_obj },\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&vectorise_tanh_obj }\n",
" // { MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&ulab_sum_obj },\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&vectorise_tanh_obj },\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR_linspace), (mp_obj_t)&numerical_linspace_obj },\n",
" { MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&numerical_sum_obj },\n",
"};\n",
"\n",
"STATIC MP_DEFINE_CONST_DICT (\n",
@ -1253,11 +1634,11 @@
},
{
"cell_type": "code",
"execution_count": 166,
"execution_count": 215,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-07T17:29:55.173608Z",
"start_time": "2019-08-07T17:29:55.164299Z"
"end_time": "2019-08-08T05:06:05.737230Z",
"start_time": "2019-08-08T05:06:05.729485Z"
}
},
"outputs": [
@ -1278,6 +1659,7 @@
"SRC_USERMOD += $(USERMODULES_DIR)/ndarray.c\n",
"SRC_USERMOD += $(USERMODULES_DIR)/linalg.c\n",
"SRC_USERMOD += $(USERMODULES_DIR)/vectorise.c\n",
"SRC_USERMOD += $(USERMODULES_DIR)/numerical.c\n",
"SRC_USERMOD += $(USERMODULES_DIR)/ulab.c\n",
"\n",
"# We can add our module folder to include paths if needed\n",
@ -1294,11 +1676,11 @@
},
{
"cell_type": "code",
"execution_count": 196,
"execution_count": 276,
"metadata": {
"ExecuteTime": {
"end_time": "2019-08-07T18:50:07.828170Z",
"start_time": "2019-08-07T18:49:50.633892Z"
"end_time": "2019-08-08T19:05:48.682377Z",
"start_time": "2019-08-08T19:05:47.879936Z"
},
"scrolled": false
},
@ -1313,167 +1695,83 @@
"GEN build/genhdr/qstr.i.last\n",
"GEN build/genhdr/qstr.split\n",
"GEN build/genhdr/qstrdefs.collected.h\n",
"QSTR updated\n",
"GEN build/genhdr/qstrdefs.generated.h\n",
"CC ../../py/mpstate.c\n",
"CC ../../py/nlr.c\n",
"CC ../../py/nlrx86.c\n",
"CC ../../py/nlrx64.c\n",
"CC ../../py/nlrthumb.c\n",
"CC ../../py/nlrxtensa.c\n",
"CC ../../py/nlrsetjmp.c\n",
"CC ../../py/malloc.c\n",
"CC ../../py/gc.c\n",
"CC ../../py/pystack.c\n",
"CC ../../py/qstr.c\n",
"CC ../../py/vstr.c\n",
"CC ../../py/mpprint.c\n",
"CC ../../py/reader.c\n",
"CC ../../py/lexer.c\n",
"CC ../../py/parse.c\n",
"CC ../../py/scope.c\n",
"CC ../../py/compile.c\n",
"CC ../../py/emitcommon.c\n",
"CC ../../py/emitbc.c\n",
"CC ../../py/asmbase.c\n",
"CC ../../py/emitnx64.c\n",
"CC ../../py/emitinlinethumb.c\n",
"CC ../../py/emitinlinextensa.c\n",
"CC ../../py/parsenum.c\n",
"CC ../../py/emitglue.c\n",
"CC ../../py/persistentcode.c\n",
"CC ../../py/runtime.c\n",
"CC ../../py/runtime_utils.c\n",
"CC ../../py/scheduler.c\n",
"CC ../../py/nativeglue.c\n",
"CC ../../py/stackctrl.c\n",
"CC ../../py/argcheck.c\n",
"CC ../../py/warning.c\n",
"CC ../../py/map.c\n",
"CC ../../py/obj.c\n",
"CC ../../py/objarray.c\n",
"CC ../../py/objattrtuple.c\n",
"CC ../../py/objbool.c\n",
"CC ../../py/objboundmeth.c\n",
"CC ../../py/objcell.c\n",
"CC ../../py/objclosure.c\n",
"CC ../../py/objcomplex.c\n",
"CC ../../py/objdeque.c\n",
"CC ../../py/objdict.c\n",
"CC ../../py/objenumerate.c\n",
"CC ../../py/objexcept.c\n",
"CC ../../py/objfilter.c\n",
"CC ../../py/objfloat.c\n",
"CC ../../py/objfun.c\n",
"CC ../../py/objgenerator.c\n",
"CC ../../py/objgetitemiter.c\n",
"CC ../../py/objint.c\n",
"CC ../../py/objint_longlong.c\n",
"CC ../../py/objint_mpz.c\n",
"CC ../../py/objlist.c\n",
"CC ../../py/objmap.c\n",
"QSTR not updated\n",
"CC ../../py/objmodule.c\n",
"CC ../../py/objobject.c\n",
"CC ../../py/objpolyiter.c\n",
"CC ../../py/objproperty.c\n",
"CC ../../py/objnone.c\n",
"CC ../../py/objnamedtuple.c\n",
"CC ../../py/objrange.c\n",
"CC ../../py/objreversed.c\n",
"CC ../../py/objset.c\n",
"CC ../../py/objsingleton.c\n",
"CC ../../py/objslice.c\n",
"CC ../../py/objstr.c\n",
"CC ../../py/objstrunicode.c\n",
"CC ../../py/objstringio.c\n",
"CC ../../py/objtuple.c\n",
"CC ../../py/objtype.c\n",
"CC ../../py/objzip.c\n",
"CC ../../py/opmethods.c\n",
"CC ../../py/sequence.c\n",
"CC ../../py/stream.c\n",
"CC ../../py/binary.c\n",
"CC ../../py/builtinimport.c\n",
"CC ../../py/builtinevex.c\n",
"CC ../../py/builtinhelp.c\n",
"CC ../../py/modarray.c\n",
"CC ../../py/modbuiltins.c\n",
"CC ../../py/modcollections.c\n",
"CC ../../py/modgc.c\n",
"CC ../../py/modio.c\n",
"CC ../../py/modmath.c\n",
"CC ../../py/modcmath.c\n",
"CC ../../py/modmicropython.c\n",
"CC ../../py/modstruct.c\n",
"CC ../../py/modsys.c\n",
"CC ../../py/moduerrno.c\n",
"CC ../../py/modthread.c\n",
"CC ../../py/vm.c\n",
"CC ../../py/bc.c\n",
"CC ../../py/showbc.c\n",
"CC ../../py/repl.c\n",
"CC ../../py/frozenmod.c\n",
"CC ../../extmod/moductypes.c\n",
"CC ../../extmod/modujson.c\n",
"CC ../../extmod/modure.c\n",
"CC ../../extmod/moduzlib.c\n",
"CC ../../extmod/moduheapq.c\n",
"CC ../../extmod/modutimeq.c\n",
"CC ../../extmod/moduhashlib.c\n",
"CC ../../extmod/moducryptolib.c\n",
"CC ../../extmod/modubinascii.c\n",
"CC ../../extmod/virtpin.c\n",
"CC ../../extmod/machine_mem.c\n",
"CC ../../extmod/machine_pinbase.c\n",
"CC ../../extmod/machine_signal.c\n",
"CC ../../extmod/machine_pulse.c\n",
"CC ../../extmod/machine_i2c.c\n",
"CC ../../extmod/machine_spi.c\n",
"CC ../../extmod/modussl_axtls.c\n",
"CC ../../extmod/modurandom.c\n",
"CC ../../extmod/moduwebsocket.c\n",
"CC ../../extmod/modwebrepl.c\n",
"CC ../../extmod/modframebuf.c\n",
"CC ../../extmod/vfs.c\n",
"CC ../../extmod/vfs_reader.c\n",
"CC ../../extmod/vfs_posix.c\n",
"CC ../../extmod/vfs_posix_file.c\n",
"CC ../../extmod/utime_mphal.c\n",
"CC ../../extmod/uos_dupterm.c\n",
"CC ../../lib/embed/abort_.c\n",
"CC ../../lib/utils/printf.c\n",
"GEN build/frozen.c\n",
"CC build/frozen.c\n",
"GEN build/frozen_mpy.c\n",
"CC build/frozen_mpy.c\n",
"CC main.c\n",
"CC gccollect.c\n",
"CC unix_mphal.c\n",
"CC mpthreadport.c\n",
"CC input.c\n",
"CC file.c\n",
"CC modmachine.c\n",
"CC modos.c\n",
"CC moduos_vfs.c\n",
"CC modtime.c\n",
"CC moduselect.c\n",
"CC alloc.c\n",
"CC coverage.c\n",
"CC ../../../usermod/ulab/ndarray.c\n",
"CC ../../../usermod/ulab/linalg.c\n",
"CC ../../../usermod/ulab/vectorise.c\n",
"CC ../../../usermod/ulab/ulab.c\n",
"CC ../../extmod/modbtree.c\n",
"CC modtermios.c\n",
"CC modusocket.c\n",
"CC modffi.c\n",
"CC ../../lib/mp-readline/readline.c\n",
"CC ../../lib/timeutils/timeutils.c\n",
"LINK micropython\n",
" text\t data\t bss\t dec\t hex\tfilename\n",
" 2085\t 6862\t 0\t 8947\t 22f3\tbuild/build/frozen_mpy.o\n",
" 2\t 0\t 0\t 2\t 2\tbuild/build/frozen.o\n",
" 447069\t 56400\t 2104\t 505573\t 7b6e5\tmicropython\n"
"CC ../../../usermod/ulab/numerical.c\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:\u001b[m\u001b[K In function ‘\u001b[01m\u001b[Knumerical_sum\u001b[m\u001b[K’:\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:106:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(uint8_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.uint8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:106:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:106:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kuint8_t *)out->data->items[i] = n_results.uint8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:109:56:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(int8_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.int8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:109:56:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:109:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kint8_t *)out->data->items[i] = n_results.int8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:112:58:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(uint16_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.uint16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:112:58:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:112:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kuint16_t *)out->data->items[i] = n_results.uint16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:115:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(int16_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.int16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:115:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:115:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kint16_t *)out->data->items[i] = n_results.int16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:118:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(float_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.float1;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:118:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:118:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kfloat_t *)out->data->items[i] = n_results.float1;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:127:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(uint8_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.uint8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:127:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:127:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kuint8_t *)out->data->items[i] = n_results.uint8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:130:56:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(int8_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.int8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:130:56:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:130:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kint8_t *)out->data->items[i] = n_results.int8;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:133:58:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(uint16_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.uint16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:133:58:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:133:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kuint16_t *)out->data->items[i] = n_results.uint16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:136:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(int16_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.int16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:136:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:136:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kint16_t *)out->data->items[i] = n_results.int16;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:139:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kpointer of type ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ used in arithmetic [\u001b[01;31m\u001b[K-Werror=pointer-arith\u001b[m\u001b[K]\n",
" *(float_t *)out->data->items\u001b[01;31m\u001b[K[\u001b[m\u001b[Ki] = n_results.float1;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:139:57:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kdereferencing ‘\u001b[01m\u001b[Kvoid *\u001b[m\u001b[K’ pointer [\u001b[01;31m\u001b[K-Werror\u001b[m\u001b[K]\n",
"\u001b[01m\u001b[K../../../usermod/ulab/numerical.c:139:30:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kinvalid use of void expression\n",
" *\u001b[01;31m\u001b[K(\u001b[m\u001b[Kfloat_t *)out->data->items[i] = n_results.float1;\n",
" \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n",
"cc1: all warnings being treated as errors\n",
"../../py/mkrules.mk:47: recipe for target 'build/ulab/numerical.o' failed\n",
"make: *** [build/ulab/numerical.o] Error 1\n"
]
}
],

1
ulab/micropython.mk

@ -5,6 +5,7 @@ USERMODULES_DIR := $(USERMOD_DIR)
SRC_USERMOD += $(USERMODULES_DIR)/ndarray.c
SRC_USERMOD += $(USERMODULES_DIR)/linalg.c
SRC_USERMOD += $(USERMODULES_DIR)/vectorise.c
SRC_USERMOD += $(USERMODULES_DIR)/numerical.c
SRC_USERMOD += $(USERMODULES_DIR)/ulab.c
# We can add our module folder to include paths if needed

6
ulab/ndarray.c

@ -61,7 +61,7 @@ void ndarray_print_row(const mp_print_t *print, mp_obj_array_t *data, size_t n0,
mp_print_str(print, "]");
}
void ulab_ndarray_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
void ndarray_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_print_str(print, "ndarray(");
@ -104,7 +104,7 @@ ndarray_obj_t *create_new_ndarray(size_t m, size_t n, uint8_t typecode) {
return ndarray;
}
mp_obj_t ulab_ndarray_copy(mp_obj_t self_in) {
mp_obj_t ndarray_copy(mp_obj_t self_in) {
// returns a verbatim (shape and typecode) copy of self_in
ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in);
ndarray_obj_t *out = create_new_ndarray(self->m, self->n, self->data->typecode);
@ -113,7 +113,7 @@ mp_obj_t ulab_ndarray_copy(mp_obj_t self_in) {
return MP_OBJ_FROM_PTR(out);
}
mp_obj_t ulab_ndarray_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
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) {
mp_arg_check_num(n_args, n_kw, 1, 3, true);
size_t len1, len2=0, i=0;

6
ulab/ndarray.h

@ -47,11 +47,11 @@ typedef struct _ndarray_obj_t {
*/
void ndarray_print_row(const mp_print_t *, mp_obj_array_t *, size_t , size_t );
void ulab_ndarray_print(const mp_print_t *, mp_obj_t , mp_print_kind_t );
void ndarray_print(const mp_print_t *, mp_obj_t , mp_print_kind_t );
void assign_elements(mp_obj_array_t *, mp_obj_t , uint8_t , size_t *);
ndarray_obj_t *create_new_ndarray(size_t , size_t , uint8_t );
mp_obj_t ulab_ndarray_copy(mp_obj_t );
mp_obj_t ulab_ndarray_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *);
mp_obj_t ndarray_copy(mp_obj_t );
mp_obj_t ndarray_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *);
mp_obj_t ndarray_shape(mp_obj_t );
mp_obj_t ndarray_size(mp_obj_t , mp_obj_t );

149
ulab/numerical.c

@ -0,0 +1,149 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Zoltán Vörös
*/
#include <math.h>
#include "py/runtime.h"
#include "numerical.h"
typedef struct {
uint8_t uint8;
int8_t int8;
uint16_t uint16;
int16_t int16;
float float1, float2; // we need two floats, so that the standard deviation can be calculated
} numerical_results;
numerical_results n_results;
mp_obj_t numerical_linspace(mp_obj_t _start, mp_obj_t _stop, mp_obj_t _len) {
// TODO: accept keyword argument endpoint=True
mp_int_t len = mp_obj_get_int_truncated(_len);
if(len < 2) {
mp_raise_ValueError("number of points must be at least 2");
}
mp_float_t value, step;
value = mp_obj_get_float(_start);
step = (mp_obj_get_float(_stop)-value)/(len-1);
ndarray_obj_t *nd_array = create_new_ndarray(1, len, NDARRAY_FLOAT);
for(size_t i=0; i < len; i++, value += step) {
mp_binary_set_val_array('f', nd_array->data->items, i, mp_obj_new_float(value));
}
return MP_OBJ_FROM_PTR(nd_array);
}
void clear_results(void) {
n_results.uint8 = 0;
n_results.int8 = 0;
n_results.uint16 = 0;
n_results.int16 = 0;
n_results.float1 = n_results.float2 = 0.0;
}
void sum_matrix(void *data, size_t start, size_t stop, size_t stride, unsigned char type) {
clear_results();
for(size_t i=start; i < stop; i+= stride) {
switch(type) {
case NDARRAY_UINT8:
n_results.uint8 += ((uint8_t *)data)[i];
break;
case NDARRAY_INT8:
n_results.int8 += ((int8_t *)data)[i];
break;
case NDARRAY_UINT16:
n_results.uint16 += ((uint16_t *)data)[i];
break;
case NDARRAY_INT16:
n_results.int16 += ((int16_t *)data)[i];
break;
case NDARRAY_FLOAT:
n_results.float1 += ((float *)data)[i];
}
}
}
mp_obj_t numerical_sum(mp_obj_t o_in, mp_obj_t axis) {
// TODO: deal with keyword argument
if(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)) {
mp_float_t _sum = 0.0;
mp_obj_iter_buf_t iter_buf;
mp_obj_t item, iterable = mp_getiter(o_in, &iter_buf);
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
_sum += mp_obj_get_float(item);
}
return mp_obj_new_float(_sum);
} else if(MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type)) {
ndarray_obj_t *o = MP_OBJ_TO_PTR(o_in);
if((o->m == 1) || (o->n == 1)) {
sum_matrix(o->data->items, 1, o->data->len, 1, o->data->typecode);
if(o->data->typecode == NDARRAY_UINT8) {
return mp_obj_new_int(n_results.uint8);
} else if(o->data->typecode == NDARRAY_INT8) {
return mp_obj_new_int(n_results.int8);
} else if(o->data->typecode == NDARRAY_UINT16) {
return mp_obj_new_int(n_results.uint16);
} else if(o->data->typecode == NDARRAY_INT16) {
return mp_obj_new_int(n_results.int16);
} else {
return mp_obj_new_float(n_results.float1);
}
} else {
size_t m = (mp_obj_get_int(axis) == 1) ? 1 : o->m;
size_t n = (mp_obj_get_int(axis) == 1) ? o->n : 1;
ndarray_obj_t *out = create_new_ndarray(m, n, o->data->typecode);
if(m == 1) { // sum vertically
for(size_t i=0; i < n; i++) {
sum_matrix(o->data->items, i, o->data->len, m, o->data->typecode);
switch(o->data->typecode) {
case NDARRAY_UINT8:
*(uint8_t *)out->data->items[i] = n_results.uint8;
break;
case NDARRAY_INT8:
*(int8_t *)out->data->items[i] = n_results.int8;
break;
case NDARRAY_UINT16:
*(uint16_t *)out->data->items[i] = n_results.uint16;
break;
case NDARRAY_INT16:
*(int16_t *)out->data->items[i] = n_results.int16;
break;
case NDARRAY_FLOAT:
*(float_t *)out->data->items[i] = n_results.float1;
break;
}
}
} else { // sum horizontally
for(size_t i=0; i < m; i++) {
sum_matrix(o->data->items, i*n, o->data->len, n, o->data->typecode);
switch(o->data->typecode) {
case NDARRAY_UINT8:
*(uint8_t *)out->data->items[i] = n_results.uint8;
break;
case NDARRAY_INT8:
*(int8_t *)out->data->items[i] = n_results.int8;
break;
case NDARRAY_UINT16:
*(uint16_t *)out->data->items[i] = n_results.uint16;
break;
case NDARRAY_INT16:
*(int16_t *)out->data->items[i] = n_results.int16;
break;
case NDARRAY_FLOAT:
*(float_t *)out->data->items[i] = n_results.float1;
break;
}
}
}
}
} else {
mp_raise_TypeError("input must be tuple, list, range, or ndarray");
}
return mp_const_none;
}

19
ulab/numerical.h

@ -0,0 +1,19 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Zoltán Vörös
*/
#ifndef _NUMERICAL_
#define _NUMERICAL_
#include "ndarray.h"
mp_obj_t numerical_linspace(mp_obj_t , mp_obj_t , mp_obj_t );
mp_obj_t numerical_sum(mp_obj_t , mp_obj_t );
#endif

22
ulab/ulab.c

@ -20,7 +20,9 @@
#include "ndarray.h"
#include "linalg.h"
#include "vectorise.h"
#include "numerical.h"
#define ULAB__VERSION 1.0
MP_DEFINE_CONST_FUN_OBJ_1(ndarray_shape_obj, ndarray_shape);
MP_DEFINE_CONST_FUN_OBJ_2(ndarray_size_obj, ndarray_size);
@ -28,6 +30,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(ndarray_rawsize_obj, ndarray_rawsize);
MP_DEFINE_CONST_FUN_OBJ_1(linalg_transpose_obj, linalg_transpose);
MP_DEFINE_CONST_FUN_OBJ_2(linalg_reshape_obj, linalg_reshape);
MP_DEFINE_CONST_FUN_OBJ_1(linalg_inv_obj, linalg_inv);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acos_obj, vectorise_acos);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acosh_obj, vectorise_acosh);
@ -53,6 +56,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_sqrt_obj, vectorise_sqrt);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_tan_obj, vectorise_tan);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_tanh_obj, vectorise_tanh);
MP_DEFINE_CONST_FUN_OBJ_3(numerical_linspace_obj, numerical_linspace);
MP_DEFINE_CONST_FUN_OBJ_2(numerical_sum_obj, numerical_sum);
STATIC const mp_rom_map_elem_t ulab_ndarray_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_shape), MP_ROM_PTR(&ndarray_shape_obj) },
{ MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&ndarray_size_obj) },
@ -74,17 +81,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 },
.name = MP_QSTR_ndarray,
.print = ulab_ndarray_print,
.make_new = ulab_ndarray_make_new,
// .unary_op = ulab_ndarray_unary_op,
.print = ndarray_print,
.make_new = ndarray_make_new,
// .unary_op = ndarray_unary_op,
// .subscr = ndarray_subscr,
// .getiter = ndarray_iterator_new,
// .binary_op = ulab_ndarray_binary_op,
// .binary_op = ndarray_binary_op,
.locals_dict = (mp_obj_dict_t*)&ulab_ndarray_locals_dict,
};
MP_DEFINE_CONST_FUN_OBJ_1(linalg_inv_obj, linalg_inv);
STATIC const mp_map_elem_t ulab_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ulab) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ndarray), (mp_obj_t)&ulab_ndarray_type },
@ -111,8 +116,9 @@ STATIC const mp_map_elem_t ulab_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_sinh), (mp_obj_t)&vectorise_sinh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&vectorise_sqrt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_tan), (mp_obj_t)&vectorise_tan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&vectorise_tanh_obj }
// { MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&ulab_sum_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&vectorise_tanh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_linspace), (mp_obj_t)&numerical_linspace_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&numerical_sum_obj },
};
STATIC MP_DEFINE_CONST_DICT (

Loading…
Cancel
Save