loadtxt can deal with multi-line comments (#720)

* loadtxt can deal with multi-line comments

* multiline headers/footers are treated correctly

* add macro to traverse arrays
This commit is contained in:
Zoltán Vörös 2025-06-06 20:58:31 +02:00 committed by GitHub
parent 88ef893540
commit 1398a8606f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 245 additions and 595 deletions

View file

@ -586,43 +586,10 @@ void ndarray_copy_array(ndarray_obj_t *source, ndarray_obj_t *target, uint8_t sh
} }
#endif #endif
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; memcpy(tarray, sarray, target->itemsize);
do { tarray += target->itemsize;
#endif ITERATOR_TAIL(source, sarray);
#if ULAB_MAX_DIMS > 2
size_t j = 0;
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
memcpy(tarray, sarray, target->itemsize);
tarray += target->itemsize;
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif
} }
ndarray_obj_t *ndarray_new_view(ndarray_obj_t *source, uint8_t ndim, size_t *shape, int32_t *strides, int32_t offset) { ndarray_obj_t *ndarray_new_view(ndarray_obj_t *source, uint8_t ndim, size_t *shape, int32_t *strides, int32_t offset) {
@ -676,69 +643,36 @@ ndarray_obj_t *ndarray_copy_view_convert_type(ndarray_obj_t *source, uint8_t dty
uint8_t complex_size = 2 * sizeof(mp_float_t); uint8_t complex_size = 2 * sizeof(mp_float_t);
#endif #endif
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD()
size_t i = 0; mp_obj_t item;
do { #if ULAB_SUPPORTS_COMPLEX
#endif if(source->dtype == NDARRAY_COMPLEX) {
#if ULAB_MAX_DIMS > 2 if(dtype != NDARRAY_COMPLEX) {
size_t j = 0; mp_raise_TypeError(MP_ERROR_TEXT("cannot convert complex type"));
do { } else {
memcpy(array, sarray, complex_size);
}
} else {
#endif #endif
#if ULAB_MAX_DIMS > 1 if((source->dtype == NDARRAY_FLOAT) && (dtype != NDARRAY_FLOAT)) {
size_t k = 0; // floats must be treated separately, because they can't directly be converted to integer types
do { mp_float_t f = ndarray_get_float_value(sarray, source->dtype);
#endif item = mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(round)(f));
size_t l = 0; } else {
do { item = mp_binary_get_val_array(source->dtype, sarray, 0);
mp_obj_t item; }
#if ULAB_SUPPORTS_COMPLEX #if ULAB_SUPPORTS_COMPLEX
if(source->dtype == NDARRAY_COMPLEX) { if(dtype == NDARRAY_COMPLEX) {
if(dtype != NDARRAY_COMPLEX) { ndarray_set_value(NDARRAY_FLOAT, array, 0, item);
mp_raise_TypeError(MP_ERROR_TEXT("cannot convert complex type")); } else {
} else { ndarray_set_value(dtype, array, 0, item);
memcpy(array, sarray, complex_size); }
} }
} else { #else
#endif ndarray_set_value(dtype, array, 0, item);
if((source->dtype == NDARRAY_FLOAT) && (dtype != NDARRAY_FLOAT)) {
// floats must be treated separately, because they can't directly be converted to integer types
mp_float_t f = ndarray_get_float_value(sarray, source->dtype);
item = mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(round)(f));
} else {
item = mp_binary_get_val_array(source->dtype, sarray, 0);
}
#if ULAB_SUPPORTS_COMPLEX
if(dtype == NDARRAY_COMPLEX) {
ndarray_set_value(NDARRAY_FLOAT, array, 0, item);
} else {
ndarray_set_value(dtype, array, 0, item);
}
}
#else
ndarray_set_value(dtype, array, 0, item);
#endif
array += ndarray->itemsize;
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif #endif
#if ULAB_MAX_DIMS > 3 array += ndarray->itemsize;
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3]; ITERATOR_TAIL(source, sarray);
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif
return ndarray; return ndarray;
} }
@ -765,54 +699,21 @@ mp_obj_t ndarray_byteswap(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} else { } else {
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; if(self->dtype == NDARRAY_FLOAT) {
do { #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
#endif SWAP(uint8_t, array[0], array[3]);
#if ULAB_MAX_DIMS > 2 SWAP(uint8_t, array[1], array[2]);
size_t j = 0; #else
do { SWAP(uint8_t, array[0], array[7]);
#endif SWAP(uint8_t, array[1], array[6]);
#if ULAB_MAX_DIMS > 1 SWAP(uint8_t, array[2], array[5]);
size_t k = 0; SWAP(uint8_t, array[3], array[4]);
do {
#endif #endif
size_t l = 0; } else {
do { SWAP(uint8_t, array[0], array[1]);
if(self->dtype == NDARRAY_FLOAT) { }
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT ITERATOR_TAIL(ndarray, array);
SWAP(uint8_t, array[0], array[3]);
SWAP(uint8_t, array[1], array[2]);
#else
SWAP(uint8_t, array[0], array[7]);
SWAP(uint8_t, array[1], array[6]);
SWAP(uint8_t, array[2], array[5]);
SWAP(uint8_t, array[3], array[4]);
#endif
} else {
SWAP(uint8_t, array[0], array[1]);
}
array += ndarray->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < ndarray->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
array -= ndarray->strides[ULAB_MAX_DIMS - 1] * ndarray->shape[ULAB_MAX_DIMS-1];
array += ndarray->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < ndarray->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
array -= ndarray->strides[ULAB_MAX_DIMS - 2] * ndarray->shape[ULAB_MAX_DIMS-2];
array += ndarray->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < ndarray->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
array -= ndarray->strides[ULAB_MAX_DIMS - 3] * ndarray->shape[ULAB_MAX_DIMS-3];
array += ndarray->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < ndarray->shape[ULAB_MAX_DIMS - 4]);
#endif
} }
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} }
@ -1441,43 +1342,10 @@ mp_obj_t ndarray_flatten(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
if(memcmp(order, "C", 1) == 0) { // C-type ordering if(memcmp(order, "C", 1) == 0) { // C-type ordering
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; memcpy(array, sarray, self->itemsize);
do { array += ndarray->strides[ULAB_MAX_DIMS - 1];
#endif ITERATOR_TAIL(self, sarray);
#if ULAB_MAX_DIMS > 2
size_t j = 0;
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
memcpy(array, sarray, self->itemsize);
array += ndarray->strides[ULAB_MAX_DIMS - 1];
sarray += self->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < self->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= self->strides[ULAB_MAX_DIMS - 1] * self->shape[ULAB_MAX_DIMS-1];
sarray += self->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < self->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
sarray -= self->strides[ULAB_MAX_DIMS - 2] * self->shape[ULAB_MAX_DIMS-2];
sarray += self->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < self->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
sarray -= self->strides[ULAB_MAX_DIMS - 3] * self->shape[ULAB_MAX_DIMS-3];
sarray += self->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < self->shape[ULAB_MAX_DIMS - 4]);
#endif
} else { // 'F', Fortran-type ordering } else { // 'F', Fortran-type ordering
#if ULAB_MAX_DIMS > 3 #if ULAB_MAX_DIMS > 3
size_t i = 0; size_t i = 0;

View file

@ -709,4 +709,89 @@ ndarray_obj_t *ndarray_from_mp_obj(mp_obj_t , uint8_t );
#endif /* ULAB_MAX_DIMS == 4 */ #endif /* ULAB_MAX_DIMS == 4 */
#endif /* ULAB_HAS_FUNCTION_ITERATOR */ #endif /* ULAB_HAS_FUNCTION_ITERATOR */
// iterator macro for traversing arrays over all dimensions
#if ULAB_MAX_DIMS == 1
#define ITERATOR_HEAD()\
size_t _l_ = 0;\
do {
#define ITERATOR_TAIL(_source_, _source_array_)\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 1];\
_l_++;\
} while(_l_ < (_source_)->shape[ULAB_MAX_DIMS - 1]);
#endif /* ULAB_MAX_DIMS == 1 */
#if ULAB_MAX_DIMS == 2
#define ITERATOR_HEAD()\
size_t _k_ = 0;\
do {\
size_t _l_ = 0;\
do {
#define ITERATOR_TAIL(_source_, _source_array_)\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 1];\
_l_++;\
} while(_l_ < (_source_)->shape[ULAB_MAX_DIMS - 1]);\
(_source_array_) -= (_source_)->strides[ULAB_MAX_DIMS - 1] * (_source_)->shape[ULAB_MAX_DIMS - 1];\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 2];\
_k_++;\
} while(_k_ < (_source_)->shape[ULAB_MAX_DIMS - 2]);
#endif /* ULAB_MAX_DIMS == 2 */
#if ULAB_MAX_DIMS == 3
#define ITERATOR_HEAD()\
size_t _j_ = 0;\
do {\
size_t _k_ = 0;\
do {\
size_t _l_ = 0;\
do {
#define ITERATOR_TAIL(_source_, _source_array_)\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 1];\
_l_++;\
} while(_l_ < (_source_)->shape[ULAB_MAX_DIMS - 1]);\
(_source_array_) -= (_source_)->strides[ULAB_MAX_DIMS - 1] * (_source_)->shape[ULAB_MAX_DIMS - 1];\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 2];\
_k_++;\
} while(_k_ < (_source_)->shape[ULAB_MAX_DIMS - 2]);\
(_source_array_) -= (_source_)->strides[ULAB_MAX_DIMS - 2] * (_source_)->shape[ULAB_MAX_DIMS - 2];\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 3];\
j++;\
} while(j < (_source_)->shape[ULAB_MAX_DIMS - 3]);
#endif /* ULAB_MAX_DIMS == 3 */
#if ULAB_MAX_DIMS == 4
#define ITERATOR_HEAD()\
size_t _i_ = 0;\
do {\
size_t _j_ = 0;\
do {\
size_t _k_ = 0;\
do {\
size_t _l_ = 0;\
do {
#define ITERATOR_TAIL(_source_, _source_array_)\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 1];\
_l_++;\
} while(_l_ < (_source_)->shape[ULAB_MAX_DIMS - 1]);\
(_source_array_) -= (_source_)->strides[ULAB_MAX_DIMS - 1] * (_source_)->shape[ULAB_MAX_DIMS - 1];\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 2];\
_k_++;\
} while(_k_ < (_source_)->shape[ULAB_MAX_DIMS - 2]);\
(_source_array_) -= (_source_)->strides[ULAB_MAX_DIMS - 2] * (_source_)->shape[ULAB_MAX_DIMS - 2];\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 3];\
_j_++;\
} while(_j_ < (_source_)->shape[ULAB_MAX_DIMS - 3]);\
(_source_array_) -= (_source_)->strides[ULAB_MAX_DIMS - 3] * (_source_)->shape[ULAB_MAX_DIMS - 3];\
(_source_array_) += (_source_)->strides[ULAB_MAX_DIMS - 4];\
_i_++;\
} while(_i_ < (_source_)->shape[ULAB_MAX_DIMS - 4]);
#endif /* ULAB_MAX_DIMS == 4 */
#endif #endif

