Compare commits

...

11 commits

Author SHA1 Message Date
Jeff Epler
a03ef91904 fix build of convolve on circuitpython 2020-02-06 15:53:49 -06:00
Jeff Epler
5216acfb6f
Merge pull request #3 from jepler/convolve-circuitpython
Convolve (for circuitpython)
2020-02-06 12:46:26 -06:00
Jeff Epler
19e86f85c8 Merge branch 'convolve' into HEAD 2020-02-06 12:44:23 -06:00
Jeff Epler
e7db2173b1
Merge pull request #2 from jepler/docs-build
ulab.rst: Fix so it can be processed by sphinx in circuitpython
2020-02-04 13:47:44 -06:00
3aa8897b90 ulab.rst: Fix so it can be processed by sphinx in circuitpython 2020-02-04 13:45:59 -06:00
Jeff Epler
467386584f
Merge pull request #1 from jepler/master
Prepare ulab to be incorporated into circuitpython as an extmod
2020-02-04 11:37:20 -06:00
cfbf5f4e84 remove files that should not be tracked 2020-02-04 11:35:36 -06:00
b4974825c6 Merge remote-tracking branch 'upstream/master' into HEAD 2020-02-04 11:28:29 -06:00
50957ec120 ndarray: Fix compile error 2020-02-04 10:31:38 -06:00
Andrew Gatherer
e7243ce38a added __init__ files 2020-01-01 16:18:52 -06:00
Andrew Gatherer
58ee495e6b initial edit to CP 2019-12-31 09:18:23 -06:00
13 changed files with 369 additions and 141 deletions

193
code/__init__.c Normal file
View file

@ -0,0 +1,193 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Zoltán Vörös
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "py/runtime.h"
#include "py/binary.h"
#include "py/obj.h"
#include "py/objarray.h"
#include "shared-bindings/ulab/ndarray.h"
#include "shared-bindings/ulab/linalg.h"
#include "shared-bindings/ulab/vectorise.h"
#include "shared-bindings/ulab/poly.h"
#include "shared-bindings/ulab/fft.h"
#include "shared-bindings/ulab/numerical.h"
#define ULAB_VERSION 0.262
typedef struct _mp_obj_float_t {
mp_obj_base_t base;
mp_float_t value;
} mp_obj_float_t;
mp_obj_float_t ulab_version = {{&mp_type_float}, ULAB_VERSION};
MP_DEFINE_CONST_FUN_OBJ_1(ndarray_shape_obj, ndarray_shape);
MP_DEFINE_CONST_FUN_OBJ_1(ndarray_rawsize_obj, ndarray_rawsize);
MP_DEFINE_CONST_FUN_OBJ_KW(ndarray_flatten_obj, 1, ndarray_flatten);
MP_DEFINE_CONST_FUN_OBJ_1(ndarray_asbytearray_obj, ndarray_asbytearray);
MP_DEFINE_CONST_FUN_OBJ_1(linalg_transpose_obj, linalg_transpose);
MP_DEFINE_CONST_FUN_OBJ_2(linalg_reshape_obj, linalg_reshape);
MP_DEFINE_CONST_FUN_OBJ_KW(linalg_size_obj, 1, linalg_size);
MP_DEFINE_CONST_FUN_OBJ_1(linalg_inv_obj, linalg_inv);
MP_DEFINE_CONST_FUN_OBJ_2(linalg_dot_obj, linalg_dot);
MP_DEFINE_CONST_FUN_OBJ_KW(linalg_zeros_obj, 0, linalg_zeros);
MP_DEFINE_CONST_FUN_OBJ_KW(linalg_ones_obj, 0, linalg_ones);
MP_DEFINE_CONST_FUN_OBJ_KW(linalg_eye_obj, 0, linalg_eye);
MP_DEFINE_CONST_FUN_OBJ_1(linalg_det_obj, linalg_det);
MP_DEFINE_CONST_FUN_OBJ_1(linalg_eig_obj, linalg_eig);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acos_obj, vectorise_acos);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acosh_obj, vectorise_acosh);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_asin_obj, vectorise_asin);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_asinh_obj, vectorise_asinh);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_atan_obj, vectorise_atan);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_atanh_obj, vectorise_atanh);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_ceil_obj, vectorise_ceil);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_cos_obj, vectorise_cos);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_erf_obj, vectorise_erf);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_erfc_obj, vectorise_erfc);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_exp_obj, vectorise_exp);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_expm1_obj, vectorise_expm1);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_floor_obj, vectorise_floor);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_gamma_obj, vectorise_gamma);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_lgamma_obj, vectorise_lgamma);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_log_obj, vectorise_log);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_log10_obj, vectorise_log10);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_log2_obj, vectorise_log2);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_sin_obj, vectorise_sin);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_sinh_obj, vectorise_sinh);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_sqrt_obj, vectorise_sqrt);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_tan_obj, vectorise_tan);
MP_DEFINE_CONST_FUN_OBJ_1(vectorise_tanh_obj, vectorise_tanh);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_linspace_obj, 2, numerical_linspace);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_sum_obj, 1, numerical_sum);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_mean_obj, 1, numerical_mean);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_std_obj, 1, numerical_std);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_min_obj, 1, numerical_min);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_max_obj, 1, numerical_max);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_argmin_obj, 1, numerical_argmin);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_argmax_obj, 1, numerical_argmax);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_roll_obj, 2, numerical_roll);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_flip_obj, 1, numerical_flip);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_diff_obj, 1, numerical_diff);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_sort_obj, 1, numerical_sort);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_sort_inplace_obj, 1, numerical_sort_inplace);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(numerical_argsort_obj, 1, numerical_argsort);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(poly_polyval_obj, poly_polyval);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poly_polyfit_obj, 2, 3, poly_polyfit);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fft_fft_obj, 1, 2, fft_fft);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fft_ifft_obj, 1, 2, fft_ifft);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fft_spectrum_obj, 1, 2, fft_spectrum);
STATIC const mp_rom_map_elem_t ulab_ndarray_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_shape), MP_ROM_PTR(&ndarray_shape_obj) },
{ MP_ROM_QSTR(MP_QSTR_rawsize), MP_ROM_PTR(&ndarray_rawsize_obj) },
{ MP_ROM_QSTR(MP_QSTR_flatten), MP_ROM_PTR(&ndarray_flatten_obj) },
{ MP_ROM_QSTR(MP_QSTR_asbytearray), MP_ROM_PTR(&ndarray_asbytearray_obj) },
{ MP_ROM_QSTR(MP_QSTR_transpose), MP_ROM_PTR(&linalg_transpose_obj) },
{ MP_ROM_QSTR(MP_QSTR_reshape), MP_ROM_PTR(&linalg_reshape_obj) },
{ MP_ROM_QSTR(MP_QSTR_sort), MP_ROM_PTR(&numerical_sort_inplace_obj) },
};
STATIC MP_DEFINE_CONST_DICT(ulab_ndarray_locals_dict, ulab_ndarray_locals_dict_table);
const mp_obj_type_t ulab_ndarray_type = {
{ &mp_type_type },
.name = MP_QSTR_ndarray,
.print = ndarray_print,
.make_new = ndarray_make_new,
.subscr = ndarray_subscr,
.getiter = ndarray_getiter,
.unary_op = ndarray_unary_op,
.binary_op = ndarray_binary_op,
.locals_dict = (mp_obj_dict_t*)&ulab_ndarray_locals_dict,
};
STATIC const mp_map_elem_t ulab_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ulab) },
{ MP_ROM_QSTR(MP_QSTR___version__), MP_ROM_PTR(&ulab_version) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&ulab_ndarray_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_size), (mp_obj_t)&linalg_size_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_inv), (mp_obj_t)&linalg_inv_obj },
{ MP_ROM_QSTR(MP_QSTR_dot), (mp_obj_t)&linalg_dot_obj },
{ MP_ROM_QSTR(MP_QSTR_zeros), (mp_obj_t)&linalg_zeros_obj },
{ MP_ROM_QSTR(MP_QSTR_ones), (mp_obj_t)&linalg_ones_obj },
{ MP_ROM_QSTR(MP_QSTR_eye), (mp_obj_t)&linalg_eye_obj },
{ MP_ROM_QSTR(MP_QSTR_det), (mp_obj_t)&linalg_det_obj },
{ MP_ROM_QSTR(MP_QSTR_eig), (mp_obj_t)&linalg_eig_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_acos), (mp_obj_t)&vectorise_acos_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_acosh), (mp_obj_t)&vectorise_acosh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_asin), (mp_obj_t)&vectorise_asin_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_asinh), (mp_obj_t)&vectorise_asinh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_atan), (mp_obj_t)&vectorise_atan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_atanh), (mp_obj_t)&vectorise_atanh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ceil), (mp_obj_t)&vectorise_ceil_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_cos), (mp_obj_t)&vectorise_cos_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_erf), (mp_obj_t)&vectorise_erf_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_erfc), (mp_obj_t)&vectorise_erfc_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_exp), (mp_obj_t)&vectorise_exp_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_expm1), (mp_obj_t)&vectorise_expm1_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_floor), (mp_obj_t)&vectorise_floor_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_gamma), (mp_obj_t)&vectorise_gamma_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_lgamma), (mp_obj_t)&vectorise_lgamma_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_log), (mp_obj_t)&vectorise_log_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_log10), (mp_obj_t)&vectorise_log10_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_log2), (mp_obj_t)&vectorise_log2_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sin), (mp_obj_t)&vectorise_sin_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sinh), (mp_obj_t)&vectorise_sinh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&vectorise_sqrt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_tan), (mp_obj_t)&vectorise_tan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&vectorise_tanh_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_linspace), (mp_obj_t)&numerical_linspace_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&numerical_sum_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mean), (mp_obj_t)&numerical_mean_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_std), (mp_obj_t)&numerical_std_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_min), (mp_obj_t)&numerical_min_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&numerical_max_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_argmin), (mp_obj_t)&numerical_argmin_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_argmax), (mp_obj_t)&numerical_argmax_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_roll), (mp_obj_t)&numerical_roll_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flip), (mp_obj_t)&numerical_flip_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_diff), (mp_obj_t)&numerical_diff_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sort), (mp_obj_t)&numerical_sort_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_argsort), (mp_obj_t)&numerical_argsort_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_polyval), (mp_obj_t)&poly_polyval_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_polyfit), (mp_obj_t)&poly_polyfit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_fft), (mp_obj_t)&fft_fft_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifft), (mp_obj_t)&fft_ifft_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_spectrum), (mp_obj_t)&fft_spectrum_obj },
// class constants
{ MP_ROM_QSTR(MP_QSTR_uint8), MP_ROM_INT(NDARRAY_UINT8) },
{ MP_ROM_QSTR(MP_QSTR_int8), MP_ROM_INT(NDARRAY_INT8) },
{ 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_float), MP_ROM_INT(NDARRAY_FLOAT) },
};
STATIC MP_DEFINE_CONST_DICT (
mp_module_ulab_globals,
ulab_globals_table
);
const mp_obj_module_t ulab_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_ulab_globals,
};
MP_REGISTER_MODULE(MP_QSTR_ulab, ulab_user_cmodule, MODULE_ULAB_ENABLED);

