ulab can now be compiled with complex support

This commit is contained in:
Zoltán Vörös 2021-11-23 18:40:12 +01:00
parent 1013daa902
commit 911fdb4587
19 changed files with 204 additions and 22 deletions

View file

@ -171,7 +171,11 @@ void ndarray_rewind_array(uint8_t ndim, uint8_t *array, size_t *shape, int32_t *
static int32_t *strides_from_shape(size_t *shape, uint8_t dtype) { static int32_t *strides_from_shape(size_t *shape, uint8_t dtype) {
// returns a strides array that corresponds to a dense array with the prescribed shape // returns a strides array that corresponds to a dense array with the prescribed shape
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS); int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
strides[ULAB_MAX_DIMS-1] = (int32_t)mp_binary_get_size('@', dtype, NULL); #if ULAB_SUPPORTS_COMPLEX
strides[ULAB_MAX_DIMS-1] = (int32_t)mp_binary_get_complex_size(dtype);
#else
strides[ULAB_MAX_DIMS-1] = (int32_t)mp_binary_get_size('@', dtype, NULL);
#endif
for(uint8_t i=ULAB_MAX_DIMS; i > 1; i--) { for(uint8_t i=ULAB_MAX_DIMS; i > 1; i--) {
strides[i-2] = strides[i-1] * shape[i-1]; strides[i-2] = strides[i-1] * shape[i-1];
} }
@ -231,7 +235,13 @@ void ndarray_dtype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
mp_print_str(print, "uint16')"); mp_print_str(print, "uint16')");
} else if(self->dtype == NDARRAY_INT16) { } else if(self->dtype == NDARRAY_INT16) {
mp_print_str(print, "int16')"); mp_print_str(print, "int16')");
} else { }
#if ULAB_SUPPORTS_COMPLEX
else if(self->dtype == NDARRAY_COMPLEX) {
mp_print_str(print, "complex')");
}
#endif
else {
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
mp_print_str(print, "float32')"); mp_print_str(print, "float32')");
#else #else
@ -280,7 +290,13 @@ mp_obj_t ndarray_dtype_make_new(const mp_obj_type_t *type, size_t n_args, size_t
_dtype = NDARRAY_INT16; _dtype = NDARRAY_INT16;
} else if(memcmp(_dtype_, "float", 5) == 0) { } else if(memcmp(_dtype_, "float", 5) == 0) {
_dtype = NDARRAY_FLOAT; _dtype = NDARRAY_FLOAT;
} else { }
#if ULAB_SUPPORTS_COMPLEX
else if(memcmp(_dtype_, "complex", 7) == 0) {
_dtype = NDARRAY_COMPLEX;
}
#endif
else {
mp_raise_TypeError(translate("data type not understood")); mp_raise_TypeError(translate("data type not understood"));
} }
} }
@ -308,7 +324,11 @@ mp_obj_t ndarray_dtype(mp_obj_t self_in) {
GET_STR_DATA_LEN(self_in, _dtype, len); GET_STR_DATA_LEN(self_in, _dtype, len);
if((len != 1) || ((*_dtype != NDARRAY_BOOL) && (*_dtype != NDARRAY_UINT8) if((len != 1) || ((*_dtype != NDARRAY_BOOL) && (*_dtype != NDARRAY_UINT8)
&& (*_dtype != NDARRAY_INT8) && (*_dtype != NDARRAY_UINT16) && (*_dtype != NDARRAY_INT8) && (*_dtype != NDARRAY_UINT16)
&& (*_dtype != NDARRAY_INT16) && (*_dtype != NDARRAY_FLOAT))) { && (*_dtype != NDARRAY_INT16) && (*_dtype != NDARRAY_FLOAT)
#if ULAB_SUPPORTS_COMPLEX
&& (*_dtype != NDARRAY_COMPLEX)
#endif
)) {
mp_raise_TypeError(translate("data type not understood")); mp_raise_TypeError(translate("data type not understood"));
} }
dtype = *_dtype; dtype = *_dtype;
@ -361,32 +381,55 @@ mp_obj_t ndarray_get_item(ndarray_obj_t *ndarray, void *array) {
} }
} }
static void ndarray_print_element(const mp_print_t *print, ndarray_obj_t *ndarray, uint8_t *array) {
#if ULAB_SUPPORTS_COMPLEX
if(ndarray->dtype == NDARRAY_COMPLEX) {
// real part first
mp_float_t fvalue = *(mp_float_t *)array;
mp_obj_print_helper(print, mp_obj_new_float(fvalue), PRINT_REPR);
// imaginary part
array += ndarray->itemsize / 2;
fvalue = *(mp_float_t *)array;
if(fvalue >= MICROPY_FLOAT_CONST(0.0) || isnan(fvalue)) {
mp_print_str(print, "+");
}
array += ndarray->itemsize / 2;
mp_obj_print_helper(print, mp_obj_new_float(fvalue), PRINT_REPR);
mp_print_str(print, "j");
} else {
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR);
}
#else
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR);
#endif
}
static void ndarray_print_row(const mp_print_t *print, ndarray_obj_t * ndarray, uint8_t *array, size_t stride, size_t n) { static void ndarray_print_row(const mp_print_t *print, ndarray_obj_t * ndarray, uint8_t *array, size_t stride, size_t n) {
if(n == 0) { if(n == 0) {
return; return;
} }
mp_print_str(print, "["); mp_print_str(print, "[");
if((n <= ndarray_print_threshold) || (n <= 2*ndarray_print_edgeitems)) { // if the array is short, print everything if((n <= ndarray_print_threshold) || (n <= 2*ndarray_print_edgeitems)) { // if the array is short, print everything
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR); ndarray_print_element(print, ndarray, array);
array += stride; array += stride;
for(size_t i=1; i < n; i++, array += stride) { for(size_t i=1; i < n; i++, array += stride) {
mp_print_str(print, ", "); mp_print_str(print, ", ");
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR); ndarray_print_element(print, ndarray, array);
} }
} else { } else {
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR); mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR);
array += stride; array += stride;
for(size_t i=1; i < ndarray_print_edgeitems; i++, array += stride) { for(size_t i=1; i < ndarray_print_edgeitems; i++, array += stride) {
mp_print_str(print, ", "); mp_print_str(print, ", ");
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR); ndarray_print_element(print, ndarray, array);
} }
mp_printf(print, ", ..., "); mp_printf(print, ", ..., ");
array += stride * (n - 2 * ndarray_print_edgeitems); array += stride * (n - 2 * ndarray_print_edgeitems);
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR); ndarray_print_element(print, ndarray, array);
array += stride; array += stride;
for(size_t i=1; i < ndarray_print_edgeitems; i++, array += stride) { for(size_t i=1; i < ndarray_print_edgeitems; i++, array += stride) {
mp_print_str(print, ", "); mp_print_str(print, ", ");
mp_obj_print_helper(print, ndarray_get_item(ndarray, array), PRINT_REPR); ndarray_print_element(print, ndarray, array);
} }
} }
mp_print_str(print, "]"); mp_print_str(print, "]");
@ -494,7 +537,19 @@ void ndarray_assign_elements(ndarray_obj_t *ndarray, mp_obj_t iterable, uint8_t
} }
} else { } else {
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
ndarray_set_value(dtype, ndarray->array, (*idx)++, item); #if ULAB_SUPPORTS_COMPLEX
mp_float_t real;
mp_float_t imag;
if(dtype == NDARRAY_COMPLEX) {
mp_obj_get_complex(item, &real, &imag);
ndarray_set_value(NDARRAY_FLOAT, ndarray->array, (*idx)++, mp_obj_new_float(real));
ndarray_set_value(NDARRAY_FLOAT, ndarray->array, (*idx)++, mp_obj_new_float(imag));
} else {
ndarray_set_value(dtype, ndarray->array, (*idx)++, item);
}
#else
ndarray_set_value(dtype, ndarray->array, (*idx)++, item);
#endif
} }
} }
} }
@ -518,7 +573,11 @@ ndarray_obj_t *ndarray_new_ndarray(uint8_t ndim, size_t *shape, int32_t *strides
ndarray->boolean = dtype == NDARRAY_BOOL ? NDARRAY_BOOLEAN : NDARRAY_NUMERIC; ndarray->boolean = dtype == NDARRAY_BOOL ? NDARRAY_BOOLEAN : NDARRAY_NUMERIC;
ndarray->ndim = ndim; ndarray->ndim = ndim;
ndarray->len = ndim == 0 ? 0 : 1; ndarray->len = ndim == 0 ? 0 : 1;
ndarray->itemsize = mp_binary_get_size('@', ndarray->dtype, NULL); #if ULAB_SUPPORTS_COMPLEX
ndarray->itemsize = mp_binary_get_complex_size(dtype);
#else
ndarray->itemsize = mp_binary_get_size('@', ndarray->dtype, NULL);
#endif
int32_t *_strides; int32_t *_strides;
if(strides == NULL) { if(strides == NULL) {
_strides = strides_from_shape(shape, ndarray->dtype); _strides = strides_from_shape(shape, ndarray->dtype);
@ -546,7 +605,11 @@ ndarray_obj_t *ndarray_new_dense_ndarray(uint8_t ndim, size_t *shape, uint8_t dt
// creates a dense array, i.e., one, where the strides are derived directly from the shapes // creates a dense array, i.e., one, where the strides are derived directly from the shapes
// the function should work in the general n-dimensional case // the function should work in the general n-dimensional case
int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS); int32_t *strides = m_new(int32_t, ULAB_MAX_DIMS);
strides[ULAB_MAX_DIMS-1] = dtype == NDARRAY_BOOL ? 1 : mp_binary_get_size('@', dtype, NULL); #if ULAB_SUPPORTS_COMPLEX
strides[ULAB_MAX_DIMS-1] = dtype == NDARRAY_BOOL ? 1 : (int32_t)mp_binary_get_complex_size(dtype);
#else
strides[ULAB_MAX_DIMS-1] = dtype == NDARRAY_BOOL ? 1 : (int32_t)mp_binary_get_size('@', dtype, NULL);
#endif
for(size_t i=ULAB_MAX_DIMS; i > 1; i--) { for(size_t i=ULAB_MAX_DIMS; i > 1; i--) {
strides[i-2] = strides[i-1] * MAX(1, shape[i-1]); strides[i-2] = strides[i-1] * MAX(1, shape[i-1]);
} }
@ -567,13 +630,18 @@ ndarray_obj_t *ndarray_new_ndarray_from_tuple(mp_obj_tuple_t *_shape, uint8_t dt
return ndarray_new_dense_ndarray(_shape->len, shape, dtype); return ndarray_new_dense_ndarray(_shape->len, shape, dtype);
} }
void ndarray_copy_array(ndarray_obj_t *source, ndarray_obj_t *target) { void ndarray_copy_array(ndarray_obj_t *source, ndarray_obj_t *target, uint8_t shift) {
// TODO: if the array is dense, the content could be copied in a single pass // TODO: if the array is dense, the content could be copied in a single pass
// copies the content of source->array into a new dense void pointer // copies the content of source->array into a new dense void pointer
// it is assumed that the dtypes in source and target are the same // it is assumed that the dtypes in source and target are the same
// Since the target is a new array, it is supposed to be dense // Since the target is a new array, it is supposed to be dense
uint8_t *sarray = (uint8_t *)source->array; uint8_t *sarray = (uint8_t *)source->array;
uint8_t *tarray = (uint8_t *)target->array; uint8_t *tarray = (uint8_t *)target->array;
#if ULAB_SUPPORTS_COMPLEX
if(source->dtype == NDARRAY_COMPLEX) {
sarray += shift;
}
#endif
#if ULAB_MAX_DIMS > 3 #if ULAB_MAX_DIMS > 3
size_t i = 0; size_t i = 0;
@ -589,7 +657,7 @@ void ndarray_copy_array(ndarray_obj_t *source, ndarray_obj_t *target) {
#endif #endif
size_t l = 0; size_t l = 0;
do { do {
memcpy(tarray, sarray, source->itemsize); memcpy(tarray, sarray, target->itemsize);
tarray += target->itemsize; tarray += target->itemsize;
sarray += source->strides[ULAB_MAX_DIMS - 1]; sarray += source->strides[ULAB_MAX_DIMS - 1];
l++; l++;
@ -648,7 +716,7 @@ ndarray_obj_t *ndarray_copy_view(ndarray_obj_t *source) {
dtype = NDARRAY_BOOLEAN; dtype = NDARRAY_BOOLEAN;
} }
ndarray_obj_t *ndarray = ndarray_new_ndarray(source->ndim, source->shape, strides, dtype); ndarray_obj_t *ndarray = ndarray_new_ndarray(source->ndim, source->shape, strides, dtype);
ndarray_copy_array(source, ndarray); ndarray_copy_array(source, ndarray, 0);
return ndarray; return ndarray;
} }
@ -1805,7 +1873,11 @@ mp_obj_t ndarray_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
if(ndarray->boolean) { if(ndarray->boolean) {
for(size_t i=0; i < ndarray->len; i++, array++) *array = *array ^ 0x01; for(size_t i=0; i < ndarray->len; i++, array++) *array = *array ^ 0x01;
} else { } else {
uint8_t itemsize = mp_binary_get_size('@', self->dtype, NULL); #if ULAB_SUPPORTS_COMPLEX
uint8_t itemsize = mp_binary_get_complex_size(self->dtype);
#else
uint8_t itemsize = mp_binary_get_size('@', self->dtype, NULL);
#endif
for(size_t i=0; i < ndarray->len*itemsize; i++, array++) *array ^= 0xFF; for(size_t i=0; i < ndarray->len*itemsize; i++, array++) *array ^= 0xFF;
} }
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
@ -1914,7 +1986,7 @@ mp_obj_t ndarray_reshape_core(mp_obj_t oin, mp_obj_t _shape, bool inplace) {
mp_raise_ValueError(translate("cannot assign new shape")); mp_raise_ValueError(translate("cannot assign new shape"));
} }
ndarray = ndarray_new_ndarray_from_tuple(shape, source->dtype); ndarray = ndarray_new_ndarray_from_tuple(shape, source->dtype);
ndarray_copy_array(source, ndarray); ndarray_copy_array(source, ndarray, 0);
} }
return MP_OBJ_FROM_PTR(ndarray); return MP_OBJ_FROM_PTR(ndarray);
} }

