Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion code/ndarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ ndarray_obj_t *ndarray_copy_view_convert_type(ndarray_obj_t *source, uint8_t dty
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(floor)(f));
item = mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(round)(f));
} else {
item = mp_binary_get_val_array(source->dtype, sarray, 0);
}
Expand Down
104 changes: 67 additions & 37 deletions code/numpy/io/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Copyright (c) 2022 Zoltán Vörös
*/

#include <math.h>
#include <string.h>

#include "py/builtin.h"
Expand Down Expand Up @@ -236,13 +237,24 @@ MP_DEFINE_CONST_FUN_OBJ_1(io_load_obj, io_load);
#endif /* ULAB_NUMPY_HAS_LOAD */

#if ULAB_NUMPY_HAS_LOADTXT
static void io_assign_value(const char *clipboard, uint8_t len, ndarray_obj_t *ndarray, size_t *idx, uint8_t dtype) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
if(dtype != NDARRAY_FLOAT) {
mp_float_t _value = mp_obj_get_float(value);
value = mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(round)(_value));
}
ndarray_set_value(dtype, ndarray->array, (*idx)++, value);
}

static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_delimiter, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_comments, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_max_rows, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } },
{ MP_QSTR_usecols, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_dtype, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = NDARRAY_FLOAT } },
{ MP_QSTR_skiprows, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } },
};

mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
Expand Down Expand Up @@ -275,9 +287,10 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
comment_char = _comment_char[0];
}

uint16_t skiprows = args[6].u_int;
uint16_t max_rows = ULAB_IO_MAX_ROWS;
if((args[3].u_int > 0) && (args[3].u_int < ULAB_IO_MAX_ROWS)) {
max_rows = args[3].u_int;
max_rows = args[3].u_int + skiprows;
}

uint16_t *cols = NULL;
Expand All @@ -304,13 +317,16 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
}
}

uint8_t dtype = args[5].u_int;

// count the columns and rows
// we actually count only the rows and the items, and assume that
// the number of columns can be gotten by means of a simple division,
// i.e., that each row has the same number of columns
char *offset;
uint16_t rows = 0, items = 0, all_rows = 0;
uint8_t read;
uint8_t len = 0;

do {
read = (uint8_t)stream_p->read(stream, buffer, ULAB_IO_BUFFER_SIZE - 1, &error);
Expand All @@ -331,9 +347,12 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw

// catch whitespaces here: if these are not on a comment line, then they delimit a number
if(*offset == '\n') {
rows++;
all_rows++;
items++;
if(all_rows > skiprows) {
rows++;
items++;
len = 0;
}
if(all_rows == max_rows) {
break;
}
Expand All @@ -345,13 +364,22 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
while((*offset == ' ') || (*offset == '\t') || (*offset == '\v') || (*offset == '\f') || (*offset == '\r')) {
offset++;
}
items++;
if(len > 0) {
if(all_rows >= skiprows) {
items++;
}
len = 0;
}
} else {
offset++;
len++;
}
}
} while((read > 0) && (all_rows < max_rows));

if(rows == 0) {
mp_raise_ValueError(translate("empty file"));
}
uint16_t columns = items / rows;

if(columns < used_columns) {
Expand All @@ -363,31 +391,30 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw

#if ULAB_MAX_DIMS == 1
shape[0] = rows;
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(1, shape, NDARRAY_FLOAT);
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(1, shape, dtype);
#else
if(args[4].u_obj == mp_const_none) {
shape[ULAB_MAX_DIMS - 1] = columns;
} else {
shape[ULAB_MAX_DIMS - 1] = used_columns;
}
shape[ULAB_MAX_DIMS - 2] = rows;
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(2, shape, NDARRAY_FLOAT);
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(2, shape, dtype);
#endif

mp_float_t *array = (mp_float_t *)ndarray->array;

struct mp_stream_seek_t seek_s;
seek_s.offset = 0;
seek_s.whence = MP_SEEK_SET;
stream_p->ioctl(stream, MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error);

char *clipboard = m_new(char, ULAB_IO_CLIPBOARD_SIZE);
char *clipboard_origin = clipboard;
uint8_t len = 0;

rows = 0;
columns = 0;
len = 0;

size_t idx = 0;
do {
read = stream_p->read(stream, buffer, ULAB_IO_BUFFER_SIZE - 1, &error);
buffer[read] = '\0';
Expand All @@ -406,40 +433,43 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
}
}