8
code/__init__.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ULAB___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_ULAB___INIT___H
#include "py/obj.h"
// Nothing now.
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ULAB___INIT___H

13
code/compat.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef MICROPY_INCLUDED_ULAB_COMPAT_H
#define MICROPY_INCLUDED_ULAB_COMPAT_H
#pragma GCC diagnostic ignored "-Wshadow"
#define mp_obj_is_type(obj, type) MP_OBJ_IS_TYPE(obj, type)
#define MP_ROM_NONE (MP_ROM_PTR(&mp_const_none_obj))
#define MP_ROM_FALSE (mp_const_false)
#define MP_ROM_TRUE (mp_const_true)
#endif // MICROPY_INCLUDED_ULAB_COMPAT_H

View file

@ -16,6 +16,7 @@
#include "py/binary.h"
#include "py/obj.h"
#include "py/objarray.h"
#include "compat.h"
#include "ndarray.h"
#include "fft.h"
@ -75,19 +76,19 @@ void fft_kernel(mp_float_t *real, mp_float_t *imag, int n, int isign) {
}
mp_obj_t fft_fft_ifft_spectrum(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_im, uint8_t type) {
if(!mp_obj_is_type(arg_re, &ulab_ndarray_type)) {
mp_raise_NotImplementedError("FFT is defined for ndarrays only");
if(!MP_OBJ_IS_TYPE(arg_re, &ulab_ndarray_type)) {
mp_raise_NotImplementedError(translate("FFT is defined for ndarrays only"));
}
if(n_args == 2) {
if(!mp_obj_is_type(arg_im, &ulab_ndarray_type)) {
mp_raise_NotImplementedError("FFT is defined for ndarrays only");
if(!MP_OBJ_IS_TYPE(arg_im, &ulab_ndarray_type)) {
mp_raise_NotImplementedError(translate("FFT is defined for ndarrays only"));
}
}
// Check if input is of length of power of 2
ndarray_obj_t *re = MP_OBJ_TO_PTR(arg_re);
uint16_t len = re->array->len;
if((len & (len-1)) != 0) {
mp_raise_ValueError("input array length must be power of 2");
mp_raise_ValueError(translate("input array length must be power of 2"));
}
ndarray_obj_t *out_re = create_new_ndarray(1, len, NDARRAY_FLOAT);
@ -108,7 +109,7 @@ mp_obj_t fft_fft_ifft_spectrum(size_t n_args, mp_obj_t arg_re, mp_obj_t arg_im,
if(n_args == 2) {
ndarray_obj_t *im = MP_OBJ_TO_PTR(arg_im);
if (re->array->len != im->array->len) {
mp_raise_ValueError("real and imaginary parts must be of equal length");
mp_raise_ValueError(translate("real and imaginary parts must be of equal length"));
}
if(im->array->typecode == NDARRAY_FLOAT) {
memcpy((mp_float_t *)out_im->array->items, (mp_float_t *)im->array->items, im->bytes);

View file

@ -13,6 +13,7 @@
#include <string.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "compat.h"
#include "filter.h"
mp_obj_t filter_convolve(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@ -25,7 +26,7 @@ mp_obj_t filter_convolve(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
mp_arg_parse_all(2, 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_obj_is_type(args[1].u_obj, &ulab_ndarray_type)) {
mp_raise_TypeError("convolve arguments must be ndarrays");
mp_raise_TypeError(translate("convolve arguments must be ndarrays"));
}
ndarray_obj_t *a = MP_OBJ_TO_PTR(args[0].u_obj);
@ -33,7 +34,7 @@ mp_obj_t filter_convolve(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
int len_a = a->array->len;
int len_c = c->array->len;
if(len_a == 0 || len_c == 0) {
mp_raise_TypeError("convolve arguments must not be empty");
mp_raise_TypeError(translate("convolve arguments must not be empty"));
}
int len = len_a + len_c - 1; // convolve mode "full"

View file

@ -14,6 +14,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "py/misc.h"
#include "compat.h"
#include "linalg.h"
mp_obj_t linalg_transpose(mp_obj_t self_in) {
@ -50,8 +51,8 @@ mp_obj_t linalg_transpose(mp_obj_t self_in) {
mp_obj_t linalg_reshape(mp_obj_t self_in, mp_obj_t shape) {
ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in);
if(!mp_obj_is_type(shape, &mp_type_tuple) || (MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(shape)) != 2)) {
mp_raise_ValueError("shape must be a 2-tuple");
if(!MP_OBJ_IS_TYPE(shape, &mp_type_tuple) || (MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(shape)) != 2)) {
mp_raise_ValueError(translate("shape must be a 2-tuple"));
}
mp_obj_iter_buf_t iter_buf;
@ -63,7 +64,7 @@ mp_obj_t linalg_reshape(mp_obj_t self_in, mp_obj_t shape) {
n = mp_obj_get_int(item);
if(m*n != self->m*self->n) {
// TODO: the proper error message would be "cannot reshape array of size %d into shape (%d, %d)"
mp_raise_ValueError("cannot reshape array (incompatible input/output shape)");
mp_raise_ValueError(translate("cannot reshape array (incompatible input/output shape)"));
}
self->m = m;
self->n = n;
@ -79,13 +80,13 @@ mp_obj_t linalg_size(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(1, 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("size is defined for ndarrays only");
if(!MP_OBJ_IS_TYPE(args[0].u_obj, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("size is defined for ndarrays only"));
} else {
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj);
if(args[1].u_obj == mp_const_none) {
return mp_obj_new_int(ndarray->array->len);
} else if(mp_obj_is_int(args[1].u_obj)) {
} else if(MP_OBJ_IS_INT(args[1].u_obj)) {
uint8_t ax = mp_obj_get_int(args[1].u_obj);
if(ax == 0) {
if(ndarray->m == 1) {
@ -95,15 +96,15 @@ mp_obj_t linalg_size(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
}
} else if(ax == 1) {
if(ndarray->m == 1) {
mp_raise_ValueError("tuple index out of range");
mp_raise_ValueError(translate("tuple index out of range"));
} else {
return mp_obj_new_int(ndarray->n);
}
} else {
mp_raise_ValueError("tuple index out of range");
mp_raise_ValueError(translate("tuple index out of range"));
}
} else {
mp_raise_TypeError("wrong argument type");
mp_raise_TypeError(translate("wrong argument type"));
}
}
}
@ -152,15 +153,15 @@ bool linalg_invert_matrix(mp_float_t *data, size_t N) {
mp_obj_t linalg_inv(mp_obj_t o_in) {
// since inv is not a class method, we have to inspect the input argument first
if(!mp_obj_is_type(o_in, &ulab_ndarray_type)) {
mp_raise_TypeError("only ndarrays can be inverted");
if(!MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("only ndarrays can be inverted"));
}
ndarray_obj_t *o = MP_OBJ_TO_PTR(o_in);
if(!mp_obj_is_type(o_in, &ulab_ndarray_type)) {
mp_raise_TypeError("only ndarray objects can be inverted");
if(!MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("only ndarray objects can be inverted"));
}
if(o->m != o->n) {
mp_raise_ValueError("only square matrices can be inverted");
mp_raise_ValueError(translate("only square matrices can be inverted"));
}
ndarray_obj_t *inverted = create_new_ndarray(o->m, o->n, NDARRAY_FLOAT);
mp_float_t *data = (mp_float_t *)inverted->array->items;
@ -178,7 +179,7 @@ mp_obj_t linalg_inv(mp_obj_t o_in) {
// TODO: I am not sure this is needed here. Otherwise,
// how should we free up the unused RAM of inverted?
m_del(mp_float_t, inverted->array->items, o->n*o->n);
mp_raise_ValueError("input matrix is singular");
mp_raise_ValueError(translate("input matrix is singular"));
}
return MP_OBJ_FROM_PTR(inverted);
}
@ -188,7 +189,7 @@ mp_obj_t linalg_dot(mp_obj_t _m1, mp_obj_t _m2) {
ndarray_obj_t *m1 = MP_OBJ_TO_PTR(_m1);
ndarray_obj_t *m2 = MP_OBJ_TO_PTR(_m2);
if(m1->n != m2->m) {
mp_raise_ValueError("matrix dimensions do not match");
mp_raise_ValueError(translate("matrix dimensions do not match"));
}
// TODO: numpy uses upcasting here
ndarray_obj_t *out = create_new_ndarray(m1->m, m2->n, NDARRAY_FLOAT);
@ -219,17 +220,17 @@ mp_obj_t linalg_zeros_ones(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
uint8_t dtype = args[1].u_int;
if(!mp_obj_is_int(args[0].u_obj) && !mp_obj_is_type(args[0].u_obj, &mp_type_tuple)) {
mp_raise_TypeError("input argument must be an integer or a 2-tuple");
if(!MP_OBJ_IS_INT(args[0].u_obj) && !MP_OBJ_IS_TYPE(args[0].u_obj, &mp_type_tuple)) {
mp_raise_TypeError(translate("input argument must be an integer or a 2-tuple"));
}
ndarray_obj_t *ndarray = NULL;
if(mp_obj_is_int(args[0].u_obj)) {
if(MP_OBJ_IS_INT(args[0].u_obj)) {
size_t n = mp_obj_get_int(args[0].u_obj);
ndarray = create_new_ndarray(1, n, dtype);
} else if(mp_obj_is_type(args[0].u_obj, &mp_type_tuple)) {
} else if(MP_OBJ_IS_TYPE(args[0].u_obj, &mp_type_tuple)) {
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(args[0].u_obj);
if(tuple->len != 2) {
mp_raise_TypeError("input argument must be an integer or a 2-tuple");
mp_raise_TypeError(translate("input argument must be an integer or a 2-tuple"));
}
ndarray = create_new_ndarray(mp_obj_get_int(tuple->items[0]),
mp_obj_get_int(tuple->items[1]), dtype);
@ -274,16 +275,16 @@ mp_obj_t linalg_eye(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
ndarray_obj_t *ndarray = create_new_ndarray(m, n, dtype);
mp_obj_t one = mp_obj_new_int(1);
size_t i = 0;
if((k >= 0) && (k < n)) {
while(k < n) {
if((k >= 0) && (abs(k) < n)) {
while(abs(k) < n) {
mp_binary_set_val_array(dtype, ndarray->array->items, i*n+k, one);
k++;
i++;
}
} else if((k < 0) && (-k < m)) {
} else if((k < 0) && (abs(k) < m)) {
k = -k;
i = 0;
while(k < m) {
while(abs(k) < m) {
mp_binary_set_val_array(dtype, ndarray->array->items, k*n+i, one);
k++;
i++;
@ -293,12 +294,12 @@ mp_obj_t linalg_eye(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
}
mp_obj_t linalg_det(mp_obj_t oin) {
if(!mp_obj_is_type(oin, &ulab_ndarray_type)) {
mp_raise_TypeError("function defined for ndarrays only");
if(!MP_OBJ_IS_TYPE(oin, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("function defined for ndarrays only"));
}
ndarray_obj_t *in = MP_OBJ_TO_PTR(oin);
if(in->m != in->n) {
mp_raise_ValueError("input must be square matrix");
mp_raise_ValueError(translate("input must be square matrix"));
}
mp_float_t *tmp = m_new(mp_float_t, in->n*in->n);
@ -330,12 +331,12 @@ mp_obj_t linalg_det(mp_obj_t oin) {
}
mp_obj_t linalg_eig(mp_obj_t oin) {
if(!mp_obj_is_type(oin, &ulab_ndarray_type)) {
mp_raise_TypeError("function defined for ndarrays only");
if(!MP_OBJ_IS_TYPE(oin, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("function defined for ndarrays only"));
}
ndarray_obj_t *in = MP_OBJ_TO_PTR(oin);
if(in->m != in->n) {
mp_raise_ValueError("input must be square matrix");
mp_raise_ValueError(translate("input must be square matrix"));
}
mp_float_t *array = m_new(mp_float_t, in->array->len);
for(size_t i=0; i < in->array->len; i++) {
@ -347,7 +348,7 @@ mp_obj_t linalg_eig(mp_obj_t oin) {
// compare entry (m, n) to (n, m)
// TODO: this must probably be scaled!
if(epsilon < MICROPY_FLOAT_C_FUN(fabs)(array[m*in->n + n] - array[n*in->n + m])) {
mp_raise_ValueError("input matrix is asymmetric");
mp_raise_ValueError(translate("input matrix is asymmetric"));
}
}
}
@ -440,7 +441,7 @@ mp_obj_t linalg_eig(mp_obj_t oin) {
if(iterations == 0) {
// the computation did not converge; numpy raises LinAlgError
m_del(mp_float_t, array, in->array->len);
mp_raise_ValueError("iterations did not converge");
mp_raise_ValueError(translate("iterations did not converge")) ;
}
ndarray_obj_t *eigenvalues = create_new_ndarray(1, in->n, NDARRAY_FLOAT);
mp_float_t *eigvalues = (mp_float_t *)eigenvalues->array->items;

View file

@ -16,6 +16,7 @@
#include "py/binary.h"
#include "py/obj.h"
#include "py/objtuple.h"
#include "compat.h"
#include "ndarray.h"
// This function is copied verbatim from objarray.c
@ -63,16 +64,15 @@ void fill_array_iterable(mp_float_t *array, mp_obj_t iterable) {
void ndarray_print_row(const mp_print_t *print, mp_obj_array_t *data, size_t n0, size_t n) {
mp_print_str(print, "[");
size_t i;
if(n < PRINT_MAX) { // if the array is short, print everything
mp_obj_print_helper(print, mp_binary_get_val_array(data->typecode, data->items, n0), PRINT_REPR);
for(i=1; i<n; i++) {
for(size_t i=1; i<n; i++) {
mp_print_str(print, ", ");
mp_obj_print_helper(print, mp_binary_get_val_array(data->typecode, data->items, n0+i), PRINT_REPR);
}
} else {
mp_obj_print_helper(print, mp_binary_get_val_array(data->typecode, data->items, n0), PRINT_REPR);
for(i=1; i<3; i++) {
for(size_t i=1; i<3; i++) {
mp_print_str(print, ", ");
mp_obj_print_helper(print, mp_binary_get_val_array(data->typecode, data->items, n0+i), PRINT_REPR);
}
@ -164,16 +164,19 @@ STATIC uint8_t ndarray_init_helper(size_t n_args, const mp_obj_t *pos_args, mp_m
return dtype;
}
mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 2, true);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
uint8_t dtype = ndarray_init_helper(n_args, args, &kw_args);
mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 1, 2, true);
size_t n_kw = 0;
if (kw_args != 0) {
n_kw = kw_args->used;
}
mp_map_init_fixed_table(kw_args, n_kw, args + n_args);
uint8_t dtype = ndarray_init_helper(n_args, args, kw_args);
size_t len1, len2=0, i=0;
mp_obj_t len_in = mp_obj_len_maybe(args[0]);
if (len_in == MP_OBJ_NULL) {
mp_raise_ValueError("first argument must be an iterable");
mp_raise_ValueError(translate("first argument must be an iterable"));
} else {
// len1 is either the number of rows (for matrices), or the number of elements (row vectors)
len1 = MP_OBJ_SMALL_INT_VALUE(len_in);
@ -188,8 +191,9 @@ mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
if(len_in != MP_OBJ_NULL) { // indeed, this seems to be an iterable
// Next, we have to check, whether all elements in the outer loop have the same length
if(i > 0) {
if(len2 != MP_OBJ_SMALL_INT_VALUE(len_in)) {
mp_raise_ValueError("iterables are not of the same length");
size_t temp = abs(MP_OBJ_SMALL_INT_VALUE(len_in));
if(len2 != temp) {
mp_raise_ValueError(translate("iterables are not of the same length"));
}
}
len2 = MP_OBJ_SMALL_INT_VALUE(len_in);
@ -231,7 +235,7 @@ size_t true_length(mp_obj_t bool_list) {
mp_obj_t item, iterable = mp_getiter(bool_list, &iter_buf);
size_t trues = 0;
while((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if(!mp_obj_is_type(item, &mp_type_bool)) {
if(!MP_OBJ_IS_TYPE(item, &mp_type_bool)) {
// numpy seems to be a little bit inconsistent in when an index is considered
// to be True/False. Bail out immediately, if the items are not True/False
return 0;
@ -248,19 +252,19 @@ mp_bound_slice_t generate_slice(mp_uint_t n, mp_obj_t index) {
mp_bound_slice_t slice;
if(mp_obj_is_type(index, &mp_type_slice)) {
mp_seq_get_fast_slice_indexes(n, index, &slice);
} else if(mp_obj_is_int(index)) {
int32_t _index = mp_obj_get_int(index);
} else if(MP_OBJ_IS_INT(index)) {
uint32_t _index = mp_obj_get_int(index);
if(_index < 0) {
_index += n;
}
if((_index >= n) || (_index < 0)) {
mp_raise_msg(&mp_type_IndexError, "index is out of bounds");
mp_raise_msg(&mp_type_IndexError, translate("index is out of bounds"));
}
slice.start = _index;
slice.stop = _index + 1;
slice.step = 1;
} else {
mp_raise_msg(&mp_type_IndexError, "indices must be integers, slices, or Boolean lists");
mp_raise_msg(&mp_type_IndexError, translate("indices must be integers, slices, or Boolean lists"));
}
return slice;
}
@ -290,7 +294,7 @@ mp_obj_t insert_slice_list(ndarray_obj_t *ndarray, size_t m, size_t n,
ndarray_obj_t *values) {
if((m != values->m) && (n != values->n)) {
if((values->array->len != 1)) { // not a single item
mp_raise_ValueError("could not broadast input array from shape");
mp_raise_ValueError(translate("could not broadast input array from shape"));
}
}
size_t cindex, rindex;
@ -352,7 +356,8 @@ mp_obj_t insert_slice_list(ndarray_obj_t *ndarray, size_t m, size_t n,
} else { // columns are indexed by a list
mp_obj_iter_buf_t column_iter_buf;
mp_obj_t column_item, column_iterable;
size_t j = 0, cindex = 0;
size_t j = 0;
cindex = 0;
while((row_item = mp_iternext(row_iterable)) != MP_OBJ_STOP_ITERATION) {
if(mp_obj_is_true(row_item)) {
column_iterable = mp_getiter(column_list, &column_iter_buf);
@ -377,7 +382,7 @@ mp_obj_t iterate_slice_list(ndarray_obj_t *ndarray, size_t m, size_t n,
mp_obj_t row_list, mp_obj_t column_list,
ndarray_obj_t *values) {
if((m == 0) || (n == 0)) {
mp_raise_msg(&mp_type_IndexError, "empty index range");
mp_raise_msg(&mp_type_IndexError, translate("empty index range"));
}
if(values != NULL) {
@ -438,7 +443,8 @@ mp_obj_t iterate_slice_list(ndarray_obj_t *ndarray, size_t m, size_t n,
} else { // columns are indexed by a list
mp_obj_iter_buf_t column_iter_buf;
mp_obj_t column_item, column_iterable;
size_t j = 0, cindex = 0;
size_t j = 0;
cindex = 0;
while((row_item = mp_iternext(row_iterable)) != MP_OBJ_STOP_ITERATION) {
if(mp_obj_is_true(row_item)) {
column_iterable = mp_getiter(column_list, &column_iter_buf);
@ -462,7 +468,7 @@ mp_obj_t ndarray_get_slice(ndarray_obj_t *ndarray, mp_obj_t index, ndarray_obj_t
mp_bound_slice_t row_slice = simple_slice(0, 0, 1), column_slice = simple_slice(0, 0, 1);
size_t m = 0, n = 0;
if(mp_obj_is_int(index) && (ndarray->m == 1) && (values == NULL)) {
if(MP_OBJ_IS_INT(index) && (ndarray->m == 1) && (values == NULL)) {
// we have a row vector, and don't want to assign
column_slice = generate_slice(ndarray->n, index);
if(slice_length(column_slice) == 1) { // we were asked for a single item
@ -471,7 +477,7 @@ mp_obj_t ndarray_get_slice(ndarray_obj_t *ndarray, mp_obj_t index, ndarray_obj_t
}
}
if(mp_obj_is_int(index) || mp_obj_is_type(index, &mp_type_slice)) {
if(MP_OBJ_IS_INT(index) || MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
if(ndarray->m == 1) { // we have a row vector
column_slice = generate_slice(ndarray->n, index);
row_slice = simple_slice(0, 1, 1);
@ -495,15 +501,15 @@ mp_obj_t ndarray_get_slice(ndarray_obj_t *ndarray, mp_obj_t index, ndarray_obj_t
else { // we certainly have a tuple, so let us deal with it
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(index);
if(tuple->len != 2) {
mp_raise_msg(&mp_type_IndexError, "too many indices");
mp_raise_msg(&mp_type_IndexError, translate("too many indices"));
}
if(!(mp_obj_is_type(tuple->items[0], &mp_type_list) ||
mp_obj_is_type(tuple->items[0], &mp_type_slice) ||
mp_obj_is_int(tuple->items[0])) ||
!(mp_obj_is_type(tuple->items[1], &mp_type_list) ||
mp_obj_is_type(tuple->items[1], &mp_type_slice) ||
mp_obj_is_int(tuple->items[1]))) {
mp_raise_msg(&mp_type_IndexError, "indices must be integers, slices, or Boolean lists");
if(!(MP_OBJ_IS_TYPE(tuple->items[0], &mp_type_list) ||
MP_OBJ_IS_TYPE(tuple->items[0], &mp_type_slice) ||
MP_OBJ_IS_INT(tuple->items[0])) ||
!(MP_OBJ_IS_TYPE(tuple->items[1], &mp_type_list) ||
MP_OBJ_IS_TYPE(tuple->items[1], &mp_type_slice) ||
MP_OBJ_IS_INT(tuple->items[1]))) {
mp_raise_msg(&mp_type_IndexError, translate("indices must be integers, slices, or Boolean lists"));
}
if(mp_obj_is_type(tuple->items[0], &mp_type_list)) { // rows are indexed by Boolean list
m = true_length(tuple->items[0]);
@ -542,12 +548,12 @@ mp_obj_t ndarray_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (value == MP_OBJ_SENTINEL) { // return value(s)
return ndarray_get_slice(self, index, NULL);
} else { // assignment to slices; the value must be an ndarray, or a scalar
if(!mp_obj_is_type(value, &ulab_ndarray_type) &&
!mp_obj_is_int(value) && !mp_obj_is_float(value)) {
mp_raise_ValueError("right hand side must be an ndarray, or a scalar");
if(!MP_OBJ_IS_TYPE(value, &ulab_ndarray_type) &&
!MP_OBJ_IS_INT(value) && !mp_obj_is_float(value)) {
mp_raise_ValueError(translate("right hand side must be an ndarray, or a scalar"));
} else {
ndarray_obj_t *values = NULL;
if(mp_obj_is_int(value)) {
if(MP_OBJ_IS_INT(value)) {
values = create_new_ndarray(1, 1, self->array->typecode);
mp_binary_set_val_array(values->array->typecode, values->array->items, 0, value);
} else if(mp_obj_is_float(value)) {
@ -655,7 +661,7 @@ mp_obj_t ndarray_flatten(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
GET_STR_DATA_LEN(args[0].u_obj, order, len);
if((len != 1) || ((memcmp(order, "C", 1) != 0) && (memcmp(order, "F", 1) != 0))) {
mp_raise_ValueError("flattening order must be either 'C', or 'F'");
mp_raise_ValueError(translate("flattening order must be either 'C', or 'F'"));
}
// if order == 'C', we simply have to set m, and n, there is nothing else to do
@ -694,7 +700,7 @@ mp_obj_t ndarray_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
// TODO: implement in-place operators
mp_obj_t RHS = MP_OBJ_NULL;
bool rhs_is_scalar = true;
if(mp_obj_is_int(rhs)) {
if(MP_OBJ_IS_INT(rhs)) {
int32_t ivalue = mp_obj_get_int(rhs);
if((ivalue > 0) && (ivalue < 256)) {
CREATE_SINGLE_ITEM(RHS, uint8_t, NDARRAY_UINT8, ivalue);
@ -715,12 +721,12 @@ mp_obj_t ndarray_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
rhs_is_scalar = false;
}
//else
if(mp_obj_is_type(lhs, &ulab_ndarray_type) && mp_obj_is_type(RHS, &ulab_ndarray_type)) {
if(MP_OBJ_IS_TYPE(lhs, &ulab_ndarray_type) && MP_OBJ_IS_TYPE(RHS, &ulab_ndarray_type)) {
// next, the ndarray stuff
ndarray_obj_t *ol = MP_OBJ_TO_PTR(lhs);
ndarray_obj_t *or = MP_OBJ_TO_PTR(RHS);
if(!rhs_is_scalar && ((ol->m != or->m) || (ol->n != or->n))) {
mp_raise_ValueError("operands could not be broadcast together");
mp_raise_ValueError(translate("operands could not be broadcast together"));
}
// At this point, the operands should have the same shape
switch(op) {
@ -823,7 +829,7 @@ mp_obj_t ndarray_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
RUN_BINARY_LOOP(NDARRAY_FLOAT, mp_float_t, mp_float_t, mp_float_t, ol, or, op);
}
} else { // this should never happen
mp_raise_TypeError("wrong input type");
mp_raise_TypeError(translate("wrong input type"));
}
// this instruction should never be reached, but we have to make the compiler happy
return MP_OBJ_NULL;
@ -831,13 +837,18 @@ mp_obj_t ndarray_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
return MP_OBJ_NULL; // op not supported
}
} else {
mp_raise_TypeError("wrong operand type on the right hand side");
mp_raise_TypeError(translate("wrong operand type on the right hand side"));
}
}
mp_obj_t ndarray_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in);
ndarray_obj_t *ndarray = NULL;
uint8_t *array8u;
int8_t *array8i;
uint16_t *array16u;
int16_t *array16i;
mp_float_t *arraymp;
switch (op) {
case MP_UNARY_OP_LEN:
if(self->m > 1) {
@ -849,33 +860,33 @@ mp_obj_t ndarray_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
case MP_UNARY_OP_INVERT:
if(self->array->typecode == NDARRAY_FLOAT) {
mp_raise_ValueError("operation is not supported for given type");
mp_raise_ValueError(translate("operation is not supported for given type"));
}
// we can invert the content byte by byte, there is no need to distinguish
// between different typecodes
ndarray = MP_OBJ_TO_PTR(ndarray_copy(self_in));
uint8_t *array = (uint8_t *)ndarray->array->items;
for(size_t i=0; i < self->bytes; i++) array[i] = ~array[i];
array8u = (uint8_t *)ndarray->array->items;
for(size_t i=0; i < self->bytes; i++) array8u[i] = ~array8u[i];
return MP_OBJ_FROM_PTR(ndarray);
break;
case MP_UNARY_OP_NEGATIVE:
ndarray = MP_OBJ_TO_PTR(ndarray_copy(self_in));
if(self->array->typecode == NDARRAY_UINT8) {
uint8_t *array = (uint8_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array[i] = -array[i];
array8u = (uint8_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array8u[i] = -array8u[i];
} else if(self->array->typecode == NDARRAY_INT8) {
int8_t *array = (int8_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array[i] = -array[i];
array8i = (int8_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array8i[i] = -array8i[i];
} else if(self->array->typecode == NDARRAY_UINT16) {
uint16_t *array = (uint16_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array[i] = -array[i];
array16u = (uint16_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array16u[i] = -array16u[i];
} else if(self->array->typecode == NDARRAY_INT16) {
int16_t *array = (int16_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array[i] = -array[i];
array16i = (int16_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array16i[i] = -array16i[i];
} else {
mp_float_t *array = (mp_float_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) array[i] = -array[i];
arraymp = (mp_float_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) arraymp[i] = -arraymp[i];
}
return MP_OBJ_FROM_PTR(ndarray);
break;
@ -888,20 +899,20 @@ mp_obj_t ndarray_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
return ndarray_copy(self_in);
}
ndarray = MP_OBJ_TO_PTR(ndarray_copy(self_in));
if((self->array->typecode == NDARRAY_INT8)) {
int8_t *array = (int8_t *)ndarray->array->items;
if(self->array->typecode == NDARRAY_INT8) {
array8i = (int8_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) {
if(array[i] < 0) array[i] = -array[i];
if(array8i[i] < 0) array8i[i] = -array8i[i];
}
} else if((self->array->typecode == NDARRAY_INT16)) {
int16_t *array = (int16_t *)ndarray->array->items;
} else if(self->array->typecode == NDARRAY_INT16) {
array16i = (int16_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) {
if(array[i] < 0) array[i] = -array[i];
if(array16i[i] < 0) array16i[i] = -array16i[i];
}
} else {
mp_float_t *array = (mp_float_t *)ndarray->array->items;
arraymp = (mp_float_t *)ndarray->array->items;
for(size_t i=0; i < self->array->len; i++) {
if(array[i] < 0) array[i] = -array[i];
if(arraymp[i] < 0) arraymp[i] = -arraymp[i];
}
}
return MP_OBJ_FROM_PTR(ndarray);

View file

@ -24,7 +24,7 @@
#define FLOAT_TYPECODE 'd'
#endif
extern const mp_obj_type_t ulab_ndarray_type;
const mp_obj_type_t ulab_ndarray_type;
enum NDARRAY_TYPE {
NDARRAY_UINT8 = 'B',
@ -53,7 +53,7 @@ void ndarray_assign_elements(mp_obj_array_t *, mp_obj_t , uint8_t , size_t *);
ndarray_obj_t *create_new_ndarray(size_t , size_t , uint8_t );
mp_obj_t ndarray_copy(mp_obj_t );
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, const mp_obj_t *, mp_map_t *);
mp_obj_t ndarray_subscr(mp_obj_t , mp_obj_t , mp_obj_t );
mp_obj_t ndarray_getiter(mp_obj_t , mp_obj_iter_buf_t *);
mp_obj_t ndarray_binary_op(mp_binary_op_t , mp_obj_t , mp_obj_t );

View file

@ -16,6 +16,7 @@
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/misc.h"
#include "compat.h"
#include "numerical.h"
enum NUMERICAL_FUNCTION_TYPE {
@ -43,7 +44,7 @@ mp_obj_t numerical_linspace(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
uint16_t len = args[2].u_int;
if(len < 2) {
mp_raise_ValueError("number of points must be at least 2");
mp_raise_ValueError(translate("number of points must be at least 2"));
}
mp_float_t value, step;
value = mp_obj_get_float(args[0].u_obj);
@ -167,7 +168,7 @@ mp_obj_t numerical_std_ndarray(ndarray_obj_t *ndarray, mp_obj_t axis, size_t ddo
axis_sorter(ndarray, axis, &m, &n, &N, &increment, &len, &start_inc);
if(ddof > len) {
mp_raise_ValueError("ddof must be smaller than length of data set");
mp_raise_ValueError(translate("ddof must be smaller than length of data set"));
}
ndarray_obj_t *results = create_new_ndarray(m, n, NDARRAY_FLOAT);
mp_float_t *farray = (mp_float_t *)results->array->items;
@ -263,7 +264,7 @@ STATIC mp_obj_t numerical_function(size_t n_args, const mp_obj_t *pos_args, mp_m
mp_obj_t axis = args[1].u_obj;
if((axis != mp_const_none) && (mp_obj_get_int(axis) != 0) && (mp_obj_get_int(axis) != 1)) {
// this seems to pass with False, and True...
mp_raise_ValueError("axis must be None, 0, or 1");
mp_raise_ValueError(translate("axis must be None, 0, or 1"));
}
if(MP_OBJ_IS_TYPE(oin, &mp_type_tuple) || MP_OBJ_IS_TYPE(oin, &mp_type_list) ||
@ -292,10 +293,10 @@ STATIC mp_obj_t numerical_function(size_t n_args, const mp_obj_t *pos_args, mp_m
case NUMERICAL_MEAN:
return numerical_sum_mean_ndarray(ndarray, axis, optype);
default:
mp_raise_NotImplementedError("operation is not implemented on ndarrays");
mp_raise_NotImplementedError(translate("operation is not implemented on ndarrays"));
}
} else {
mp_raise_TypeError("input must be tuple, list, range, or ndarray");
mp_raise_TypeError(translate("input must be tuple, list, range, or ndarray"));
}
return mp_const_none;
}
@ -339,7 +340,7 @@ mp_obj_t numerical_std(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
size_t ddof = args[2].u_int;
if((axis != mp_const_none) && (mp_obj_get_int(axis) != 0) && (mp_obj_get_int(axis) != 1)) {
// this seems to pass with False, and True...
mp_raise_ValueError("axis must be None, 0, or 1");
mp_raise_ValueError(translate("axis must be None, 0, or 1"));
}
if(MP_OBJ_IS_TYPE(oin, &mp_type_tuple) || MP_OBJ_IS_TYPE(oin, &mp_type_list) || MP_OBJ_IS_TYPE(oin, &mp_type_range)) {
return numerical_sum_mean_std_iterable(oin, NUMERICAL_STD, ddof);
@ -347,7 +348,7 @@ mp_obj_t numerical_std(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(oin);
return numerical_std_ndarray(ndarray, axis, ddof);
} else {
mp_raise_TypeError("input must be tuple, list, range, or ndarray");
mp_raise_TypeError(translate("input must be tuple, list, range, or ndarray"));
}
return mp_const_none;
}
@ -367,7 +368,7 @@ mp_obj_t numerical_roll(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
if((args[2].u_obj != mp_const_none) &&
(mp_obj_get_int(args[2].u_obj) != 0) &&
(mp_obj_get_int(args[2].u_obj) != 1)) {
mp_raise_ValueError("axis must be None, 0, or 1");
mp_raise_ValueError(translate("axis must be None, 0, or 1"));
}
ndarray_obj_t *in = MP_OBJ_TO_PTR(oin);
@ -442,12 +443,12 @@ mp_obj_t numerical_flip(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
mp_arg_parse_all(1, 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("flip argument must be an ndarray");
mp_raise_TypeError(translate("flip argument must be an ndarray"));
}
if((args[1].u_obj != mp_const_none) &&
(mp_obj_get_int(args[1].u_obj) != 0) &&
(mp_obj_get_int(args[1].u_obj) != 1)) {
mp_raise_ValueError("axis must be None, 0, or 1");
mp_raise_ValueError(translate("axis must be None, 0, or 1"));
}
ndarray_obj_t *in = MP_OBJ_TO_PTR(args[0].u_obj);
@ -490,7 +491,7 @@ mp_obj_t numerical_diff(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
mp_arg_parse_all(1, 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("diff argument must be an ndarray");
mp_raise_TypeError(translate("diff argument must be an ndarray"));
}
ndarray_obj_t *in = MP_OBJ_TO_PTR(args[0].u_obj);
@ -500,10 +501,10 @@ mp_obj_t numerical_diff(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
} else if(args[2].u_int == 0) { // differtiate along vertical axis
increment = in->n;
} else {
mp_raise_ValueError("axis must be -1, 0, or 1");
mp_raise_ValueError(translate("axis must be -1, 0, or 1"));
}
if((args[1].u_int < 0) || (args[1].u_int > 9)) {
mp_raise_ValueError("n must be between 0, and 9");
mp_raise_ValueError(translate("n must be between 0, and 9"));
}
uint8_t n = args[1].u_int;
int8_t *stencil = m_new(int8_t, n+1);
@ -549,7 +550,7 @@ mp_obj_t numerical_diff(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
mp_obj_t numerical_sort_helper(mp_obj_t oin, mp_obj_t axis, uint8_t inplace) {
if(!mp_obj_is_type(oin, &ulab_ndarray_type)) {
mp_raise_TypeError("sort argument must be an ndarray");
mp_raise_TypeError(translate("sort argument must be an ndarray"));
}
ndarray_obj_t *ndarray;
@ -580,7 +581,7 @@ mp_obj_t numerical_sort_helper(mp_obj_t oin, mp_obj_t axis, uint8_t inplace) {
end = ndarray->m;
N = ndarray->m;
} else {
mp_raise_ValueError("axis must be -1, 0, None, or 1");
mp_raise_ValueError(translate("axis must be -1, 0, None, or 1"));
}
size_t q, k, p, c;
@ -636,7 +637,7 @@ mp_obj_t numerical_argsort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(1, 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("argsort argument must be an ndarray");
mp_raise_TypeError(translate("argsort argument must be an ndarray"));
}
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(args[0].u_obj);
@ -666,7 +667,7 @@ mp_obj_t numerical_argsort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
end = m;
N = m;
} else {
mp_raise_ValueError("axis must be -1, 0, None, or 1");
mp_raise_ValueError(translate("axis must be -1, 0, None, or 1"));
}
// at the expense of flash, we could save RAM by creating

View file

@ -11,23 +11,24 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "py/objarray.h"
#include "compat.h"
#include "ndarray.h"
#include "linalg.h"
#include "poly.h"
bool object_is_nditerable(mp_obj_t o_in) {
if(mp_obj_is_type(o_in, &ulab_ndarray_type) ||
mp_obj_is_type(o_in, &mp_type_tuple) ||
mp_obj_is_type(o_in, &mp_type_list) ||
mp_obj_is_type(o_in, &mp_type_range)) {
if(MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type) ||
MP_OBJ_IS_TYPE(o_in, &mp_type_tuple) ||
MP_OBJ_IS_TYPE(o_in, &mp_type_list) ||
MP_OBJ_IS_TYPE(o_in, &mp_type_range)) {
return true;
}
return false;
}
size_t get_nditerable_len(mp_obj_t o_in) {
if(mp_obj_is_type(o_in, &ulab_ndarray_type)) {
if(MP_OBJ_IS_TYPE(o_in, &ulab_ndarray_type)) {
ndarray_obj_t *in = MP_OBJ_TO_PTR(o_in);
return in->array->len;
} else {
@ -84,10 +85,10 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) {
mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) {
if((n_args != 2) && (n_args != 3)) {
mp_raise_ValueError("number of arguments must be 2, or 3");
mp_raise_ValueError(translate("number of arguments must be 2, or 3"));
}
if(!object_is_nditerable(args[0])) {
mp_raise_ValueError("input data must be an iterable");
mp_raise_ValueError(translate("input data must be an iterable"));
}
uint16_t lenx, leny;
uint8_t deg;
@ -99,7 +100,7 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) {
leny = (uint16_t)mp_obj_get_int(mp_obj_len_maybe(args[0]));
deg = (uint8_t)mp_obj_get_int(args[1]);
if(leny < deg) {
mp_raise_ValueError("more degrees of freedom than data points");
mp_raise_ValueError(translate("more degrees of freedom than data points"));
}
lenx = leny;
x = m_new(mp_float_t, lenx); // assume uniformly spaced data points
@ -112,11 +113,11 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) {
lenx = (uint16_t)mp_obj_get_int(mp_obj_len_maybe(args[0]));
leny = (uint16_t)mp_obj_get_int(mp_obj_len_maybe(args[0]));
if(lenx != leny) {
mp_raise_ValueError("input vectors must be of equal length");
mp_raise_ValueError(translate("input vectors must be of equal length"));
}
deg = (uint8_t)mp_obj_get_int(args[2]);
if(leny < deg) {
mp_raise_ValueError("more degrees of freedom than data points");
mp_raise_ValueError(translate("more degrees of freedom than data points"));
}
x = m_new(mp_float_t, lenx);
fill_array_iterable(x, args[0]);
@ -156,7 +157,7 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) {
m_del(mp_float_t, x, lenx);
m_del(mp_float_t, y, lenx);
m_del(mp_float_t, prod, (deg+1)*(deg+1));
mp_raise_ValueError("could not invert Vandermonde matrix");
mp_raise_ValueError(translate("could not invert Vandermonde matrix"));
}
// at this point, we have the inverse of X^T * X
// y is a column vector; x is free now, we can use it for storing intermediate values

View file

@ -17,6 +17,7 @@
#include "py/obj.h"
#include "py/objarray.h"
#include "compat.h"
#include "ndarray.h"
#include "linalg.h"
#include "vectorise.h"

View file

@ -15,6 +15,7 @@
#include "py/binary.h"
#include "py/obj.h"
#include "py/objarray.h"
#include "compat.h"
#include "vectorise.h"
#ifndef MP_PI

View file

@ -1046,10 +1046,6 @@ take the following snippet from the micropython manual:
return result
return new_func
.. parsed-literal::
.. code::
@ -2052,6 +2048,7 @@ spaced numbers between 0, and two pi, and sort them:
print('b: ', b)
sort_time(b)
print('\nb sorted:\n', b)
argsort
-------
@ -3013,11 +3010,10 @@ By combining the two observations above, if you place the first signal,
combined signal, then the Fourier transforms of the two components can
be recovered as
:raw-latex:`\begin{eqnarray}
Y_1(k) &=& \frac{1}{2}\left(Y(k) + Y^*(N-k)\right)
\\
Y_2(k) &=& -\frac{i}{2}\left(Y(k) - Y^*(N-k)\right)
\end{eqnarray}` where :math:`N` is the length of :math:`y_1`, and
| :math:`Y_1(k) = \frac{1}{2}\left(Y(k) + Y^*(N-k)\right)`
| :math:`Y_2(k) = -\frac{i}{2}\left(Y(k) - Y^*(N-k)\right)`
where :math:`N` is the length of :math:`y_1`, and
:math:`Y_1, Y_2`, and :math:`Y`, respectively, are the Fourier
transforms of :math:`y_1, y_2`, and :math:`y = y_1 + iy_2`.