|
13 | 13 | #include "string.h"
|
14 | 14 | #include "umath.h"
|
15 | 15 |
|
| 16 | +static int |
| 17 | +add_strided_loop(PyArrayMethod_Context *NPY_UNUSED(context), |
| 18 | + char *const data[], npy_intp const dimensions[], |
| 19 | + npy_intp const strides[], NpyAuxData *NPY_UNUSED(auxdata)) |
| 20 | +{ |
| 21 | + npy_intp N = dimensions[0]; |
| 22 | + char *in1 = data[0]; |
| 23 | + char *in2 = data[1]; |
| 24 | + char *out = data[2]; |
| 25 | + npy_intp in1_stride = strides[0]; |
| 26 | + npy_intp in2_stride = strides[1]; |
| 27 | + npy_intp out_stride = strides[2]; |
| 28 | + |
| 29 | + ss *s1 = NULL, *s2 = NULL, *os = NULL; |
| 30 | + int newlen = 0; |
| 31 | + |
| 32 | + while (N--) { |
| 33 | + s1 = (ss *)in1; |
| 34 | + s2 = (ss *)in2; |
| 35 | + os = (ss *)out; |
| 36 | + newlen = s1->len + s2->len; |
| 37 | + |
| 38 | + ssfree(os); |
| 39 | + if (ssnewemptylen(newlen, os) < 0) { |
| 40 | + return -1; |
| 41 | + } |
| 42 | + |
| 43 | + memcpy(os->buf, s1->buf, s1->len); |
| 44 | + memcpy(os->buf + s1->len, s2->buf, s2->len); |
| 45 | + os->buf[newlen] = '\0'; |
| 46 | + |
| 47 | + in1 += in1_stride; |
| 48 | + in2 += in2_stride; |
| 49 | + out += out_stride; |
| 50 | + } |
| 51 | + return 0; |
| 52 | +} |
| 53 | + |
16 | 54 | static int
|
17 | 55 | minmax_resolve_descriptors(struct PyArrayMethodObject_tag *NPY_UNUSED(method),
|
18 | 56 | PyArray_DTypeMeta *NPY_UNUSED(dtypes[]),
|
19 | 57 | PyArray_Descr *given_descrs[],
|
20 | 58 | PyArray_Descr *loop_descrs[],
|
21 | 59 | npy_intp *NPY_UNUSED(view_offset))
|
22 | 60 | {
|
23 |
| - Py_INCREF(given_descrs[0]); |
24 |
| - loop_descrs[0] = given_descrs[0]; |
25 |
| - Py_INCREF(given_descrs[1]); |
26 |
| - loop_descrs[1] = given_descrs[1]; |
27 |
| - |
28 | 61 | StringDTypeObject *new = new_stringdtype_instance();
|
29 | 62 | if (new == NULL) {
|
30 | 63 | return -1;
|
31 | 64 | }
|
| 65 | + Py_INCREF(given_descrs[0]); |
| 66 | + loop_descrs[0] = given_descrs[0]; |
| 67 | + Py_INCREF(given_descrs[1]); |
| 68 | + loop_descrs[1] = given_descrs[1]; |
32 | 69 | loop_descrs[2] = (PyArray_Descr *)new;
|
33 | 70 |
|
34 | 71 | return NPY_NO_CASTING;
|
@@ -270,20 +307,26 @@ init_ufunc(PyObject *numpy, const char *ufunc_name, PyArray_DTypeMeta **dtypes,
|
270 | 307 | return -1;
|
271 | 308 | }
|
272 | 309 |
|
273 |
| - PyType_Slot slots[] = {{NPY_METH_resolve_descriptors, resolve_func}, |
274 |
| - {NPY_METH_strided_loop, loop_func}, |
275 |
| - {0, NULL}}; |
276 |
| - |
277 | 310 | PyArrayMethod_Spec spec = {
|
278 | 311 | .name = loop_name,
|
279 | 312 | .nin = nin,
|
280 | 313 | .nout = nout,
|
281 | 314 | .casting = casting,
|
282 | 315 | .flags = flags,
|
283 | 316 | .dtypes = dtypes,
|
284 |
| - .slots = slots, |
285 | 317 | };
|
286 | 318 |
|
| 319 | + if (resolve_func == NULL) { |
| 320 | + PyType_Slot slots[] = {{NPY_METH_strided_loop, loop_func}, {0, NULL}}; |
| 321 | + spec.slots = slots; |
| 322 | + } |
| 323 | + else { |
| 324 | + PyType_Slot slots[] = {{NPY_METH_resolve_descriptors, resolve_func}, |
| 325 | + {NPY_METH_strided_loop, loop_func}, |
| 326 | + {0, NULL}}; |
| 327 | + spec.slots = slots; |
| 328 | + } |
| 329 | + |
287 | 330 | if (PyUFunc_AddLoopFromSpec(ufunc, &spec) < 0) {
|
288 | 331 | Py_DECREF(ufunc);
|
289 | 332 | return -1;
|
@@ -378,6 +421,13 @@ init_ufuncs(void)
|
378 | 421 | goto error;
|
379 | 422 | }
|
380 | 423 |
|
| 424 | + PyArray_DTypeMeta *add_types[] = {&StringDType, &StringDType, |
| 425 | + &StringDType}; |
| 426 | + if (init_ufunc(numpy, "add", add_types, NULL, &add_strided_loop, |
| 427 | + "string_add", 2, 1, NPY_NO_CASTING, 0) < 0) { |
| 428 | + goto error; |
| 429 | + } |
| 430 | + |
381 | 431 | Py_DECREF(numpy);
|
382 | 432 | return 0;
|
383 | 433 |
|
|
0 commit comments