if(rows == max_rows) {
break;
}

if((*offset == ' ') || (*offset == '\t') || (*offset == '\v') ||
(*offset == '\f') || (*offset == '\r') || (*offset == '\n') || (*offset == delimiter)) {
offset++;
while((*offset == ' ') || (*offset == '\t') || (*offset == '\v') || (*offset == '\f') || (*offset == '\r') || (*offset == '\n')) {
while((*offset == ' ') || (*offset == '\t') || (*offset == '\v') ||
(*offset == '\f') || (*offset == '\r') || (*offset == '\n')) {
offset++;
}
clipboard = clipboard_origin;
#if ULAB_MAX_DIMS == 1
if(columns == cols[0]) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
*array++ = mp_obj_get_float(value);
}
#else
if(args[4].u_obj == mp_const_none) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
*array++ = mp_obj_get_float(value);
} else {
for(uint8_t c = 0; c < used_columns; c++) {
if(columns == cols[c]) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
*array++ = mp_obj_get_float(value);
break;
if(len > 0) {
clipboard = clipboard_origin;
if(rows >= skiprows) {
#if ULAB_MAX_DIMS == 1
if(columns == cols[0]) {
io_assign_value(clipboard, len, ndarray, &idx, dtype);
}
#else
if(args[4].u_obj == mp_const_none) {
io_assign_value(clipboard, len, ndarray, &idx, dtype);
} else {
for(uint8_t c = 0; c < used_columns; c++) {
if(columns == cols[c]) {
io_assign_value(clipboard, len, ndarray, &idx, dtype);
break;
}
}
}
#endif
}
}
#endif
columns++;
len = 0;
columns++;
len = 0;

if(offset[-1] == '\n') {
columns = 0;
rows++;
if(rows == max_rows) {
break;
if(offset[-1] == '\n') {
columns = 0;
rows++;
}
}
} else {
Expand Down Expand Up @@ -721,7 +751,7 @@ static mp_obj_t io_savetxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
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, "#", 1, &error);
stream_p->write(stream, "# ", 2, &error);
}
const char *header = mp_obj_str_get_data(args[3].u_obj, &_len);
stream_p->write(stream, header, _len, &error);
Expand Down Expand Up @@ -769,7 +799,7 @@ static mp_obj_t io_savetxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
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, "#", 1, &error);
stream_p->write(stream, "# ", 2, &error);
}
const char *footer = mp_obj_str_get_data(args[4].u_obj, &_len);
stream_p->write(stream, footer, _len, &error);
Expand Down
8 changes: 4 additions & 4 deletions code/numpy/linalg/linalg.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,22 +435,22 @@ static mp_obj_t linalg_qr(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
// [[c s],
// [s -c]]
if(MICROPY_FLOAT_C_FUN(fabs)(rarray[i * n + j]) < LINALG_EPSILON) { // r[i, j]
c = (rarray[(i - 1) * n + j] >= 0.0) ? 1.0 : -1.0; // r[i-1, j]
c = (rarray[(i - 1) * n + j] >= MICROPY_FLOAT_CONST(0.0)) ? MICROPY_FLOAT_CONST(1.0) : MICROPY_FLOAT_CONST(-1.0); // r[i-1, j]
s = 0.0;
} else if(MICROPY_FLOAT_C_FUN(fabs)(rarray[(i - 1) * n + j]) < LINALG_EPSILON) { // r[i-1, j]
c = 0.0;
s = (rarray[i * n + j] >= 0.0) ? -1.0 : 1.0; // r[i, j]
s = (rarray[i * n + j] >= MICROPY_FLOAT_CONST(0.0)) ? MICROPY_FLOAT_CONST(-1.0) : MICROPY_FLOAT_CONST(1.0); // r[i, j]
} else {
mp_float_t t, u;
if(MICROPY_FLOAT_C_FUN(fabs)(rarray[(i - 1) * n + j]) > MICROPY_FLOAT_C_FUN(fabs)(rarray[i * n + j])) { // r[i-1, j], r[i, j]
t = rarray[i * n + j] / rarray[(i - 1) * n + j]; // r[i, j]/r[i-1, j]
u = MICROPY_FLOAT_C_FUN(sqrt)(1 + t * t);
c = -1.0 / u;
c = MICROPY_FLOAT_CONST(-1.0) / u;
s = c * t;
} else {
t = rarray[(i - 1) * n + j] / rarray[i * n + j]; // r[i-1, j]/r[i, j]
u = MICROPY_FLOAT_C_FUN(sqrt)(1 + t * t);
s = -1.0 / u;
s = MICROPY_FLOAT_CONST(-1.0) / u;
c = s * t;
}
}
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 4.4.0
#define ULAB_VERSION 4.4.2
#define xstr(s) str(s)
#define str(s) #s

Expand Down
2 changes: 1 addition & 1 deletion docs/manual/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
author = 'Zoltán Vörös'

# The full version, including alpha/beta/rc tags
release = '4.4.0'
release = '4.4.2'


# -- General configuration ---------------------------------------------------
Expand Down
41 changes: 36 additions & 5 deletions docs/manual/source/numpy-functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1027,10 +1027,17 @@ https://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html

The function reads data from a text file, and returns the generated
array. It takes a file name as the single positional argument, and the
``comments`` (with a default value of ``#``), the ``delimiter`` (with a
default value of ``,``), ``usecols`` (with a default of all columns),
and ``max_rows`` (with a default of all rows) keyword arguments. The
array returned is always of type ``float``.
following keyword arguments:

1. ``comments='#'``
2. ``dtype=float``
3. ``delimiter=','``
4. ``max_rows`` (with a default of all rows)
5. ``skip_rows=0``
6. ``usecols`` (with a default of all columns)

If ``dtype`` is supplied and is not ``float``, the data entries will be
converted to the appropriate integer type by rounding the values.

.. code::

Expand All @@ -1040,8 +1047,15 @@ array returned is always of type ``float``.

print('read all data')
print(np.loadtxt('loadtxt.dat'))

print('\nread maximum 5 rows (first row is a comment line)')
print(np.loadtxt('loadtxt.dat', max_rows=5))

print('\nread maximum 5 rows, convert dtype (first row is a comment line)')
print(np.loadtxt('loadtxt.dat', max_rows=5, dtype=np.uint8))

print('\nskip the first 3 rows, convert dtype (first row is a comment line)')
print(np.loadtxt('loadtxt.dat', skiprows=3, dtype=np.uint8))

.. parsed-literal::

Expand All @@ -1052,14 +1066,31 @@ array returned is always of type ``float``.
[12.0, 13.0, 14.0, 15.0],
[16.0, 17.0, 18.0, 19.0],
[20.0, 21.0, 22.0, 23.0],
[24.0, 25.0, 26.0, 27.0]], dtype=float64)
[24.0, 25.0, 26.0, 27.0],
[28.00000000000001, 29.0, 30.0, 31.0],
[32.0, 33.0, 34.00000000000001, 35.0]], dtype=float64)

read maximum 5 rows (first row is a comment line)
array([[0.0, 1.0, 2.0, 3.0],
[4.0, 5.0, 6.0, 7.0],
[8.0, 9.0, 10.0, 11.0],
[12.0, 13.0, 14.0, 15.0]], dtype=float64)

read maximum 5 rows, convert dtype (first row is a comment line)
array([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11],
[12, 13, 14, 15]], dtype=uint8)

skip the first 3 rows, convert dtype (first row is a comment line)
array([[8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31],
[32, 33, 34, 35]], dtype=uint8)




Expand Down
Loading