Compare commits

...

3 commits

Author SHA1 Message Date
Zoltán Vörös
ec7caa8c27 add keyword handling 2025-08-27 21:39:21 +02:00
Zoltán Vörös
03c8655b06 integer arrays can be binned 2025-08-25 21:08:01 +02:00
Zoltán Vörös
13974df0cd working skeletoon of bincount 2025-08-25 20:32:06 +02:00
5 changed files with 139 additions and 4 deletions

View file

@ -6,7 +6,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2020-2021 Zoltán Vörös
* Copyright (c) 2020-2025 Zoltán Vörös
* 2020 Jeff Epler for Adafruit Industries
*/
@ -23,6 +23,133 @@
#include "carray/carray_tools.h"
#include "compare.h"
#ifdef ULAB_NUMPY_HAS_BINCOUNT
mp_obj_t compare_bincount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = MP_ROM_NONE} } ,
{ MP_QSTR_weights, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_rom_obj = MP_ROM_NONE } },
{ MP_QSTR_minlength, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .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);
if(!mp_obj_is_type(args[0].u_obj, &ulab_ndarray_type)) {
mp_raise_TypeError(MP_ERROR_TEXT("input must be an ndarray"));
}
ndarray_obj_t *input = MP_OBJ_TO_PTR(args[0].u_obj);
#if ULAB_MAX_DIMS > 1
// no need to check anything, if the maximum number of dimensions is 1
if(input->ndim != 1) {
mp_raise_ValueError(MP_ERROR_TEXT("object too deep for desired array"));
}
#endif
if((input->dtype != NDARRAY_UINT8) && (input->dtype != NDARRAY_UINT16)) {
mp_raise_TypeError(MP_ERROR_TEXT("cannot cast array data from dtype"));
}
// first find the maximum of the array, and figure out how long the result should be
size_t length = 0;
int32_t stride = input->strides[ULAB_MAX_DIMS - 1];
if(input->dtype == NDARRAY_UINT8) {
uint8_t *iarray = (uint8_t *)input->array;
for(size_t i = 0; i < input->len; i++) {
if(*iarray > length) {
length = *iarray;
}
iarray += stride;
}
} else if(input->dtype == NDARRAY_UINT16) {
stride /= 2;
uint16_t *iarray = (uint16_t *)input->array;
for(size_t i = 0; i < input->len; i++) {
if(*iarray > length) {
length = *iarray;
}
iarray += stride;
}
}
length += 1;
if(args[2].u_obj != mp_const_none) {
int32_t minlength = mp_obj_get_int(args[2].u_obj);
if(minlength < 0) {
mp_raise_ValueError(MP_ERROR_TEXT("minlength must not be negative"));
}
if((size_t)minlength > length) {
length = minlength;
}
}
ndarray_obj_t *result = NULL;
ndarray_obj_t *weights = NULL;
if(args[1].u_obj == mp_const_none) {
result = ndarray_new_linear_array(length, NDARRAY_UINT16);
} else {
if(!mp_obj_is_type(args[1].u_obj, &ulab_ndarray_type)) {
mp_raise_TypeError(MP_ERROR_TEXT("input must be an ndarray"));
}
weights = MP_OBJ_TO_PTR(args[1].u_obj);
result = ndarray_new_linear_array(length, NDARRAY_FLOAT);
}
// now we can do the binning
if(result->dtype == NDARRAY_UINT16) {
uint16_t *rarray = (uint16_t *)result->array;
if(input->dtype == NDARRAY_UINT8) {
uint8_t *iarray = (uint8_t *)input->array;
for(size_t i = 0; i < input->len; i++) {
rarray[*iarray] += 1;
iarray += stride;
}
} else if(input->dtype == NDARRAY_UINT16) {
uint16_t *iarray = (uint16_t *)input->array;
for(size_t i = 0; i < input->len; i++) {
rarray[*iarray] += 1;
iarray += stride;
}
}
} else {
mp_float_t *rarray = (mp_float_t *)result->array;
if(input->dtype == NDARRAY_UINT8) {
uint8_t *iarray = (uint8_t *)input->array;
for(size_t i = 0; i < input->len; i++) {
rarray[*iarray] += MICROPY_FLOAT_CONST(1.0);
iarray += stride;
}
} else if(input->dtype == NDARRAY_UINT16) {
uint16_t *iarray = (uint16_t *)input->array;
for(size_t i = 0; i < input->len; i++) {
rarray[*iarray] += MICROPY_FLOAT_CONST(1.0);
iarray += stride;
}
}
}
if(weights != NULL) {
mp_float_t (*get_weights)(void *) = ndarray_get_float_function(weights->dtype);
mp_float_t *rarray = (mp_float_t *)result->array;
uint8_t *warray = (uint8_t *)weights->array;
size_t fill_length = result->len;
if(weights->len < result->len) {
fill_length = weights->len;
}
for(size_t i = 0; i < fill_length; i++) {
*rarray = *rarray * get_weights(warray);
rarray++;
warray += weights->strides[ULAB_MAX_DIMS - 1];
}
}
return MP_OBJ_FROM_PTR(result);
}
MP_DEFINE_CONST_FUN_OBJ_KW(compare_bincount_obj, 1, compare_bincount);
#endif /* ULAB_NUMPY_HAS_BINCOUNT */
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 *rhs = ndarray_from_mp_obj(x2, 0);

View file

@ -6,7 +6,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2020-2021 Zoltán Vörös
* Copyright (c) 2020-2025 Zoltán Vörös
*/
#ifndef _COMPARE_
@ -23,6 +23,7 @@ enum COMPARE_FUNCTION_TYPE {
COMPARE_CLIP,
};
MP_DECLARE_CONST_FUN_OBJ_KW(compare_bincount_obj);
MP_DECLARE_CONST_FUN_OBJ_3(compare_clip_obj);
MP_DECLARE_CONST_FUN_OBJ_2(compare_equal_obj);
MP_DECLARE_CONST_FUN_OBJ_2(compare_isfinite_obj);

View file

@ -169,6 +169,9 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = {
#if ULAB_NUMPY_HAS_ZEROS
{ MP_ROM_QSTR(MP_QSTR_zeros), MP_ROM_PTR(&create_zeros_obj) },
#endif
#if ULAB_NUMPY_HAS_BINCOUNT
{ MP_ROM_QSTR(MP_QSTR_bincount), MP_ROM_PTR(&compare_bincount_obj) },
#endif
#if ULAB_NUMPY_HAS_CLIP
{ MP_ROM_QSTR(MP_QSTR_clip), MP_ROM_PTR(&compare_clip_obj) },
#endif

View file

@ -33,7 +33,7 @@
#include "user/user.h"
#include "utils/utils.h"
#define ULAB_VERSION 6.9.0
#define ULAB_VERSION 6.10.0
#define xstr(s) str(s)
#define str(s) #s

View file

@ -374,6 +374,10 @@
#endif
// functions that compare arrays
#ifndef ULAB_NUMPY_HAS_BINCOUNT
#define ULAB_NUMPY_HAS_BINCOUNT (1)
#endif
#ifndef ULAB_NUMPY_HAS_CLIP
#define ULAB_NUMPY_HAS_CLIP (1)
#endif