add random module (#654)
* add random module skeleton * add Generator object * add placeholder for random.random method * add rudimentary random.random implementation * generator object accept seed(s) argument * add out keyword * add support for out keyword argument * update change log * add links to header files * fix file link * fix error messages * add uniform to random module * add normal distribution * fix argument options in normal and uniform * update documentation
This commit is contained in:
parent
7a9370612f
commit
f2fad82a97
20 changed files with 1277 additions and 68 deletions
|
|
@ -25,6 +25,7 @@ SRC_USERMOD += $(USERMODULES_DIR)/numpy/linalg/linalg.c
|
|||
SRC_USERMOD += $(USERMODULES_DIR)/numpy/linalg/linalg_tools.c
|
||||
SRC_USERMOD += $(USERMODULES_DIR)/numpy/numerical.c
|
||||
SRC_USERMOD += $(USERMODULES_DIR)/numpy/poly.c
|
||||
SRC_USERMOD += $(USERMODULES_DIR)/numpy/random/random.c
|
||||
SRC_USERMOD += $(USERMODULES_DIR)/numpy/stats.c
|
||||
SRC_USERMOD += $(USERMODULES_DIR)/numpy/transform.c
|
||||
SRC_USERMOD += $(USERMODULES_DIR)/numpy/vector.c
|
||||
|
|
|
|||
|
|
@ -559,11 +559,11 @@ ndarray_obj_t *ndarray_new_ndarray_from_tuple(mp_obj_tuple_t *_shape, uint8_t dt
|
|||
// creates a dense array from a tuple
|
||||
// the function should work in the general n-dimensional case
|
||||
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
|
||||
for(size_t i=0; i < ULAB_MAX_DIMS; i++) {
|
||||
for(size_t i = 0; i < ULAB_MAX_DIMS; i++) {
|
||||
if(i >= _shape->len) {
|
||||
shape[ULAB_MAX_DIMS - i] = 0;
|
||||
shape[ULAB_MAX_DIMS - 1 - i] = 0;
|
||||
} else {
|
||||
shape[ULAB_MAX_DIMS - i] = mp_obj_get_int(_shape->items[i]);
|
||||
shape[ULAB_MAX_DIMS - 1 - i] = mp_obj_get_int(_shape->items[i]);
|
||||
}
|
||||
}
|
||||
return ndarray_new_dense_ndarray(_shape->len, shape, dtype);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
// Constant float objects are a struct in ROM and are referenced via their pointer.
|
||||
|
||||
// Use ULAB_DEFINE_FLOAT_CONST to define a constant float object.
|
||||
// id is the name of the constant, num is it's floating point value.
|
||||
// id is the name of the constant, num is its floating point value.
|
||||
// hex32 is computed as: hex(int.from_bytes(array.array('f', [num]), 'little'))
|
||||
// hex64 is computed as: hex(int.from_bytes(array.array('d', [num]), 'little'))
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "io/io.h"
|
||||
#include "linalg/linalg.h"
|
||||
#include "numerical.h"
|
||||
#include "random/random.h"
|
||||
#include "stats.h"
|
||||
#include "transform.h"
|
||||
#include "poly.h"
|
||||
|
|
@ -110,6 +111,9 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = {
|
|||
#if ULAB_NUMPY_HAS_LINALG_MODULE
|
||||
{ MP_ROM_QSTR(MP_QSTR_linalg), MP_ROM_PTR(&ulab_linalg_module) },
|
||||
#endif
|
||||
#if ULAB_NUMPY_HAS_RANDOM_MODULE
|
||||
{ MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&ulab_numpy_random_module) },
|
||||
#endif
|
||||
#if ULAB_HAS_PRINTOPTIONS
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_printoptions), MP_ROM_PTR(&ndarray_set_printoptions_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_printoptions), MP_ROM_PTR(&ndarray_get_printoptions_obj) },
|
||||
|
|
|
|||
378
code/numpy/random/random.c
Normal file
378
code/numpy/random/random.c
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* This file is part of the micropython-ulab project,
|
||||
*
|
||||
* https://github.com/v923z/micropython-ulab
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2024 Zoltán Vörös
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "py/builtin.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "random.h"
|
||||
|
||||
ULAB_DEFINE_FLOAT_CONST(random_zero, MICROPY_FLOAT_CONST(0.0), 0UL, 0ULL);
|
||||
ULAB_DEFINE_FLOAT_CONST(random_one, MICROPY_FLOAT_CONST(1.0), 0x3f800000UL, 0x3ff0000000000000ULL);
|
||||
|
||||
// methods of the Generator object
|
||||
static const mp_rom_map_elem_t random_generator_locals_dict_table[] = {
|
||||
#if ULAB_NUMPY_RANDOM_HAS_NORMAL
|
||||
{ MP_ROM_QSTR(MP_QSTR_normal), MP_ROM_PTR(&random_normal_obj) },
|
||||
#endif
|
||||
#if ULAB_NUMPY_RANDOM_HAS_RANDOM
|
||||
{ MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&random_random_obj) },
|
||||
#endif
|
||||
#if ULAB_NUMPY_RANDOM_HAS_UNIFORM
|
||||
{ MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&random_uniform_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
static MP_DEFINE_CONST_DICT(random_generator_locals_dict, random_generator_locals_dict_table);
|
||||
|
||||
// random's Generator object is defined here
|
||||
#if defined(MP_DEFINE_CONST_OBJ_TYPE)
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
random_generator_type,
|
||||
MP_QSTR_generator,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
print, random_generator_print,
|
||||
make_new, random_generator_make_new,
|
||||
locals_dict, &random_generator_locals_dict
|
||||
);
|
||||
#else
|
||||
const mp_obj_type_t random_generator_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_generator,
|
||||
.print = random_generator_print,
|
||||
.make_new = random_generator_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&random_generator_locals_dict
|
||||
};
|
||||
#endif
|
||||
|
||||
void random_generator_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
random_generator_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(MP_PYTHON_PRINTER, "Gnerator() at 0x%p", self);
|
||||
}
|
||||
|
||||
mp_obj_t random_generator_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
(void) type;
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, true);
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
};
|
||||
mp_arg_val_t _args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, _args);
|
||||
|
||||
|
||||
if(args[0] == mp_const_none) {
|
||||
#ifndef MICROPY_PY_RANDOM_SEED_INIT_FUNC
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("no default seed"));
|
||||
#endif
|
||||
random_generator_obj_t *generator = m_new_obj(random_generator_obj_t);
|
||||
generator->base.type = &random_generator_type;
|
||||
generator->state = MICROPY_PY_RANDOM_SEED_INIT_FUNC;
|
||||
return MP_OBJ_FROM_PTR(generator);
|
||||
} else if(mp_obj_is_int(args[0])) {
|
||||
random_generator_obj_t *generator = m_new_obj(random_generator_obj_t);
|
||||
generator->base.type = &random_generator_type;
|
||||
generator->state = (size_t)mp_obj_get_int(args[0]);
|
||||
return MP_OBJ_FROM_PTR(generator);
|
||||
} else if(mp_obj_is_type(args[0], &mp_type_tuple)){
|
||||
mp_obj_tuple_t *seeds = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_obj_t *items = m_new(mp_obj_t, seeds->len);
|
||||
|
||||
for(uint8_t i = 0; i < seeds->len; i++) {
|
||||
random_generator_obj_t *generator = m_new_obj(random_generator_obj_t);
|
||||
generator->base.type = &random_generator_type;
|
||||
generator->state = (size_t)mp_obj_get_int(seeds->items[i]);
|
||||
items[i] = generator;
|
||||
}
|
||||
return mp_obj_new_tuple(seeds->len, items);
|
||||
} else {
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("argument must be None, an integer or a tuple of integers"));
|
||||
}
|
||||
// we should never end up here
|
||||
return mp_const_none;
|
||||
}
|
||||
// END OF GENERATOR COMPONENTS
|
||||
|
||||
|
||||
static inline uint32_t pcg32_next(uint64_t *state) {
|
||||
uint64_t old_state = *state;
|
||||
*state = old_state * PCG_MULTIPLIER_64 + PCG_INCREMENT_64;
|
||||
uint32_t value = (uint32_t)((old_state ^ (old_state >> 18)) >> 27);
|
||||
int rot = old_state >> 59;
|
||||
return rot ? (value >> rot) | (value << (32 - rot)) : value;
|
||||
}
|
||||
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
|
||||
static inline uint64_t pcg32_next64(uint64_t *state) {
|
||||
uint64_t value = pcg32_next(state);
|
||||
value <<= 32;
|
||||
value |= pcg32_next(state);
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ULAB_NUMPY_RANDOM_HAS_NORMAL
|
||||
static mp_obj_t random_normal(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_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
{ MP_QSTR_loc, MP_ARG_OBJ, { .u_rom_obj = ULAB_REFERENCE_FLOAT_CONST(random_zero) } },
|
||||
{ MP_QSTR_scale, MP_ARG_OBJ, { .u_rom_obj = ULAB_REFERENCE_FLOAT_CONST(random_one) } },
|
||||
{ MP_QSTR_size, MP_ARG_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
random_generator_obj_t *self = MP_OBJ_TO_PTR(args[0].u_obj);
|
||||
mp_float_t loc = mp_obj_get_float(args[1].u_obj);
|
||||
mp_float_t scale = mp_obj_get_float(args[2].u_obj);
|
||||
mp_obj_t size = args[3].u_obj;
|
||||
|
||||
ndarray_obj_t *ndarray = NULL;
|
||||
mp_float_t u, v, value;
|
||||
|
||||
if(size != mp_const_none) {
|
||||
if(mp_obj_is_int(size)) {
|
||||
ndarray = ndarray_new_linear_array((size_t)mp_obj_get_int(size), NDARRAY_FLOAT);
|
||||
} else if(mp_obj_is_type(size, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *_shape = MP_OBJ_TO_PTR(size);
|
||||
if(_shape->len > ULAB_MAX_DIMS) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("maximum number of dimensions is " MP_STRINGIFY(ULAB_MAX_DIMS)));
|
||||
}
|
||||
ndarray = ndarray_new_ndarray_from_tuple(_shape, NDARRAY_FLOAT);
|
||||
} else { // input type not supported
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("shape must be None, and integer or a tuple of integers"));
|
||||
}
|
||||
} else {
|
||||
// return single value
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
uint32_t x = pcg32_next(&self->state);
|
||||
u = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
x = pcg32_next(&self->state);
|
||||
v = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
#else
|
||||
uint64_t x = pcg32_next64(&self->state);
|
||||
u = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
x = pcg32_next64(&self->state);
|
||||
v = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
#endif
|
||||
mp_float_t sqrt_log = MICROPY_FLOAT_C_FUN(sqrt)(-MICROPY_FLOAT_CONST(2.0) * MICROPY_FLOAT_C_FUN(log)(u));
|
||||
value = sqrt_log * MICROPY_FLOAT_C_FUN(cos)(MICROPY_FLOAT_CONST(2.0) * MP_PI * v);
|
||||
return mp_obj_new_float(loc + scale * value);
|
||||
}
|
||||
|
||||
mp_float_t *array = (mp_float_t *)ndarray->array;
|
||||
|
||||
// numpy's random supports only dense output arrays, so we can simply
|
||||
// loop through the elements in a linear fashion
|
||||
for(size_t i = 0; i < ndarray->len; i = i + 2) {
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
uint32_t x = pcg32_next(&self->state);
|
||||
u = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
x = pcg32_next(&self->state);
|
||||
v = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
#else
|
||||
uint64_t x = pcg32_next64(&self->state);
|
||||
u = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
x = pcg32_next64(&self->state);
|
||||
v = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
#endif
|
||||
mp_float_t sqrt_log = MICROPY_FLOAT_C_FUN(sqrt)(-MICROPY_FLOAT_CONST(2.0) * MICROPY_FLOAT_C_FUN(log)(u));
|
||||
value = sqrt_log * MICROPY_FLOAT_C_FUN(cos)(MICROPY_FLOAT_CONST(2.0) * MP_PI * v);
|
||||
*array++ = loc + scale * value;
|
||||
if((i & 1) == 0) {
|
||||
value = sqrt_log * MICROPY_FLOAT_C_FUN(sin)(MICROPY_FLOAT_CONST(2.0) * MP_PI * v);
|
||||
*array++ = loc + scale * value;
|
||||
}
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(ndarray);
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(random_normal_obj, 1, random_normal);
|
||||
#endif /* ULAB_NUMPY_RANDOM_HAS_NORMAL */
|
||||
|
||||
#if ULAB_NUMPY_RANDOM_HAS_RANDOM
|
||||
static mp_obj_t random_random(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_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
{ MP_QSTR_size, MP_ARG_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
{ MP_QSTR_out, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
random_generator_obj_t *self = MP_OBJ_TO_PTR(args[0].u_obj);
|
||||
|
||||
mp_obj_t size = args[1].u_obj;
|
||||
mp_obj_t out = args[2].u_obj;
|
||||
|
||||
ndarray_obj_t *ndarray = NULL;
|
||||
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
|
||||
uint8_t ndim = 1;
|
||||
|
||||
if(size != mp_const_none) {
|
||||
if(mp_obj_is_int(size)) {
|
||||
shape[ULAB_MAX_DIMS - 1] = (size_t)mp_obj_get_int(size);
|
||||
} else if(mp_obj_is_type(size, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *_shape = MP_OBJ_TO_PTR(size);
|
||||
if(_shape->len > ULAB_MAX_DIMS) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("maximum number of dimensions is " MP_STRINGIFY(ULAB_MAX_DIMS)));
|
||||
}
|
||||
ndim = _shape->len;
|
||||
for(size_t i = 0; i < ULAB_MAX_DIMS; i++) {
|
||||
if(i >= ndim) {
|
||||
shape[ULAB_MAX_DIMS - 1 - i] = 0;
|
||||
} else {
|
||||
shape[ULAB_MAX_DIMS - 1 - i] = mp_obj_get_int(_shape->items[i]);
|
||||
}
|
||||
}
|
||||
} else { // input type not supported
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("shape must be None, and integer or a tuple of integers"));
|
||||
}
|
||||
}
|
||||
|
||||
if(out != mp_const_none) {
|
||||
if(!mp_obj_is_type(out, &ulab_ndarray_type)) {
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("out has wrong type"));
|
||||
}
|
||||
|
||||
ndarray = MP_OBJ_TO_PTR(out);
|
||||
|
||||
if(ndarray->dtype != NDARRAY_FLOAT) {
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("output array has wrong type"));
|
||||
}
|
||||
if(size != mp_const_none) {
|
||||
for(uint8_t i = 0; i < ULAB_MAX_DIMS; i++) {
|
||||
if(ndarray->shape[i] != shape[i]) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("size must match out.shape when used together"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!ndarray_is_dense(ndarray)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("output array must be contiguous"));
|
||||
}
|
||||
} else { // out == None
|
||||
if(size != mp_const_none) {
|
||||
ndarray = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
|
||||
} else {
|
||||
// return single value
|
||||
mp_float_t value;
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
uint32_t x = pcg32_next(&self->state);
|
||||
value = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
#else
|
||||
uint64_t x = pcg32_next64(&self->state);
|
||||
value = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
#endif
|
||||
return mp_obj_new_float(value);
|
||||
}
|
||||
}
|
||||
|
||||
mp_float_t *array = (mp_float_t *)ndarray->array;
|
||||
|
||||
// numpy's random supports only dense output arrays, so we can simply
|
||||
// loop through the elements in a linear fashion
|
||||
for(size_t i = 0; i < ndarray->len; i++) {
|
||||
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
uint32_t x = pcg32_next(&self->state);
|
||||
*array = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
#else
|
||||
uint64_t x = pcg32_next64(&self->state);
|
||||
*array = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
#endif
|
||||
|
||||
array++;
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(ndarray);
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(random_random_obj, 1, random_random);
|
||||
#endif /* ULAB_NUMPY_RANDOM_HAS_RANDOM */
|
||||
|
||||
#if ULAB_NUMPY_RANDOM_HAS_UNIFORM
|
||||
static mp_obj_t random_uniform(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_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
{ MP_QSTR_low, MP_ARG_OBJ, { .u_rom_obj = ULAB_REFERENCE_FLOAT_CONST(random_zero) } },
|
||||
{ MP_QSTR_high, MP_ARG_OBJ, { .u_rom_obj = ULAB_REFERENCE_FLOAT_CONST(random_one) } },
|
||||
{ MP_QSTR_size, MP_ARG_OBJ, { .u_rom_obj = MP_ROM_NONE } },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
random_generator_obj_t *self = MP_OBJ_TO_PTR(args[0].u_obj);
|
||||
mp_float_t low = mp_obj_get_float(args[1].u_obj);
|
||||
mp_float_t high = mp_obj_get_float(args[2].u_obj);
|
||||
mp_obj_t size = args[3].u_obj;
|
||||
|
||||
ndarray_obj_t *ndarray = NULL;
|
||||
|
||||
if(size == mp_const_none) {
|
||||
// return single value
|
||||
mp_float_t value;
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
uint32_t x = pcg32_next(&self->state);
|
||||
value = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
#else
|
||||
uint64_t x = pcg32_next64(&self->state);
|
||||
value = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
#endif
|
||||
return mp_obj_new_float(value);
|
||||
} else if(mp_obj_is_type(size, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *_shape = MP_OBJ_TO_PTR(size);
|
||||
// TODO: this could be reduced, if the inspection was in the ndarray_new_ndarray_from_tuple function
|
||||
if(_shape->len > ULAB_MAX_DIMS) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("maximum number of dimensions is " MP_STRINGIFY(ULAB_MAX_DIMS)));
|
||||
}
|
||||
ndarray = ndarray_new_ndarray_from_tuple(_shape, NDARRAY_FLOAT);
|
||||
} else { // input type not supported
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("shape must be None, and integer or a tuple of integers"));
|
||||
}
|
||||
|
||||
mp_float_t *array = (mp_float_t *)ndarray->array;
|
||||
mp_float_t diff = high - low;
|
||||
for(size_t i = 0; i < ndarray->len; i++) {
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
uint32_t x = pcg32_next(&self->state);
|
||||
*array = (float)(int32_t)(x >> 8) * 0x1.0p-24f;
|
||||
#else
|
||||
uint64_t x = pcg32_next64(&self->state);
|
||||
*array = (double)(int64_t)(x >> 11) * 0x1.0p-53;
|
||||
#endif
|
||||
*array = low + diff * *array;
|
||||
array++;
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(ndarray);
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(random_uniform_obj, 1, random_uniform);
|
||||
#endif /* ULAB_NUMPY_RANDOM_HAS_UNIFORM */
|
||||
|
||||
|
||||
static const mp_rom_map_elem_t ulab_numpy_random_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_random) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Generator), MP_ROM_PTR(&random_generator_type) },
|
||||
};
|
||||
|
||||
static MP_DEFINE_CONST_DICT(mp_module_ulab_numpy_random_globals, ulab_numpy_random_globals_table);
|
||||
|
||||
const mp_obj_module_t ulab_numpy_random_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_ulab_numpy_random_globals,
|
||||
};
|
||||
|
||||
37
code/numpy/random/random.h
Normal file
37
code/numpy/random/random.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* This file is part of the micropython-ulab project,
|
||||
*
|
||||
* https://github.com/v923z/micropython-ulab
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2024 Zoltán Vörös
|
||||
*/
|
||||
|
||||
#include "../../ndarray.h"
|
||||
|
||||
#ifndef _NUMPY_RANDOM_
|
||||
#define _NUMPY_RANDOM_
|
||||
|
||||
|
||||
#define PCG_MULTIPLIER_64 6364136223846793005ULL
|
||||
#define PCG_INCREMENT_64 1442695040888963407ULL
|
||||
|
||||
extern const mp_obj_module_t ulab_numpy_random_module;
|
||||
|
||||
extern const mp_obj_type_t random_generator_type;
|
||||
|
||||
typedef struct _random_generator_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint64_t state;
|
||||
} random_generator_obj_t;
|
||||
|
||||
mp_obj_t random_generator_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *);
|
||||
void random_generator_print(const mp_print_t *, mp_obj_t , mp_print_kind_t );
|
||||
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(random_normal_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(random_random_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(random_uniform_obj);
|
||||
|
||||
#endif
|
||||
|
|
@ -609,9 +609,6 @@ static mp_obj_t vector_exp(mp_obj_t o_in) {
|
|||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
mp_obj_t o_in = args[0].u_obj;
|
||||
mp_obj_t out = args[1].u_obj;
|
||||
if(out != mp_const_none) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("out keyword is not supported for complex dtype"));
|
||||
}
|
||||
#endif /* ULAB_MATH_FUNCTIONS_OUT_KEYWORD */
|
||||
|
||||
if(mp_obj_is_type(o_in, &mp_type_complex)) {
|
||||
|
|
@ -621,6 +618,13 @@ static mp_obj_t vector_exp(mp_obj_t o_in) {
|
|||
return mp_obj_new_complex(exp_real * MICROPY_FLOAT_C_FUN(cos)(imag), exp_real * MICROPY_FLOAT_C_FUN(sin)(imag));
|
||||
} else if(mp_obj_is_type(o_in, &ulab_ndarray_type)) {
|
||||
ndarray_obj_t *source = MP_OBJ_TO_PTR(o_in);
|
||||
|
||||
#if ULAB_MATH_FUNCTIONS_OUT_KEYWORD
|
||||
if((out != mp_const_none) && (source->dtype == NDARRAY_COMPLEX)){
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("out keyword is not supported for complex dtype"));
|
||||
}
|
||||
#endif /* ULAB_MATH_FUNCTIONS_OUT_KEYWORD */
|
||||
|
||||
if(source->dtype == NDARRAY_COMPLEX) {
|
||||
uint8_t *sarray = (uint8_t *)source->array;
|
||||
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_COMPLEX);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include "user/user.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#define ULAB_VERSION 6.4.3
|
||||
#define ULAB_VERSION 6.5.0
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
|
|
|
|||
18
code/ulab.h
18
code/ulab.h
|
|
@ -697,6 +697,24 @@
|
|||
#define ULAB_NUMPY_HAS_SORT_COMPLEX (1)
|
||||
#endif
|
||||
|
||||
// random module
|
||||
#ifndef ULAB_NUMPY_HAS_RANDOM_MODULE
|
||||
#define ULAB_NUMPY_HAS_RANDOM_MODULE (1)
|
||||
#endif
|
||||
|
||||
#ifndef ULAB_NUMPY_RANDOM_HAS_NORMAL
|
||||
#define ULAB_NUMPY_RANDOM_HAS_NORMAL (1)
|
||||
#endif
|
||||
|
||||
#ifndef ULAB_NUMPY_RANDOM_HAS_RANDOM
|
||||
#define ULAB_NUMPY_RANDOM_HAS_RANDOM (1)
|
||||
#endif
|
||||
|
||||
#ifndef ULAB_NUMPY_RANDOM_HAS_UNIFORM
|
||||
#define ULAB_NUMPY_RANDOM_HAS_UNIFORM (1)
|
||||
#endif
|
||||
|
||||
|
||||
// scipy modules
|
||||
#ifndef ULAB_SCIPY_HAS_LINALG_MODULE
|
||||
#define ULAB_SCIPY_HAS_LINALG_MODULE (1)
|
||||
|
|
|
|||
|
|
@ -43,4 +43,8 @@ void ulab_rescale_float_strides(int32_t *);
|
|||
#endif
|
||||
|
||||
bool ulab_tools_mp_obj_is_scalar(mp_obj_t );
|
||||
|
||||
#if ULAB_NUMPY_HAS_RANDOM_MODULE
|
||||
ndarray_obj_t *ulab_tools_create_out(mp_obj_tuple_t , mp_obj_t , uint8_t , bool );
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ from sphinx import addnodes
|
|||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'The ulab book'
|
||||
copyright = '2019-2022, Zoltán Vörös and contributors'
|
||||
copyright = '2019-2024, Zoltán Vörös and contributors'
|
||||
author = 'Zoltán Vörös'
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '5.1.0'
|
||||
release = '6.5.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Welcome to the ulab book!
|
|||
numpy-universal
|
||||
numpy-fft
|
||||
numpy-linalg
|
||||
numpy-random
|
||||
scipy-linalg
|
||||
scipy-optimize
|
||||
scipy-signal
|
||||
|
|
|
|||
|
|
@ -12,43 +12,48 @@ the firmware was compiled with complex support.
|
|||
4. `numpy.argmin <#argmin>`__
|
||||
5. `numpy.argsort <#argsort>`__
|
||||
6. `numpy.asarray\* <#asarray>`__
|
||||
7. `numpy.clip <#clip>`__
|
||||
8. `numpy.compress\* <#compress>`__
|
||||
9. `numpy.conjugate\* <#conjugate>`__
|
||||
10. `numpy.convolve\* <#convolve>`__
|
||||
11. `numpy.delete <#delete>`__
|
||||
12. `numpy.diff <#diff>`__
|
||||
13. `numpy.dot <#dot>`__
|
||||
14. `numpy.equal <#equal>`__
|
||||
15. `numpy.flip\* <#flip>`__
|
||||
16. `numpy.imag\* <#imag>`__
|
||||
17. `numpy.interp <#interp>`__
|
||||
18. `numpy.isfinite <#isfinite>`__
|
||||
19. `numpy.isinf <#isinf>`__
|
||||
20. `numpy.load <#load>`__
|
||||
21. `numpy.loadtxt <#loadtxt>`__
|
||||
22. `numpy.max <#max>`__
|
||||
23. `numpy.maximum <#maximum>`__
|
||||
24. `numpy.mean <#mean>`__
|
||||
25. `numpy.median <#median>`__
|
||||
26. `numpy.min <#min>`__
|
||||
27. `numpy.minimum <#minimum>`__
|
||||
28. `numpy.nozero <#nonzero>`__
|
||||
29. `numpy.not_equal <#equal>`__
|
||||
30. `numpy.polyfit <#polyfit>`__
|
||||
31. `numpy.polyval <#polyval>`__
|
||||
32. `numpy.real\* <#real>`__
|
||||
33. `numpy.roll <#roll>`__
|
||||
34. `numpy.save <#save>`__
|
||||
35. `numpy.savetxt <#savetxt>`__
|
||||
36. `numpy.size <#size>`__
|
||||
37. `numpy.sort <#sort>`__
|
||||
38. `numpy.sort_complex\* <#sort_complex>`__
|
||||
39. `numpy.std <#std>`__
|
||||
40. `numpy.sum <#sum>`__
|
||||
41. `numpy.trace <#trace>`__
|
||||
42. `numpy.trapz <#trapz>`__
|
||||
43. `numpy.where <#where>`__
|
||||
7. `numpy.bitwise_and <#bitwise_and>`__
|
||||
8. `numpy.bitwise_or <#bitwise_and>`__
|
||||
9. `numpy.bitwise_xor <#bitwise_and>`__
|
||||
10. `numpy.clip <#clip>`__
|
||||
11. `numpy.compress\* <#compress>`__
|
||||
12. `numpy.conjugate\* <#conjugate>`__
|
||||
13. `numpy.convolve\* <#convolve>`__
|
||||
14. `numpy.delete <#delete>`__
|
||||
15. `numpy.diff <#diff>`__
|
||||
16. `numpy.dot <#dot>`__
|
||||
17. `numpy.equal <#equal>`__
|
||||
18. `numpy.flip\* <#flip>`__
|
||||
19. `numpy.imag\* <#imag>`__
|
||||
20. `numpy.interp <#interp>`__
|
||||
21. `numpy.isfinite <#isfinite>`__
|
||||
22. `numpy.isinf <#isinf>`__
|
||||
23. `numpy.left_shift <#left_shift>`__
|
||||
24. `numpy.load <#load>`__
|
||||
25. `numpy.loadtxt <#loadtxt>`__
|
||||
26. `numpy.max <#max>`__
|
||||
27. `numpy.maximum <#maximum>`__
|
||||
28. `numpy.mean <#mean>`__
|
||||
29. `numpy.median <#median>`__
|
||||
30. `numpy.min <#min>`__
|
||||
31. `numpy.minimum <#minimum>`__
|
||||
32. `numpy.nozero <#nonzero>`__
|
||||
33. `numpy.not_equal <#equal>`__
|
||||
34. `numpy.polyfit <#polyfit>`__
|
||||
35. `numpy.polyval <#polyval>`__
|
||||
36. `numpy.real\* <#real>`__
|
||||
37. `numpy.right_shift <#right_shift>`__
|
||||
38. `numpy.roll <#roll>`__
|
||||
39. `numpy.save <#save>`__
|
||||
40. `numpy.savetxt <#savetxt>`__
|
||||
41. `numpy.size <#size>`__
|
||||
42. `numpy.sort <#sort>`__
|
||||
43. `numpy.sort_complex\* <#sort_complex>`__
|
||||
44. `numpy.std <#std>`__
|
||||
45. `numpy.sum <#sum>`__
|
||||
46. `numpy.trace <#trace>`__
|
||||
47. `numpy.trapz <#trapz>`__
|
||||
48. `numpy.where <#where>`__
|
||||
|
||||
all
|
||||
---
|
||||
|
|
@ -323,6 +328,58 @@ an alias for ``array``.
|
|||
|
||||
|
||||
|
||||
bitwise_and
|
||||
-----------
|
||||
|
||||
``numpy``: https://numpy.org/doc/stable/reference/routines.bitwise.html
|
||||
|
||||
``numpy``:
|
||||
https://numpy.org/doc/stable/reference/generated/numpy.bitwise_and.html
|
||||
|
||||
``numpy``:
|
||||
https://numpy.org/doc/stable/reference/generated/numpy.bitwise_or.html
|
||||
|
||||
``numpy``:
|
||||
https://numpy.org/doc/stable/reference/generated/numpy.bitwise_xor.html
|
||||
|
||||
Each of ``bitwise_and``, ``bitwise_or``, and ``bitwise_xor`` takes two
|
||||
integer-type ``ndarray``\ s as arguments, and returns the element-wise
|
||||
results of the ``AND``, ``OR``, and ``XOR`` operators. Broadcasting is
|
||||
supported. If the ``dtype`` of the input arrays is not an integer, and
|
||||
exception will be raised.
|
||||
|
||||
.. code::
|
||||
|
||||
# code to be run in micropython
|
||||
|
||||
from ulab import numpy as np
|
||||
|
||||
a = np.array(range(8), dtype=np.uint8)
|
||||
b = a + 1
|
||||
|
||||
print(a)
|
||||
print(b)
|
||||
print('\nbitwise_and:\n', np.bitwise_and(a, b))
|
||||
print('\nbitwise_or:\n', np.bitwise_or(a, b))
|
||||
print('\nbitwise_xor:\n', np.bitwise_xor(a, b))
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
array([0, 1, 2, 3, 4, 5, 6, 7], dtype=uint8)
|
||||
array([1, 2, 3, 4, 5, 6, 7, 8], dtype=uint8)
|
||||
|
||||
bitwise_and:
|
||||
array([0, 0, 2, 0, 4, 4, 6, 0], dtype=uint8)
|
||||
|
||||
bitwise_or:
|
||||
array([1, 3, 3, 7, 5, 7, 7, 15], dtype=uint8)
|
||||
|
||||
bitwise_xor:
|
||||
array([1, 3, 1, 7, 1, 3, 1, 15], dtype=uint8)
|
||||
|
||||
|
||||
|
||||
|
||||
clip
|
||||
----
|
||||
|
||||
|
|
@ -987,6 +1044,52 @@ positions, where the input is infinite. Integer types return the
|
|||
|
||||
|
||||
|
||||
left_shift
|
||||
----------
|
||||
|
||||
``numpy``:
|
||||
https://numpy.org/doc/stable/reference/generated/numpy.left_shift.html
|
||||
|
||||
``numpy``:
|
||||
https://numpy.org/doc/stable/reference/generated/numpy.right_shift.html
|
||||
|
||||
``left_shift``, and ``right_shift`` both take two integer-type
|
||||
``ndarray``\ s, and bit-wise shift the elements of the first array by an
|
||||
amount given by the second array to the left, and right, respectively.
|
||||
Broadcasting is supported. If the ``dtype`` of the input arrays is not
|
||||
an integer, and exception will be raised.
|
||||
|
||||
.. code::
|
||||
|
||||
# code to be run in micropython
|
||||
|
||||
from ulab import numpy as np
|
||||
|
||||
a = np.ones(7, dtype=np.uint8)
|
||||
b = np.zeros(7, dtype=np.uint8) + 255
|
||||
c = np.array(range(7), dtype=np.uint8) + 1
|
||||
|
||||
print('a: ', a)
|
||||
print('b: ', b)
|
||||
print('c: ', c)
|
||||
print('\na left shifted by c:\n', np.left_shift(a, c))
|
||||
print('\nb right shifted by c:\n', np.right_shift(b, c))
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
a: array([1, 1, 1, 1, 1, 1, 1], dtype=uint8)
|
||||
b: array([255, 255, 255, 255, 255, 255, 255], dtype=uint8)
|
||||
c: array([1, 2, 3, 4, 5, 6, 7], dtype=uint8)
|
||||
|
||||
a left shifted by c:
|
||||
array([2, 4, 8, 16, 32, 64, 128], dtype=uint8)
|
||||
|
||||
b right shifted by c:
|
||||
array([127, 63, 31, 15, 7, 3, 1], dtype=uint8)
|
||||
|
||||
|
||||
|
||||
|
||||
load
|
||||
----
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,18 @@ operate on, or can return complex arrays):
|
|||
``acos``, ``acosh``, ``arctan2``, ``around``, ``asin``, ``asinh``,
|
||||
``atan``, ``arctan2``, ``atanh``, ``ceil``, ``cos``, ``degrees``,
|
||||
``exp*``, ``expm1``, ``floor``, ``log``, ``log10``, ``log2``,
|
||||
``radians``, ``sin``, ``sinh``, ``sqrt*``, ``tan``, ``tanh``.
|
||||
``radians``, ``sin``, ``sinc``, ``sinh``, ``sqrt*``, ``tan``, ``tanh``.
|
||||
|
||||
These functions are applied element-wise to the arguments, thus, e.g.,
|
||||
the exponential of a matrix cannot be calculated in this way, only the
|
||||
exponential of the matrix entries.
|
||||
|
||||
In order to avoid repeated memory allocations, functions can take the
|
||||
``out=None`` optional argument, which must be a floating point
|
||||
``ndarray`` of the same size as the input ``array``. If these conditions
|
||||
are not fulfilled, and exception will be raised. If ``out=None``, a new
|
||||
array will be created upon each invocation of the function.
|
||||
|
||||
.. code::
|
||||
|
||||
# code to be run in micropython
|
||||
|
|
@ -47,6 +53,13 @@ exponential of the matrix entries.
|
|||
c = np.array(range(9)).reshape((3, 3))
|
||||
print('\n=============\nc:\n', c)
|
||||
print('exp(c):\n', np.exp(c))
|
||||
|
||||
# using the `out` argument
|
||||
d = np.array(range(9)).reshape((3, 3))
|
||||
|
||||
print('\nd before invoking the function:\n', d)
|
||||
np.exp(c, out=d)
|
||||
print('\nd afteri nvoking the function:\n', d)
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
|
@ -69,6 +82,16 @@ exponential of the matrix entries.
|
|||
[20.08553692318767, 54.59815003314424, 148.4131591025766],
|
||||
[403.4287934927351, 1096.633158428459, 2980.957987041728]], dtype=float64)
|
||||
|
||||
d before invoking the function:
|
||||
array([[0.0, 1.0, 2.0],
|
||||
[3.0, 4.0, 5.0],
|
||||
[6.0, 7.0, 8.0]], dtype=float64)
|
||||
|
||||
d afteri nvoking the function:
|
||||
array([[1.0, 2.718281828459045, 7.38905609893065],
|
||||
[20.08553692318767, 54.59815003314424, 148.4131591025766],
|
||||
[403.4287934927351, 1096.633158428459, 2980.957987041728]], dtype=float64)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1816,12 +1816,17 @@ Binary operators
|
|||
|
||||
``ulab`` implements the ``+``, ``-``, ``*``, ``/``, ``**``, ``<``,
|
||||
``>``, ``<=``, ``>=``, ``==``, ``!=``, ``+=``, ``-=``, ``*=``, ``/=``,
|
||||
``**=`` binary operators that work element-wise. Broadcasting is
|
||||
available, meaning that the two operands do not even have to have the
|
||||
same shape. If the lengths along the respective axes are equal, or one
|
||||
of them is 1, or the axis is missing, the element-wise operation can
|
||||
still be carried out. A thorough explanation of broadcasting can be
|
||||
found under https://numpy.org/doc/stable/user/basics.broadcasting.html.
|
||||
``**=`` binary operators, as well as the ``AND``, ``OR``, ``XOR``
|
||||
bit-wise operators that work element-wise. Note that the bit-wise
|
||||
operators will raise an exception, if either of the operands is of
|
||||
``float`` or ``complex`` type.
|
||||
|
||||
Broadcasting is available, meaning that the two operands do not even
|
||||
have to have the same shape. If the lengths along the respective axes
|
||||
are equal, or one of them is 1, or the axis is missing, the element-wise
|
||||
operation can still be carried out. A thorough explanation of
|
||||
broadcasting can be found under
|
||||
https://numpy.org/doc/stable/user/basics.broadcasting.html.
|
||||
|
||||
**WARNING**: note that relational operators (``<``, ``>``, ``<=``,
|
||||
``>=``, ``==``, ``!=``) should have the ``ndarray`` on their left hand
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@
|
|||
" if args.unix: # tests the code on the unix port. Note that this works on unix only\n",
|
||||
" with open('/dev/shm/micropython.py', 'w') as fout:\n",
|
||||
" fout.write(cell)\n",
|
||||
" proc = subprocess.Popen([\"../micropython/ports/unix/micropython-2\", \"/dev/shm/micropython.py\"], \n",
|
||||
" proc = subprocess.Popen([\"../micropython/ports/unix/build-2/micropython-2\", \"/dev/shm/micropython.py\"], \n",
|
||||
" stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n",
|
||||
" print(proc.stdout.read().decode(\"utf-8\"))\n",
|
||||
" print(proc.stderr.read().decode(\"utf-8\"))\n",
|
||||
|
|
@ -238,6 +238,9 @@
|
|||
"1. [numpy.argmin](#argmin)\n",
|
||||
"1. [numpy.argsort](#argsort)\n",
|
||||
"1. [numpy.asarray*](#asarray)\n",
|
||||
"1. [numpy.bitwise_and](#bitwise_and)\n",
|
||||
"1. [numpy.bitwise_or](#bitwise_and)\n",
|
||||
"1. [numpy.bitwise_xor](#bitwise_and)\n",
|
||||
"1. [numpy.clip](#clip)\n",
|
||||
"1. [numpy.compress*](#compress)\n",
|
||||
"1. [numpy.conjugate*](#conjugate)\n",
|
||||
|
|
@ -251,6 +254,7 @@
|
|||
"1. [numpy.interp](#interp)\n",
|
||||
"1. [numpy.isfinite](#isfinite)\n",
|
||||
"1. [numpy.isinf](#isinf)\n",
|
||||
"1. [numpy.left_shift](#left_shift)\n",
|
||||
"1. [numpy.load](#load)\n",
|
||||
"1. [numpy.loadtxt](#loadtxt)\n",
|
||||
"1. [numpy.max](#max)\n",
|
||||
|
|
@ -264,6 +268,7 @@
|
|||
"1. [numpy.polyfit](#polyfit)\n",
|
||||
"1. [numpy.polyval](#polyval)\n",
|
||||
"1. [numpy.real*](#real)\n",
|
||||
"1. [numpy.right_shift](#right_shift)\n",
|
||||
"1. [numpy.roll](#roll)\n",
|
||||
"1. [numpy.save](#save)\n",
|
||||
"1. [numpy.savetxt](#savetxt)\n",
|
||||
|
|
@ -606,6 +611,63 @@
|
|||
"print('a == c: {}'.format(a is c))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## bitwise_and\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/routines.bitwise.html\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/generated/numpy.bitwise_and.html\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/generated/numpy.bitwise_or.html\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/generated/numpy.bitwise_xor.html\n",
|
||||
"\n",
|
||||
"Each of `bitwise_and`, `bitwise_or`, and `bitwise_xor` takes two integer-type `ndarray`s as arguments, and returns the element-wise results of the `AND`, `OR`, and `XOR` operators. Broadcasting is supported. If the `dtype` of the input arrays is not an integer, and exception will be raised."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"array([0, 1, 2, 3, 4, 5, 6, 7], dtype=uint8)\n",
|
||||
"array([1, 2, 3, 4, 5, 6, 7, 8], dtype=uint8)\n",
|
||||
"\n",
|
||||
"bitwise_and:\n",
|
||||
" array([0, 0, 2, 0, 4, 4, 6, 0], dtype=uint8)\n",
|
||||
"\n",
|
||||
"bitwise_or:\n",
|
||||
" array([1, 3, 3, 7, 5, 7, 7, 15], dtype=uint8)\n",
|
||||
"\n",
|
||||
"bitwise_xor:\n",
|
||||
" array([1, 3, 1, 7, 1, 3, 1, 15], dtype=uint8)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%micropython -unix 1\n",
|
||||
"\n",
|
||||
"from ulab import numpy as np\n",
|
||||
"\n",
|
||||
"a = np.array(range(8), dtype=np.uint8)\n",
|
||||
"b = a + 1\n",
|
||||
"\n",
|
||||
"print(a)\n",
|
||||
"print(b)\n",
|
||||
"print('\\nbitwise_and:\\n', np.bitwise_and(a, b))\n",
|
||||
"print('\\nbitwise_or:\\n', np.bitwise_or(a, b))\n",
|
||||
"print('\\nbitwise_xor:\\n', np.bitwise_xor(a, b))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
|
|
@ -1423,6 +1485,58 @@
|
|||
"print('\\nisinf(c):\\n', np.isinf(c))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## left_shift\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/generated/numpy.left_shift.html\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/generated/numpy.right_shift.html\n",
|
||||
"\n",
|
||||
"`left_shift`, and `right_shift` both take two integer-type `ndarray`s, and bit-wise shift the elements of the first array by an amount given by the second array to the left, and right, respectively. Broadcasting is supported. If the `dtype` of the input arrays is not an integer, and exception will be raised."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"a: array([1, 1, 1, 1, 1, 1, 1], dtype=uint8)\n",
|
||||
"b: array([255, 255, 255, 255, 255, 255, 255], dtype=uint8)\n",
|
||||
"c: array([1, 2, 3, 4, 5, 6, 7], dtype=uint8)\n",
|
||||
"\n",
|
||||
"a left shifted by c:\n",
|
||||
" array([2, 4, 8, 16, 32, 64, 128], dtype=uint8)\n",
|
||||
"\n",
|
||||
"b right shifted by c:\n",
|
||||
" array([127, 63, 31, 15, 7, 3, 1], dtype=uint8)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%micropython -unix 1\n",
|
||||
"\n",
|
||||
"from ulab import numpy as np\n",
|
||||
"\n",
|
||||
"a = np.ones(7, dtype=np.uint8)\n",
|
||||
"b = np.zeros(7, dtype=np.uint8) + 255\n",
|
||||
"c = np.array(range(7), dtype=np.uint8) + 1\n",
|
||||
"\n",
|
||||
"print('a: ', a)\n",
|
||||
"print('b: ', b)\n",
|
||||
"print('c: ', c)\n",
|
||||
"print('\\na left shifted by c:\\n', np.left_shift(a, c))\n",
|
||||
"print('\\nb right shifted by c:\\n', np.right_shift(b, c))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
|
|
@ -2786,7 +2900,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.5"
|
||||
"version": "3.9.13"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
|
|
|
|||
492
docs/numpy-random.ipynb
Normal file
492
docs/numpy-random.ipynb
Normal file
|
|
@ -0,0 +1,492 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-05-01T09:27:13.438054Z",
|
||||
"start_time": "2020-05-01T09:27:13.191491Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Populating the interactive namespace from numpy and matplotlib\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%pylab inline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Notebook magic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2022-01-07T18:24:48.499467Z",
|
||||
"start_time": "2022-01-07T18:24:48.488004Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from IPython.core.magic import Magics, magics_class, line_cell_magic\n",
|
||||
"from IPython.core.magic import cell_magic, register_cell_magic, register_line_magic\n",
|
||||
"from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring\n",
|
||||
"import subprocess\n",
|
||||
"import os"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-07-23T20:31:25.296014Z",
|
||||
"start_time": "2020-07-23T20:31:25.265937Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@magics_class\n",
|
||||
"class PyboardMagic(Magics):\n",
|
||||
" @cell_magic\n",
|
||||
" @magic_arguments()\n",
|
||||
" @argument('-skip')\n",
|
||||
" @argument('-unix')\n",
|
||||
" @argument('-pyboard')\n",
|
||||
" @argument('-file')\n",
|
||||
" @argument('-data')\n",
|
||||
" @argument('-time')\n",
|
||||
" @argument('-memory')\n",
|
||||
" def micropython(self, line='', cell=None):\n",
|
||||
" args = parse_argstring(self.micropython, line)\n",
|
||||
" if args.skip: # doesn't care about the cell's content\n",
|
||||
" print('skipped execution')\n",
|
||||
" return None # do not parse the rest\n",
|
||||
" if args.unix: # tests the code on the unix port. Note that this works on unix only\n",
|
||||
" with open('/dev/shm/micropython.py', 'w') as fout:\n",
|
||||
" fout.write(cell)\n",
|
||||
" proc = subprocess.Popen([\"../micropython/ports/unix/build-2/micropython-2\", \"/dev/shm/micropython.py\"], \n",
|
||||
" stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n",
|
||||
" print(proc.stdout.read().decode(\"utf-8\"))\n",
|
||||
" print(proc.stderr.read().decode(\"utf-8\"))\n",
|
||||
" return None\n",
|
||||
" if args.file: # can be used to copy the cell content onto the pyboard's flash\n",
|
||||
" spaces = \" \"\n",
|
||||
" try:\n",
|
||||
" with open(args.file, 'w') as fout:\n",
|
||||
" fout.write(cell.replace('\\t', spaces))\n",
|
||||
" printf('written cell to {}'.format(args.file))\n",
|
||||
" except:\n",
|
||||
" print('Failed to write to disc!')\n",
|
||||
" return None # do not parse the rest\n",
|
||||
" if args.data: # can be used to load data from the pyboard directly into kernel space\n",
|
||||
" message = pyb.exec(cell)\n",
|
||||
" if len(message) == 0:\n",
|
||||
" print('pyboard >>>')\n",
|
||||
" else:\n",
|
||||
" print(message.decode('utf-8'))\n",
|
||||
" # register new variable in user namespace\n",
|
||||
" self.shell.user_ns[args.data] = string_to_matrix(message.decode(\"utf-8\"))\n",
|
||||
" \n",
|
||||
" if args.time: # measures the time of executions\n",
|
||||
" pyb.exec('import utime')\n",
|
||||
" message = pyb.exec('t = utime.ticks_us()\\n' + cell + '\\ndelta = utime.ticks_diff(utime.ticks_us(), t)' + \n",
|
||||
" \"\\nprint('execution time: {:d} us'.format(delta))\")\n",
|
||||
" print(message.decode('utf-8'))\n",
|
||||
" \n",
|
||||
" if args.memory: # prints out memory information \n",
|
||||
" message = pyb.exec('from micropython import mem_info\\nprint(mem_info())\\n')\n",
|
||||
" print(\"memory before execution:\\n========================\\n\", message.decode('utf-8'))\n",
|
||||
" message = pyb.exec(cell)\n",
|
||||
" print(\">>> \", message.decode('utf-8'))\n",
|
||||
" message = pyb.exec('print(mem_info())')\n",
|
||||
" print(\"memory after execution:\\n========================\\n\", message.decode('utf-8'))\n",
|
||||
"\n",
|
||||
" if args.pyboard:\n",
|
||||
" message = pyb.exec(cell)\n",
|
||||
" print(message.decode('utf-8'))\n",
|
||||
"\n",
|
||||
"ip = get_ipython()\n",
|
||||
"ip.register_magics(PyboardMagic)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## pyboard"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 57,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-05-07T07:35:35.126401Z",
|
||||
"start_time": "2020-05-07T07:35:35.105824Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pyboard\n",
|
||||
"pyb = pyboard.Pyboard('/dev/ttyACM0')\n",
|
||||
"pyb.enter_raw_repl()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-05-19T19:11:18.145548Z",
|
||||
"start_time": "2020-05-19T19:11:18.137468Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pyb.exit_raw_repl()\n",
|
||||
"pyb.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 58,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2020-05-07T07:35:38.725924Z",
|
||||
"start_time": "2020-05-07T07:35:38.645488Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%micropython -pyboard 1\n",
|
||||
"\n",
|
||||
"import utime\n",
|
||||
"import ulab as np\n",
|
||||
"\n",
|
||||
"def timeit(n=1000):\n",
|
||||
" def wrapper(f, *args, **kwargs):\n",
|
||||
" func_name = str(f).split(' ')[1]\n",
|
||||
" def new_func(*args, **kwargs):\n",
|
||||
" run_times = np.zeros(n, dtype=np.uint16)\n",
|
||||
" for i in range(n):\n",
|
||||
" t = utime.ticks_us()\n",
|
||||
" result = f(*args, **kwargs)\n",
|
||||
" run_times[i] = utime.ticks_diff(utime.ticks_us(), t)\n",
|
||||
" print('{}() execution times based on {} cycles'.format(func_name, n, (delta2-delta1)/n))\n",
|
||||
" print('\\tbest: %d us'%np.min(run_times))\n",
|
||||
" print('\\tworst: %d us'%np.max(run_times))\n",
|
||||
" print('\\taverage: %d us'%np.mean(run_times))\n",
|
||||
" print('\\tdeviation: +/-%.3f us'%np.std(run_times)) \n",
|
||||
" return result\n",
|
||||
" return new_func\n",
|
||||
" return wrapper\n",
|
||||
"\n",
|
||||
"def timeit(f, *args, **kwargs):\n",
|
||||
" func_name = str(f).split(' ')[1]\n",
|
||||
" def new_func(*args, **kwargs):\n",
|
||||
" t = utime.ticks_us()\n",
|
||||
" result = f(*args, **kwargs)\n",
|
||||
" print('execution time: ', utime.ticks_diff(utime.ticks_us(), t), ' us')\n",
|
||||
" return result\n",
|
||||
" return new_func"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"__END_OF_DEFS__"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# numpy.random\n",
|
||||
"\n",
|
||||
"Random numbers drawn specific distributions can be generated by instantiating a `Generator` object, and calling its methods. The module defines the following three functions:\n",
|
||||
"\n",
|
||||
"1. [numpy.random.Generator.normal](#normal)\n",
|
||||
"1. [numpy.random.Generator.random](#random)\n",
|
||||
"1. [numpy.random.Generator.uniform](#uniform)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"The `Generator` object, when instantiated, takes a single integer as its argument. This integer is the seed, which will be fed to the 32-bit or 64-bit routine. More details can be found under https://www.pcg-random.org/index.html. The generator is a standard `python` object that keeps track of its state.\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/random/index.html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## normal\n",
|
||||
"\n",
|
||||
"A random set of number from the `normal` distribution can be generated by calling the generator's `normal` method. The method takes three optional arguments, `loc=0.0`, the centre of the distribution, `scale=1.0`, the width of the distribution, and `size=None`, a tuple containing the shape of the returned array. In case `size` is `None`, a single floating point number is returned.\n",
|
||||
"\n",
|
||||
"The `normal` method of the `Generator` object is based on the [Box-Muller transform](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform).\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.normal.html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2019-10-19T13:08:17.647416Z",
|
||||
"start_time": "2019-10-19T13:08:17.597456Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Gnerator() at 0x7fa9dae05340\n",
|
||||
"-6.285246229407202\n",
|
||||
"array([[24.95816273705659, 15.2670302229426, 14.81001577336041],\n",
|
||||
" [20.17589833056986, 23.14539083787544, 26.37772041367461],\n",
|
||||
" [41.94894234387275, 37.11027030608206, 25.65889562100477]], dtype=float64)\n",
|
||||
"array([[21.52562779033434, 12.74685887865834, 24.08404670765186],\n",
|
||||
" [4.728112596365396, 7.667757906857082, 21.61576094228444],\n",
|
||||
" [2.432338873595267, 27.75945683572574, 5.730827584659245]], dtype=float64)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%micropython -unix 1\n",
|
||||
"\n",
|
||||
"from ulab import numpy as np\n",
|
||||
"\n",
|
||||
"rng = np.random.Generator(123456)\n",
|
||||
"print(rng)\n",
|
||||
"\n",
|
||||
"# return single number from a distribution of scale 1, and location 0\n",
|
||||
"print(rng.normal())\n",
|
||||
"\n",
|
||||
"print(rng.normal(loc=20.0, scale=10.0, size=(3,3)))\n",
|
||||
"# same as above, with positional arguments\n",
|
||||
"print(rng.normal(20.0, 10.0, (3,3)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## random\n",
|
||||
"\n",
|
||||
"A random set of number from the uniform distribution in the interval [0, 1] can be generated by calling the generator's `random` method. The method takes two optional arguments, `size=None`, a tuple containing the shape of the returned array, and `out`. In case `size` is `None`, a single floating point number is returned. \n",
|
||||
"\n",
|
||||
"`out` can be used, if a floating point array is available. An exception will be raised, if the array is not of `float` `dtype`, or if both `size` and `out` are supplied, and there is a conflict in their shapes.\n",
|
||||
"\n",
|
||||
"If `size` is `None`, a single floating point number will be returned.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.random.html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Gnerator() at 0x7f299de05340\n",
|
||||
"6.384615058863119e-11\n",
|
||||
"\n",
|
||||
" array([[0.4348157846574171, 0.7906325931024071, 0.878697619856133],\n",
|
||||
" [0.8738606263361598, 0.4946080034142021, 0.7765890156101152],\n",
|
||||
" [0.1770783715717074, 0.02080447648492112, 0.1053837559005948]], dtype=float64)\n",
|
||||
"\n",
|
||||
"buffer array before:\n",
|
||||
" array([[0.0, 1.0, 2.0],\n",
|
||||
" [3.0, 4.0, 5.0],\n",
|
||||
" [6.0, 7.0, 8.0]], dtype=float64)\n",
|
||||
"\n",
|
||||
"buffer array after:\n",
|
||||
" array([[0.8508024287393201, 0.9848489829156055, 0.7598167589604003],\n",
|
||||
" [0.782995698302952, 0.2866337782847831, 0.7915884498022229],\n",
|
||||
" [0.4614071706315902, 0.4792657443088592, 0.1581582066230718]], dtype=float64)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%micropython -unix 1\n",
|
||||
"\n",
|
||||
"from ulab import numpy as np\n",
|
||||
"\n",
|
||||
"rng = np.random.Generator(123456)\n",
|
||||
"print(rng)\n",
|
||||
"\n",
|
||||
"# returning new objects\n",
|
||||
"print(rng.random())\n",
|
||||
"print('\\n', rng.random(size=(3,3)))\n",
|
||||
"\n",
|
||||
"# supplying a buffer\n",
|
||||
"a = np.array(range(9), dtype=np.float).reshape((3,3))\n",
|
||||
"print('\\nbuffer array before:\\n', a)\n",
|
||||
"rng.random(out=a)\n",
|
||||
"print('\\nbuffer array after:\\n', a)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## uniform\n",
|
||||
"\n",
|
||||
"`uniform` is similar to `random`, except that the interval over which the numbers are distributed can be specified, while the `out` argument cannot. In addition to `size` specifying the shape of the output, `low=0.0`, and `high=1.0` are accepted arguments. With the indicated defaults, `uniform` is identical to `random`, which can be seen from the fact that the first 3-by-3 tensor below is the same as the one produced by `rng.random(size=(3,3))` above.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"If `size` is `None`, a single floating point number will be returned.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"`numpy`: https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.uniform.html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Gnerator() at 0x7f1891205340\n",
|
||||
"6.384615058863119e-11\n",
|
||||
"\n",
|
||||
" array([[0.4348157846574171, 0.7906325931024071, 0.878697619856133],\n",
|
||||
" [0.8738606263361598, 0.4946080034142021, 0.7765890156101152],\n",
|
||||
" [0.1770783715717074, 0.02080447648492112, 0.1053837559005948]], dtype=float64)\n",
|
||||
"\n",
|
||||
" array([[18.5080242873932, 19.84848982915605, 17.598167589604],\n",
|
||||
" [17.82995698302952, 12.86633778284783, 17.91588449802223],\n",
|
||||
" [14.6140717063159, 14.79265744308859, 11.58158206623072]], dtype=float64)\n",
|
||||
"\n",
|
||||
" array([[14.3380400319162, 12.72487657409978, 15.77119643621117],\n",
|
||||
" [13.61835831436355, 18.96062889255558, 15.78847796795966],\n",
|
||||
" [12.59435855187034, 17.68262037443622, 14.77943040598734]], dtype=float64)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%micropython -unix 1\n",
|
||||
"\n",
|
||||
"from ulab import numpy as np\n",
|
||||
"\n",
|
||||
"rng = np.random.Generator(123456)\n",
|
||||
"print(rng)\n",
|
||||
"\n",
|
||||
"print(rng.uniform())\n",
|
||||
"# returning numbers between 0, and 1\n",
|
||||
"print('\\n', rng.uniform(size=(3,3)))\n",
|
||||
"\n",
|
||||
"# returning numbers between 10, and 20\n",
|
||||
"print('\\n', rng.uniform(low=10, high=20, size=(3,3)))\n",
|
||||
"\n",
|
||||
"# same as above, without the keywords\n",
|
||||
"print('\\n', rng.uniform(10, 20, (3,3)))"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.13"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": true,
|
||||
"sideBar": true,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {
|
||||
"height": "calc(100% - 180px)",
|
||||
"left": "10px",
|
||||
"top": "150px",
|
||||
"width": "382.797px"
|
||||
},
|
||||
"toc_section_display": true,
|
||||
"toc_window_display": true
|
||||
},
|
||||
"varInspector": {
|
||||
"cols": {
|
||||
"lenName": 16,
|
||||
"lenType": 16,
|
||||
"lenVar": 40
|
||||
},
|
||||
"kernels_config": {
|
||||
"python": {
|
||||
"delete_cmd_postfix": "",
|
||||
"delete_cmd_prefix": "del ",
|
||||
"library": "var_list.py",
|
||||
"varRefreshCmd": "print(var_dic_list())"
|
||||
},
|
||||
"r": {
|
||||
"delete_cmd_postfix": ") ",
|
||||
"delete_cmd_prefix": "rm(",
|
||||
"library": "var_list.r",
|
||||
"varRefreshCmd": "cat(var_dic_list()) "
|
||||
}
|
||||
},
|
||||
"types_to_exclude": [
|
||||
"module",
|
||||
"function",
|
||||
"builtin_function_or_method",
|
||||
"instance",
|
||||
"_Feature"
|
||||
],
|
||||
"window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2022-01-07T19:10:30.696795Z",
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2022-01-07T19:10:30.785887Z",
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
" if args.unix: # tests the code on the unix port. Note that this works on unix only\n",
|
||||
" with open('/dev/shm/micropython.py', 'w') as fout:\n",
|
||||
" fout.write(cell)\n",
|
||||
" proc = subprocess.Popen([\"../micropython/ports/unix/micropython-2\", \"/dev/shm/micropython.py\"], \n",
|
||||
" proc = subprocess.Popen([\"../micropython/ports/unix/build-2/micropython-2\", \"/dev/shm/micropython.py\"], \n",
|
||||
" stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n",
|
||||
" print(proc.stdout.read().decode(\"utf-8\"))\n",
|
||||
" print(proc.stderr.read().decode(\"utf-8\"))\n",
|
||||
|
|
@ -229,14 +229,16 @@
|
|||
"\n",
|
||||
"At present, the following functions are supported (starred functions can operate on, or can return complex arrays):\n",
|
||||
"\n",
|
||||
"`acos`, `acosh`, `arctan2`, `around`, `asin`, `asinh`, `atan`, `arctan2`, `atanh`, `ceil`, `cos`, `degrees`, `exp*`, `expm1`, `floor`, `log`, `log10`, `log2`, `radians`, `sin`, `sinh`, `sqrt*`, `tan`, `tanh`.\n",
|
||||
"`acos`, `acosh`, `arctan2`, `around`, `asin`, `asinh`, `atan`, `arctan2`, `atanh`, `ceil`, `cos`, `degrees`, `exp*`, `expm1`, `floor`, `log`, `log10`, `log2`, `radians`, `sin`, `sinc`, `sinh`, `sqrt*`, `tan`, `tanh`.\n",
|
||||
"\n",
|
||||
"These functions are applied element-wise to the arguments, thus, e.g., the exponential of a matrix cannot be calculated in this way, only the exponential of the matrix entries."
|
||||
"These functions are applied element-wise to the arguments, thus, e.g., the exponential of a matrix cannot be calculated in this way, only the exponential of the matrix entries.\n",
|
||||
"\n",
|
||||
"In order to avoid repeated memory allocations, functions can take the `out=None` optional argument, which must be a floating point `ndarray` of the same size as the input `array`. If these conditions are not fulfilled, and exception will be raised. If `out=None`, a new array will be created upon each invocation of the function."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2021-01-13T19:11:07.579601Z",
|
||||
|
|
@ -267,6 +269,16 @@
|
|||
" [20.08553692318767, 54.59815003314424, 148.4131591025766],\n",
|
||||
" [403.4287934927351, 1096.633158428459, 2980.957987041728]], dtype=float64)\n",
|
||||
"\n",
|
||||
"d before invoking the function:\n",
|
||||
" array([[0.0, 1.0, 2.0],\n",
|
||||
" [3.0, 4.0, 5.0],\n",
|
||||
" [6.0, 7.0, 8.0]], dtype=float64)\n",
|
||||
"\n",
|
||||
"d afteri nvoking the function:\n",
|
||||
" array([[1.0, 2.718281828459045, 7.38905609893065],\n",
|
||||
" [20.08553692318767, 54.59815003314424, 148.4131591025766],\n",
|
||||
" [403.4287934927351, 1096.633158428459, 2980.957987041728]], dtype=float64)\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
|
|
@ -290,7 +302,14 @@
|
|||
"# as well as with matrices\n",
|
||||
"c = np.array(range(9)).reshape((3, 3))\n",
|
||||
"print('\\n=============\\nc:\\n', c)\n",
|
||||
"print('exp(c):\\n', np.exp(c))"
|
||||
"print('exp(c):\\n', np.exp(c))\n",
|
||||
"\n",
|
||||
"# using the `out` argument\n",
|
||||
"d = np.array(range(9)).reshape((3, 3))\n",
|
||||
"\n",
|
||||
"print('\\nd before invoking the function:\\n', d)\n",
|
||||
"np.exp(c, out=d)\n",
|
||||
"print('\\nd afteri nvoking the function:\\n', d)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -814,7 +833,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.5"
|
||||
"version": "3.9.13"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
Tue, 9 Jan 2024
|
||||
|
||||
version 6.5.0
|
||||
|
||||
add random module
|
||||
|
||||
Mon, 25 Dec 2023
|
||||
|
||||
version 6.4.3
|
||||
|
|
@ -14,9 +20,7 @@ Thu, 10 Aug 2023
|
|||
|
||||
version 6.4.1
|
||||
|
||||
```
|
||||
fix BOOLEAN issue, which would cause numpy.where funciton abnormally on RP2040(#643)
|
||||
```
|
||||
fix BOOLEAN issue, which would cause numpy.where funciton abnormally on RP2040(#643)
|
||||
|
||||
Thu, 20 Jul 2023
|
||||
|
||||
|
|
|
|||
|
|
@ -2599,7 +2599,9 @@
|
|||
"source": [
|
||||
"# Binary operators\n",
|
||||
"\n",
|
||||
"`ulab` implements the `+`, `-`, `*`, `/`, `**`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `+=`, `-=`, `*=`, `/=`, `**=` binary operators that work element-wise. Broadcasting is available, meaning that the two operands do not even have to have the same shape. If the lengths along the respective axes are equal, or one of them is 1, or the axis is missing, the element-wise operation can still be carried out. \n",
|
||||
"`ulab` implements the `+`, `-`, `*`, `/`, `**`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `+=`, `-=`, `*=`, `/=`, `**=` binary operators, as well as the `AND`, `OR`, `XOR` bit-wise operators that work element-wise. Note that the bit-wise operators will raise an exception, if either of the operands is of `float` or `complex` type.\n",
|
||||
"\n",
|
||||
"Broadcasting is available, meaning that the two operands do not even have to have the same shape. If the lengths along the respective axes are equal, or one of them is 1, or the axis is missing, the element-wise operation can still be carried out. \n",
|
||||
"A thorough explanation of broadcasting can be found under https://numpy.org/doc/stable/user/basics.broadcasting.html. \n",
|
||||
"\n",
|
||||
"**WARNING**: note that relational operators (`<`, `>`, `<=`, `>=`, `==`, `!=`) should have the `ndarray` on their left hand side, when compared to scalars. This means that the following works"
|
||||
|
|
|
|||
Loading…
Reference in a new issue