8000 Merge branch 'array_params_from_object' of https://github.com/m-parad… · numpy/numpy@1d952a5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1d952a5

Browse files
committed
Merge branch 'array_params_from_object' of https://github.com/m-paradox/numpy into params_from_object
2 parents 51d10b0 + b8921fc commit 1d952a5

File tree

11 files changed

+751
-514
lines changed

11 files changed

+751
-514
lines changed

numpy/core/code_generators/numpy_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@
311311
'PyArray_EinsteinSum': 274,
312312
'PyArray_FillWithZero': 275,
313313
'PyArray_NewLikeArray': 276,
314+
'PyArray_GetArrayParamsFromObject': 277,
314315
}
315316

316317
ufunc_types_api = {

numpy/core/src/multiarray/arrayobject.c

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,13 @@ PyArray_Size(PyObject *op)
6868
NPY_NO_EXPORT int
6969
PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
7070
{
71-
PyArrayObject *src;
72-
PyObject *r;
7371
int ret;
72+
PyArrayObject *src;
73+
PyArray_Descr *dtype = NULL;
74+
int ndim = 0;
75+
npy_intp dims[NPY_MAXDIMS];
7476

77+
Py_INCREF(src_object);
7578
/*
7679
* Special code to mimic Numeric behavior for
7780
* character arrays.
@@ -90,33 +93,87 @@ PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
9093
memset(new_string + n_old, ' ', n_new - n_old);
9194
tmp = PyString_FromStringAndSize(new_string, n_new);
9295
free(new_string);
96+
Py_DECREF(src_object);
9397
src_object = tmp;
9498
}
9599
}
96100

97-
if (PyArray_Check(src_object)) {
98-
src = (PyArrayObject *)src_object;
99-
Py_INCREF(src);
100-
}
101-
else if (!PyArray_IsScalar(src_object, Generic) &&
102-
PyArray_HasArrayInterface(src_object, r)) {
103-
src = (PyArrayObject *)r;
104-
}
105-
else {
106-
PyArray_Descr* dtype;
107-
dtype = dest->descr;
108-
Py_INCREF(dtype);
109-
src = (PyArrayObject *)PyArray_FromAny(src_object, dtype, 0,
110-
dest->nd,
111-
FORTRAN_IF(dest),
112-
NULL);
101+
/*
102+
* Get either an array object we can copy from, or its parameters
103+
* if there isn't a convenient array available.
104+
*/
105+
if (PyArray_GetArrayParamsFromObject(src_object, PyArray_DESCR(dest),
106+
0, &dtype, &ndim, dims, &src, NULL) < 0) {
107+
Py_DECREF(src_object);
108+
return -1;
113109
}
110+
111+
/* If it's not an array, either assign from a sequence or as a scalar */
114112
if (src == NULL) {
115-
return -1;
113+
/* If the input is scalar */
114+
if (ndim == 0) {
115+
/* If there's one dest element and src is a Python scalar */
116+
if (PyArray_IsScalar(src_object, Generic)) {
117+
src = (PyArrayObject *)PyArray_FromScalar(src_object, dtype);
118+
if (src == NULL) {
119+
Py_DECREF(src_object);
120+
return -1;
121+
}
122+
}
123+
else {
124+
if (PyArray_SIZE(dest) == 1) {
125+
Py_DECREF(dtype);
126+
return PyArray_DESCR(dest)->f->setitem(src_object,
127+
PyArray_DATA(dest), dest);
128+
}
129+
else {
130+
src = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
131+
B41A dtype, 0, NULL, NULL,
132+
NULL, 0, NULL);
133+
if (src == NULL) {
134+
Py_DECREF(src_object);
135+
return -1;
136+
}
137+
if (PyArray_DESCR(src)->f->setitem(src_object,
138+
PyArray_DATA(src), src) < 0) {
139+
Py_DECREF(src_object);
140+
Py_DECREF(src);
141+
return -1;
142+
}
143+
}
144+
}
145+
}
146+
else {
147+
/* If the dims match exactly, can assign directly */
148+
if (ndim == PyArray_NDIM(dest) &&
149+
PyArray_CompareLists(dims, PyArray_DIMS(dest),
150+
ndim)) {
151+
int res;
152+
Py_DECREF(dtype);
153+
res = PyArray_AssignFromSequence(dest, src_object);
154+
Py_DECREF(src_object);
155+
return res;
156+
}
157+
/* Otherwise convert to an array and do an array-based copy */
158+
src = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
159+
dtype, ndim, dims, NULL, NULL,
160+
PyArray_ISFORTRAN(dest), NULL);
161+
if (src == NULL) {
162+
Py_DECREF(src_object);
163+
return -1;
164+
}
165+
if (PyArray_AssignFromSequence(src, src_object) < 0) {
166+
Py_DECREF(src);
167+
Py_DECREF(src_object);
168+
return -1;
169+
}
170+
}
116171
}
117172

