added function pointer tools

This commit is contained in:
Zoltán Vörös 2020-11-06 17:49:56 +01:00
parent 148c948fa4
commit b7c135faf7
9 changed files with 153 additions and 51 deletions

View file

@ -20,6 +20,8 @@
#include "py/binary.h"
#include "py/obj.h"
#include "py/objarray.h"
#include "../ulab_tools.h"
#include "fft.h"
#if ULAB_FFT_MODULE
@ -101,8 +103,10 @@ mp_obj_t fft_fft_ifft_spectrum(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_im,
mp_float_t *data_re = (mp_float_t *)out_re->array;
uint8_t *array = (uint8_t *)re->array;
mp_float_t (*func)(void *) = ndarray_get_float_function(re->dtype);
for(size_t i=0; i < len; i++) {
*data_re++ = ndarray_get_float_value(array, re->dtype);
*data_re++ = func(array);
array += re->strides[ULAB_MAX_DIMS - 1];
}
data_re -= len;
@ -120,8 +124,9 @@ mp_obj_t fft_fft_ifft_spectrum(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_im,
mp_raise_ValueError(translate("real and imaginary parts must be of equal length"));
}
array = (uint8_t *)im->array;
func = ndarray_get_float_function(im->dtype);
for(size_t i=0; i < len; i++) {
*data_im++ = ndarray_get_float_value(array, im->dtype);
*data_im++ = func(array);
array += im->strides[ULAB_MAX_DIMS - 1];
}
data_im -= len;

View file

@ -3,6 +3,7 @@ USERMODULES_DIR := $(USERMOD_DIR)
# Add all C files to SRC_USERMOD.
SRC_USERMOD += $(USERMODULES_DIR)/ndarray_operators.c
SRC_USERMOD += $(USERMODULES_DIR)/ulab_tools.c
SRC_USERMOD += $(USERMODULES_DIR)/ndarray.c
SRC_USERMOD += $(USERMODULES_DIR)/ulab_create.c
SRC_USERMOD += $(USERMODULES_DIR)/linalg/linalg.c

View file

@ -19,6 +19,8 @@
#include "py/binary.h"
#include "py/obj.h"
#include "py/objtuple.h"
#include "ulab_tools.h"
#include "ndarray.h"
#include "ndarray_operators.h"
@ -283,38 +285,6 @@ void mp_obj_slice_indices(mp_obj_t self_in, mp_int_t length, mp_bound_slice_t *r
}
#endif
mp_float_t ndarray_get_float_index(void *data, uint8_t typecode, size_t index) {
// Returns a float value from an arbitrary data type
// The value in question is supposed to be located at the head of the pointer
if(typecode == NDARRAY_UINT8) {
return (mp_float_t)((uint8_t *)data)[index];
} else if(typecode == NDARRAY_INT8) {
return (mp_float_t)((int8_t *)data)[index];
} else if(typecode == NDARRAY_UINT16) {
return (mp_float_t)((uint16_t *)data)[index];
} else if(typecode == NDARRAY_INT16) {
return (mp_float_t)((int16_t *)data)[index];
} else {
return (mp_float_t)((mp_float_t *)data)[index];
}
}
mp_float_t ndarray_get_float_value(void *data, uint8_t typecode) {
// Returns a float value from an arbitrary data type
// The value in question is supposed to be located at the head of the pointer
if(typecode == NDARRAY_UINT8) {
return (mp_float_t)(*(uint8_t *)data);
} else if(typecode == NDARRAY_INT8) {
return (mp_float_t)(*(int8_t *)data);
} else if(typecode == NDARRAY_UINT16) {
return (mp_float_t)(*(uint16_t *)data);
} else if(typecode == NDARRAY_INT16) {
return (mp_float_t)(*(int16_t *)data);
} else {
return *((mp_float_t *)data);
}
}
void ndarray_fill_array_iterable(mp_float_t *array, mp_obj_t iterable) {
mp_obj_iter_buf_t x_buf;
mp_obj_t x_item, x_iterable = mp_getiter(iterable, &x_buf);

View file

@ -19,6 +19,8 @@
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/misc.h"
#include "../ulab_tools.h"
#include "numerical.h"
#if ULAB_NUMERICAL_MODULE
@ -209,8 +211,9 @@ static mp_obj_t numerical_argmin_argmax_ndarray(ndarray_obj_t *ndarray, mp_obj_t
if(axis == mp_const_none) {
// work with the flattened array
mp_float_t (*func)(void *) = ndarray_get_float_function(ndarray->dtype);
uint8_t *array = (uint8_t *)ndarray->array;
mp_float_t best_value = ndarray_get_float_value(array, ndarray->dtype);
mp_float_t best_value = func(array);
mp_float_t value;
size_t index = 0, best_index = 0;
@ -228,7 +231,7 @@ static mp_obj_t numerical_argmin_argmax_ndarray(ndarray_obj_t *ndarray, mp_obj_t
#endif
size_t l = 0;
do {
value = ndarray_get_float_value(array, ndarray->dtype);
value = func(array);
if((optype == NUMERICAL_ARGMAX) || (optype == NUMERICAL_MAX)) {
if(best_value < value) {
best_value = value;

View file

@ -16,6 +16,8 @@
#include "py/runtime.h"
#include "py/objarray.h"
#include "../linalg/linalg.h"
#include "../ulab_tools.h"
#include "poly.h"
#if ULAB_POLY_MODULE
@ -178,6 +180,8 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) {
ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_FLOAT);
mp_float_t *array = (mp_float_t *)ndarray->array;
mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype);
// TODO: these loops are really nothing, but the re-impplementation of
// ITERATE_VECTOR from vectorise.c. We could pass a function pointer here
#if ULAB_MAX_DIMS > 3
@ -195,7 +199,7 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) {
size_t l = 0;
do {
mp_float_t y = p[0];
mp_float_t _x = ndarray_get_float_value(sarray, source->dtype);
mp_float_t _x = func(sarray);
for(uint8_t m=0; m < plen-1; m++) {
y *= _x;
y += p[m+1];

View file

@ -32,7 +32,7 @@
#include "user/user.h"
#include "vector/vectorise.h"
#define ULAB_VERSION 1.2.0
#define ULAB_VERSION 1.2.2
#define xstr(s) str(s)
#define str(s) #s
#if ULAB_NUMPY_COMPATIBILITY

92
code/ulab_tools.c Normal file
View file

@ -0,0 +1,92 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Zoltán Vörös
*/
#include "py/runtime.h"
#include "ulab.h"
#include "ndarray.h"
#include "ulab_tools.h"
// The following five functions return a float from a void type
// The value in question is supposed to be located at the head of the pointer
mp_float_t ndarray_get_float_uint8(void *data) {
// Returns a float value from an uint8_t type
return (mp_float_t)(*(uint8_t *)data);
}
mp_float_t ndarray_get_float_int8(void *data) {
// Returns a float value from an int8_t type
return (mp_float_t)(*(int8_t *)data);
}
mp_float_t ndarray_get_float_uint16(void *data) {
// Returns a float value from an uint16_t type
return (mp_float_t)(*(uint16_t *)data);
}
mp_float_t ndarray_get_float_int16(void *data) {
// Returns a float value from an int16_t type
return (mp_float_t)(*(int16_t *)data);
}
mp_float_t ndarray_get_float_float(void *data) {
// Returns a float value from an mp_float_t type
return *((mp_float_t *)data);
}
// returns a single function pointer, depending on the dtype
void *ndarray_get_float_function(uint8_t dtype) {
if(dtype == NDARRAY_UINT8) {
return ndarray_get_float_uint8;
} else if(dtype == NDARRAY_INT8) {
return ndarray_get_float_int8;
} else if(dtype == NDARRAY_UINT16) {
return ndarray_get_float_uint16;
} else if(dtype == NDARRAY_INT16) {
return ndarray_get_float_int16;
} else {
return ndarray_get_float_float;
}
}
mp_float_t ndarray_get_float_index(void *data, uint8_t dtype, size_t index) {
// returns a single float value from an array located at index
if(dtype == NDARRAY_UINT8) {
return (mp_float_t)((uint8_t *)data)[index];
} else if(dtype == NDARRAY_INT8) {
return (mp_float_t)((int8_t *)data)[index];
} else if(dtype == NDARRAY_UINT16) {
return (mp_float_t)((uint16_t *)data)[index];
} else if(dtype == NDARRAY_INT16) {
return (mp_float_t)((int16_t *)data)[index];
} else {
return (mp_float_t)((mp_float_t *)data)[index];
}
}
mp_float_t ndarray_get_float_value(void *data, uint8_t dtype) {
// Returns a float value from an arbitrary data type
// The value in question is supposed to be located at the head of the pointer
if(dtype == NDARRAY_UINT8) {
return (mp_float_t)(*(uint8_t *)data);
} else if(dtype == NDARRAY_INT8) {
return (mp_float_t)(*(int8_t *)data);
} else if(dtype == NDARRAY_UINT16) {
return (mp_float_t)(*(uint16_t *)data);
} else if(dtype == NDARRAY_INT16) {
return (mp_float_t)(*(int16_t *)data);
} else {
return *((mp_float_t *)data);
}
}

21
code/ulab_tools.h Normal file
View file

@ -0,0 +1,21 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Zoltán Vörös
*/
#ifndef _TOOLS_
#define _TOOLS_
mp_float_t ndarray_get_float_uint8(void *);
mp_float_t ndarray_get_float_int8(void *);
mp_float_t ndarray_get_float_uint16(void *);
mp_float_t ndarray_get_float_int16(void *);
mp_float_t ndarray_get_float_float(void *);
void *ndarray_get_float_function(uint8_t );
#endif

View file

@ -19,6 +19,7 @@
#include "py/binary.h"
#include "py/obj.h"
#include "py/objarray.h"
#include "../ulab_tools.h"
#include "vectorise.h"
#if ULAB_VECTORISE_MODULE
@ -137,6 +138,8 @@ mp_obj_t vectorise_around(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
mp_float_t *narray = (mp_float_t *)ndarray->array;
uint8_t *sarray = (uint8_t *)source->array;
mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype);
#if ULAB_MAX_DIMS > 3
size_t i = 0;
do {
@ -151,7 +154,7 @@ mp_obj_t vectorise_around(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
#endif
size_t l = 0;
do {
mp_float_t f = ndarray_get_float_value(sarray, source->dtype);
mp_float_t f = func(sarray);
*narray++ = MICROPY_FLOAT_C_FUN(round)(f * mul) / mul;
sarray += source->strides[ULAB_MAX_DIMS - 1];
l++;
@ -219,6 +222,9 @@ mp_obj_t vectorise_arctan2(mp_obj_t y, mp_obj_t x) {
ndarray_obj_t *results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
mp_float_t *rarray = (mp_float_t *)results->array;
mp_float_t (*funcx)(void *) = ndarray_get_float_function(ndarray_x->dtype);
mp_float_t (*funcy)(void *) = ndarray_get_float_function(ndarray_y->dtype);
#if ULAB_MAX_DIMS > 3
size_t i = 0;
do {
@ -233,8 +239,8 @@ mp_obj_t vectorise_arctan2(mp_obj_t y, mp_obj_t x) {
#endif
size_t l = 0;
do {
mp_float_t _x = ndarray_get_float_value(xarray, ndarray_x->dtype);
mp_float_t _y = ndarray_get_float_value(yarray, ndarray_y->dtype);
mp_float_t _x = funcx(xarray);
mp_float_t _y = funcy(yarray);
*rarray++ = MICROPY_FLOAT_C_FUN(atan2)(_y, _x);
xarray += xstrides[ULAB_MAX_DIMS - 1];
yarray += ystrides[ULAB_MAX_DIMS - 1];