summaryrefslogtreecommitdiff
path: root/numpy/core/src
diff options
context:
space:
mode:
authormattip <matti.picus@gmail.com>2023-01-23 21:18:05 +0200
committermattip <matti.picus@gmail.com>2023-01-30 21:32:35 +0200
commit7910e2bf14b8bef95c3180fbf667458e29426a0e (patch)
treeb2442cad1940633758dabb9b2113dc101dfb7de9 /numpy/core/src
parent3ba259d20ec57052ee8df915eab308370e4a7bae (diff)
downloadnumpy-7910e2bf14b8bef95c3180fbf667458e29426a0e.tar.gz
ENH: add indexed lower loops and connect them to ufuncs
Diffstat (limited to 'numpy/core/src')
-rw-r--r--numpy/core/src/multiarray/argfunc.dispatch.c.src4
-rw-r--r--numpy/core/src/multiarray/array_method.c5
-rw-r--r--numpy/core/src/multiarray/array_method.h4
-rw-r--r--numpy/core/src/umath/loops.c.src49
-rw-r--r--numpy/core/src/umath/loops.h.src21
-rw-r--r--numpy/core/src/umath/loops_arithm_fp.dispatch.c.src14
-rw-r--r--numpy/core/src/umath/loops_arithmetic.dispatch.c.src42
7 files changed, 126 insertions, 13 deletions
diff --git a/numpy/core/src/multiarray/argfunc.dispatch.c.src b/numpy/core/src/multiarray/argfunc.dispatch.c.src
index 1d7753275..88c1028dc 100644
--- a/numpy/core/src/multiarray/argfunc.dispatch.c.src
+++ b/numpy/core/src/multiarray/argfunc.dispatch.c.src
@@ -194,7 +194,7 @@ simd_@func@_@sfx@(npyv_lanetype_@sfx@ *ip, npy_intp len)
npyv_@bsfx@ nnan_ab = npyv_and_@bsfx@(nnan_a, nnan_b);
npyv_@bsfx@ nnan_cd = npyv_and_@bsfx@(nnan_c, nnan_d);
npy_uint64 nnan = npyv_tobits_@bsfx@(npyv_and_@bsfx@(nnan_ab, nnan_cd));
- if (nnan != ((1LL << vstep) - 1)) {
+ if ((long long int)nnan != ((1LL << vstep) - 1)) {
npy_uint64 nnan_4[4];
nnan_4[0] = npyv_tobits_@bsfx@(nnan_a);
nnan_4[1] = npyv_tobits_@bsfx@(nnan_b);
@@ -219,7 +219,7 @@ simd_@func@_@sfx@(npyv_lanetype_@sfx@ *ip, npy_intp len)
#if @is_fp@
npyv_@bsfx@ nnan_a = npyv_notnan_@sfx@(a);
npy_uint64 nnan = npyv_tobits_@bsfx@(nnan_a);
- if (nnan != ((1LL << vstep) - 1)) {
+ if ((long long int)nnan != ((1LL << vstep) - 1)) {
for (int vi = 0; vi < vstep; ++vi) {
if (!((nnan >> vi) & 1)) {
return i + vi;
diff --git a/numpy/core/src/multiarray/array_method.c b/numpy/core/src/multiarray/array_method.c
index eeebf2d9b..5001a67e9 100644
--- a/numpy/core/src/multiarray/array_method.c
+++ b/numpy/core/src/multiarray/array_method.c
@@ -291,6 +291,9 @@ fill_arraymethod_from_slots(
case NPY_METH_get_reduction_initial:
meth->get_reduction_initial = slot->pfunc;
continue;
+ case NPY_METH_contiguous_indexed_loop:
+ meth->contiguous_indexed_loop = slot->pfunc;
+ continue;
default:
break;
}
@@ -891,7 +894,7 @@ generic_masked_strided_loop(PyArrayMethod_Context *context,
/*
* Fetches a strided-loop function that supports a boolean mask as additional
* (last) operand to the strided-loop. It is otherwise largely identical to
- * the `get_loop` method which it wraps.
+ * the `get_strided_loop` method which it wraps.
* This is the core implementation for the ufunc `where=...` keyword argument.
*
* NOTE: This function does not support `move_references` or inner dimensions.
diff --git a/numpy/core/src/multiarray/array_method.h b/numpy/core/src/multiarray/array_method.h
index ef4648443..138df69fa 100644
--- a/numpy/core/src/multiarray/array_method.h
+++ b/numpy/core/src/multiarray/array_method.h
@@ -73,7 +73,7 @@ struct PyArrayMethodObject_tag;
* TODO: Before making this public, we should review which information should
* be stored on the Context/BoundArrayMethod vs. the ArrayMethod.
*/
-typedef struct {
+typedef struct PyArrayMethod_Context_tag {
PyObject *caller; /* E.g. the original ufunc, may be NULL */
struct PyArrayMethodObject_tag *method;
@@ -223,6 +223,7 @@ typedef struct PyArrayMethodObject_tag {
PyArrayMethod_StridedLoop *contiguous_loop;
PyArrayMethod_StridedLoop *unaligned_strided_loop;
PyArrayMethod_StridedLoop *unaligned_contiguous_loop;
+ PyArrayMethod_StridedLoop *contiguous_indexed_loop;
/* Chunk only used for wrapping array method defined in umath */
struct PyArrayMethodObject_tag *wrapped_meth;
PyArray_DTypeMeta **wrapped_dtypes;
@@ -266,6 +267,7 @@ extern NPY_NO_EXPORT PyTypeObject PyBoundArrayMethod_Type;
#define NPY_METH_contiguous_loop 5
#define NPY_METH_unaligned_strided_loop 6
#define NPY_METH_unaligned_contiguous_loop 7
+#define NPY_METH_contiguous_indexed_loop 8
/*
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src
index 085712f38..d4e246783 100644
--- a/numpy/core/src/umath/loops.c.src
+++ b/numpy/core/src/umath/loops.c.src
@@ -541,15 +541,21 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
}
}
-NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_@kind@@isa@_indexed(char const *ip1, npy_intp const *indx, char *value,
- npy_intp const *dimensions, npy_intp const *steps) {
+NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ int
+@TYPE@_@kind@@isa@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char * const*args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func))
+{
+ char *ip1 = args[0];
+ npy_intp *indx = (npy_intp *)args[1];
+ char *value = args[2];
npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];
npy_intp n = dimensions[0];
npy_intp i;
+ @type@ *indexed;
for(i = 0; i < n; i++, indx += is2, value += os1) {
- @type@ op1 = *(@type@ *)(ip1 + is1 * indx[0]) + value[0];
+ indexed = (@type@ *)(ip1 + is1 * indx[0]);
+ indexed[0] = indexed[0] @OP@ *(@type@ *)value;
}
+ return 0;
}
#endif
@@ -1546,6 +1552,23 @@ LONGDOUBLE_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps
}
}
}
+
+NPY_NO_EXPORT void
+LONGDOUBLE_@kind@_indexed(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
+{
+ char *ip1 = args[0];
+ npy_intp *indx = (npy_intp *)args[1];
+ char *value = args[2];
+ npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];
+ npy_intp n = dimensions[0];
+ npy_intp i;
+ npy_longdouble *indexed;
+ for(i = 0; i < n; i++, indx += is2, value += os1) {
+ indexed = (npy_longdouble *)(ip1 + is1 * indx[0]);
+ indexed[0] = indexed[0] @OP@ *(npy_longdouble *)value;
+ }
+}
+
/**end repeat**/
/**begin repeat
@@ -1651,6 +1674,24 @@ HALF_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void
}
}
}
+
+NPY_NO_EXPORT int
+HALF_@kind@_indexed(void *NPY_UNUSED(context), char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
+{
+ char *ip1 = args[0];
+ npy_intp *indx = (npy_intp *)args[1];
+ char *value = args[2];
+ npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];
+ npy_intp n = dimensions[0];
+ npy_intp i;
+ npy_half *indexed;
+ for(i = 0; i < n; i++, indx += is2, value += os1) {
+ indexed = (npy_half *)(ip1 + is1 * indx[0]);
+ const float v = npy_half_to_float(*(npy_half *)value);
+ indexed[0] = npy_float_to_half(npy_half_to_float(indexed[0]) @OP@ v);
+ }
+ return 0;
+}
/**end repeat**/
#define _HALF_LOGICAL_AND(a,b) (!npy_half_iszero(a) && !npy_half_iszero(b))
diff --git a/numpy/core/src/umath/loops.h.src b/numpy/core/src/umath/loops.h.src
index 26742946f..ee69330dd 100644
--- a/numpy/core/src/umath/loops.h.src
+++ b/numpy/core/src/umath/loops.h.src
@@ -33,6 +33,9 @@
// #define BOOL_fmax BOOL_maximum
// #define BOOL_fmin BOOL_minimum
+typedef struct PyArrayMethod_Context_tag PyArrayMethod_Context;
+typedef struct NpyAuxData_tag NpyAuxData;
+
#ifndef NPY_DISABLE_OPTIMIZATION
#include "loops_comparison.dispatch.h"
#endif
@@ -81,6 +84,11 @@ BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void
*/
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_divide,
(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
+
+NPY_NO_EXPORT int
+@TYPE@_divide_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));
+
+/**end repeat3**/
/**end repeat**/
#ifndef NPY_DISABLE_OPTIMIZATION
@@ -163,6 +171,9 @@ NPY_NO_EXPORT void
NPY_NO_EXPORT void
@S@@TYPE@_@kind@@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+NPY_NO_EXPORT int
+@S@@TYPE@_@kind@@isa@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));
+
/**end repeat3**/
/**begin repeat3
@@ -285,10 +296,13 @@ NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
/**begin repeat1
* Arithmetic
* # kind = add, subtract, multiply, divide#
- * # OP = +, -, *, /#
*/
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
+
+NPY_NO_EXPORT int
+@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));
+
/**end repeat1**/
/**end repeat**/
@@ -424,6 +438,11 @@ NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@, (
*/
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+
+NPY_NO_EXPORT int
+@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));
+
+/**end repeat1**/
/**end repeat1**/
/**begin repeat1
diff --git a/numpy/core/src/umath/loops_arithm_fp.dispatch.c.src b/numpy/core/src/umath/loops_arithm_fp.dispatch.c.src
index 1436c46f4..1874573ce 100644
--- a/numpy/core/src/umath/loops_arithm_fp.dispatch.c.src
+++ b/numpy/core/src/umath/loops_arithm_fp.dispatch.c.src
@@ -547,15 +547,21 @@ NPY_NO_EXPORT void NPY_CPU_DISPATCH_CURFX(@TYPE@_@kind@)
}
}
-NPY_NO_EXPORT void NPY_CPU_DISPATCH_CURFX(@TYPE@_@kind@_indexed)
-(char const *ip1, npy_intp const *indx, char *value,
- npy_intp const *dimensions, npy_intp const *steps) {
+NPY_NO_EXPORT int NPY_CPU_DISPATCH_CURFX(@TYPE@_@kind@_indexed)
+(PyArrayMethod_Context *NPY_UNUSED(context), char * const*args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func))
+{
+ char *ip1 = args[0];
+ npy_intp *indx = (npy_intp *)args[1];
+ char *value = args[2];
npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];
npy_intp n = dimensions[0];
npy_intp i;
+ @type@ *indexed;
for(i = 0; i < n; i++, indx += is2, value += os1) {
- @type@ op1 = *(@type@ *)(ip1 + is1 * indx[0]) + value[0];
+ indexed = (@type@ *)(ip1 + is1 * indx[0]);
+ indexed[0] = indexed[0] @OP@ *(@type@ *)value;
}
+ return 0;
}
/**end repeat1**/
diff --git a/numpy/core/src/umath/loops_arithmetic.dispatch.c.src b/numpy/core/src/umath/loops_arithmetic.dispatch.c.src
index ea8685002..573590b1f 100644
--- a/numpy/core/src/umath/loops_arithmetic.dispatch.c.src
+++ b/numpy/core/src/umath/loops_arithmetic.dispatch.c.src
@@ -395,6 +395,24 @@ NPY_NO_EXPORT void NPY_CPU_DISPATCH_CURFX(@TYPE@_divide)
}
}
}
+
+NPY_NO_EXPORT int NPY_CPU_DISPATCH_CURFX(@TYPE@_divide_indexed)
+(PyArrayMethod_Context *NPY_UNUSED(context), char * const*args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func))
+{
+ char *ip1 = args[0];
+ npy_intp *indx = (npy_intp *)args[1];
+ char *value = args[2];
+ npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];
+ npy_intp n = dimensions[0];
+ npy_intp i;
+ @type@ *indexed;
+ for(i = 0; i < n; i++, indx += is2, value += os1) {
+ indexed = (@type@ *)(ip1 + is1 * indx[0]);
+ indexed[0] = floor_div_@TYPE@(indexed[0], *(@type@ *)value);
+ }
+ return 0;
+}
+
/**end repeat**/
/**begin repeat
@@ -463,4 +481,28 @@ NPY_NO_EXPORT void NPY_CPU_DISPATCH_CURFX(@TYPE@_divide)
}
}
}
+
+NPY_NO_EXPORT int NPY_CPU_DISPATCH_CURFX(@TYPE@_divide_indexed)
+(PyArrayMethod_Context *NPY_UNUSED(context), char * const*args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func))
+{
+ char *ip1 = args[0];
+ npy_intp *indx = (npy_intp *)args[1];
+ char *value = args[2];
+ npy_intp is1 = steps[0], is2 = steps[1], os1 = steps[2];
+ npy_intp n = dimensions[0];
+ npy_intp i;
+ @type@ *indexed;
+ for(i = 0; i < n; i++, indx += is2, value += os1) {
+ indexed = (@type@ *)(ip1 + is1 * indx[0]);
+ @type@ in2 = *(@type@ *)value;
+ if (NPY_UNLIKELY(in2 == 0)) {
+ npy_set_floatstatus_divbyzero();
+ indexed[0] = 0;
+ } else {
+ indexed[0] = indexed[0] / in2;
+ }
+ }
+ return 0;
+}
+
/**end repeat**/