1
#define PY_SSIZE_T_CLEAN
2
#include <Python.h>
3

4
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
5
#define _MULTIARRAYMODULE
6
#include "numpy/arrayobject.h"
7

8
#include "npy_config.h"
9
#include "npy_pycompat.h"
10
#include "common.h"
11

12
#include "abstractdtypes.h"
13
#include "usertypes.h"
14

15
#include "npy_buffer.h"
16

17
#include "get_attr_string.h"
18
#include "mem_overlap.h"
19
#include "array_coercion.h"
20

21
/*
22
 * The casting to use for implicit assignment operations resulting from
23
 * in-place operations (like +=) and out= arguments. (Notice that this
24
 * variable is misnamed, but it's part of the public API so I'm not sure we
25
 * can just change it. Maybe someone should try and see if anyone notices.
26
 */
27
/*
28
 * In numpy 1.6 and earlier, this was NPY_UNSAFE_CASTING. In a future
29
 * release, it will become NPY_SAME_KIND_CASTING.  Right now, during the
30
 * transitional period, we continue to follow the NPY_UNSAFE_CASTING rules (to
31
 * avoid breaking people's code), but we also check for whether the cast would
32
 * be allowed under the NPY_SAME_KIND_CASTING rules, and if not we issue a
33
 * warning (that people's code will be broken in a future release.)
34
 */
35

36
NPY_NO_EXPORT NPY_CASTING NPY_DEFAULT_ASSIGN_CASTING = NPY_SAME_KIND_CASTING;
37

38

39
NPY_NO_EXPORT PyArray_Descr *
40 1
_array_find_python_scalar_type(PyObject *op)
41
{
42 1
    if (PyFloat_Check(op)) {
43 1
        return PyArray_DescrFromType(NPY_DOUBLE);
44
    }
45 1
    else if (PyComplex_Check(op)) {
46 0
        return PyArray_DescrFromType(NPY_CDOUBLE);
47
    }
48 1
    else if (PyLong_Check(op)) {
49 0
        return PyArray_PyIntAbstractDType.discover_descr_from_pyobject(
50
                    &PyArray_PyIntAbstractDType, op);
51
    }
52
    return NULL;
53
}
54

55

56
/*
57
 * Get a suitable string dtype by calling `__str__`.
58
 * For `np.bytes_`, this assumes an ASCII encoding.
59
 */
60
NPY_NO_EXPORT PyArray_Descr *
61 1
PyArray_DTypeFromObjectStringDiscovery(
62
        PyObject *obj, PyArray_Descr *last_dtype, int string_type)
63
{
64
    int itemsize;
65

66 1
    if (string_type == NPY_STRING) {
67 1
        PyObject *temp = PyObject_Str(obj);
68 1
        if (temp == NULL) {
69
            return NULL;
70
        }
71
        /* assume that when we do the encoding elsewhere we'll use ASCII */
72 1
        itemsize = PyUnicode_GetLength(temp);
73 1
        Py_DECREF(temp);
74 1
        if (itemsize < 0) {
75
            return NULL;
76
        }
77
    }
78 1
    else if (string_type == NPY_UNICODE) {
79 1
        PyObject *temp = PyObject_Str(obj);
80 1
        if (temp == NULL) {
81
            return NULL;
82
        }
83 1
        itemsize = PyUnicode_GetLength(temp);
84 1
        Py_DECREF(temp);
85 1
        if (itemsize < 0) {
86
            return NULL;
87
        }
88 1
        itemsize *= 4;  /* convert UCS4 codepoints to bytes */
89
    }
90
    else {
91
        return NULL;
92
    }
93 1
    if (last_dtype != NULL &&
94 0
        last_dtype->type_num == string_type &&
95 0
        last_dtype->elsize >= itemsize) {
96 0
        Py_INCREF(last_dtype);
97 0
        return last_dtype;
98
    }
99 1
    PyArray_Descr *dtype = PyArray_DescrNewFromType(string_type);
100 1
    if (dtype == NULL) {
101
        return NULL;
102
    }
103 1
    dtype->elsize = itemsize;
104 1
    return dtype;
105
}
106

107

108
/*
109
 * This function is now identical to the new PyArray_DiscoverDTypeAndShape
110
 * but only returns the the dtype. It should in most cases be slowly phased
111
 * out. (Which may need some refactoring to PyArray_FromAny to make it simpler)
112
 */
