Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dtype mod #327

Draft
wants to merge 20 commits into
base: master
Choose a base branch
from
Draft
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
151 changes: 151 additions & 0 deletions code/blocks/blocks.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@

/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Zoltán Vörös
*/

#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/misc.h"

#include "ndarray.h"
#include "../ulab_tools.h"
#include "blocks.h"

#if ULAB_HAS_BLOCKS

const mp_obj_type_t blocks_transformer_type = {
{ &mp_type_type },
.name = MP_QSTR_transformer,
};

size_t *blocks_coords_from_pointer(void *p1, ndarray_obj_t *ndarray) {
// Calculates the coordinates in the original tensor from the position of the pointer
// The original view is assumed to be dense, i.e., the strides can be computed from the shape
// This is a utility function, and is not exposed to the python interpreter
blocks_block_obj_t *block = ndarray->block;
size_t diff = (uint8_t *)p1 - (uint8_t *)block->origin;
size_t stride = ndarray->itemsize;
size_t *coords = m_new(size_t, ULAB_MAX_DIMS);

// first, calculate the very first stride
for(uint8_t i = 0; i < block->ndim - 1; i++) {
stride *= block->shape[ULAB_MAX_DIMS - i - 1];
}
for(uint8_t i = block->ndim; i > 1; i--) {
coords[ULAB_MAX_DIMS - i] = diff / stride;
diff -= coords[ULAB_MAX_DIMS - i] * block->shape[ULAB_MAX_DIMS - i];
stride /= block->shape[ULAB_MAX_DIMS - i + 1];
}
return coords;
}

void blocks_block_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
blocks_block_obj_t *self = MP_OBJ_TO_PTR(self_in);
ndarray_obj_t *ndarray = (ndarray_obj_t *)self->ndarray;
mp_printf(print, "block(shape=(%ld,", ndarray->shape[ULAB_MAX_DIMS - ndarray->ndim]);
for(uint8_t i = 1; i < ndarray->ndim - 1; i++) {
mp_printf(print, " %ld,", ndarray->shape[ULAB_MAX_DIMS - ndarray->ndim + i]);
}
if(ndarray->ndim > 1) {
mp_printf(print, " %ld", ndarray->shape[ULAB_MAX_DIMS - 1]);
}
mp_print_str(print, "), dtype=");
ndarray_print_dtype(print, ndarray);
mp_print_str(print, ")");
}

const mp_obj_type_t blocks_block_type = {
{ &mp_type_type },
.name = MP_QSTR_block,
.print = blocks_block_print,
};

mp_obj_t blocks_new_ndarray(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_shape, MP_ARG_OBJ | MP_ARG_REQUIRED, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_transformer, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_dtype, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = MP_ROM_INT(NDARRAY_FLOAT) } },
};

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);

if(!MP_OBJ_IS_TYPE(args[0].u_obj, &mp_type_tuple)) {
mp_raise_TypeError(translate("shape must be a tuple"));
}
mp_obj_tuple_t *shape_tuple = MP_OBJ_TO_PTR(args[0].u_obj);
if(shape_tuple->len > ULAB_MAX_DIMS) {
mp_raise_ValueError(translate("too many dimensions"));
}

uint8_t _dtype;
#if ULAB_HAS_DTYPE_OBJECT
if(MP_OBJ_IS_TYPE(args[1].u_obj, &ulab_dtype_type)) {
dtype_obj_t *dtype = MP_OBJ_TO_PTR(args[2].u_obj);
_dtype = dtype->dtype.type;
} else {
_dtype = mp_obj_get_int(args[2].u_obj);
}
#else
_dtype = mp_obj_get_int(args[2].u_obj);
#endif

size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
memset(shape, 0, sizeof(size_t) * ULAB_MAX_DIMS);
size_t len = 0;
for(uint8_t i=0; i < shape_tuple->len; i++) {
shape[ULAB_MAX_DIMS - i - 1] = mp_obj_get_int(shape_tuple->items[shape_tuple->len - i - 1]);
// reserve as much space that data for the longest array can still be accommodated
if(shape[ULAB_MAX_DIMS - i - 1] > len) {
len = shape[ULAB_MAX_DIMS - i - 1];
}
}
ndarray_obj_t *ndarray = ndarray_new_ndarray_header(shape_tuple->len, shape, NULL, _dtype);
ndarray->flags = BLOCK_IS_READ_ONLY;
blocks_block_obj_t *block = m_new_obj(blocks_block_obj_t);
block->base.type = &blocks_block_type;
block->ndim = ndarray->ndim;
// store a pointer to the ndarray
block->ndarray = ndarray;

uint8_t *barray = m_new(uint8_t, ndarray->itemsize * len);
block->subarray = barray;
// store the original array dimensions; block->shape should never be touched
memcpy(&(block->shape), &(ndarray->shape), sizeof(size_t) * ULAB_MAX_DIMS);
// store the original address of the array; block->origin should never be touched
block->origin = ndarray->array;

// get the pointer to the reader function
blocks_transformer_obj_t *transformer = MP_OBJ_TO_PTR(args[1].u_obj);
block->arrfunc = transformer->arrfunc;
ndarray->array = transformer->array;
ndarray->block = block;
return ndarray;
}

MP_DEFINE_CONST_FUN_OBJ_KW(blocks_new_ndarray_obj, 0, blocks_new_ndarray);

static const mp_rom_map_elem_t ulab_blocks_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_blocks) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ndarray), (mp_obj_t)&blocks_new_ndarray_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_block), (mp_obj_t)&blocks_block_type },
};

static MP_DEFINE_CONST_DICT(mp_module_ulab_blocks_globals, ulab_blocks_globals_table);

mp_obj_module_t ulab_blocks_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_ulab_blocks_globals,
};

#endif
35 changes: 35 additions & 0 deletions code/blocks/blocks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2020-2021 Zoltán Vörös
*/

#ifndef _BLOCKS_
#define _BLOCKS_

#include "ulab.h"
#include "ndarray.h"

#define BLOCK_NO_FLAG 0x00
#define BLOCK_IS_READ_ONLY 0x01
#define BLOCK_IS_READ_WRITE 0x02

typedef struct _blocks_transformer_obj_t {
mp_obj_base_t base;
void *arrfunc;
void *array;
} blocks_transformer_obj_t;

extern const mp_obj_type_t blocks_transformer_type;

extern const mp_obj_type_t blocks_block_type;
extern mp_obj_module_t ulab_blocks_module;

size_t *blocks_coords_from_pointer(void *, ndarray_obj_t *);

#endif
2 changes: 1 addition & 1 deletion code/micropython.mk
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

USERMODULES_DIR := $(USERMOD_DIR)

# Add all C files to SRC_USERMOD.
SRC_USERMOD += $(USERMODULES_DIR)/scipy/optimize/optimize.c
SRC_USERMOD += $(USERMODULES_DIR)/scipy/signal/signal.c
SRC_USERMOD += $(USERMODULES_DIR)/scipy/special/special.c
Expand All @@ -22,6 +21,7 @@ SRC_USERMOD += $(USERMODULES_DIR)/numpy/stats/stats.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/transform/transform.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/vector/vector.c
SRC_USERMOD += $(USERMODULES_DIR)/user/user.c
SRC_USERMOD += $(USERMODULES_DIR)/blocks/blocks.c

SRC_USERMOD += $(USERMODULES_DIR)/numpy/numpy.c
SRC_USERMOD += $(USERMODULES_DIR)/scipy/scipy.c
Expand Down
Loading