View file

@ -77,6 +77,9 @@ enum NDARRAY_TYPE {
NDARRAY_INT8 = 'b', NDARRAY_INT8 = 'b',
NDARRAY_UINT16 = 'H', NDARRAY_UINT16 = 'H',
NDARRAY_INT16 = 'h', NDARRAY_INT16 = 'h',
#if ULAB_SUPPORTS_COMPLEX
NDARRAY_COMPLEX = 'c',
#endif
NDARRAY_FLOAT = FLOAT_TYPECODE, NDARRAY_FLOAT = FLOAT_TYPECODE,
}; };
@ -138,7 +141,7 @@ ndarray_obj_t *ndarray_new_linear_array(size_t , uint8_t );
ndarray_obj_t *ndarray_new_view(ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t ); ndarray_obj_t *ndarray_new_view(ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t );
bool ndarray_is_dense(ndarray_obj_t *); bool ndarray_is_dense(ndarray_obj_t *);
ndarray_obj_t *ndarray_copy_view(ndarray_obj_t *); ndarray_obj_t *ndarray_copy_view(ndarray_obj_t *);
void ndarray_copy_array(ndarray_obj_t *, ndarray_obj_t *); void ndarray_copy_array(ndarray_obj_t *, ndarray_obj_t *, uint8_t );
MP_DECLARE_CONST_FUN_OBJ_KW(ndarray_array_constructor_obj); MP_DECLARE_CONST_FUN_OBJ_KW(ndarray_array_constructor_obj);
mp_obj_t ndarray_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *); mp_obj_t ndarray_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *);

