Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions code/ndarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,10 @@ void ndarray_fill_array_iterable(mp_float_t *array, mp_obj_t iterable) {

#if ULAB_HAS_FUNCTION_ITERATOR
size_t *ndarray_new_coords(uint8_t ndim) {
size_t *coords = m_new(size_t, ndim);
size_t *coords = m_new0(size_t, ndim);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(coords, 0, ndim*sizeof(size_t));
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to use both m_new9 and MICROPY_GC_CONSERVATIVE_CLEAR. You can select one of these options:

size_t *coords = m_new0(size_t, ndim);

or:

size_t *coords = m_new(size_t, ndim);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(coords, 0, ndim*sizeof(size_t));
#endif

Have a look at the source code of m_malloc0 to understand better.

The first option (just call m_new0) is much simpler and I suggest to do that. The API of m_new0 is unlikely to change. But the macro MICROPY_GC_CONSERVATIVE_CLEAR may one day be removed.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have obviously tanked it completely. Thanks for pointing this out!

return coords;
}

Expand Down Expand Up @@ -618,10 +620,12 @@ ndarray_obj_t *ndarray_new_ndarray(uint8_t ndim, size_t *shape, int32_t *strides

// if the length is 0, still allocate a single item, so that contractions can be handled
size_t len = ndarray->itemsize * MAX(1, ndarray->len);
uint8_t *array = m_new(byte, len);
uint8_t *array = m_new0(byte, len);
// this should set all elements to 0, irrespective of the of the dtype (all bits are zero)
// we could, perhaps, leave this step out, and initialise the array only, when needed
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(array, 0, len);
#endif
ndarray->array = array;
ndarray->origin = array;
return ndarray;
Expand Down Expand Up @@ -1060,8 +1064,11 @@ bool ndarray_can_broadcast(ndarray_obj_t *lhs, ndarray_obj_t *rhs, uint8_t *ndim
//
// 1. the two shapes are either equal
// 2. one of the shapes is 1
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(lstrides, 0, sizeof(size_t)*ULAB_MAX_DIMS);
memset(rstrides, 0, sizeof(size_t)*ULAB_MAX_DIMS);
#endif

lstrides[ULAB_MAX_DIMS - 1] = lhs->strides[ULAB_MAX_DIMS - 1];
rstrides[ULAB_MAX_DIMS - 1] = rhs->strides[ULAB_MAX_DIMS - 1];
for(uint8_t i=ULAB_MAX_DIMS; i > 0; i--) {
Expand Down Expand Up @@ -1094,7 +1101,10 @@ bool ndarray_can_broadcast_inplace(ndarray_obj_t *lhs, ndarray_obj_t *rhs, int32
//
// 1. the two shapes are either equal
// 2. the shapes on the right hand side is 1
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(rstrides, 0, sizeof(size_t)*ULAB_MAX_DIMS);
#endif

rstrides[ULAB_MAX_DIMS - 1] = rhs->strides[ULAB_MAX_DIMS - 1];
for(uint8_t i=ULAB_MAX_DIMS; i > 0; i--) {
if((lhs->shape[i-1] == rhs->shape[i-1]) || (rhs->shape[i-1] == 0) || (rhs->shape[i-1] == 1)) {
Expand Down Expand Up @@ -1142,10 +1152,12 @@ static mp_bound_slice_t generate_slice(mp_int_t n, mp_obj_t index) {
}

static ndarray_obj_t *ndarray_view_from_slices(ndarray_obj_t *ndarray, mp_obj_tuple_t *tuple) {
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *strides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
memset(strides, 0, sizeof(size_t)*ULAB_MAX_DIMS);
#endif

uint8_t ndim = ndarray->ndim;

Expand Down Expand Up @@ -1846,9 +1858,9 @@ mp_obj_t ndarray_binary_op(mp_binary_op_t _op, mp_obj_t lobj, mp_obj_t robj) {
}

uint8_t ndim = 0;
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
int32_t *lstrides = m_new(int32_t, ULAB_MAX_DIMS);
int32_t *rstrides = m_new(int32_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *lstrides = m_new0(int32_t, ULAB_MAX_DIMS);
int32_t *rstrides = m_new0(int32_t, ULAB_MAX_DIMS);
uint8_t broadcastable;
if((op == MP_BINARY_OP_INPLACE_ADD) || (op == MP_BINARY_OP_INPLACE_MULTIPLY) || (op == MP_BINARY_OP_INPLACE_POWER) ||
(op == MP_BINARY_OP_INPLACE_SUBTRACT) || (op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE)) {
Expand Down Expand Up @@ -2157,8 +2169,11 @@ mp_obj_t ndarray_reshape_core(mp_obj_t oin, mp_obj_t _shape, bool inplace) {
if(shape->len > ULAB_MAX_DIMS) {
mp_raise_ValueError(translate("maximum number of dimensions is 4"));
}
size_t *new_shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *new_shape = m_new0(size_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(new_shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
#endif

size_t new_length = 1;
for(uint8_t i=0; i < shape->len; i++) {
new_shape[ULAB_MAX_DIMS - i - 1] = mp_obj_get_int(shape->items[shape->len - i - 1]);
Expand Down
9 changes: 7 additions & 2 deletions code/numpy/create.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ static mp_obj_t create_zeros_ones_full(mp_obj_t oshape, uint8_t dtype, mp_obj_t
if(len > ULAB_MAX_DIMS) {
mp_raise_TypeError(translate("too many dimensions"));
}
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, ULAB_MAX_DIMS * sizeof(size_t));
#endif

size_t i = 0;
mp_obj_iter_buf_t iter_buf;
mp_obj_t item, iterable = mp_getiter(oshape, &iter_buf);
Expand Down Expand Up @@ -245,8 +248,10 @@ mp_obj_t create_concatenate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
mp_raise_TypeError(translate("first argument must be a tuple of ndarrays"));
}
int8_t axis = (int8_t)args[1].u_int;
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
#endif
mp_obj_tuple_t *ndarrays = MP_OBJ_TO_PTR(args[0].u_obj);

// first check, whether the arrays are compatible
Expand Down
8 changes: 6 additions & 2 deletions code/numpy/io/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,10 @@ static mp_obj_t io_load(mp_obj_t file) {

io_read_(stream, stream_p, buffer, "', 'fortran_order': False, 'shape': (", 37, &error);

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t) * ULAB_MAX_DIMS);
#endif

uint16_t bytes_to_read = MIN(ULAB_IO_BUFFER_SIZE, header_length - 51);
// bytes_to_read is 128 at most. This should be enough to contain a
Expand Down Expand Up @@ -386,8 +388,10 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
mp_raise_ValueError(translate("usecols is too high"));
}

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t) * ULAB_MAX_DIMS);
#endif

#if ULAB_MAX_DIMS == 1
shape[0] = rows;
Expand Down
17 changes: 10 additions & 7 deletions code/numpy/linalg/linalg_tools.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

#include "linalg_tools.h"

/*
* The following function inverts a matrix, whose entries are given in the input array
/*
* The following function inverts a matrix, whose entries are given in the input array
* The function has no dependencies beyond micropython itself (for the definition of mp_float_t),
* and can be used independent of ulab.
*/
Expand All @@ -26,10 +26,13 @@ bool linalg_invert_matrix(mp_float_t *data, size_t N) {

// initially, this is the unit matrix: the contents of this matrix is what
// will be returned after all the transformations
mp_float_t *unit = m_new(mp_float_t, N*N);
mp_float_t *unit = m_new0(mp_float_t, N*N);
mp_float_t elem = 1.0;
// initialise the unit matrix
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(unit, 0, sizeof(mp_float_t)*N*N);
#endif

for(size_t m=0; m < N; m++) {
memcpy(&unit[m * (N+1)], &elem, sizeof(mp_float_t));
}
Expand Down Expand Up @@ -78,9 +81,9 @@ bool linalg_invert_matrix(mp_float_t *data, size_t N) {
return true;
}

/*
* The following function calculates the eigenvalues and eigenvectors of a symmetric
* real matrix, whose entries are given in the input array.
/*
* The following function calculates the eigenvalues and eigenvectors of a symmetric
* real matrix, whose entries are given in the input array.
* The function has no dependencies beyond micropython itself (for the definition of mp_float_t),
* and can be used independent of ulab.
*/
Expand Down Expand Up @@ -166,6 +169,6 @@ size_t linalg_jacobi_rotations(mp_float_t *array, mp_float_t *eigvectors, size_t
eigvectors[m * S + N] = s * vm + c * vn;
}
} while(iterations > 0);

return iterations;
}
52 changes: 34 additions & 18 deletions code/numpy/numerical.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,10 +515,13 @@ static mp_obj_t numerical_argmin_argmax_ndarray(ndarray_obj_t *ndarray, mp_obj_t
int8_t ax = tools_get_axis(axis, ndarray->ndim);

uint8_t *array = (uint8_t *)ndarray->array;
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *strides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(strides, 0, sizeof(uint32_t)*ULAB_MAX_DIMS);
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
#endif

numerical_reduce_axes(ndarray, ax, shape, strides);
uint8_t index = ULAB_MAX_DIMS - ndarray->ndim + ax;

Expand Down Expand Up @@ -636,10 +639,13 @@ static mp_obj_t numerical_sort_helper(mp_obj_t oin, mp_obj_t axis, uint8_t inpla
ax = tools_get_axis(axis, ndarray->ndim);
}

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *strides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
memset(strides, 0, sizeof(uint32_t)*ULAB_MAX_DIMS);
#endif

numerical_reduce_axes(ndarray, ax, shape, strides);
ax = ULAB_MAX_DIMS - ndarray->ndim + ax;
// we work with the typed array, so re-scale the stride
Expand Down Expand Up @@ -733,10 +739,12 @@ mp_obj_t numerical_argsort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
}
int8_t ax = tools_get_axis(args[1].u_obj, ndarray->ndim);

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *strides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
memset(strides, 0, sizeof(uint32_t)*ULAB_MAX_DIMS);
#endif
numerical_reduce_axes(ndarray, ax, shape, strides);

// We could return an NDARRAY_UINT8 array, if all lengths are shorter than 256
Expand Down Expand Up @@ -931,13 +939,12 @@ mp_obj_t numerical_diff(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar

int8_t *stencil = m_new(int8_t, N+1);
stencil[0] = 1;
for(uint8_t i=1; i < N+1; i++) {
for(uint8_t i = 1; i < N+1; i++) {
stencil[i] = -stencil[i-1]*(N-i+1)/i;
}

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
for(uint8_t i=0; i < ULAB_MAX_DIMS; i++) {
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
for(uint8_t i = 0; i < ULAB_MAX_DIMS; i++) {
shape[i] = ndarray->shape[i];
if(i == index) {
shape[i] -= N;
Expand All @@ -948,8 +955,10 @@ mp_obj_t numerical_diff(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
uint8_t *rarray = (uint8_t *)results->array;

memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
int32_t *strides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(strides, 0, sizeof(int32_t)*ULAB_MAX_DIMS);
#endif
numerical_reduce_axes(ndarray, ax, shape, strides);

if(ndarray->dtype == NDARRAY_UINT8) {
Expand Down Expand Up @@ -1083,11 +1092,14 @@ mp_obj_t numerical_median(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
} else {
int8_t ax = tools_get_axis(args[1].u_obj, ndarray->ndim);

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *strides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
memset(strides, 0, sizeof(uint32_t)*ULAB_MAX_DIMS);
#endif
numerical_reduce_axes(ndarray, ax, shape, strides);

ax = ULAB_MAX_DIMS - ndarray->ndim + ax;
ndarray_obj_t *results = ndarray_new_dense_ndarray(ndarray->ndim-1, shape, NDARRAY_FLOAT);
mp_float_t *rarray = (mp_float_t *)results->array;
Expand Down Expand Up @@ -1237,16 +1249,20 @@ mp_obj_t numerical_roll(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
} else if(mp_obj_is_int(args[2].u_obj)){
int8_t ax = tools_get_axis(args[2].u_obj, ndarray->ndim);

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
size_t *shape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *strides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(shape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
memset(strides, 0, sizeof(int32_t)*ULAB_MAX_DIMS);
#endif
numerical_reduce_axes(ndarray, ax, shape, strides);

size_t *rshape = m_new(size_t, ULAB_MAX_DIMS);
size_t *rshape = m_new0(size_t, ULAB_MAX_DIMS);
int32_t *rstrides = m_new0(int32_t, ULAB_MAX_DIMS);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(rshape, 0, sizeof(size_t)*ULAB_MAX_DIMS);
int32_t *rstrides = m_new(int32_t, ULAB_MAX_DIMS);
memset(rstrides, 0, sizeof(int32_t)*ULAB_MAX_DIMS);
#endif
numerical_reduce_axes(results, ax, rshape, rstrides);

ax = ULAB_MAX_DIMS - ndarray->ndim + ax;
Expand Down
9 changes: 7 additions & 2 deletions code/numpy/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,14 @@ static mp_obj_t transform_compress(size_t n_args, const mp_obj_t *pos_args, mp_m
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
memcpy(strides, ndarray->strides, ULAB_MAX_DIMS * sizeof(int32_t));

int32_t *rstrides = m_new(int32_t, ULAB_MAX_DIMS);
int32_t *rstrides = m_new0(int32_t, ULAB_MAX_DIMS);

if(axis == mp_const_none) {
result = ndarray_new_linear_array(true_count, ndarray->dtype);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(rstrides, 0, ndarray->ndim * sizeof(int32_t));
#endif

rstrides[ULAB_MAX_DIMS - 1] = ndarray->itemsize;
rshape[ULAB_MAX_DIMS - 1] = 0;
} else {
Expand Down Expand Up @@ -245,13 +248,15 @@ static mp_obj_t transform_delete(size_t n_args, const mp_obj_t *pos_args, mp_map
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
memcpy(strides, ndarray->strides, ULAB_MAX_DIMS * sizeof(int32_t));

int32_t *rstrides = m_new(int32_t, ULAB_MAX_DIMS);
int32_t *rstrides = m_new0(int32_t, ULAB_MAX_DIMS);

ndarray_obj_t *result = NULL;

if(axis == mp_const_none) {
result = ndarray_new_linear_array(ndarray->len - index_len, ndarray->dtype);
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(rstrides, 0, ndarray->ndim * sizeof(int32_t));
#endif
rstrides[ULAB_MAX_DIMS - 1] = ndarray->itemsize;
memset(rshape, 0, sizeof(size_t) * ULAB_MAX_DIMS);
// rshape[ULAB_MAX_DIMS - 1] = 0;
Expand Down
2 changes: 1 addition & 1 deletion code/ulab.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "user/user.h"
#include "utils/utils.h"

#define ULAB_VERSION 5.0.5
#define ULAB_VERSION 5.0.6
#define xstr(s) str(s)
#define str(s) #s

Expand Down
5 changes: 5 additions & 0 deletions docs/ulab-change-log.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
Thu, 14 Apr 2022
version 5.0.6

use m_new0 conditionally

Thu, 14 Apr 2022

version 5.0.5

Expand Down