173+
/* If it's an array, do a move (handling possible overlapping data) */
118174
ret = PyArray_MoveInto(dest, src);
119175
Py_DECREF(src);
176+
Py_DECREF(src_object);
120177
return ret;
121178
}
122179

@@ -627,7 +684,7 @@ _uni_release(char *ptr, int nc)
627684
relfunc(aptr, N1); \
628685
return -1; \
629686
} \
630-
val = cmpfunc(aptr, bptr, N1, N2); \
687+
val = compfunc(aptr, bptr, N1, N2); \
631688
*dptr = (val CMP 0); \
632689
PyArray_ITER_NEXT(iself); \
633690
PyArray_ITER_NEXT(iother); \
@@ -639,7 +696,7 @@ _uni_release(char *ptr, int nc)
639696

640697
#define _reg_loop(CMP) { \
641698
while(size--) { \
642-
val = cmpfunc((void *)iself->dataptr, \
699+
val = compfunc((void *)iself->dataptr, \
643700
(void *)iother->dataptr, \
644701
N1, N2); \
645702
*dptr = (val CMP 0); \
@@ -661,18 +718,18 @@ _compare_strings(PyObject *result, PyArrayMultiIterObject *multi,
661718
npy_intp size;
662719
int val;
663720
int N1, N2;
664-
int (*cmpfunc)(void *, void *, int, int);
721+
int (*compfunc)(void *, void *, int, int);
665722
void (*relfunc)(char *, int);
666723
char* (*stripfunc)(char *, char *, int);
667724

668-
cmpfunc = func;
725+
compfunc = func;
669726
dptr = (Bool *)PyArray_DATA(result);
670727
iself = multi->iters[0];
671728
iother = multi->iters[1];
672729
size = multi->size;
673730
N1 = iself->ao->descr->elsize;
674731
N2 = iother->ao->descr->elsize;
675-
if ((void *)cmpfunc == (void *)_myunincmp) {
732+
if ((void *)compfunc == (void *)_myunincmp) {
676733
N1 >>= 2;
677734
N2 >>= 2;
678735
stripfunc = _uni_copy_n_strip;

numpy/core/src/multiarray/arraytypes.c.src

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ static int
149149
temp = (@type@)@func2@(op);
150150
}
151151
if (PyErr_Occurred()) {
152-
if (PySequence_Check(op)) {
152+
if (PySequence_Check(op) && !PyString_Check(op) &&
153+
!PyUnicode_Check(op)) {
153154
PyErr_Clear();
154155
PyErr_SetString(PyExc_ValueError,
155156
"setting an array element with a sequence.");
@@ -438,6 +439,19 @@ STRING_setitem(PyObject *op, char *ov, PyArrayObject *ap)
438439
Py_ssize_t len;
439440
PyObject *temp = NULL;
440441

442+
/* Handle case of assigning from an array scalar */
443+
if (PyArray_Check(op) && PyArray_NDIM(op) == 0) {
444+
temp = PyArray_ToScalar(PyArray_DATA(op), op);
445+
if (temp == NULL) {
446+
return -1;
447+
}
448+
else {
449+
int res = STRING_setitem(temp, ov, ap);
450+
Py_DECREF(temp);
451+
return res;
452+
}
453+
}
454+
441455
if (!PyBytes_Check(op) && !PyUnicode_Check(op)
442456
&& PySequence_Check(op) && PySequence_Size(op) != 0) {
443457
PyErr_SetString(PyExc_ValueError,

0 commit comments

Comments
 (0)
0