View file

@ -260,48 +260,14 @@ static mp_obj_t compare_isinf_isfinite(mp_obj_t _x, uint8_t mask) {
} }
uint8_t *xarray = (uint8_t *)x->array; uint8_t *xarray = (uint8_t *)x->array;
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; mp_float_t value = *(mp_float_t *)xarray;
do { if(isnan(value)) {
#endif *rarray++ = 0;
#if ULAB_MAX_DIMS > 2 } else {
size_t j = 0; *rarray++ = isinf(value) ? mask : 1 - mask;
do { }
#endif ITERATOR_TAIL(x, xarray);
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
mp_float_t value = *(mp_float_t *)xarray;
if(isnan(value)) {
*rarray++ = 0;
} else {
*rarray++ = isinf(value) ? mask : 1 - mask;
}
xarray += x->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < x->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
xarray -= x->strides[ULAB_MAX_DIMS - 1] * x->shape[ULAB_MAX_DIMS-1];
xarray += x->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < x->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
xarray -= x->strides[ULAB_MAX_DIMS - 2] * x->shape[ULAB_MAX_DIMS-2];
xarray += x->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < x->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
xarray -= x->strides[ULAB_MAX_DIMS - 3] * x->shape[ULAB_MAX_DIMS-3];
xarray += x->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < x->shape[ULAB_MAX_DIMS - 4]);
#endif
return MP_OBJ_FROM_PTR(results); return MP_OBJ_FROM_PTR(results);
} else { } else {
mp_raise_TypeError(MP_ERROR_TEXT("wrong input type")); mp_raise_TypeError(MP_ERROR_TEXT("wrong input type"));

View file

@ -338,7 +338,7 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
buffer[read] = '\0'; buffer[read] = '\0';
offset = buffer; offset = buffer;
while(*offset != '\0') { while(*offset != '\0') {
if(*offset == comment_char) { while(*offset == comment_char) {
// clear the line till the end, or the buffer's end // clear the line till the end, or the buffer's end
while((*offset != '\0')) { while((*offset != '\0')) {
offset++; offset++;
@ -425,7 +425,7 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
offset = buffer; offset = buffer;
while(*offset != '\0') { while(*offset != '\0') {
if(*offset == comment_char) { while(*offset == comment_char) {
// clear the line till the end, or the buffer's end // clear the line till the end, or the buffer's end
while((*offset != '\0')) { while((*offset != '\0')) {
offset++; offset++;
@ -619,48 +619,14 @@ static mp_obj_t io_save(mp_obj_t file, mp_obj_t ndarray_) {
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; memcpy(buffer+offset, array, sz);
do { offset += sz;
#endif if(offset == ULAB_IO_BUFFER_SIZE) {
#if ULAB_MAX_DIMS > 2 stream_p->write(stream, buffer, offset, &error);
size_t j = 0; offset = 0;
do { }
#endif ITERATOR_TAIL(ndarray, array);
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
memcpy(buffer+offset, array, sz);
offset += sz;
if(offset == ULAB_IO_BUFFER_SIZE) {
stream_p->write(stream, buffer, offset, &error);
offset = 0;
}
array += ndarray->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < ndarray->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
array -= ndarray->strides[ULAB_MAX_DIMS - 1] * ndarray->shape[ULAB_MAX_DIMS-1];
array += ndarray->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < ndarray->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
array -= ndarray->strides[ULAB_MAX_DIMS - 2] * ndarray->shape[ULAB_MAX_DIMS-2];
array += ndarray->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < ndarray->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
array -= ndarray->strides[ULAB_MAX_DIMS - 3] * ndarray->shape[ULAB_MAX_DIMS-3];
array += ndarray->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < ndarray->shape[ULAB_MAX_DIMS - 4]);
#endif
stream_p->write(stream, buffer, offset, &error); stream_p->write(stream, buffer, offset, &error);
stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error); stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error);
@ -751,16 +717,32 @@ static mp_obj_t io_savetxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
char *buffer = m_new(char, ULAB_IO_BUFFER_SIZE); char *buffer = m_new(char, ULAB_IO_BUFFER_SIZE);
int error; int error;
size_t len_comment;
char *comments;
if(mp_obj_is_str(args[5].u_obj)) {
const char *_comments = mp_obj_str_get_data(args[5].u_obj, &len_comment);
comments = (char *)_comments;
} else {
len_comment = 2;
comments = m_new(char, len_comment);
comments[0] = '#';
comments[1] = ' ';
}
if(mp_obj_is_str(args[3].u_obj)) { if(mp_obj_is_str(args[3].u_obj)) {
size_t _len; size_t _len;
if(mp_obj_is_str(args[5].u_obj)) {
const char *comments = mp_obj_str_get_data(args[5].u_obj, &_len);
stream_p->write(stream, comments, _len, &error);
} else {
stream_p->write(stream, "# ", 2, &error);
}
const char *header = mp_obj_str_get_data(args[3].u_obj, &_len); const char *header = mp_obj_str_get_data(args[3].u_obj, &_len);
stream_p->write(stream, header, _len, &error);
stream_p->write(stream, comments, len_comment, &error);
// We can't write the header in the single chunk, for it might contain line breaks
for(size_t i = 0; i < _len; header++, i++) {
stream_p->write(stream, header, 1, &error);
if((*header == '\n') && (i < _len)) {
stream_p->write(stream, comments, len_comment, &error);
}
}
stream_p->write(stream, "\n", 1, &error); stream_p->write(stream, "\n", 1, &error);
} }
@ -799,16 +781,19 @@ static mp_obj_t io_savetxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
} while(k < ndarray->shape[ULAB_MAX_DIMS - 2]); } while(k < ndarray->shape[ULAB_MAX_DIMS - 2]);
#endif #endif
if(mp_obj_is_str(args[4].u_obj)) { if(mp_obj_is_str(args[4].u_obj)) { // footer string
size_t _len; size_t _len;
if(mp_obj_is_str(args[5].u_obj)) {
const char *comments = mp_obj_str_get_data(args[5].u_obj, &_len);
stream_p->write(stream, comments, _len, &error);
} else {
stream_p->write(stream, "# ", 2, &error);
}
const char *footer = mp_obj_str_get_data(args[4].u_obj, &_len); const char *footer = mp_obj_str_get_data(args[4].u_obj, &_len);
stream_p->write(stream, footer, _len, &error);
stream_p->write(stream, comments, len_comment, &error);
// We can't write the header in the single chunk, for it might contain line breaks
for(size_t i = 0; i < _len; footer++, i++) {
stream_p->write(stream, footer, 1, &error);
if((*footer == '\n') && (i < _len)) {
stream_p->write(stream, comments, len_comment, &error);
}
}
stream_p->write(stream, "\n", 1, &error); stream_p->write(stream, "\n", 1, &error);
} }

View file

@ -197,42 +197,9 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) {
// TODO: these loops are really nothing, but the re-impplementation of // TODO: these loops are really nothing, but the re-impplementation of
// ITERATE_VECTOR from vectorise.c. We could pass a function pointer here // ITERATE_VECTOR from vectorise.c. We could pass a function pointer here
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; *array++ = poly_eval(func(sarray), p, plen);
do { ITERATOR_TAIL(source, sarray);
#endif
#if ULAB_MAX_DIMS > 2
size_t j = 0;
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
*array++ = poly_eval(func(sarray), p, plen);
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif
} else { } else {
// o_x had better be a one-dimensional standard iterable // o_x had better be a one-dimensional standard iterable
ndarray = ndarray_new_linear_array(mp_obj_get_int(mp_obj_len_maybe(o_x)), NDARRAY_FLOAT); ndarray = ndarray_new_linear_array(mp_obj_get_int(mp_obj_len_maybe(o_x)), NDARRAY_FLOAT);

View file

@ -91,43 +91,10 @@ static mp_obj_t vector_generic_vector(size_t n_args, const mp_obj_t *pos_args, m
mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype); mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype);
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; mp_float_t value = func(sarray);
do { *tarray++ = f(value);
#endif ITERATOR_TAIL(source, sarray);
#if ULAB_MAX_DIMS > 2
size_t j = 0;
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
mp_float_t value = func(sarray);
*tarray++ = f(value);
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif /* ULAB_MAX_DIMS > 1 */
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif /* ULAB_MAX_DIMS > 2 */
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif /* ULAB_MAX_DIMS > 3 */
#else #else
if(source->dtype == NDARRAY_UINT8) { if(source->dtype == NDARRAY_UINT8) {
ITERATE_VECTOR(uint8_t, target, tarray, tstrides, source, sarray); ITERATE_VECTOR(uint8_t, target, tarray, tstrides, source, sarray);
@ -171,43 +138,10 @@ static mp_obj_t vector_generic_vector(mp_obj_t o_in, mp_float_t (*f)(mp_float_t)
mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype); mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype);
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; mp_float_t value = func(sarray);
do { *array++ = f(value);
#endif ITERATOR_TAIL(source, sarray);
#if ULAB_MAX_DIMS > 2
size_t j = 0;
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
mp_float_t value = func(sarray);
*array++ = f(value);
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif /* ULAB_MAX_DIMS > 1 */
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif /* ULAB_MAX_DIMS > 2 */
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif /* ULAB_MAX_DIMS > 3 */
#else #else
if(source->dtype == NDARRAY_UINT8) { if(source->dtype == NDARRAY_UINT8) {
ITERATE_VECTOR(uint8_t, array, source, sarray); ITERATE_VECTOR(uint8_t, array, source, sarray);
@ -327,43 +261,11 @@ mp_obj_t vector_around(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype); mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype);
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; mp_float_t f = func(sarray);
do { *narray++ = MICROPY_FLOAT_C_FUN(round)(f * mul) / mul;
#endif ITERATOR_TAIL(source, sarray);
#if ULAB_MAX_DIMS > 2
size_t j = 0;
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
mp_float_t f = func(sarray);
*narray++ = MICROPY_FLOAT_C_FUN(round)(f * mul) / mul;
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} }
@ -631,46 +533,13 @@ static mp_obj_t vector_exp(mp_obj_t o_in) {
mp_float_t *array = (mp_float_t *)ndarray->array; mp_float_t *array = (mp_float_t *)ndarray->array;
uint8_t itemsize = sizeof(mp_float_t); uint8_t itemsize = sizeof(mp_float_t);
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; mp_float_t real = *(mp_float_t *)sarray;
do { mp_float_t imag = *(mp_float_t *)(sarray + itemsize);
#endif mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real);
#if ULAB_MAX_DIMS > 2 *array++ = exp_real * MICROPY_FLOAT_C_FUN(cos)(imag);
size_t j = 0; *array++ = exp_real * MICROPY_FLOAT_C_FUN(sin)(imag);
do { ITERATOR_TAIL(source, sarray);
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
mp_float_t real = *(mp_float_t *)sarray;
mp_float_t imag = *(mp_float_t *)(sarray + itemsize);
mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real);
*array++ = exp_real * MICROPY_FLOAT_C_FUN(cos)(imag);
*array++ = exp_real * MICROPY_FLOAT_C_FUN(sin)(imag);
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif /* ULAB_MAX_DIMS > 1 */
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif /* ULAB_MAX_DIMS > 2 */
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif /* ULAB_MAX_DIMS > 3 */
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} }
} }
@ -921,97 +790,33 @@ mp_obj_t vector_sqrt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
mp_float_t *array = (mp_float_t *)ndarray->array; mp_float_t *array = (mp_float_t *)ndarray->array;
uint8_t itemsize = sizeof(mp_float_t); uint8_t itemsize = sizeof(mp_float_t);
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; mp_float_t real = *(mp_float_t *)sarray;
do { mp_float_t imag = *(mp_float_t *)(sarray + itemsize);
#endif mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(sqrt)(real * real + imag * imag);
#if ULAB_MAX_DIMS > 2 sqrt_abs = MICROPY_FLOAT_C_FUN(sqrt)(sqrt_abs);
size_t j = 0; mp_float_t theta = MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(atan2)(imag, real);
do { *array++ = sqrt_abs * MICROPY_FLOAT_C_FUN(cos)(theta);
#endif *array++ = sqrt_abs * MICROPY_FLOAT_C_FUN(sin)(theta);
#if ULAB_MAX_DIMS > 1 ITERATOR_TAIL(source, sarray);
size_t k = 0;
do {
#endif
size_t l = 0;
do {
mp_float_t real = *(mp_float_t *)sarray;
mp_float_t imag = *(mp_float_t *)(sarray + itemsize);
mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(sqrt)(real * real + imag * imag);
sqrt_abs = MICROPY_FLOAT_C_FUN(sqrt)(sqrt_abs);
mp_float_t theta = MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(atan2)(imag, real);
*array++ = sqrt_abs * MICROPY_FLOAT_C_FUN(cos)(theta);
*array++ = sqrt_abs * MICROPY_FLOAT_C_FUN(sin)(theta);
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif /* ULAB_MAX_DIMS > 1 */
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif /* ULAB_MAX_DIMS > 2 */
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif /* ULAB_MAX_DIMS > 3 */
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} else if(source->dtype == NDARRAY_FLOAT) { } else if(source->dtype == NDARRAY_FLOAT) {
uint8_t *sarray = (uint8_t *)source->array; uint8_t *sarray = (uint8_t *)source->array;
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_COMPLEX); ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_COMPLEX);
mp_float_t *array = (mp_float_t *)ndarray->array; mp_float_t *array = (mp_float_t *)ndarray->array;
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; mp_float_t value = *(mp_float_t *)sarray;
do { if(value >= MICROPY_FLOAT_CONST(0.0)) {
#endif *array++ = MICROPY_FLOAT_C_FUN(sqrt)(value);
#if ULAB_MAX_DIMS > 2 array++;
size_t j = 0; } else {
do { array++;
#endif *array++ = MICROPY_FLOAT_C_FUN(sqrt)(-value);
#if ULAB_MAX_DIMS > 1 }
size_t k = 0; ITERATOR_TAIL(source, sarray);
do {
#endif
size_t l = 0;
do {
mp_float_t value = *(mp_float_t *)sarray;
if(value >= MICROPY_FLOAT_CONST(0.0)) {
*array++ = MICROPY_FLOAT_C_FUN(sqrt)(value);
array++;
} else {
array++;
*array++ = MICROPY_FLOAT_C_FUN(sqrt)(-value);
}
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS-1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif /* ULAB_MAX_DIMS > 1 */
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS-2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif /* ULAB_MAX_DIMS > 2 */
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS-3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif /* ULAB_MAX_DIMS > 3 */
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} else { } else {
mp_raise_TypeError(MP_ERROR_TEXT("input dtype must be float or complex")); mp_raise_TypeError(MP_ERROR_TEXT("input dtype must be float or complex"));
@ -1071,45 +876,12 @@ static mp_obj_t vector_vectorized_function_call(mp_obj_t self_in, size_t n_args,
uint8_t *sarray = (uint8_t *)source->array; uint8_t *sarray = (uint8_t *)source->array;
uint8_t *narray = (uint8_t *)ndarray->array; uint8_t *narray = (uint8_t *)ndarray->array;
#if ULAB_MAX_DIMS > 3 ITERATOR_HEAD();
size_t i = 0; avalue[0] = mp_binary_get_val_array(source->dtype, sarray, 0);
do { fvalue = MP_OBJ_TYPE_GET_SLOT(self->type, call)(self->fun, 1, 0, avalue);
#endif ndarray_set_value(self->otypes, narray, 0, fvalue);
#if ULAB_MAX_DIMS > 2 narray += ndarray->itemsize;
size_t j = 0; ITERATOR_TAIL(source, sarray);
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
avalue[0] = mp_binary_get_val_array(source->dtype, sarray, 0);
fvalue = MP_OBJ_TYPE_GET_SLOT(self->type, call)(self->fun, 1, 0, avalue);
ndarray_set_value(self->otypes, narray, 0, fvalue);
sarray += source->strides[ULAB_MAX_DIMS - 1];
narray += ndarray->itemsize;
l++;
} while(l < source->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
sarray -= source->strides[ULAB_MAX_DIMS - 1] * source->shape[ULAB_MAX_DIMS - 1];
sarray += source->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < source->shape[ULAB_MAX_DIMS - 2]);
#endif /* ULAB_MAX_DIMS > 1 */
#if ULAB_MAX_DIMS > 2
sarray -= source->strides[ULAB_MAX_DIMS - 2] * source->shape[ULAB_MAX_DIMS - 2];
sarray += source->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < source->shape[ULAB_MAX_DIMS - 3]);
#endif /* ULAB_MAX_DIMS > 2 */
#if ULAB_MAX_DIMS > 3
sarray -= source->strides[ULAB_MAX_DIMS - 3] * source->shape[ULAB_MAX_DIMS - 3];
sarray += source->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < source->shape[ULAB_MAX_DIMS - 4]);
#endif /* ULAB_MAX_DIMS > 3 */
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} else if(mp_obj_is_type(args[0], &mp_type_tuple) || mp_obj_is_type(args[0], &mp_type_list) || } else if(mp_obj_is_type(args[0], &mp_type_tuple) || mp_obj_is_type(args[0], &mp_type_list) ||

View file

@ -33,7 +33,7 @@
#include "user/user.h" #include "user/user.h"
#include "utils/utils.h" #include "utils/utils.h"
#define ULAB_VERSION 6.7.4 #define ULAB_VERSION 6.7.6
#define xstr(s) str(s) #define xstr(s) str(s)
#define str(s) #s #define str(s) #s

View file

@ -1,8 +1,15 @@
Thu, 29 May 2025 Thu, 29 May 2025
version 6.7.6
loadtxt can deal with multi-line comments
Thu, 29 May 2025
version 6.7.5 version 6.7.5
fix typo and shape in radnom module fix typo and shape in radnom module
Sun, 16 Mar 2025 Sun, 16 Mar 2025
version 6.7.4 version 6.7.4