113
NPY_NO_EXPORT int
114 1
PyArray_DTypeFromObject(PyObject *obj, int maxdims, PyArray_Descr **out_dtype)
115
{
116 1
    coercion_cache_obj *cache = NULL;
117
    npy_intp shape[NPY_MAXDIMS];
118
    int ndim;
119

120 1
    ndim = PyArray_DiscoverDTypeAndShape(
121
            obj, maxdims, shape, &cache, NULL, NULL, out_dtype);
122 1
    if (ndim < 0) {
123
        return -1;
124
    }
125 1
    npy_free_coercion_cache(cache);
126 1
    return 0;
127
}
128

129
NPY_NO_EXPORT char *
130 1
index2ptr(PyArrayObject *mp, npy_intp i)
131
{
132
    npy_intp dim0;
133

134 1
    if (PyArray_NDIM(mp) == 0) {
135 0
        PyErr_SetString(PyExc_IndexError, "0-d arrays can't be indexed");
136 0
        return NULL;
137
    }
138 1
    dim0 = PyArray_DIMS(mp)[0];
139 1
    if (check_and_adjust_index(&i, dim0, 0, NULL) < 0)
140
        return NULL;
141 1
    if (i == 0) {
142 1
        return PyArray_DATA(mp);
143
    }
144 1
    return PyArray_BYTES(mp)+i*PyArray_STRIDES(mp)[0];
145
}
146

147
NPY_NO_EXPORT int
148 1
_zerofill(PyArrayObject *ret)
149
{
150 1
    if (PyDataType_REFCHK(PyArray_DESCR(ret))) {
151 1
        PyObject *zero = PyLong_FromLong(0);
152 1
        PyArray_FillObjectArray(ret, zero);
153 1
        Py_DECREF(zero);
154 1
        if (PyErr_Occurred()) {
155 0
            Py_DECREF(ret);
156
            return -1;
157
        }
158
    }
159
    else {
160 1
        npy_intp n = PyArray_NBYTES(ret);
161 1
        memset(PyArray_DATA(ret), 0, n);
162
    }
163
    return 0;
164
}
165