View file

@ -19,6 +19,7 @@
#include "../ulab.h" #include "../ulab.h"
#include "../ulab_tools.h" #include "../ulab_tools.h"
#include "carray/carray_tools.h"
#include "approx.h" #include "approx.h"
//| """Numerical approximation methods""" //| """Numerical approximation methods"""
@ -60,6 +61,9 @@ STATIC mp_obj_t approx_interp(size_t n_args, const mp_obj_t *pos_args, mp_map_t
ndarray_obj_t *x = ndarray_from_mp_obj(args[0].u_obj, 0); ndarray_obj_t *x = ndarray_from_mp_obj(args[0].u_obj, 0);
ndarray_obj_t *xp = ndarray_from_mp_obj(args[1].u_obj, 0); // xp must hold an increasing sequence of independent values ndarray_obj_t *xp = ndarray_from_mp_obj(args[1].u_obj, 0); // xp must hold an increasing sequence of independent values
ndarray_obj_t *fp = ndarray_from_mp_obj(args[2].u_obj, 0); ndarray_obj_t *fp = ndarray_from_mp_obj(args[2].u_obj, 0);
COMPLEX_DTYPE_NOT_IMPLEMENTED(x->dtype)
COMPLEX_DTYPE_NOT_IMPLEMENTED(xp->dtype)
COMPLEX_DTYPE_NOT_IMPLEMENTED(fp->dtype)
if((xp->ndim != 1) || (fp->ndim != 1) || (xp->len < 2) || (fp->len < 2) || (xp->len != fp->len)) { if((xp->ndim != 1) || (fp->ndim != 1) || (xp->len < 2) || (fp->len < 2) || (xp->len != fp->len)) {
mp_raise_ValueError(translate("interp is defined for 1D iterables of equal length")); mp_raise_ValueError(translate("interp is defined for 1D iterables of equal length"));
} }
@ -157,6 +161,7 @@ STATIC mp_obj_t approx_trapz(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
ndarray_obj_t *y = ndarray_from_mp_obj(args[0].u_obj, 0); ndarray_obj_t *y = ndarray_from_mp_obj(args[0].u_obj, 0);
COMPLEX_DTYPE_NOT_IMPLEMENTED(y->dtype)
ndarray_obj_t *x; ndarray_obj_t *x;
mp_float_t mean = MICROPY_FLOAT_CONST(0.0); mp_float_t mean = MICROPY_FLOAT_CONST(0.0);
if(y->len < 2) { if(y->len < 2) {
@ -174,6 +179,7 @@ STATIC mp_obj_t approx_trapz(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
if(args[1].u_obj != mp_const_none) { if(args[1].u_obj != mp_const_none) {
x = ndarray_from_mp_obj(args[1].u_obj, 0); // x must hold an increasing sequence of independent values x = ndarray_from_mp_obj(args[1].u_obj, 0); // x must hold an increasing sequence of independent values
COMPLEX_DTYPE_NOT_IMPLEMENTED(x->dtype)
if((x->ndim != 1) || (y->len != x->len)) { if((x->ndim != 1) || (y->len != x->len)) {
mp_raise_ValueError(translate("trapz is defined for 1D arrays of equal length")); mp_raise_ValueError(translate("trapz is defined for 1D arrays of equal length"));
} }

View file

@ -20,11 +20,17 @@
#include "../ulab.h" #include "../ulab.h"
#include "../ndarray_operators.h" #include "../ndarray_operators.h"
#include "../ulab_tools.h" #include "../ulab_tools.h"
#include "carray/carray_tools.h"
#include "compare.h" #include "compare.h"
static mp_obj_t compare_function(mp_obj_t x1, mp_obj_t x2, uint8_t op) { static mp_obj_t compare_function(mp_obj_t x1, mp_obj_t x2, uint8_t op) {
ndarray_obj_t *lhs = ndarray_from_mp_obj(x1, 0); ndarray_obj_t *lhs = ndarray_from_mp_obj(x1, 0);
ndarray_obj_t *rhs = ndarray_from_mp_obj(x2, 0); ndarray_obj_t *rhs = ndarray_from_mp_obj(x2, 0);
#if ULAB_SUPPORTS_COMPLEX
if((lhs->dtype == NDARRAY_COMPLEX) || (rhs->dtype == NDARRAY_COMPLEX)) {
NOT_IMPLEMENTED_FOR_COMPLEX()
}
#endif
uint8_t ndim = 0; uint8_t ndim = 0;
size_t *shape = m_new(size_t, ULAB_MAX_DIMS); size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
int32_t *lstrides = m_new(int32_t, ULAB_MAX_DIMS); int32_t *lstrides = m_new(int32_t, ULAB_MAX_DIMS);
@ -197,6 +203,7 @@ static mp_obj_t compare_isinf_isfinite(mp_obj_t _x, uint8_t mask) {
} }
} else if(mp_obj_is_type(_x, &ulab_ndarray_type)) { } else if(mp_obj_is_type(_x, &ulab_ndarray_type)) {
ndarray_obj_t *x = MP_OBJ_TO_PTR(_x); ndarray_obj_t *x = MP_OBJ_TO_PTR(_x);
COMPLEX_DTYPE_NOT_IMPLEMENTED(x->dtype)
ndarray_obj_t *results = ndarray_new_dense_ndarray(x->ndim, x->shape, NDARRAY_BOOL); ndarray_obj_t *results = ndarray_new_dense_ndarray(x->ndim, x->shape, NDARRAY_BOOL);
// At this point, results is all False // At this point, results is all False
uint8_t *rarray = (uint8_t *)results->array; uint8_t *rarray = (uint8_t *)results->array;
@ -313,6 +320,10 @@ mp_obj_t compare_where(mp_obj_t _condition, mp_obj_t _x, mp_obj_t _y) {
ndarray_obj_t *x = ndarray_from_mp_obj(_x, 0); ndarray_obj_t *x = ndarray_from_mp_obj(_x, 0);
ndarray_obj_t *y = ndarray_from_mp_obj(_y, 0); ndarray_obj_t *y = ndarray_from_mp_obj(_y, 0);
COMPLEX_DTYPE_NOT_IMPLEMENTED(c->dtype)
COMPLEX_DTYPE_NOT_IMPLEMENTED(x->dtype)
COMPLEX_DTYPE_NOT_IMPLEMENTED(y->dtype)
int32_t *cstrides = m_new(int32_t, ULAB_MAX_DIMS); int32_t *cstrides = m_new(int32_t, ULAB_MAX_DIMS);
int32_t *xstrides = m_new(int32_t, ULAB_MAX_DIMS); int32_t *xstrides = m_new(int32_t, ULAB_MAX_DIMS);
int32_t *ystrides = m_new(int32_t, ULAB_MAX_DIMS); int32_t *ystrides = m_new(int32_t, ULAB_MAX_DIMS);

View file

@ -20,6 +20,7 @@
#include "py/obj.h" #include "py/obj.h"
#include "py/objarray.h" #include "py/objarray.h"
#include "../carray/carray_tools.h"
#include "fft.h" #include "fft.h"
//| """Frequency-domain functions""" //| """Frequency-domain functions"""
@ -60,6 +61,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fft_fft_obj, 1, 2, fft_fft);
//| //|
static mp_obj_t fft_ifft(size_t n_args, const mp_obj_t *args) { static mp_obj_t fft_ifft(size_t n_args, const mp_obj_t *args) {
NOT_IMPLEMENTED_FOR_COMPLEX()
if(n_args == 2) { if(n_args == 2) {
return fft_fft_ifft_spectrogram(n_args, args[0], args[1], FFT_IFFT); return fft_fft_ifft_spectrogram(n_args, args[0], args[1], FFT_IFFT);
} else { } else {

View file

@ -13,6 +13,7 @@
#include "../../ndarray.h" #include "../../ndarray.h"
#include "../../ulab_tools.h" #include "../../ulab_tools.h"
#include "../carray/carray_tools.h"
#include "fft_tools.h" #include "fft_tools.h"
#ifndef MP_PI #ifndef MP_PI
@ -95,6 +96,7 @@ mp_obj_t fft_fft_ifft_spectrogram(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_i
ndarray_obj_t *re = MP_OBJ_TO_PTR(arg_re); ndarray_obj_t *re = MP_OBJ_TO_PTR(arg_re);
#if ULAB_MAX_DIMS > 1 #if ULAB_MAX_DIMS > 1
if(re->ndim != 1) { if(re->ndim != 1) {
COMPLEX_DTYPE_NOT_IMPLEMENTED(re->dtype)
mp_raise_TypeError(translate("FFT is implemented for linear arrays only")); mp_raise_TypeError(translate("FFT is implemented for linear arrays only"));
} }
#endif #endif
@ -122,6 +124,7 @@ mp_obj_t fft_fft_ifft_spectrogram(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_i
ndarray_obj_t *im = MP_OBJ_TO_PTR(arg_im); ndarray_obj_t *im = MP_OBJ_TO_PTR(arg_im);
#if ULAB_MAX_DIMS > 1 #if ULAB_MAX_DIMS > 1
if(im->ndim != 1) { if(im->ndim != 1) {
COMPLEX_DTYPE_NOT_IMPLEMENTED(im->dtype)
mp_raise_TypeError(translate("FFT is implemented for linear arrays only")); mp_raise_TypeError(translate("FFT is implemented for linear arrays only"));
} }
#endif #endif

View file

@ -21,6 +21,7 @@
#include "../ulab.h" #include "../ulab.h"
#include "../scipy/signal/signal.h" #include "../scipy/signal/signal.h"
#include "carray/carray_tools.h"
#include "filter.h" #include "filter.h"
#if ULAB_NUMPY_HAS_CONVOLVE #if ULAB_NUMPY_HAS_CONVOLVE
@ -40,6 +41,8 @@ mp_obj_t filter_convolve(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
ndarray_obj_t *a = MP_OBJ_TO_PTR(args[0].u_obj); ndarray_obj_t *a = MP_OBJ_TO_PTR(args[0].u_obj);
ndarray_obj_t *c = MP_OBJ_TO_PTR(args[1].u_obj); ndarray_obj_t *c = MP_OBJ_TO_PTR(args[1].u_obj);
COMPLEX_DTYPE_NOT_IMPLEMENTED(a->dtype)
COMPLEX_DTYPE_NOT_IMPLEMENTED(c->dtype)
// deal with linear arrays only // deal with linear arrays only
#if ULAB_MAX_DIMS > 1 #if ULAB_MAX_DIMS > 1
if((a->ndim != 1) || (c->ndim != 1)) { if((a->ndim != 1) || (c->ndim != 1)) {

View file

@ -22,6 +22,7 @@
#include "../../ulab.h" #include "../../ulab.h"
#include "../../ulab_tools.h" #include "../../ulab_tools.h"
#include "../carray/carray_tools.h"
#include "linalg.h" #include "linalg.h"
#if ULAB_NUMPY_HAS_LINALG_MODULE #if ULAB_NUMPY_HAS_LINALG_MODULE
@ -44,6 +45,7 @@
static mp_obj_t linalg_cholesky(mp_obj_t oin) { static mp_obj_t linalg_cholesky(mp_obj_t oin) {
ndarray_obj_t *ndarray = tools_object_is_square(oin); ndarray_obj_t *ndarray = tools_object_is_square(oin);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
ndarray_obj_t *L = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, ndarray->shape[ULAB_MAX_DIMS - 1], ndarray->shape[ULAB_MAX_DIMS - 1]), NDARRAY_FLOAT); ndarray_obj_t *L = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, ndarray->shape[ULAB_MAX_DIMS - 1], ndarray->shape[ULAB_MAX_DIMS - 1]), NDARRAY_FLOAT);
mp_float_t *Larray = (mp_float_t *)L->array; mp_float_t *Larray = (mp_float_t *)L->array;
@ -110,6 +112,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_cholesky_obj, linalg_cholesky);
static mp_obj_t linalg_det(mp_obj_t oin) { static mp_obj_t linalg_det(mp_obj_t oin) {
ndarray_obj_t *ndarray = tools_object_is_square(oin); ndarray_obj_t *ndarray = tools_object_is_square(oin);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
size_t N = ndarray->shape[ULAB_MAX_DIMS - 1]; size_t N = ndarray->shape[ULAB_MAX_DIMS - 1];
mp_float_t *tmp = m_new(mp_float_t, N * N); mp_float_t *tmp = m_new(mp_float_t, N * N);
@ -182,6 +185,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_det_obj, linalg_det);
static mp_obj_t linalg_eig(mp_obj_t oin) { static mp_obj_t linalg_eig(mp_obj_t oin) {
ndarray_obj_t *in = tools_object_is_square(oin); ndarray_obj_t *in = tools_object_is_square(oin);
COMPLEX_DTYPE_NOT_IMPLEMENTED(in->dtype)
uint8_t *iarray = (uint8_t *)in->array; uint8_t *iarray = (uint8_t *)in->array;
size_t S = in->shape[ULAB_MAX_DIMS - 1]; size_t S = in->shape[ULAB_MAX_DIMS - 1];
mp_float_t *array = m_new(mp_float_t, S*S); mp_float_t *array = m_new(mp_float_t, S*S);
@ -243,6 +247,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_eig_obj, linalg_eig);
//| //|
static mp_obj_t linalg_inv(mp_obj_t o_in) { static mp_obj_t linalg_inv(mp_obj_t o_in) {
ndarray_obj_t *ndarray = tools_object_is_square(o_in); ndarray_obj_t *ndarray = tools_object_is_square(o_in);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
size_t N = ndarray->shape[ULAB_MAX_DIMS - 1]; size_t N = ndarray->shape[ULAB_MAX_DIMS - 1];
ndarray_obj_t *inverted = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, N, N), NDARRAY_FLOAT); ndarray_obj_t *inverted = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, N, N), NDARRAY_FLOAT);
@ -305,6 +310,7 @@ static mp_obj_t linalg_norm(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(dot * (count - 1))); return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(dot * (count - 1)));
} else if(mp_obj_is_type(x, &ulab_ndarray_type)) { } else if(mp_obj_is_type(x, &ulab_ndarray_type)) {
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(x); ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(x);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
// always get a float, so that we don't have to resolve the dtype later // always get a float, so that we don't have to resolve the dtype later
mp_float_t (*func)(void *) = ndarray_get_float_function(ndarray->dtype); mp_float_t (*func)(void *) = ndarray_get_float_function(ndarray->dtype);

View file

@ -22,6 +22,7 @@
#include "../ulab.h" #include "../ulab.h"
#include "../ulab_tools.h" #include "../ulab_tools.h"
#include "./carray/carray_tools.h"
#include "numerical.h" #include "numerical.h"
enum NUMERICAL_FUNCTION_TYPE { enum NUMERICAL_FUNCTION_TYPE {
@ -97,6 +98,7 @@ static mp_obj_t numerical_all_any(mp_obj_t oin, mp_obj_t axis, uint8_t optype) {
bool anytype = optype == NUMERICAL_ALL ? 1 : 0; bool anytype = optype == NUMERICAL_ALL ? 1 : 0;
if(mp_obj_is_type(oin, &ulab_ndarray_type)) { if(mp_obj_is_type(oin, &ulab_ndarray_type)) {
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(oin); ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(oin);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
if(ndarray->len == 0) { // return immediately with empty arrays if(ndarray->len == 0) { // return immediately with empty arrays
if(optype == NUMERICAL_ALL) { if(optype == NUMERICAL_ALL) {
@ -237,6 +239,7 @@ static mp_obj_t numerical_sum_mean_std_iterable(mp_obj_t oin, uint8_t optype, si
} }
static mp_obj_t numerical_sum_mean_std_ndarray(ndarray_obj_t *ndarray, mp_obj_t axis, uint8_t optype, size_t ddof) { static mp_obj_t numerical_sum_mean_std_ndarray(ndarray_obj_t *ndarray, mp_obj_t axis, uint8_t optype, size_t ddof) {
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
uint8_t *array = (uint8_t *)ndarray->array; uint8_t *array = (uint8_t *)ndarray->array;
shape_strides _shape_strides = tools_reduce_axes(ndarray, axis); shape_strides _shape_strides = tools_reduce_axes(ndarray, axis);
@ -558,9 +561,11 @@ static mp_obj_t numerical_function(size_t n_args, const mp_obj_t *pos_args, mp_m
case NUMERICAL_MAX: case NUMERICAL_MAX:
case NUMERICAL_ARGMIN: case NUMERICAL_ARGMIN:
case NUMERICAL_ARGMAX: case NUMERICAL_ARGMAX:
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
return numerical_argmin_argmax_ndarray(ndarray, axis, optype); return numerical_argmin_argmax_ndarray(ndarray, axis, optype);
case NUMERICAL_SUM: case NUMERICAL_SUM:
case NUMERICAL_MEAN: case NUMERICAL_MEAN:
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
return numerical_sum_mean_std_ndarray(ndarray, axis, optype, 0); return numerical_sum_mean_std_ndarray(ndarray, axis, optype, 0);
default: default:
mp_raise_NotImplementedError(translate("operation is not implemented on ndarrays")); mp_raise_NotImplementedError(translate("operation is not implemented on ndarrays"));
@ -583,6 +588,7 @@ static mp_obj_t numerical_sort_helper(mp_obj_t oin, mp_obj_t axis, uint8_t inpla
} else { } else {
ndarray = ndarray_copy_view(MP_OBJ_TO_PTR(oin)); ndarray = ndarray_copy_view(MP_OBJ_TO_PTR(oin));
} }
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
int8_t ax = 0; int8_t ax = 0;
if(axis == mp_const_none) { if(axis == mp_const_none) {
@ -685,6 +691,7 @@ mp_obj_t numerical_argsort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
} }
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj); ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
if(args[1].u_obj == mp_const_none) { if(args[1].u_obj == mp_const_none) {
// bail out, though dense arrays could still be sorted // bail out, though dense arrays could still be sorted
mp_raise_NotImplementedError(translate("argsort is not implemented for flattened arrays")); mp_raise_NotImplementedError(translate("argsort is not implemented for flattened arrays"));
@ -788,6 +795,8 @@ static mp_obj_t numerical_cross(mp_obj_t _a, mp_obj_t _b) {
} }
ndarray_obj_t *a = MP_OBJ_TO_PTR(_a); ndarray_obj_t *a = MP_OBJ_TO_PTR(_a);
ndarray_obj_t *b = MP_OBJ_TO_PTR(_b); ndarray_obj_t *b = MP_OBJ_TO_PTR(_b);
COMPLEX_DTYPE_NOT_IMPLEMENTED(a->dtype)
COMPLEX_DTYPE_NOT_IMPLEMENTED(b->dtype)
if((a->ndim != 1) || (b->ndim != 1) || (a->len != b->len) || (a->len != 3)) { if((a->ndim != 1) || (b->ndim != 1) || (a->len != b->len) || (a->len != 3)) {
mp_raise_ValueError(translate("cross is defined for 1D arrays of length 3")); mp_raise_ValueError(translate("cross is defined for 1D arrays of length 3"));
} }
@ -876,6 +885,7 @@ mp_obj_t numerical_diff(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
} }
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj); ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
int8_t ax = args[2].u_int; int8_t ax = args[2].u_int;
if(ax < 0) ax += ndarray->ndim; if(ax < 0) ax += ndarray->ndim;
@ -959,7 +969,7 @@ mp_obj_t numerical_flip(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj); ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj);
if(args[1].u_obj == mp_const_none) { // flip the flattened array if(args[1].u_obj == mp_const_none) { // flip the flattened array
results = ndarray_new_linear_array(ndarray->len, ndarray->dtype); results = ndarray_new_linear_array(ndarray->len, ndarray->dtype);
ndarray_copy_array(ndarray, results); ndarray_copy_array(ndarray, results, 0);
uint8_t *rarray = (uint8_t *)results->array; uint8_t *rarray = (uint8_t *)results->array;
rarray += (results->len - 1) * results->itemsize; rarray += (results->len - 1) * results->itemsize;
results->array = rarray; results->array = rarray;

View file

@ -19,6 +19,7 @@
#include "numpy.h" #include "numpy.h"
#include "../ulab_create.h" #include "../ulab_create.h"
#include "approx.h" #include "approx.h"
#include "carray/carray.h"
#include "compare.h" #include "compare.h"
#include "fft/fft.h" #include "fft/fft.h"
#include "filter.h" #include "filter.h"
@ -125,6 +126,9 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_uint16), MP_ROM_INT(NDARRAY_UINT16) }, { MP_ROM_QSTR(MP_QSTR_uint16), MP_ROM_INT(NDARRAY_UINT16) },
{ MP_ROM_QSTR(MP_QSTR_int16), MP_ROM_INT(NDARRAY_INT16) }, { MP_ROM_QSTR(MP_QSTR_int16), MP_ROM_INT(NDARRAY_INT16) },
{ MP_ROM_QSTR(MP_QSTR_float), MP_ROM_INT(NDARRAY_FLOAT) }, { MP_ROM_QSTR(MP_QSTR_float), MP_ROM_INT(NDARRAY_FLOAT) },
#if ULAB_SUPPORTS_COMPLEX
{ MP_ROM_QSTR(MP_QSTR_complex), MP_ROM_INT(NDARRAY_COMPLEX) },
#endif
// modules of numpy // modules of numpy
#if ULAB_NUMPY_HAS_FFT_MODULE #if ULAB_NUMPY_HAS_FFT_MODULE
{ MP_ROM_QSTR(MP_QSTR_fft), MP_ROM_PTR(&ulab_fft_module) }, { MP_ROM_QSTR(MP_QSTR_fft), MP_ROM_PTR(&ulab_fft_module) },
@ -350,7 +354,10 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = {
#if ULAB_NUMPY_HAS_VECTORIZE #if ULAB_NUMPY_HAS_VECTORIZE
{ MP_OBJ_NEW_QSTR(MP_QSTR_vectorize), (mp_obj_t)&vectorise_vectorize_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_vectorize), (mp_obj_t)&vectorise_vectorize_obj },
#endif #endif
#if ULAB_SUPPORTS_COMPLEX
{ MP_OBJ_NEW_QSTR(MP_QSTR_real), (mp_obj_t)&carray_real_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_imag), (mp_obj_t)&carray_imag_obj },
#endif
}; };
static MP_DEFINE_CONST_DICT(mp_module_ulab_numpy_globals, ulab_numpy_globals_table); static MP_DEFINE_CONST_DICT(mp_module_ulab_numpy_globals, ulab_numpy_globals_table);

View file

@ -19,6 +19,7 @@
#include "../ulab.h" #include "../ulab.h"
#include "linalg/linalg_tools.h" #include "linalg/linalg_tools.h"
#include "../ulab_tools.h" #include "../ulab_tools.h"
#include "carray/carray_tools.h"
#include "poly.h" #include "poly.h"
#if ULAB_NUMPY_HAS_POLYFIT #if ULAB_NUMPY_HAS_POLYFIT
@ -27,6 +28,12 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) {
if(!ndarray_object_is_array_like(args[0])) { if(!ndarray_object_is_array_like(args[0])) {
mp_raise_ValueError(translate("input data must be an iterable")); mp_raise_ValueError(translate("input data must be an iterable"));
} }
#if ULAB_SUPPORTS_COMPLEX
if(MP_OBJ_IS_TYPE(args[0], &ulab_ndarray_type)) {
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0]);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
}
#endif
size_t lenx = 0, leny = 0; size_t lenx = 0, leny = 0;
uint8_t deg = 0; uint8_t deg = 0;
mp_float_t *x, *XT, *y, *prod; mp_float_t *x, *XT, *y, *prod;
@ -142,6 +149,17 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) {
if(!ndarray_object_is_array_like(o_p) || !ndarray_object_is_array_like(o_x)) { if(!ndarray_object_is_array_like(o_p) || !ndarray_object_is_array_like(o_x)) {
mp_raise_TypeError(translate("inputs are not iterable")); mp_raise_TypeError(translate("inputs are not iterable"));
} }
#if ULAB_SUPPORTS_COMPLEX
ndarray_obj_t *input;
if(MP_OBJ_IS_TYPE(o_p, &ulab_ndarray_type)) {
input = MP_OBJ_TO_PTR(o_p);
COMPLEX_DTYPE_NOT_IMPLEMENTED(input->dtype)
}
if(MP_OBJ_IS_TYPE(o_x, &ulab_ndarray_type)) {
input = MP_OBJ_TO_PTR(o_x);
COMPLEX_DTYPE_NOT_IMPLEMENTED(input->dtype)
}
#endif
// p had better be a one-dimensional standard iterable // p had better be a one-dimensional standard iterable
uint8_t plen = mp_obj_get_int(mp_obj_len_maybe(o_p)); uint8_t plen = mp_obj_get_int(mp_obj_len_maybe(o_p));
mp_float_t *p = m_new(mp_float_t, plen); mp_float_t *p = m_new(mp_float_t, plen);

View file

@ -21,6 +21,7 @@
#include "../ulab.h" #include "../ulab.h"
#include "../ulab_tools.h" #include "../ulab_tools.h"
#include "carray/carray_tools.h"
#include "stats.h" #include "stats.h"
#if ULAB_MAX_DIMS > 1 #if ULAB_MAX_DIMS > 1
@ -36,6 +37,7 @@
static mp_obj_t stats_trace(mp_obj_t oin) { static mp_obj_t stats_trace(mp_obj_t oin) {
ndarray_obj_t *ndarray = tools_object_is_square(oin); ndarray_obj_t *ndarray = tools_object_is_square(oin);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
mp_float_t trace = 0.0; mp_float_t trace = 0.0;
for(size_t i=0; i < ndarray->shape[ULAB_MAX_DIMS - 1]; i++) { for(size_t i=0; i < ndarray->shape[ULAB_MAX_DIMS - 1]; i++) {
int32_t pos = i * (ndarray->strides[ULAB_MAX_DIMS - 1] + ndarray->strides[ULAB_MAX_DIMS - 2]); int32_t pos = i * (ndarray->strides[ULAB_MAX_DIMS - 1] + ndarray->strides[ULAB_MAX_DIMS - 2]);

View file

@ -18,6 +18,7 @@
#include "../ulab.h" #include "../ulab.h"
#include "../ulab_tools.h" #include "../ulab_tools.h"
#include "carray/carray_tools.h"
#include "transform.h" #include "transform.h"
#if ULAB_MAX_DIMS > 1 #if ULAB_MAX_DIMS > 1
@ -39,6 +40,9 @@ mp_obj_t transform_dot(mp_obj_t _m1, mp_obj_t _m2) {
} }
ndarray_obj_t *m1 = MP_OBJ_TO_PTR(_m1); ndarray_obj_t *m1 = MP_OBJ_TO_PTR(_m1);
ndarray_obj_t *m2 = MP_OBJ_TO_PTR(_m2); ndarray_obj_t *m2 = MP_OBJ_TO_PTR(_m2);
COMPLEX_DTYPE_NOT_IMPLEMENTED(m1->dtype)
COMPLEX_DTYPE_NOT_IMPLEMENTED(m2->dtype)
uint8_t *array1 = (uint8_t *)m1->array; uint8_t *array1 = (uint8_t *)m1->array;
uint8_t *array2 = (uint8_t *)m2->array; uint8_t *array2 = (uint8_t *)m2->array;

View file

@ -22,6 +22,7 @@
#include "../ulab.h" #include "../ulab.h"
#include "../ulab_tools.h" #include "../ulab_tools.h"
#include "carray/carray_tools.h"
#include "vector.h" #include "vector.h"
//| """Element-by-element functions //| """Element-by-element functions
@ -39,6 +40,7 @@ static mp_obj_t vectorise_generic_vector(mp_obj_t o_in, mp_float_t (*f)(mp_float
ndarray_obj_t *ndarray = NULL; ndarray_obj_t *ndarray = NULL;
if(mp_obj_is_type(o_in, &ulab_ndarray_type)) { if(mp_obj_is_type(o_in, &ulab_ndarray_type)) {
ndarray_obj_t *source = MP_OBJ_TO_PTR(o_in); ndarray_obj_t *source = MP_OBJ_TO_PTR(o_in);
COMPLEX_DTYPE_NOT_IMPLEMENTED(source->dtype)
uint8_t *sarray = (uint8_t *)source->array; uint8_t *sarray = (uint8_t *)source->array;
ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_FLOAT); ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_FLOAT);
mp_float_t *array = (mp_float_t *)ndarray->array; mp_float_t *array = (mp_float_t *)ndarray->array;
@ -169,6 +171,7 @@ mp_obj_t vectorise_around(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
int8_t n = args[1].u_int; int8_t n = args[1].u_int;
mp_float_t mul = MICROPY_FLOAT_C_FUN(pow)(10.0, n); mp_float_t mul = MICROPY_FLOAT_C_FUN(pow)(10.0, n);
ndarray_obj_t *source = MP_OBJ_TO_PTR(args[0].u_obj); ndarray_obj_t *source = MP_OBJ_TO_PTR(args[0].u_obj);
COMPLEX_DTYPE_NOT_IMPLEMENTED(source->dtype)
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_FLOAT); ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_FLOAT);
mp_float_t *narray = (mp_float_t *)ndarray->array; mp_float_t *narray = (mp_float_t *)ndarray->array;
uint8_t *sarray = (uint8_t *)source->array; uint8_t *sarray = (uint8_t *)source->array;
@ -238,7 +241,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_atan_obj, vectorise_atan);
mp_obj_t vectorise_arctan2(mp_obj_t y, mp_obj_t x) { mp_obj_t vectorise_arctan2(mp_obj_t y, mp_obj_t x) {
ndarray_obj_t *ndarray_x = ndarray_from_mp_obj(x, 0); ndarray_obj_t *ndarray_x = ndarray_from_mp_obj(x, 0);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray_x->dtype)
ndarray_obj_t *ndarray_y = ndarray_from_mp_obj(y, 0); ndarray_obj_t *ndarray_y = ndarray_from_mp_obj(y, 0);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray_y->dtype)
uint8_t ndim = 0; uint8_t ndim = 0;
size_t *shape = m_new(size_t, ULAB_MAX_DIMS); size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
@ -544,6 +550,7 @@ static mp_obj_t vectorise_vectorized_function_call(mp_obj_t self_in, size_t n_ar
mp_obj_t fvalue; mp_obj_t fvalue;
if(mp_obj_is_type(args[0], &ulab_ndarray_type)) { if(mp_obj_is_type(args[0], &ulab_ndarray_type)) {
ndarray_obj_t *source = MP_OBJ_TO_PTR(args[0]); ndarray_obj_t *source = MP_OBJ_TO_PTR(args[0]);
COMPLEX_DTYPE_NOT_IMPLEMENTED(source->dtype)
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, self->otypes); ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, self->otypes);
for(size_t i=0; i < source->len; i++) { for(size_t i=0; i < source->len; i++) {
avalue[0] = mp_binary_get_val_array(source->dtype, source->array, i); avalue[0] = mp_binary_get_val_array(source->dtype, source->array, i);

View file

@ -18,6 +18,7 @@
#include "../../ulab.h" #include "../../ulab.h"
#include "../../ndarray.h" #include "../../ndarray.h"
#include "../../numpy/carray/carray_tools.h"
#include "../../numpy/fft/fft_tools.h" #include "../../numpy/fft/fft_tools.h"
#if ULAB_SCIPY_SIGNAL_HAS_SPECTROGRAM #if ULAB_SCIPY_SIGNAL_HAS_SPECTROGRAM
@ -68,6 +69,12 @@ mp_obj_t signal_sosfilt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
if(!ndarray_object_is_array_like(args[0].u_obj) || !ndarray_object_is_array_like(args[1].u_obj)) { if(!ndarray_object_is_array_like(args[0].u_obj) || !ndarray_object_is_array_like(args[1].u_obj)) {
mp_raise_TypeError(translate("sosfilt requires iterable arguments")); mp_raise_TypeError(translate("sosfilt requires iterable arguments"));
} }
#if ULAB_SUPPORTS_COMPLEX
if(MP_OBJ_IS_TYPE(args[1].u_obj, &ulab_ndarray_type)) {
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[1].u_obj);
COMPLEX_DTYPE_NOT_IMPLEMENTED(ndarray->dtype)
}
#endif
size_t lenx = (size_t)mp_obj_get_int(mp_obj_len_maybe(args[1].u_obj)); size_t lenx = (size_t)mp_obj_get_int(mp_obj_len_maybe(args[1].u_obj));
ndarray_obj_t *y = ndarray_new_linear_array(lenx, NDARRAY_FLOAT); ndarray_obj_t *y = ndarray_new_linear_array(lenx, NDARRAY_FLOAT);
mp_float_t *yarray = (mp_float_t *)y->array; mp_float_t *yarray = (mp_float_t *)y->array;

View file

@ -31,6 +31,10 @@
#include ULAB_CONFIG_FILE #include ULAB_CONFIG_FILE
#endif #endif
// Adds support for complex ndarrays
#ifndef ULAB_SUPPORTS_COMPLEX
#define ULAB_SUPPORTS_COMPLEX (1)
#endif
// Determines, whether scipy is defined in ulab. The sub-modules and functions // Determines, whether scipy is defined in ulab. The sub-modules and functions
// of scipy have to be defined separately // of scipy have to be defined separately

View file

@ -19,6 +19,7 @@
#include "ulab.h" #include "ulab.h"
#include "ulab_create.h" #include "ulab_create.h"
#include "ulab_tools.h"
#if ULAB_NUMPY_HAS_ONES | ULAB_NUMPY_HAS_ZEROS | ULAB_NUMPY_HAS_FULL | ULAB_NUMPY_HAS_EMPTY #if ULAB_NUMPY_HAS_ONES | ULAB_NUMPY_HAS_ZEROS | ULAB_NUMPY_HAS_FULL | ULAB_NUMPY_HAS_EMPTY
static mp_obj_t create_zeros_ones_full(mp_obj_t oshape, uint8_t dtype, mp_obj_t value) { static mp_obj_t create_zeros_ones_full(mp_obj_t oshape, uint8_t dtype, mp_obj_t value) {
@ -530,7 +531,11 @@ mp_obj_t create_frombuffer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
if(mp_get_buffer(args[0].u_obj, &bufinfo, MP_BUFFER_READ)) { if(mp_get_buffer(args[0].u_obj, &bufinfo, MP_BUFFER_READ)) {
size_t sz = 1; size_t sz = 1;
if(dtype != NDARRAY_BOOL) { // mp_binary_get_size doesn't work with Booleans if(dtype != NDARRAY_BOOL) { // mp_binary_get_size doesn't work with Booleans
sz = mp_binary_get_size('@', dtype, NULL); #if ULAB_SUPPORTS_COMPLEX
sz = mp_binary_get_complex_size(dtype);
#else
sz = mp_binary_get_size('@', dtype, NULL);
#endif
} }
if(bufinfo.len < offset) { if(bufinfo.len < offset) {
mp_raise_ValueError(translate("offset must be non-negative and no greater than buffer length")); mp_raise_ValueError(translate("offset must be non-negative and no greater than buffer length"));

View file

@ -231,3 +231,13 @@ ndarray_obj_t *tools_object_is_square(mp_obj_t obj) {
return ndarray; return ndarray;
} }
#endif #endif
#if ULAB_SUPPORTS_COMPLEX
uint8_t mp_binary_get_complex_size(uint8_t dtype) {
if(dtype == NDARRAY_COMPLEX) {
return 2 * (uint8_t)mp_binary_get_size('@', NDARRAY_FLOAT, NULL);
} else {
return dtype == NDARRAY_BOOL ? 1 : mp_binary_get_size('@', dtype, NULL);
}
}
#endif

View file

@ -34,4 +34,6 @@ void *ndarray_set_float_function(uint8_t );
shape_strides tools_reduce_axes(ndarray_obj_t *, mp_obj_t ); shape_strides tools_reduce_axes(ndarray_obj_t *, mp_obj_t );
ndarray_obj_t *tools_object_is_square(mp_obj_t ); ndarray_obj_t *tools_object_is_square(mp_obj_t );
uint8_t mp_binary_get_complex_size(uint8_t );
#endif #endif