summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSayed Adel <seiko@imavr.com>2020-09-15 15:04:28 +0200
committerSayed Adel <seiko@imavr.com>2020-10-27 11:46:58 +0000
commite19f7a8cfe59226fed6cc7a7da9e881218364d49 (patch)
tree1322cbaeb5bd1afb599f86d4e7e4efedb57b12ad
parent92a4693cb0df392003cf99a2f1abe8927cdd58b4 (diff)
downloadnumpy-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.src6
-rw-r--r--numpy/core/src/_simd/_simd_inc.h.src33
-rw-r--r--numpy/core/src/_simd/_simd_inc_arg.h38
-rw-r--r--numpy/core/src/_simd/_simd_inc_easyintrin.h52
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, \