166
NPY_NO_EXPORT npy_bool
167 1
_IsWriteable(PyArrayObject *ap)
168
{
169 1
    PyObject *base = PyArray_BASE(ap);
170
    Py_buffer view;
171

172
    /*
173
     * C-data wrapping arrays may not own their data while not having a base;
174
     * WRITEBACKIFCOPY arrays have a base, but do own their data.
175
     */
176 1
    if (base == NULL || PyArray_CHKFLAGS(ap, NPY_ARRAY_OWNDATA)) {
177
        /*
178
         * This is somewhat unsafe for directly wrapped non-writable C-arrays,
179
         * which do not know whether the memory area is writable or not and
180
         * do not own their data (but have no base).
181
         * It would be better if this returned PyArray_ISWRITEABLE(ap).
182
         * Since it is hard to deprecate, this is deprecated only on the Python
183
         * side, but not on in PyArray_UpdateFlags.
184
         */
185
        return NPY_TRUE;
186
    }
187

188
    /*
189
     * Get to the final base object.
190
     * If it is a writeable array, then return True if we can
191
     * find an array object or a writeable buffer object as
192
     * the final base object.
193
     */
194 1
    while (PyArray_Check(base)) {
195 1
        ap = (PyArrayObject *)base;
196 1
        base = PyArray_BASE(ap);
197

198 1
        if (PyArray_ISWRITEABLE(ap)) {
199
            /*
200
             * If any base is writeable, it must be OK to switch, note that
201
             * bases are typically collapsed to always point to the most
202
             * general one.
203
             */
204
            return NPY_TRUE;
205
        }
206

207 1
        if (base == NULL || PyArray_CHKFLAGS(ap, NPY_ARRAY_OWNDATA)) {
208
            /* there is no further base to test the writeable flag for */
209
            return NPY_FALSE;
210
        }
211
        assert(!PyArray_CHKFLAGS(ap, NPY_ARRAY_OWNDATA));
212
    }
213

214 1
    if (PyObject_GetBuffer(base, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
215 1
        PyErr_Clear();
216 1
        return NPY_FALSE;
217
    }
218 1
    PyBuffer_Release(&view);
219 1
    return NPY_TRUE;
220
}
221

222

223
/**
224
 * Convert an array shape to a string such as "(1, 2)".
225
 *
226
 * @param Dimensionality of the shape
227
 * @param npy_intp pointer to shape array
228
 * @param String to append after the shape `(1, 2)%s`.
229
 *
230
 * @return Python unicode string
231
 */
232
NPY_NO_EXPORT PyObject *
233 1
convert_shape_to_string(npy_intp n, npy_intp const *vals, char *ending)
234
{
235
    npy_intp i;
236
    PyObject *ret, *tmp;
237

238
    /*
239
     * Negative dimension indicates "newaxis", which can
240
     * be discarded for printing if it's a leading dimension.
241
     * Find the first non-"newaxis" dimension.
242
     */
243 1
    for (i = 0; i < n && vals[i] < 0; i++);
244

245 1
    if (i == n) {
246 1
        return PyUnicode_FromFormat("()%s", ending);
247
    }
248
    else {
249 1
        ret = PyUnicode_FromFormat("(%" NPY_INTP_FMT, vals[i++]);
250 1
        if (ret == NULL) {
251
            return NULL;
252
        }
253
    }
254

255 1
    for (; i < n; ++i) {
256 1
        if (vals[i] < 0) {
257 1
            tmp = PyUnicode_FromString(",newaxis");
258
        }
259
        else {
260 1
            tmp = PyUnicode_FromFormat(",%" NPY_INTP_FMT, vals[i]);
261
        }
262 1
        if (tmp == NULL) {
263 0
            Py_DECREF(ret);
264
            return NULL;
265
        }
266

267 1
        PyUString_ConcatAndDel(&ret, tmp);
268 1
        if (ret == NULL) {
269
            return NULL;
270
        }
271
    }
272

273 1
    if (i == 1) {
274 1
        tmp = PyUnicode_FromFormat(",)%s", ending);
275
    }
276
    else {
277 1
        tmp = PyUnicode_FromFormat(")%s", ending);
278
    }
279 1
    PyUString_ConcatAndDel(&ret, tmp);
280 1
    return ret;
281
}
282

283

284
NPY_NO_EXPORT void
285 1
dot_alignment_error(PyArrayObject *a, int i, PyArrayObject *b, int j)
286
{
287 1
    PyObject *errmsg = NULL, *format = NULL, *fmt_args = NULL,
288 1
             *i_obj = NULL, *j_obj = NULL,
289 1
             *shape1 = NULL, *shape2 = NULL,
290 1
             *shape1_i = NULL, *shape2_j = NULL;
291

292 1
    format = PyUnicode_FromString("shapes %s and %s not aligned:"
293
                                  " %d (dim %d) != %d (dim %d)");
294

295 1
    shape1 = convert_shape_to_string(PyArray_NDIM(a), PyArray_DIMS(a), "");
296 1
    shape2 = convert_shape_to_string(PyArray_NDIM(b), PyArray_DIMS(b), "");
297

298 1
    i_obj = PyLong_FromLong(i);
299 1
    j_obj = PyLong_FromLong(j);
300

301 1
    shape1_i = PyLong_FromSsize_t(PyArray_DIM(a, i));
302 1
    shape2_j = PyLong_FromSsize_t(PyArray_DIM(b, j));
303

304 1
    if (!format || !shape1 || !shape2 || !i_obj || !j_obj ||
305 1
            !shape1_i || !shape2_j) {
306
        goto end;
307
    }
308

309 1
    fmt_args = PyTuple_Pack(6, shape1, shape2,
310
                            shape1_i, i_obj, shape2_j, j_obj);
311 1
    if (fmt_args == NULL) {
312
        goto end;
313
    }
314

315 1
    errmsg = PyUnicode_Format(format, fmt_args);
316 1
    if (errmsg != NULL) {
317 1
        PyErr_SetObject(PyExc_ValueError, errmsg);
318
    }
319
    else {
320 0
        PyErr_SetString(PyExc_ValueError, "shapes are not aligned");
321
    }
322

323 1
end:
324 1
    Py_XDECREF(errmsg);
325 1
    Py_XDECREF(fmt_args);
326 1
    Py_XDECREF(format);
327 1
    Py_XDECREF(i_obj);
328 1
    Py_XDECREF(j_obj);
329 1
    Py_XDECREF(shape1);
330 1
    Py_XDECREF(shape2);
331 1
    Py_XDECREF(shape1_i);
332 1
    Py_XDECREF(shape2_j);
333
}
334

335
/**
336
 * unpack tuple of dtype->fields (descr, offset, title[not-needed])
337
 *
338
 * @param "value" should be the tuple.
339
 *
340
 * @return "descr" will be set to the field's dtype
341
 * @return "offset" will be set to the field's offset
342
 *
343
 * returns -1 on failure, 0 on success.
344
 */
345
NPY_NO_EXPORT int
346 1
_unpack_field(PyObject *value, PyArray_Descr **descr, npy_intp *offset)
347
{
348
    PyObject * off;
349 1
    if (PyTuple_GET_SIZE(value) < 2) {
350
        return -1;
351
    }
352 1
    *descr = (PyArray_Descr *)PyTuple_GET_ITEM(value, 0);
353 1
    off  = PyTuple_GET_ITEM(value, 1);
354

355 1
    if (PyLong_Check(off)) {
356 1
        *offset = PyLong_AsSsize_t(off);
357
    }
358
    else {
359 0
        PyErr_SetString(PyExc_IndexError, "can't convert offset");
360 0
        return -1;
361
    }
362

363 1
    return 0;
364
}
365

366
/*
367
 * check whether arrays with datatype dtype might have object fields. This will
368
 * only happen for structured dtypes (which may have hidden objects even if the
369
 * HASOBJECT flag is false), object dtypes, or subarray dtypes whose base type
370
 * is either of these.
371
 */
372
NPY_NO_EXPORT int
373 1
_may_have_objects(PyArray_Descr *dtype)
374
{
375 1
    PyArray_Descr *base = dtype;
376 1
    if (PyDataType_HASSUBARRAY(dtype)) {
377 1
        base = dtype->subarray->base;
378
    }
379

380 1
    return (PyDataType_HASFIELDS(base) ||
381 1
            PyDataType_FLAGCHK(base, NPY_ITEM_HASOBJECT) );
382
}
383

384
/*
385
 * Make a new empty array, of the passed size, of a type that takes the
386
 * priority of ap1 and ap2 into account.
387
 *
388
 * If `out` is non-NULL, memory overlap is checked with ap1 and ap2, and an
389
 * updateifcopy temporary array may be returned. If `result` is non-NULL, the
390
 * output array to be returned (`out` if non-NULL and the newly allocated array
391
 * otherwise) is incref'd and put to *result.
392
 */
393
NPY_NO_EXPORT PyArrayObject *
394 1
new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
395
                  int nd, npy_intp dimensions[], int typenum, PyArrayObject **result)
