diff options
author | Sayed Adel <seiko@imavr.com> | 2020-09-15 15:04:28 +0200 |
---|---|---|
committer | Sayed Adel <seiko@imavr.com> | 2020-10-27 11:46:58 +0000 |
commit | e19f7a8cfe59226fed6cc7a7da9e881218364d49 (patch) | |
tree | 1322cbaeb5bd1afb599f86d4e7e4efedb57b12ad | |
parent | 92a4693cb0df392003cf99a2f1abe8927cdd58b4 (diff) | |
download | numpy-e19f7a8cfe59226fed6cc7a7da9e881218364d49.tar.gz |
MAINT, TST: use PyArg_ParseTuple() instead of iterate Python tuple directly
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
-rw-r--r-- | numpy/core/src/_simd/_simd.dispatch.c.src | 6 | ||||
-rw-r--r-- | numpy/core/src/_simd/_simd_inc.h.src | 33 | ||||
-rw-r--r-- | numpy/core/src/_simd/_simd_inc_arg.h | 38 | ||||
-rw-r--r-- | numpy/core/src/_simd/_simd_inc_easyintrin.h | 52 |
4 files changed, 61 insertions, 68 deletions
diff --git a/numpy/core/src/_simd/_simd.dispatch.c.src b/numpy/core/src/_simd/_simd.dispatch.c.src index 506ef93f0..a776ba37b 100644 --- a/numpy/core/src/_simd/_simd.dispatch.c.src +++ b/numpy/core/src/_simd/_simd.dispatch.c.src @@ -43,7 +43,11 @@ simd__intrin_@intrin@_@sfx@(PyObject* NPY_UNUSED(self), PyObject *args) {.dtype = simd_data_q@sfx@}, {.dtype = simd_data_v@sfx@}, }; - if (simd_args_from_tuple(args, req_args, 2, "@intrin@_@sfx@")) { + if (!PyArg_ParseTuple( + args, "O&O&:@intrin@_@sfx@", + simd_arg_converter, &req_args[0], + simd_arg_converter, &req_args[1] + )) { return NULL; } npyv_@intrin@_@sfx@( diff --git a/numpy/core/src/_simd/_simd_inc.h.src b/numpy/core/src/_simd/_simd_inc.h.src index 4261ce148..530c7a736 100644 --- a/numpy/core/src/_simd/_simd_inc.h.src +++ b/numpy/core/src/_simd/_simd_inc.h.src @@ -306,7 +306,7 @@ typedef struct { simd_data_type dtype; simd_data data; - // set by simd_args_from_tuple() + // set by simd_arg_converter() PyObject *obj; } simd_arg; /** @@ -365,9 +365,8 @@ simd_arg_from_obj(PyObject *obj, simd_arg *arg); static PyObject * simd_arg_to_obj(const simd_arg *arg); /** - * Similar to simd_arg_from_obj() but convert multiple objects - * from a Python tuple. - * This function is used to parse method parameters. + * Converter function used similar to simd_arg_from_obj() but + * used with PyArg_Parse*(). * * Notes: * - requires `simd_args_sequence_free()` or `simd_sequence_free()` @@ -376,16 +375,26 @@ simd_arg_to_obj(const simd_arg *arg); * types is the number of lanes of the equivalent vector data type. * - use 'arg->obj' to retrieve the parameter obj. * - * Parameters: - * - `tuple_obj`: a valid Python tuple - * - `args`: array of 'simd_arg' contain valid data types - * - `args_len`: length of `args`. - * - `method_name`: method name, required for exception message. - * - * Return -1 and raise Python exception on failure, otherwise return 0. + * Example: + ** simd_arg req_args[] = { + ** {.dtype = simd_data_qf32}, + ** {.dtype = simd_data_vf32}, + ** }; + ** if (!PyArg_ParseTuple( + ** args, "O&O&:add_sum_f32", + ** simd_arg_converter, &req_args[0], + ** simd_arg_converter, &req_args[1] + ** )) { + ** // fail + ** return; + ** } + ** npyv_f32 load_a = npyv_load_f32(req_args[0].data.qf32); + ** npyv_f32 sum = npyv_add_f32(load_a, req_args[1].data.vf32); + ** ... + ** simd_args_sequence_free(req_args, 2); */ static int -simd_args_from_tuple(PyObject *tuple_obj, simd_arg *args, int args_len, const char *method_name); +simd_arg_converter(PyObject *obj, simd_arg *arg); /** * Free the allocated C array for sequence data types. */ diff --git a/numpy/core/src/_simd/_simd_inc_arg.h b/numpy/core/src/_simd/_simd_inc_arg.h index 1db1ff202..eabf49c5f 100644 --- a/numpy/core/src/_simd/_simd_inc_arg.h +++ b/numpy/core/src/_simd/_simd_inc_arg.h @@ -73,36 +73,16 @@ simd_args_sequence_free(simd_arg *args, int args_len) } static int -simd_args_from_tuple(PyObject *tuple_obj, simd_arg *args, int args_len, const char *method_name) +simd_arg_converter(PyObject *obj, simd_arg *arg) { - assert(args_len > 0); - assert(PyTuple_Check(tuple_obj)); - - Py_ssize_t obj_arg_len = PyTuple_GET_SIZE(tuple_obj); - if (obj_arg_len != args_len) { - if (args_len == 1) { - PyErr_Format(PyExc_TypeError, - "%s() takes only one argument (%d given)", method_name, obj_arg_len - ); - return -1; - } - PyErr_Format(PyExc_TypeError, - "%s() takes exactly %d arguments (%d given)", method_name, args_len, obj_arg_len - ); - return -1; - } - for (int arg_pos = 0; arg_pos < args_len; ++arg_pos) { - simd_arg *arg = &args[arg_pos]; - arg->obj = PyTuple_GET_ITEM(tuple_obj, arg_pos); - assert(arg->obj != NULL); - if (simd_arg_from_obj(arg->obj, arg) != 0) { - // free previous args - if (arg_pos > 0) { - simd_args_sequence_free(args, arg_pos); - } - // TODO: improve log by add argument number and method name - return -1; + if (obj != NULL) { + if (simd_arg_from_obj(obj, arg) < 0) { + return 0; } + arg->obj = obj; + return Py_CLEANUP_SUPPORTED; + } else { + simd_args_sequence_free(arg, 1); } - return 0; + return 1; } diff --git a/numpy/core/src/_simd/_simd_inc_easyintrin.h b/numpy/core/src/_simd/_simd_inc_easyintrin.h index 7216b373a..9ff227999 100644 --- a/numpy/core/src/_simd/_simd_inc_easyintrin.h +++ b/numpy/core/src/_simd/_simd_inc_easyintrin.h @@ -50,19 +50,18 @@ static int simd__no_arguments(PyObject *args, const char* method_name) static PyObject *simd__intrin_##NAME \ (PyObject* NPY_UNUSED(self), PyObject *args) \ { \ - simd_arg req_args[] = { \ - {.dtype = simd_data_##IN0}, \ - }; \ - if (simd_args_from_tuple( \ - args, req_args, 1, NPY_TOSTRING(NAME)) \ - ) return NULL; \ + simd_arg arg = {.dtype = simd_data_##IN0}; \ + if (!PyArg_ParseTuple( \ + args, "O&:"NPY_TOSTRING(NAME), \ + simd_arg_converter, &arg \ + )) return NULL; \ simd_data r = {.RET = npyv_##NAME( \ - req_args[0].data.IN0 \ + arg.data.IN0 \ )}; \ - simd_args_sequence_free(req_args, 1); \ - req_args[0].data = r; \ - req_args[0].dtype = simd_data_##RET; \ - return simd_arg_to_obj(req_args); \ + simd_args_sequence_free(&arg, 1); \ + arg.data = r; \ + arg.dtype = simd_data_##RET; \ + return simd_arg_to_obj(&arg); \ } #define SIMD_IMPL_INTRIN_2(NAME, RET, IN0, IN1) \ @@ -73,11 +72,11 @@ static int simd__no_arguments(PyObject *args, const char* method_name) {.dtype = simd_data_##IN0}, \ {.dtype = simd_data_##IN1}, \ }; \ - if (simd_args_from_tuple( \ - args, req_args, 2, NPY_TOSTRING(NAME)) \ - ) { \ - return NULL; \ - } \ + if (!PyArg_ParseTuple( \ + args, "O&O&:"NPY_TOSTRING(NAME), \ + simd_arg_converter, &req_args[0], \ + simd_arg_converter, &req_args[1] \ + )) return NULL; \ simd_data r = {.RET = npyv_##NAME( \ req_args[0].data.IN0, \ req_args[1].data.IN1 \ @@ -99,11 +98,11 @@ static int simd__no_arguments(PyObject *args, const char* method_name) {.dtype = simd_data_##IN0}, \ {.dtype = simd_data_u8}, \ }; \ - if (simd_args_from_tuple( \ - args, req_args, 2, NPY_TOSTRING(NAME)) \ - ) { \ - return NULL; \ - } \ + if (!PyArg_ParseTuple( \ + args, "O&O&:"NPY_TOSTRING(NAME), \ + simd_arg_converter, &req_args[0], \ + simd_arg_converter, &req_args[1] \ + )) return NULL; \ simd_data r; \ r.RET = NPY_CAT(SIMD__IMPL_COUNT_, CONST_RNG)( \ SIMD__REPEAT_2IMM, NAME, IN0 \ @@ -123,11 +122,12 @@ static int simd__no_arguments(PyObject *args, const char* method_name) {.dtype = simd_data_##IN1}, \ {.dtype = simd_data_##IN2}, \ }; \ - if (simd_args_from_tuple( \ - args, req_args, 3, NPY_TOSTRING(NAME)) \ - ) { \ - return NULL; \ - } \ + if (!PyArg_ParseTuple( \ + args, "O&O&O&:"NPY_TOSTRING(NAME), \ + simd_arg_converter, &req_args[0], \ + simd_arg_converter, &req_args[1], \ + simd_arg_converter, &req_args[2] \ + )) return NULL; \ simd_data r = {.RET = npyv_##NAME( \ req_args[0].data.IN0, \ req_args[1].data.IN1, \ |