396
{
397
    PyArrayObject *out_buf;
398

399 1
    if (out) {
400
        int d;
401

402
        /* verify that out is usable */
403 1
        if (PyArray_NDIM(out) != nd ||
404 1
            PyArray_TYPE(out) != typenum ||
405 1
            !PyArray_ISCARRAY(out)) {
406 1
            PyErr_SetString(PyExc_ValueError,
407
                "output array is not acceptable (must have the right datatype, "
408
                "number of dimensions, and be a C-Array)");
409 1
            return 0;
410
        }
411 1
        for (d = 0; d < nd; ++d) {
412 1
            if (dimensions[d] != PyArray_DIM(out, d)) {
413 1
                PyErr_SetString(PyExc_ValueError,
414
                    "output array has wrong dimensions");
415 1
                return 0;
416
            }
417
        }
418

419
        /* check for memory overlap */
420 1
        if (!(solve_may_share_memory(out, ap1, 1) == 0 &&
421 1
              solve_may_share_memory(out, ap2, 1) == 0)) {
422
            /* allocate temporary output array */
423 1
            out_buf = (PyArrayObject *)PyArray_NewLikeArray(out, NPY_CORDER,
424
                                                            NULL, 0);
425 1
            if (out_buf == NULL) {
426
                return NULL;
427
            }
428

429
            /* set copy-back */
430 1
            Py_INCREF(out);
431 1
            if (PyArray_SetWritebackIfCopyBase(out_buf, out) < 0) {
432 0
                Py_DECREF(out);
433 0
                Py_DECREF(out_buf);
434
                return NULL;
435
            }
436
        }
437
        else {
438 1
            Py_INCREF(out);
439 1
            out_buf = out;
440
        }
441

442 1
        if (result) {
443 1
            Py_INCREF(out);
444 1
            *result = out;
445
        }
446

447
        return out_buf;
448
    }
449
    else {
450
        PyTypeObject *subtype;
451
        double prior1, prior2;
452
        /*
453
         * Need to choose an output array that can hold a sum
454
         * -- use priority to determine which subtype.
455
         */
456 1
        if (Py_TYPE(ap2) != Py_TYPE(ap1)) {
457 1
            prior2 = PyArray_GetPriority((PyObject *)ap2, 0.0);
458 1
            prior1 = PyArray_GetPriority((PyObject *)ap1, 0.0);
459 1
            subtype = (prior2 > prior1 ? Py_TYPE(ap2) : Py_TYPE(ap1));
460
        }
461
        else {
462
            prior1 = prior2 = 0.0;
463
            subtype = Py_TYPE(ap1);
464
        }
465

466 1
        out_buf = (PyArrayObject *)PyArray_New(subtype, nd, dimensions,
467
                                               typenum, NULL, NULL, 0, 0,
468
                                               (PyObject *)
469
                                               (prior2 > prior1 ? ap2 : ap1));
470

471 1
        if (out_buf != NULL && result) {
472 1
            Py_INCREF(out_buf);
473 1
            *result = out_buf;
474
        }
475

476
        return out_buf;
477
    }
478
}
479

Read our documentation on viewing source code .

Loading