File: | _typeof.c |
Warning: | line 533, column 22 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #include "_pymodule.h" | ||||
2 | |||||
3 | #include <string.h> | ||||
4 | #include <time.h> | ||||
5 | #include <assert.h> | ||||
6 | |||||
7 | #include "_numba_common.h" | ||||
8 | #include "_typeof.h" | ||||
9 | #include "_hashtable.h" | ||||
10 | #include "_devicearray.h" | ||||
11 | #include "pyerrors.h" | ||||
12 | |||||
13 | #define NPY_NO_DEPRECATED_API0x00000007 NPY_1_7_API_VERSION0x00000007 | ||||
14 | #include <numpy/ndarrayobject.h> | ||||
15 | |||||
16 | |||||
17 | /* Cached typecodes for basic scalar types */ | ||||
18 | static int tc_int8; | ||||
19 | static int tc_int16; | ||||
20 | static int tc_int32; | ||||
21 | static int tc_int64; | ||||
22 | static int tc_uint8; | ||||
23 | static int tc_uint16; | ||||
24 | static int tc_uint32; | ||||
25 | static int tc_uint64; | ||||
26 | static int tc_float32; | ||||
27 | static int tc_float64; | ||||
28 | static int tc_complex64; | ||||
29 | static int tc_complex128; | ||||
30 | static int BASIC_TYPECODES[12]; | ||||
31 | |||||
32 | static int tc_intp; | ||||
33 | |||||
34 | /* The type object for the numba .dispatcher.OmittedArg class | ||||
35 | * that wraps omitted arguments. | ||||
36 | */ | ||||
37 | static PyObject *omittedarg_type; | ||||
38 | |||||
39 | static PyObject *typecache; | ||||
40 | static PyObject *ndarray_typecache; | ||||
41 | static PyObject *structured_dtypes; | ||||
42 | |||||
43 | static PyObject *str_typeof_pyval = NULL((void*)0); | ||||
44 | static PyObject *str_value = NULL((void*)0); | ||||
45 | static PyObject *str_numba_type = NULL((void*)0); | ||||
46 | |||||
47 | /* CUDA device array API */ | ||||
48 | void **DeviceArray_API; | ||||
49 | |||||
50 | /* | ||||
51 | * Type fingerprint computation. | ||||
52 | */ | ||||
53 | |||||
54 | typedef struct { | ||||
55 | /* A buffer the fingerprint will be written to */ | ||||
56 | char *buf; | ||||
57 | size_t n; | ||||
58 | size_t allocated; | ||||
59 | /* A preallocated buffer, sufficient to fit the fingerprint for most types */ | ||||
60 | char static_buf[40]; | ||||
61 | } string_writer_t; | ||||
62 | |||||
63 | static void | ||||
64 | string_writer_init(string_writer_t *w) | ||||
65 | { | ||||
66 | w->buf = w->static_buf; | ||||
67 | w->n = 0; | ||||
68 | w->allocated = sizeof(w->static_buf) / sizeof(unsigned char); | ||||
69 | } | ||||
70 | |||||
71 | static void | ||||
72 | string_writer_clear(string_writer_t *w) | ||||
73 | { | ||||
74 | if (w->buf != w->static_buf) | ||||
75 | free(w->buf); | ||||
76 | } | ||||
77 | |||||
78 | static void | ||||
79 | string_writer_move(string_writer_t *dest, const string_writer_t *src) | ||||
80 | { | ||||
81 | dest->n = src->n; | ||||
82 | dest->allocated = src->allocated; | ||||
83 | if (src->buf == src->static_buf) { | ||||
84 | dest->buf = dest->static_buf; | ||||
85 | memcpy(dest->buf, src->buf, src->n); | ||||
86 | } | ||||
87 | else { | ||||
88 | dest->buf = src->buf; | ||||
89 | } | ||||
90 | } | ||||
91 | |||||
92 | /* Ensure at least *bytes* can be appended to the string writer's buffer. */ | ||||
93 | static int | ||||
94 | string_writer_ensure(string_writer_t *w, size_t bytes) | ||||
95 | { | ||||
96 | size_t newsize; | ||||
97 | bytes += w->n; | ||||
98 | if (bytes <= w->allocated) | ||||
99 | return 0; | ||||
100 | newsize = (w->allocated << 2) + 1; | ||||
101 | if (newsize < bytes) | ||||
102 | newsize = bytes; | ||||
103 | if (w->buf == w->static_buf) | ||||
104 | w->buf = malloc(newsize); | ||||
105 | else | ||||
106 | w->buf = realloc(w->buf, newsize); | ||||
107 | if (w->buf) { | ||||
108 | w->allocated = newsize; | ||||
109 | return 0; | ||||
110 | } | ||||
111 | else { | ||||
112 | PyErr_NoMemory(); | ||||
113 | return -1; | ||||
114 | } | ||||
115 | } | ||||
116 | |||||
117 | static int | ||||
118 | string_writer_put_char(string_writer_t *w, unsigned char c) | ||||
119 | { | ||||
120 | if (string_writer_ensure(w, 1)) | ||||
121 | return -1; | ||||
122 | w->buf[w->n++] = c; | ||||
123 | return 0; | ||||
124 | } | ||||
125 | |||||
126 | static int | ||||
127 | string_writer_put_int32(string_writer_t *w, unsigned int v) | ||||
128 | { | ||||
129 | if (string_writer_ensure(w, 4)) | ||||
130 | return -1; | ||||
131 | w->buf[w->n] = v & 0xff; | ||||
132 | w->buf[w->n + 1] = (v >> 8) & 0xff; | ||||
133 | w->buf[w->n + 2] = (v >> 16) & 0xff; | ||||
134 | w->buf[w->n + 3] = (v >> 24) & 0xff; | ||||
135 | w->n += 4; | ||||
136 | return 0; | ||||
137 | } | ||||
138 | |||||
139 | static int | ||||
140 | string_writer_put_intp(string_writer_t *w, npy_intp v) | ||||
141 | { | ||||
142 | if (string_writer_ensure(w, NPY_SIZEOF_PY_INTPTR_T8)) | ||||
143 | return -1; | ||||
144 | w->buf[w->n] = v & 0xff; | ||||
145 | w->buf[w->n + 1] = (v >> 8) & 0xff; | ||||
146 | w->buf[w->n + 2] = (v >> 16) & 0xff; | ||||
147 | w->buf[w->n + 3] = (v >> 24) & 0xff; | ||||
148 | #if NPY_SIZEOF_PY_INTPTR_T8 == 8 | ||||
149 | w->buf[w->n + 4] = (v >> 32) & 0xff; | ||||
150 | w->buf[w->n + 5] = (v >> 40) & 0xff; | ||||
151 | w->buf[w->n + 6] = (v >> 48) & 0xff; | ||||
152 | w->buf[w->n + 7] = (v >> 56) & 0xff; | ||||
153 | #endif | ||||
154 | w->n += NPY_SIZEOF_PY_INTPTR_T8; | ||||
155 | return 0; | ||||
156 | } | ||||
157 | |||||
158 | static int | ||||
159 | string_writer_put_string(string_writer_t *w, const char *s) | ||||
160 | { | ||||
161 | if (s == NULL((void*)0)) { | ||||
162 | return string_writer_put_char(w, 0); | ||||
163 | } | ||||
164 | else { | ||||
165 | size_t N = strlen(s) + 1; | ||||
166 | if (string_writer_ensure(w, N)) | ||||
167 | return -1; | ||||
168 | memcpy(w->buf + w->n, s, N); | ||||
169 | w->n += N; | ||||
170 | return 0; | ||||
171 | } | ||||
172 | } | ||||
173 | |||||
174 | enum opcode { | ||||
175 | OP_START_TUPLE = '(', | ||||
176 | OP_END_TUPLE = ')', | ||||
177 | OP_INT = 'i', | ||||
178 | OP_FLOAT = 'f', | ||||
179 | OP_COMPLEX = 'c', | ||||
180 | OP_BOOL = '?', | ||||
181 | OP_OMITTED = '!', | ||||
182 | |||||
183 | OP_BYTEARRAY = 'a', | ||||
184 | OP_BYTES = 'b', | ||||
185 | OP_NONE = 'n', | ||||
186 | OP_LIST = '[', | ||||
187 | OP_SET = '{', | ||||
188 | |||||
189 | OP_BUFFER = 'B', | ||||
190 | OP_NP_SCALAR = 'S', | ||||
191 | OP_NP_ARRAY = 'A', | ||||
192 | OP_NP_DTYPE = 'D' | ||||
193 | }; | ||||
194 | |||||
195 | #define TRY(func, w, arg)do { if (func(w, arg)) return -1; } while (0) \ | ||||
196 | do { \ | ||||
197 | if (func(w, arg)) return -1; \ | ||||
198 | } while (0) | ||||
199 | |||||
200 | |||||
201 | static int | ||||
202 | fingerprint_unrecognized(void) | ||||
203 | { | ||||
204 | PyErr_SetString(PyExc_NotImplementedError, | ||||
205 | "cannot compute type fingerprint for value"); | ||||
206 | return -1; | ||||
207 | } | ||||
208 | |||||
209 | static int | ||||
210 | compute_dtype_fingerprint(string_writer_t *w, PyArray_Descr *descr) | ||||
211 | { | ||||
212 | int typenum = descr->type_num; | ||||
213 | if (typenum < NPY_OBJECT) | ||||
214 | return string_writer_put_char(w, (char) typenum); | ||||
215 | if (typenum == NPY_VOID) { | ||||
216 | /* Structured dtype: serialize the dtype pointer. Unfortunately, | ||||
217 | * some structured dtypes can be ephemeral, so we have to | ||||
218 | * intern them to avoid pointer reuse and fingerprint collisions. | ||||
219 | * (e.g. np.recarray(dtype=some_dtype) creates a new dtype | ||||
220 | * equal to some_dtype) | ||||
221 | */ | ||||
222 | PyObject *interned = PyDict_GetItem(structured_dtypes, | ||||
223 | (PyObject *) descr); | ||||
224 | if (interned == NULL((void*)0)) { | ||||
225 | interned = (PyObject *) descr; | ||||
226 | if (PyDict_SetItem(structured_dtypes, interned, interned)) | ||||
227 | return -1; | ||||
228 | } | ||||
229 | TRY(string_writer_put_char, w, (char) typenum)do { if (string_writer_put_char(w, (char) typenum)) return -1 ; } while (0); | ||||
230 | return string_writer_put_intp(w, (npy_intp) interned); | ||||
231 | } | ||||
232 | #if NPY_API_VERSION0x0000000D >= 0x00000007 | ||||
233 | if (PyTypeNum_ISDATETIME(typenum)(((typenum) >=NPY_DATETIME) && ((typenum) <=NPY_TIMEDELTA ))) { | ||||
234 | PyArray_DatetimeMetaData *md; | ||||
235 | md = &(((PyArray_DatetimeDTypeMetaData *)descr->c_metadata)->meta); | ||||
236 | TRY(string_writer_put_char, w, (char) typenum)do { if (string_writer_put_char(w, (char) typenum)) return -1 ; } while (0); | ||||
237 | TRY(string_writer_put_char, w, (char) md->base)do { if (string_writer_put_char(w, (char) md->base)) return -1; } while (0); | ||||
238 | return string_writer_put_int32(w, (char) md->num); | ||||
239 | } | ||||
240 | #endif | ||||
241 | |||||
242 | return fingerprint_unrecognized(); | ||||
243 | } | ||||
244 | |||||
245 | static int | ||||
246 | compute_fingerprint(string_writer_t *w, PyObject *val) | ||||
247 | { | ||||
248 | /* | ||||
249 | * Implementation note: for performance, we start with common | ||||
250 | * types that can be tested with fast checks. | ||||
251 | */ | ||||
252 | if (val == Py_None(&_Py_NoneStruct)) | ||||
253 | return string_writer_put_char(w, OP_NONE); | ||||
254 | if (PyBool_Check(val)((((PyObject*)(val))->ob_type) == &PyBool_Type)) | ||||
255 | return string_writer_put_char(w, OP_BOOL); | ||||
256 | /* Note we avoid matching int subclasses such as IntEnum */ | ||||
257 | if (PyInt_CheckExact(val)((((PyObject*)(val))->ob_type) == &PyLong_Type) || PyLong_CheckExact(val)((((PyObject*)(val))->ob_type) == &PyLong_Type)) | ||||
258 | return string_writer_put_char(w, OP_INT); | ||||
259 | if (PyFloat_Check(val)((((PyObject*)(val))->ob_type) == (&PyFloat_Type) || PyType_IsSubtype ((((PyObject*)(val))->ob_type), (&PyFloat_Type)))) | ||||
260 | return string_writer_put_char(w, OP_FLOAT); | ||||
261 | if (PyComplex_CheckExact(val)((((PyObject*)(val))->ob_type) == &PyComplex_Type)) | ||||
262 | return string_writer_put_char(w, OP_COMPLEX); | ||||
263 | if (PyTuple_Check(val)((((((PyObject*)(val))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||
264 | if(PyTuple_CheckExact(val)((((PyObject*)(val))->ob_type) == &PyTuple_Type)) { | ||||
265 | Py_ssize_t i, n; | ||||
266 | n = PyTuple_GET_SIZE(val)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(val))))-> ob_size); | ||||
267 | TRY(string_writer_put_char, w, OP_START_TUPLE)do { if (string_writer_put_char(w, OP_START_TUPLE)) return -1 ; } while (0); | ||||
268 | for (i = 0; i < n; i++) | ||||
269 | TRY(compute_fingerprint, w, PyTuple_GET_ITEM(val, i))do { if (compute_fingerprint(w, ((((void) (0)), (PyTupleObject *)(val))->ob_item[i]))) return -1; } while (0); | ||||
270 | TRY(string_writer_put_char, w, OP_END_TUPLE)do { if (string_writer_put_char(w, OP_END_TUPLE)) return -1; } while (0); | ||||
271 | return 0; | ||||
272 | } | ||||
273 | /* as per typeof.py, check "_asdict" for namedtuple. */ | ||||
274 | else if(PyObject_HasAttrString(val, "_asdict")) | ||||
275 | { | ||||
276 | /* | ||||
277 | * This encodes the class name and field names of a namedtuple into | ||||
278 | * the fingerprint on the condition that the number of fields is | ||||
279 | * small (<10) and that the class name and field names are encodable | ||||
280 | * as ASCII. | ||||
281 | */ | ||||
282 | PyObject * clazz = NULL((void*)0); | ||||
283 | PyObject * name = NULL((void*)0); | ||||
284 | PyObject * _fields = PyObject_GetAttrString(val, "_fields"); | ||||
285 | PyObject * field = NULL((void*)0); | ||||
286 | PyObject * ascii_str = NULL((void*)0); | ||||
287 | Py_ssize_t i, n, j, flen; | ||||
288 | char * buf = NULL((void*)0); | ||||
289 | int ret; | ||||
290 | |||||
291 | clazz = PyObject_GetAttrString(val, "__class__"); | ||||
292 | if (clazz == NULL((void*)0)) | ||||
293 | return -1; | ||||
294 | |||||
295 | name = PyObject_GetAttrString(clazz, "__name__"); | ||||
296 | Py_DECREF(clazz)_Py_DECREF(((PyObject*)(clazz))); | ||||
297 | if (name == NULL((void*)0)) | ||||
298 | return -1; | ||||
299 | |||||
300 | ascii_str = PyUnicode_AsEncodedString(name, "ascii", "ignore"); | ||||
301 | Py_DECREF(name)_Py_DECREF(((PyObject*)(name))); | ||||
302 | if (ascii_str == NULL((void*)0)) | ||||
303 | return -1; | ||||
304 | ret = PyBytes_AsStringAndSize(ascii_str, &buf, &flen); | ||||
305 | |||||
306 | if (ret == -1) | ||||
307 | return -1; | ||||
308 | for(j = 0; j < flen; j++) { | ||||
309 | TRY(string_writer_put_char, w, buf[j])do { if (string_writer_put_char(w, buf[j])) return -1; } while (0); | ||||
310 | } | ||||
311 | Py_DECREF(ascii_str)_Py_DECREF(((PyObject*)(ascii_str))); | ||||
312 | |||||
313 | if (_fields == NULL((void*)0)) | ||||
314 | return -1; | ||||
315 | |||||
316 | n = PyTuple_GET_SIZE(val)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(val))))-> ob_size); | ||||
317 | |||||
318 | TRY(string_writer_put_char, w, OP_START_TUPLE)do { if (string_writer_put_char(w, OP_START_TUPLE)) return -1 ; } while (0); | ||||
319 | for (i = 0; i < n; i++) { | ||||
320 | field = PyTuple_GET_ITEM(_fields, i)((((void) (0)), (PyTupleObject *)(_fields))->ob_item[i]); | ||||
321 | if (field == NULL((void*)0)) | ||||
322 | return -1; | ||||
323 | ascii_str = PyUnicode_AsEncodedString(field, "ascii", "ignore"); | ||||
324 | if (ascii_str == NULL((void*)0)) | ||||
325 | return -1; | ||||
326 | ret = PyBytes_AsStringAndSize(ascii_str, &buf, &flen); | ||||
327 | if (ret == -1) | ||||
328 | return -1; | ||||
329 | for(j = 0; j < flen; j++) { | ||||
330 | TRY(string_writer_put_char, w, buf[j])do { if (string_writer_put_char(w, buf[j])) return -1; } while (0); | ||||
331 | } | ||||
332 | Py_DECREF(ascii_str)_Py_DECREF(((PyObject*)(ascii_str))); | ||||
333 | TRY(compute_fingerprint, w, PyTuple_GET_ITEM(val, i))do { if (compute_fingerprint(w, ((((void) (0)), (PyTupleObject *)(val))->ob_item[i]))) return -1; } while (0); | ||||
334 | } | ||||
335 | TRY(string_writer_put_char, w, OP_END_TUPLE)do { if (string_writer_put_char(w, OP_END_TUPLE)) return -1; } while (0); | ||||
336 | Py_DECREF(_fields)_Py_DECREF(((PyObject*)(_fields))); | ||||
337 | return 0; | ||||
338 | } | ||||
339 | } | ||||
340 | if (PyBytes_Check(val)((((((PyObject*)(val))->ob_type))->tp_flags & ((1UL << 27))) != 0)) | ||||
341 | return string_writer_put_char(w, OP_BYTES); | ||||
342 | if (PyByteArray_Check(val)((((PyObject*)(val))->ob_type) == (&PyByteArray_Type) || PyType_IsSubtype((((PyObject*)(val))->ob_type), (&PyByteArray_Type )))) | ||||
343 | return string_writer_put_char(w, OP_BYTEARRAY); | ||||
344 | if ((PyObject *) Py_TYPE(val)(((PyObject*)(val))->ob_type) == omittedarg_type) { | ||||
345 | PyObject *default_val = PyObject_GetAttr(val, str_value); | ||||
346 | if (default_val == NULL((void*)0)) | ||||
347 | return -1; | ||||
348 | TRY(string_writer_put_char, w, OP_OMITTED)do { if (string_writer_put_char(w, OP_OMITTED)) return -1; } while (0); | ||||
349 | TRY(compute_fingerprint, w, default_val)do { if (compute_fingerprint(w, default_val)) return -1; } while (0); | ||||
350 | Py_DECREF(default_val)_Py_DECREF(((PyObject*)(default_val))); | ||||
351 | return 0; | ||||
352 | } | ||||
353 | if (PyArray_IsScalar(val, Generic)(((((PyObject*)(val))->ob_type) == (&(*(PyTypeObject * )PyArray_API[10])) || PyType_IsSubtype((((PyObject*)(val))-> ob_type), (&(*(PyTypeObject *)PyArray_API[10])))))) { | ||||
354 | /* Note: PyArray_DescrFromScalar() may be a bit slow on | ||||
355 | non-trivial types. */ | ||||
356 | PyArray_Descr *descr = PyArray_DescrFromScalar(*(PyArray_Descr * (*)(PyObject *)) PyArray_API[57])(val); | ||||
357 | if (descr == NULL((void*)0)) | ||||
358 | return -1; | ||||
359 | TRY(string_writer_put_char, w, OP_NP_SCALAR)do { if (string_writer_put_char(w, OP_NP_SCALAR)) return -1; } while (0); | ||||
360 | TRY(compute_dtype_fingerprint, w, descr)do { if (compute_dtype_fingerprint(w, descr)) return -1; } while (0); | ||||
361 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||
362 | return 0; | ||||
363 | } | ||||
364 | if (PyArray_Check(val)((((PyObject*)(val))->ob_type) == (&(*(PyTypeObject *) PyArray_API[2])) || PyType_IsSubtype((((PyObject*)(val))-> ob_type), (&(*(PyTypeObject *)PyArray_API[2]))))) { | ||||
365 | PyArrayObject *ary = (PyArrayObject *) val; | ||||
366 | int ndim = PyArray_NDIM(ary); | ||||
367 | |||||
368 | TRY(string_writer_put_char, w, OP_NP_ARRAY)do { if (string_writer_put_char(w, OP_NP_ARRAY)) return -1; } while (0); | ||||
369 | TRY(string_writer_put_int32, w, ndim)do { if (string_writer_put_int32(w, ndim)) return -1; } while (0); | ||||
370 | if (PyArray_IS_C_CONTIGUOUS(ary)PyArray_CHKFLAGS((ary), 0x0001)) | ||||
371 | TRY(string_writer_put_char, w, 'C')do { if (string_writer_put_char(w, 'C')) return -1; } while ( 0); | ||||
372 | else if (PyArray_IS_F_CONTIGUOUS(ary)PyArray_CHKFLAGS((ary), 0x0002)) | ||||
373 | TRY(string_writer_put_char, w, 'F')do { if (string_writer_put_char(w, 'F')) return -1; } while ( 0); | ||||
374 | else | ||||
375 | TRY(string_writer_put_char, w, 'A')do { if (string_writer_put_char(w, 'A')) return -1; } while ( 0); | ||||
376 | if (PyArray_ISWRITEABLE(ary)PyArray_CHKFLAGS((ary), 0x0400)) | ||||
377 | TRY(string_writer_put_char, w, 'W')do { if (string_writer_put_char(w, 'W')) return -1; } while ( 0); | ||||
378 | else | ||||
379 | TRY(string_writer_put_char, w, 'R')do { if (string_writer_put_char(w, 'R')) return -1; } while ( 0); | ||||
380 | return compute_dtype_fingerprint(w, PyArray_DESCR(ary)); | ||||
381 | } | ||||
382 | if (PyList_Check(val)((((((PyObject*)(val))->ob_type))->tp_flags & ((1UL << 25))) != 0)) { | ||||
383 | Py_ssize_t n = PyList_GET_SIZE(val)(((void) (0)), (((PyVarObject*)(val))->ob_size)); | ||||
384 | if (n == 0) { | ||||
385 | PyErr_SetString(PyExc_ValueError, | ||||
386 | "cannot compute fingerprint of empty list"); | ||||
387 | return -1; | ||||
388 | } | ||||
389 | /* Only the first item is considered, as in typeof.py */ | ||||
390 | TRY(string_writer_put_char, w, OP_LIST)do { if (string_writer_put_char(w, OP_LIST)) return -1; } while (0); | ||||
391 | TRY(compute_fingerprint, w, PyList_GET_ITEM(val, 0))do { if (compute_fingerprint(w, (((PyListObject *)(val))-> ob_item[0]))) return -1; } while (0); | ||||
392 | return 0; | ||||
393 | } | ||||
394 | /* Note we only accept sets, not frozensets */ | ||||
395 | if (Py_TYPE(val)(((PyObject*)(val))->ob_type) == &PySet_Type) { | ||||
396 | Py_hash_t h; | ||||
397 | PyObject *item; | ||||
398 | Py_ssize_t pos = 0; | ||||
399 | /* Only one item is considered, as in typeof.py */ | ||||
400 | if (!_PySet_NextEntry(val, &pos, &item, &h)) { | ||||
401 | /* Empty set */ | ||||
402 | PyErr_SetString(PyExc_ValueError, | ||||
403 | "cannot compute fingerprint of empty set"); | ||||
404 | return -1; | ||||
405 | } | ||||
406 | TRY(string_writer_put_char, w, OP_SET)do { if (string_writer_put_char(w, OP_SET)) return -1; } while (0); | ||||
407 | TRY(compute_fingerprint, w, item)do { if (compute_fingerprint(w, item)) return -1; } while (0); | ||||
408 | return 0; | ||||
409 | } | ||||
410 | if (PyObject_CheckBuffer(val)(((val)->ob_type->tp_as_buffer != ((void*)0)) && ((val)->ob_type->tp_as_buffer->bf_getbuffer != ((void *)0)))) { | ||||
411 | Py_buffer buf; | ||||
412 | int flags = PyBUF_ND0x0008 | PyBUF_STRIDES(0x0010 | 0x0008) | PyBUF_FORMAT0x0004; | ||||
413 | char contig; | ||||
414 | int ndim; | ||||
415 | char readonly; | ||||
416 | |||||
417 | /* Attempt to get a writable buffer, then fallback on read-only */ | ||||
418 | if (PyObject_GetBuffer(val, &buf, flags | PyBUF_WRITABLE0x0001)) { | ||||
419 | PyErr_Clear(); | ||||
420 | if (PyObject_GetBuffer(val, &buf, flags)) | ||||
421 | goto _unrecognized; | ||||
422 | } | ||||
423 | if (PyBuffer_IsContiguous(&buf, 'C')) | ||||
424 | contig = 'C'; | ||||
425 | else if (PyBuffer_IsContiguous(&buf, 'F')) | ||||
426 | contig = 'F'; | ||||
427 | else | ||||
428 | contig = 'A'; | ||||
429 | ndim = buf.ndim; | ||||
430 | readonly = buf.readonly ? 'R' : 'W'; | ||||
431 | if (string_writer_put_char(w, OP_BUFFER) || | ||||
432 | string_writer_put_int32(w, ndim) || | ||||
433 | string_writer_put_char(w, contig) || | ||||
434 | string_writer_put_char(w, readonly) || | ||||
435 | string_writer_put_string(w, buf.format) || | ||||
436 | /* We serialize the object's Python type as well, to | ||||
437 | distinguish between types which have Numba specializations | ||||
438 | (e.g. array.array() vs. memoryview) | ||||
439 | */ | ||||
440 | string_writer_put_intp(w, (npy_intp) Py_TYPE(val)(((PyObject*)(val))->ob_type))) { | ||||
441 | PyBuffer_Release(&buf); | ||||
442 | return -1; | ||||
443 | } | ||||
444 | PyBuffer_Release(&buf); | ||||
445 | return 0; | ||||
446 | } | ||||
447 | if (NUMBA_PyArray_DescrCheck(val)((((PyObject*)(val))->ob_type) == (&(*(PyTypeObject *) PyArray_API[3])) || PyType_IsSubtype((((PyObject*)(val))-> ob_type), (&(*(PyTypeObject *)PyArray_API[3]))))) { | ||||
448 | TRY(string_writer_put_char, w, OP_NP_DTYPE)do { if (string_writer_put_char(w, OP_NP_DTYPE)) return -1; } while (0); | ||||
449 | return compute_dtype_fingerprint(w, (PyArray_Descr *) val); | ||||
450 | } | ||||
451 | |||||
452 | _unrecognized: | ||||
453 | /* Type not recognized */ | ||||
454 | return fingerprint_unrecognized(); | ||||
455 | } | ||||
456 | |||||
457 | PyObject * | ||||
458 | typeof_compute_fingerprint(PyObject *val) | ||||
459 | { | ||||
460 | PyObject *res; | ||||
461 | string_writer_t w; | ||||
462 | |||||
463 | string_writer_init(&w); | ||||
464 | |||||
465 | if (compute_fingerprint(&w, val)) | ||||
466 | goto error; | ||||
467 | res = PyBytes_FromStringAndSize(w.buf, w.n); | ||||
468 | |||||
469 | string_writer_clear(&w); | ||||
470 | return res; | ||||
471 | |||||
472 | error: | ||||
473 | string_writer_clear(&w); | ||||
474 | return NULL((void*)0); | ||||
475 | } | ||||
476 | |||||
477 | /* | ||||
478 | * Getting the typecode from a Type object. | ||||
479 | */ | ||||
480 | static int | ||||
481 | _typecode_from_type_object(PyObject *tyobj) { | ||||
482 | int typecode; | ||||
483 | PyObject *tmpcode = PyObject_GetAttrString(tyobj, "_code"); | ||||
484 | if (tmpcode == NULL((void*)0)) { | ||||
485 | return -1; | ||||
486 | } | ||||
487 | typecode = PyLong_AsLong(tmpcode); | ||||
488 | Py_DECREF(tmpcode)_Py_DECREF(((PyObject*)(tmpcode))); | ||||
489 | return typecode; | ||||
490 | } | ||||
491 | |||||
492 | /* When we want to cache the type's typecode for later lookup, we need to | ||||
493 | keep a reference to the returned type object so that it cannot be | ||||
494 | deleted. This is because of the following events occurring when first | ||||
495 | using a @jit function for a given set of types: | ||||
496 | |||||
497 | 1. typecode_fallback requests a new typecode for an arbitrary Python value; | ||||
498 | this implies creating a Numba type object (on the first dispatcher call); | ||||
499 | the typecode cache is then populated. | ||||
500 | 2. matching of the typecode list in _dispatcherimpl.cpp fails, since the | ||||
501 | typecode is new. | ||||
502 | 3. we have to compile: compile_and_invoke() is called, it will invoke | ||||
503 | Dispatcher_Insert to register the new signature. | ||||
504 | |||||
505 | The reference to the Numba type object returned in step 1 is deleted as | ||||
506 | soon as we call Py_DECREF() on it, since we are holding the only | ||||
507 | reference. If this happens and we use the typecode we got to populate the | ||||
508 | cache, then the cache won't ever return the correct typecode, and the | ||||
509 | dispatcher will never successfully match the typecodes with those of | ||||
510 | some already-compiled instance. So we need to make sure that we don't | ||||
511 | call Py_DECREF() on objects whose typecode will be used to populate the | ||||
512 | cache. This is ensured by calling _typecode_fallback with | ||||
513 | retain_reference == 0. | ||||
514 | |||||
515 | Note that technically we are leaking the reference, since we do not continue | ||||
516 | to hold a pointer to the type object that we get back from typeof_pyval. | ||||
517 | However, we don't need to refer to it again, we just need to make sure that | ||||
518 | it is never deleted. | ||||
519 | */ | ||||
520 | static int | ||||
521 | _typecode_fallback(PyObject *dispatcher, PyObject *val, | ||||
522 | int retain_reference) { | ||||
523 | PyObject *numba_type; | ||||
524 | int typecode; | ||||
525 | |||||
526 | /* | ||||
527 | * For values that define "_numba_type_", which holds a numba Type | ||||
528 | * instance that should be used as the type of the value. | ||||
529 | * Note this is done here, not in typeof_typecode(), so that | ||||
530 | * some values can still benefit from fingerprint caching. | ||||
531 | */ | ||||
532 | if (PyObject_HasAttr(val, str_numba_type)) { | ||||
533 | numba_type = PyObject_GetAttrString(val, "_numba_type_"); | ||||
| |||||
534 | if (!numba_type) | ||||
535 | return -1; | ||||
536 | } | ||||
537 | else { | ||||
538 | // Go back to the interpreter | ||||
539 | numba_type = PyObject_CallMethodObjArgs((PyObject *) dispatcher, | ||||
540 | str_typeof_pyval, val, NULL((void*)0)); | ||||
541 | } | ||||
542 | if (!numba_type
| ||||
543 | return -1; | ||||
544 | typecode = _typecode_from_type_object(numba_type); | ||||
545 | if (!retain_reference
| ||||
546 | Py_DECREF(numba_type)_Py_DECREF(((PyObject*)(numba_type))); | ||||
547 | return typecode; | ||||
548 | } | ||||
549 | |||||
550 | /* Variations on _typecode_fallback for convenience */ | ||||
551 | |||||
552 | static | ||||
553 | int typecode_fallback(PyObject *dispatcher, PyObject *val) { | ||||
554 | return _typecode_fallback(dispatcher, val, 0); | ||||
555 | } | ||||
556 | |||||
557 | static | ||||
558 | int typecode_fallback_keep_ref(PyObject *dispatcher, PyObject *val) { | ||||
559 | return _typecode_fallback(dispatcher, val, 1); | ||||
560 | } | ||||
561 | |||||
562 | |||||
563 | /* A cache mapping fingerprints (string_writer_t *) to typecodes (int). */ | ||||
564 | static _Numba_hashtable_t *fingerprint_hashtable = NULL((void*)0); | ||||
565 | |||||
566 | static Py_uhash_t | ||||
567 | hash_writer(const void *key) | ||||
568 | { | ||||
569 | string_writer_t *writer = (string_writer_t *) key; | ||||
570 | Py_uhash_t x = 0; | ||||
571 | |||||
572 | /* The old FNV algorithm used by Python 2 */ | ||||
573 | if (writer->n > 0) { | ||||
574 | unsigned char *p = (unsigned char *) writer->buf; | ||||
575 | Py_ssize_t len = writer->n; | ||||
576 | x ^= *p << 7; | ||||
577 | while (--len >= 0) | ||||
578 | x = (1000003*x) ^ *p++; | ||||
579 | x ^= writer->n; | ||||
580 | if (x == (Py_uhash_t) -1) | ||||
581 | x = -2; | ||||
582 | } | ||||
583 | return x; | ||||
584 | } | ||||
585 | |||||
586 | static int | ||||
587 | compare_writer(const void *key, const _Numba_hashtable_entry_t *entry) | ||||
588 | { | ||||
589 | string_writer_t *v = (string_writer_t *) key; | ||||
590 | string_writer_t *w = (string_writer_t *) entry->key; | ||||
591 | if (v->n != w->n) | ||||
592 | return 0; | ||||
593 | return memcmp(v->buf, w->buf, v->n) == 0; | ||||
594 | } | ||||
595 | |||||
596 | /* Try to compute *val*'s typecode using its fingerprint and the | ||||
597 | * fingerprint->typecode cache. | ||||
598 | */ | ||||
599 | static int | ||||
600 | typecode_using_fingerprint(PyObject *dispatcher, PyObject *val) | ||||
601 | { | ||||
602 | int typecode; | ||||
603 | string_writer_t w; | ||||
604 | |||||
605 | string_writer_init(&w); | ||||
606 | |||||
607 | if (compute_fingerprint(&w, val)) { | ||||
608 | string_writer_clear(&w); | ||||
609 | if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) { | ||||
610 | /* Can't compute a type fingerprint for the given value, | ||||
611 | fall back on typeof() without caching. */ | ||||
612 | PyErr_Clear(); | ||||
613 | return typecode_fallback(dispatcher, val); | ||||
614 | } | ||||
615 | return -1; | ||||
616 | } | ||||
617 | if (_Numba_HASHTABLE_GET(fingerprint_hashtable, &w, typecode)_Numba_hashtable_get(fingerprint_hashtable, &w, &(typecode ), sizeof(typecode)) > 0) { | ||||
618 | /* Cache hit */ | ||||
619 | string_writer_clear(&w); | ||||
620 | return typecode; | ||||
621 | } | ||||
622 | |||||
623 | /* Not found in cache: invoke pure Python typeof() and cache result. | ||||
624 | * Note we have to keep the type alive forever as explained | ||||
625 | * above in _typecode_fallback(). | ||||
626 | */ | ||||
627 | typecode = typecode_fallback_keep_ref(dispatcher, val); | ||||
628 | if (typecode >= 0) { | ||||
629 | string_writer_t *key = (string_writer_t *) malloc(sizeof(string_writer_t)); | ||||
630 | if (key == NULL((void*)0)) { | ||||
631 | string_writer_clear(&w); | ||||
632 | PyErr_NoMemory(); | ||||
633 | return -1; | ||||
634 | } | ||||
635 | /* Ownership of the string writer's buffer will be transferred | ||||
636 | * to the hash table. | ||||
637 | */ | ||||
638 | string_writer_move(key, &w); | ||||
639 | if (_Numba_HASHTABLE_SET(fingerprint_hashtable, key, typecode)_Numba_hashtable_set(fingerprint_hashtable, key, &(typecode ), sizeof(typecode))) { | ||||
640 | string_writer_clear(&w); | ||||
641 | PyErr_NoMemory(); | ||||
642 | return -1; | ||||
643 | } | ||||
644 | } | ||||
645 | return typecode; | ||||
646 | } | ||||
647 | |||||
648 | |||||
649 | /* | ||||
650 | * Direct lookup table for extra-fast typecode resolution of simple array types. | ||||
651 | */ | ||||
652 | |||||
653 | #define N_DTYPES12 12 | ||||
654 | #define N_NDIM5 5 /* Fast path for up to 5D array */ | ||||
655 | #define N_LAYOUT3 3 | ||||
656 | static int cached_arycode[N_NDIM5][N_LAYOUT3][N_DTYPES12]; | ||||
657 | |||||
658 | /* Convert a Numpy dtype number to an internal index into cached_arycode. | ||||
659 | The returned value must also be a valid index into BASIC_TYPECODES. */ | ||||
660 | static int dtype_num_to_typecode(int type_num) { | ||||
661 | int dtype; | ||||
662 | switch(type_num) { | ||||
663 | case NPY_INT8NPY_BYTE: | ||||
664 | dtype = 0; | ||||
665 | break; | ||||
666 | case NPY_INT16NPY_SHORT: | ||||
667 | dtype = 1; | ||||
668 | break; | ||||
669 | case NPY_INT32NPY_INT: | ||||
670 | dtype = 2; | ||||
671 | break; | ||||
672 | case NPY_INT64NPY_LONG: | ||||
673 | dtype = 3; | ||||
674 | break; | ||||
675 | case NPY_UINT8NPY_UBYTE: | ||||
676 | dtype = 4; | ||||
677 | break; | ||||
678 | case NPY_UINT16NPY_USHORT: | ||||
679 | dtype = 5; | ||||
680 | break; | ||||
681 | case NPY_UINT32NPY_UINT: | ||||
682 | dtype = 6; | ||||
683 | break; | ||||
684 | case NPY_UINT64NPY_ULONG: | ||||
685 | dtype = 7; | ||||
686 | break; | ||||
687 | case NPY_FLOAT32NPY_FLOAT: | ||||
688 | dtype = 8; | ||||
689 | break; | ||||
690 | case NPY_FLOAT64NPY_DOUBLE: | ||||
691 | dtype = 9; | ||||
692 | break; | ||||
693 | case NPY_COMPLEX64NPY_CFLOAT: | ||||
694 | dtype = 10; | ||||
695 | break; | ||||
696 | case NPY_COMPLEX128NPY_CDOUBLE: | ||||
697 | dtype = 11; | ||||
698 | break; | ||||
699 | default: | ||||
700 | /* Type not included in the global lookup table */ | ||||
701 | dtype = -1; | ||||
702 | } | ||||
703 | return dtype; | ||||
704 | } | ||||
705 | |||||
706 | static | ||||
707 | int get_cached_typecode(PyArray_Descr* descr) { | ||||
708 | PyObject* tmpobject = PyDict_GetItem(typecache, (PyObject*)descr); | ||||
709 | if (tmpobject == NULL((void*)0)) | ||||
710 | return -1; | ||||
711 | |||||
712 | return PyLong_AsLong(tmpobject); | ||||
713 | } | ||||
714 | |||||
715 | static | ||||
716 | void cache_typecode(PyArray_Descr* descr, int typecode) { | ||||
717 | PyObject* value = PyLong_FromLong(typecode); | ||||
718 | PyDict_SetItem(typecache, (PyObject*)descr, value); | ||||
719 | Py_DECREF(value)_Py_DECREF(((PyObject*)(value))); | ||||
720 | } | ||||
721 | |||||
722 | static | ||||
723 | PyObject* ndarray_key(int ndim, int layout, PyArray_Descr* descr) { | ||||
724 | PyObject* tmpndim = PyLong_FromLong(ndim); | ||||
725 | PyObject* tmplayout = PyLong_FromLong(layout); | ||||
726 | PyObject* key = PyTuple_Pack(3, tmpndim, tmplayout, descr); | ||||
727 | Py_DECREF(tmpndim)_Py_DECREF(((PyObject*)(tmpndim))); | ||||
728 | Py_DECREF(tmplayout)_Py_DECREF(((PyObject*)(tmplayout))); | ||||
729 | return key; | ||||
730 | } | ||||
731 | |||||
732 | static | ||||
733 | int get_cached_ndarray_typecode(int ndim, int layout, PyArray_Descr* descr) { | ||||
734 | PyObject* key = ndarray_key(ndim, layout, descr); | ||||
735 | PyObject *tmpobject = PyDict_GetItem(ndarray_typecache, key); | ||||
736 | if (tmpobject == NULL((void*)0)) | ||||
737 | return -1; | ||||
738 | |||||
739 | Py_DECREF(key)_Py_DECREF(((PyObject*)(key))); | ||||
740 | return PyLong_AsLong(tmpobject); | ||||
741 | } | ||||
742 | |||||
743 | static | ||||
744 | void cache_ndarray_typecode(int ndim, int layout, PyArray_Descr* descr, | ||||
745 | int typecode) { | ||||
746 | PyObject* key = ndarray_key(ndim, layout, descr); | ||||
747 | PyObject* value = PyLong_FromLong(typecode); | ||||
748 | PyDict_SetItem(ndarray_typecache, key, value); | ||||
749 | Py_DECREF(key)_Py_DECREF(((PyObject*)(key))); | ||||
750 | Py_DECREF(value)_Py_DECREF(((PyObject*)(value))); | ||||
751 | } | ||||
752 | |||||
753 | static | ||||
754 | int typecode_ndarray(PyObject *dispatcher, PyArrayObject *ary) { | ||||
755 | int typecode; | ||||
756 | int dtype; | ||||
757 | int ndim = PyArray_NDIM(ary); | ||||
758 | int layout = 0; | ||||
759 | |||||
760 | /* The order in which we check for the right contiguous-ness is important. | ||||
761 | The order must match the order by numba.numpy_support.map_layout. | ||||
762 | Further, only *contiguous-ness* is checked, not alignment, byte order or | ||||
763 | write permissions. | ||||
764 | */ | ||||
765 | if (PyArray_IS_C_CONTIGUOUS(ary)PyArray_CHKFLAGS((ary), 0x0001)){ | ||||
766 | layout = 1; | ||||
767 | } else if (PyArray_IS_F_CONTIGUOUS(ary)PyArray_CHKFLAGS((ary), 0x0002)) { | ||||
768 | layout = 2; | ||||
769 | } | ||||
770 | |||||
771 | /* the typecode cache by convention is for "behaved" arrays (aligned and | ||||
772 | * writeable), all others must be forced to the fall back */ | ||||
773 | if (!PyArray_ISBEHAVED(ary)(PyArray_CHKFLAGS(ary, (0x0100 | 0x0400)) && ((PyArray_DESCR (ary)->byteorder) != '>'))) goto FALLBACK; | ||||
774 | |||||
775 | if (ndim <= 0 || ndim > N_NDIM5) goto FALLBACK; | ||||
776 | |||||
777 | dtype = dtype_num_to_typecode(PyArray_TYPE(ary)); | ||||
778 | if (dtype == -1) goto FALLBACK; | ||||
779 | |||||
780 | /* Fast path, using direct table lookup */ | ||||
781 | assert(layout < N_LAYOUT)((void) (0)); | ||||
782 | assert(ndim <= N_NDIM)((void) (0)); | ||||
783 | assert(dtype < N_DTYPES)((void) (0)); | ||||
784 | |||||
785 | typecode = cached_arycode[ndim - 1][layout][dtype]; | ||||
786 | if (typecode == -1) { | ||||
787 | /* First use of this table entry, so it requires populating */ | ||||
788 | typecode = typecode_fallback_keep_ref(dispatcher, (PyObject*)ary); | ||||
789 | cached_arycode[ndim - 1][layout][dtype] = typecode; | ||||
790 | } | ||||
791 | return typecode; | ||||
792 | |||||
793 | FALLBACK: | ||||
794 | /* Slower path, for non-trivial array types */ | ||||
795 | |||||
796 | /* If this isn't a structured array then we can't use the cache */ | ||||
797 | if (PyArray_TYPE(ary) != NPY_VOID) | ||||
798 | return typecode_using_fingerprint(dispatcher, (PyObject *) ary); | ||||
799 | |||||
800 | /* Check type cache */ | ||||
801 | typecode = get_cached_ndarray_typecode(ndim, layout, PyArray_DESCR(ary)); | ||||
802 | if (typecode == -1) { | ||||
803 | /* First use of this type, use fallback and populate the cache */ | ||||
804 | typecode = typecode_fallback_keep_ref(dispatcher, (PyObject*)ary); | ||||
805 | cache_ndarray_typecode(ndim, layout, PyArray_DESCR(ary), typecode); | ||||
806 | } | ||||
807 | return typecode; | ||||
808 | } | ||||
809 | |||||
810 | static | ||||
811 | int typecode_arrayscalar(PyObject *dispatcher, PyObject* aryscalar) { | ||||
812 | int typecode; | ||||
813 | PyArray_Descr *descr; | ||||
814 | descr = PyArray_DescrFromScalar(*(PyArray_Descr * (*)(PyObject *)) PyArray_API[57])(aryscalar); | ||||
815 | if (!descr) | ||||
816 | return typecode_using_fingerprint(dispatcher, aryscalar); | ||||
817 | |||||
818 | /* Is it a structured scalar? */ | ||||
819 | if (descr->type_num == NPY_VOID) { | ||||
820 | typecode = get_cached_typecode(descr); | ||||
821 | if (typecode == -1) { | ||||
822 | /* Resolve through fallback then populate cache */ | ||||
823 | typecode = typecode_fallback_keep_ref(dispatcher, aryscalar); | ||||
824 | cache_typecode(descr, typecode); | ||||
825 | } | ||||
826 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||
827 | return typecode; | ||||
828 | } | ||||
829 | |||||
830 | /* Is it one of the well-known basic types? */ | ||||
831 | typecode = dtype_num_to_typecode(descr->type_num); | ||||
832 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | ||||
833 | if (typecode == -1) | ||||
834 | return typecode_using_fingerprint(dispatcher, aryscalar); | ||||
835 | return BASIC_TYPECODES[typecode]; | ||||
836 | } | ||||
837 | |||||
838 | static | ||||
839 | int typecode_devicendarray(PyObject *dispatcher, PyObject *ary) | ||||
840 | { | ||||
841 | int typecode; | ||||
842 | int dtype; | ||||
843 | int ndim; | ||||
844 | int layout = 0; | ||||
845 | |||||
846 | PyObject* flags = PyObject_GetAttrString(ary, "flags"); | ||||
847 | if (flags == NULL((void*)0)) | ||||
848 | { | ||||
849 | PyErr_Clear(); | ||||
850 | goto FALLBACK; | ||||
851 | } | ||||
852 | |||||
853 | if (PyDict_GetItemString(flags, "C_CONTIGUOUS") == Py_True((PyObject *) &_Py_TrueStruct)) { | ||||
854 | layout = 1; | ||||
855 | } else if (PyDict_GetItemString(flags, "F_CONTIGUOUS") == Py_True((PyObject *) &_Py_TrueStruct)) { | ||||
856 | layout = 2; | ||||
857 | } | ||||
858 | |||||
859 | Py_DECREF(flags)_Py_DECREF(((PyObject*)(flags))); | ||||
860 | |||||
861 | PyObject *ndim_obj = PyObject_GetAttrString(ary, "ndim"); | ||||
862 | if (ndim_obj == NULL((void*)0)) { | ||||
863 | /* If there's no ndim, try to proceed by clearing the error and using the | ||||
864 | * fallback. */ | ||||
865 | PyErr_Clear(); | ||||
866 | goto FALLBACK; | ||||
867 | } | ||||
868 | |||||
869 | ndim = PyLong_AsLong(ndim_obj); | ||||
870 | Py_DECREF(ndim_obj)_Py_DECREF(((PyObject*)(ndim_obj))); | ||||
871 | |||||
872 | if (PyErr_Occurred()) { | ||||
873 | /* ndim wasn't an integer for some reason - unlikely to happen, but try | ||||
874 | * the fallback. */ | ||||
875 | PyErr_Clear(); | ||||
876 | goto FALLBACK; | ||||
877 | } | ||||
878 | |||||
879 | if (ndim <= 0 || ndim > N_NDIM5) | ||||
880 | goto FALLBACK; | ||||
881 | |||||
882 | PyObject* dtype_obj = PyObject_GetAttrString(ary, "dtype"); | ||||
883 | if (dtype_obj == NULL((void*)0)) { | ||||
884 | /* No dtype: try the fallback. */ | ||||
885 | PyErr_Clear(); | ||||
886 | goto FALLBACK; | ||||
887 | } | ||||
888 | |||||
889 | PyObject* num_obj = PyObject_GetAttrString(dtype_obj, "num"); | ||||
890 | Py_DECREF(dtype_obj)_Py_DECREF(((PyObject*)(dtype_obj))); | ||||
891 | |||||
892 | if (num_obj == NULL((void*)0)) { | ||||
893 | /* This strange dtype has no num - try the fallback. */ | ||||
894 | PyErr_Clear(); | ||||
895 | goto FALLBACK; | ||||
896 | } | ||||
897 | |||||
898 | int dtype_num = PyLong_AsLong(num_obj); | ||||
899 | Py_DECREF(num_obj)_Py_DECREF(((PyObject*)(num_obj))); | ||||
900 | |||||
901 | if (PyErr_Occurred()) { | ||||
902 | /* num wasn't an integer for some reason - unlikely to happen, but try | ||||
903 | * the fallback. */ | ||||
904 | PyErr_Clear(); | ||||
905 | goto FALLBACK; | ||||
906 | } | ||||
907 | |||||
908 | dtype = dtype_num_to_typecode(dtype_num); | ||||
909 | if (dtype == -1) { | ||||
910 | /* Not a dtype we have in the global lookup table. */ | ||||
911 | goto FALLBACK; | ||||
912 | } | ||||
913 | |||||
914 | /* Fast path, using direct table lookup */ | ||||
915 | assert(layout < N_LAYOUT)((void) (0)); | ||||
916 | assert(ndim <= N_NDIM)((void) (0)); | ||||
917 | assert(dtype < N_DTYPES)((void) (0)); | ||||
918 | typecode = cached_arycode[ndim - 1][layout][dtype]; | ||||
919 | |||||
920 | if (typecode == -1) { | ||||
921 | /* First use of this table entry, so it requires populating */ | ||||
922 | typecode = typecode_fallback_keep_ref(dispatcher, (PyObject*)ary); | ||||
923 | cached_arycode[ndim - 1][layout][dtype] = typecode; | ||||
924 | } | ||||
925 | |||||
926 | return typecode; | ||||
927 | |||||
928 | FALLBACK: | ||||
929 | /* Slower path, for non-trivial array types. At present this always uses | ||||
930 | the fingerprinting to get the typecode. Future optimization might | ||||
931 | implement a cache, but this would require some fast equivalent of | ||||
932 | PyArray_DESCR for a device array. */ | ||||
933 | |||||
934 | return typecode_using_fingerprint(dispatcher, (PyObject *) ary); | ||||
935 | } | ||||
936 | |||||
937 | int | ||||
938 | typeof_typecode(PyObject *dispatcher, PyObject *val) | ||||
939 | { | ||||
940 | PyTypeObject *tyobj = Py_TYPE(val)(((PyObject*)(val))->ob_type); | ||||
941 | int subtype_attr; | ||||
942 | /* This needs to be kept in sync with Dispatcher.typeof_pyval(), | ||||
943 | * otherwise funny things may happen. | ||||
944 | */ | ||||
945 | if (tyobj == &PyInt_TypePyLong_Type || tyobj == &PyLong_Type) { | ||||
| |||||
946 | #if SIZEOF_VOID_P8 < 8 | ||||
947 | /* On 32-bit platforms, choose between tc_intp (32-bit) and tc_int64 */ | ||||
948 | PY_LONG_LONGlong long ll = PyLong_AsLongLong(val); | ||||
949 | if (ll == -1 && PyErr_Occurred()) { | ||||
950 | /* The integer is too large, let us truncate it */ | ||||
951 | PyErr_Clear(); | ||||
952 | return tc_int64; | ||||
953 | } | ||||
954 | if ((ll & 0xffffffff) != ll) | ||||
955 | return tc_int64; | ||||
956 | #endif | ||||
957 | return tc_intp; | ||||
958 | } | ||||
959 | else if (tyobj == &PyFloat_Type) | ||||
960 | return tc_float64; | ||||
961 | else if (tyobj == &PyComplex_Type) | ||||
962 | return tc_complex128; | ||||
963 | /* Array scalar handling */ | ||||
964 | else if (PyArray_CheckScalar(val)((((((PyObject*)(val))->ob_type) == (&(*(PyTypeObject * )PyArray_API[10])) || PyType_IsSubtype((((PyObject*)(val))-> ob_type), (&(*(PyTypeObject *)PyArray_API[10]))))) || ((( ((PyObject*)(val))->ob_type) == (&(*(PyTypeObject *)PyArray_API [2])) || PyType_IsSubtype((((PyObject*)(val))->ob_type), ( &(*(PyTypeObject *)PyArray_API[2])))) && (PyArray_NDIM ((PyArrayObject *)val) == 0)))) { | ||||
965 | return typecode_arrayscalar(dispatcher, val); | ||||
966 | } | ||||
967 | /* Array handling */ | ||||
968 | else if (tyobj == &PyArray_Type(*(PyTypeObject *)PyArray_API[2])) { | ||||
969 | return typecode_ndarray(dispatcher, (PyArrayObject*)val); | ||||
970 | } | ||||
971 | /* Subtype of CUDA device array */ | ||||
972 | else if (PyType_IsSubtype(tyobj, &DeviceArrayType(*(PyTypeObject*)DeviceArray_API[0]))) { | ||||
973 | return typecode_devicendarray(dispatcher, val); | ||||
974 | } | ||||
975 | /* Subtypes of Array handling */ | ||||
976 | else if (PyType_IsSubtype(tyobj, &PyArray_Type(*(PyTypeObject *)PyArray_API[2]))) { | ||||
977 | /* By default, Numba will treat all numpy.ndarray subtypes as if they | ||||
978 | were the base numpy.ndarray type. In this way, ndarray subtypes | ||||
979 | can easily use all of the support that Numba has for ndarray | ||||
980 | methods. | ||||
981 | EXPERIMENTAL: There may be cases where a programmer would NOT want | ||||
982 | ndarray subtypes to be treated exactly like the base numpy.ndarray. | ||||
983 | For this purpose, a currently experimental feature allows a | ||||
984 | programmer to add an attribute named | ||||
985 | __numba_array_subtype_dispatch__ to their ndarray subtype. This | ||||
986 | attribute can have any value as Numba only checks for the presence | ||||
987 | of the attribute and not its value. When present, a ndarray subtype | ||||
988 | will NOT be typed by Numba as a regular ndarray but this code will | ||||
989 | fallthrough to the typecode_using_fingerprint call, which will | ||||
990 | create a new unique Numba typecode for this ndarray subtype. This | ||||
991 | behavior has several significant effects. First, since this | ||||
992 | ndarray subtype will be treated as a different type by Numba, | ||||
993 | the Numba dispatcher would then specialize on this type. So, if | ||||
994 | there was a function that had several parameters that were | ||||
995 | expected to be either numpy.ndarray or a subtype of ndarray, then | ||||
996 | Numba would compile a custom version of this function for each | ||||
997 | combination of base and subtypes that were actually passed to the | ||||
998 | function. Second, because this subtype would now be treated as | ||||
999 | a totally separate type, it will cease to function in Numba unless | ||||
1000 | an implementation of that type is provided to Numba through the | ||||
1001 | Numba type extension mechanisms (e.g., overload). This would | ||||
1002 | typically start with defining a Numba type corresponding to the | ||||
1003 | ndarray subtype. This is the same concept as how Numba has a | ||||
1004 | corollary of numpy.ndarray in its type system as types.Array. | ||||
1005 | Next, one would typically defining boxing and unboxing routines | ||||
1006 | and the associated memory model. Then, overloads for NumPy | ||||
1007 | functions on that type would be created. However, | ||||
1008 | if the same default array memory model is used then there are tricks | ||||
1009 | one can do to look at Numba's internal types.Array registries and | ||||
1010 | to quickly apply those to the subtype as well. In this manner, | ||||
1011 | only those cases where the base ndarray and the ndarray subtype | ||||
1012 | behavior differ would new custom functions need to be written for | ||||
1013 | the subtype. Finally, | ||||
1014 | after adding support for the new type, you would have a separate | ||||
1015 | ndarray subtype that could operate with other objects of the same | ||||
1016 | subtype but would not support interoperation with regular NumPy | ||||
1017 | ndarrays. In standard Python, this interoperation is provided | ||||
1018 | through the __array_ufunc__ magic method in the ndarray subtype | ||||
1019 | class and in that case the function operates on ndarrays or their | ||||
1020 | subtypes. This idea is extended into Numba such that | ||||
1021 | __array_ufunc__ can be present in a Numba array type object. | ||||
1022 | In this case, this function is consulted during Numba typing and | ||||
1023 | so the arguments to __array_ufunc__ are Numba types instead of | ||||
1024 | ndarray subtypes. The array type __array_ufunc__ returns the | ||||
1025 | type of the output of the given ufunc. | ||||
1026 | */ | ||||
1027 | subtype_attr = PyObject_HasAttrString(val, "__numba_array_subtype_dispatch__"); | ||||
1028 | if (!subtype_attr) { | ||||
1029 | return typecode_ndarray(dispatcher, (PyArrayObject*)val); | ||||
1030 | } | ||||
1031 | } | ||||
1032 | |||||
1033 | return typecode_using_fingerprint(dispatcher, val); | ||||
1034 | } | ||||
1035 | |||||
1036 | |||||
1037 | static | ||||
1038 | void* wrap_import_array(void) { | ||||
1039 | import_array(){if (_import_array() < 0) {PyErr_Print(); PyErr_SetString( PyExc_ImportError, "numpy.core.multiarray failed to import"); return ((void*)0); } }; /* import array returns NULL on failure */ | ||||
1040 | return (void*)1; | ||||
1041 | } | ||||
1042 | |||||
1043 | |||||
1044 | static | ||||
1045 | int init_numpy(void) { | ||||
1046 | return wrap_import_array() != NULL((void*)0); | ||||
1047 | } | ||||
1048 | |||||
1049 | |||||
1050 | /* | ||||
1051 | * typeof_init(omittedarg_type, typecode_dict) | ||||
1052 | * (called from dispatcher.py to fill in missing information) | ||||
1053 | */ | ||||
1054 | PyObject * | ||||
1055 | typeof_init(PyObject *self, PyObject *args) | ||||
1056 | { | ||||
1057 | PyObject *tmpobj; | ||||
1058 | PyObject *dict; | ||||
1059 | int index = 0; | ||||
1060 | |||||
1061 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O!O!:typeof_init", | ||||
1062 | &PyType_Type, &omittedarg_type, | ||||
1063 | &PyDict_Type, &dict)) | ||||
1064 | return NULL((void*)0); | ||||
1065 | |||||
1066 | /* Initialize Numpy API */ | ||||
1067 | if ( ! init_numpy() ) { | ||||
1068 | return NULL((void*)0); | ||||
1069 | } | ||||
1070 | |||||
1071 | #define UNWRAP_TYPE(S) \ | ||||
1072 | if(!(tmpobj = PyDict_GetItemString(dict, #S))) return NULL((void*)0); \ | ||||
1073 | else { tc_##S = PyLong_AsLong(tmpobj); \ | ||||
1074 | BASIC_TYPECODES[index++] = tc_##S; } | ||||
1075 | |||||
1076 | UNWRAP_TYPE(int8) | ||||
1077 | UNWRAP_TYPE(int16) | ||||
1078 | UNWRAP_TYPE(int32) | ||||
1079 | UNWRAP_TYPE(int64) | ||||
1080 | |||||
1081 | UNWRAP_TYPE(uint8) | ||||
1082 | UNWRAP_TYPE(uint16) | ||||
1083 | UNWRAP_TYPE(uint32) | ||||
1084 | UNWRAP_TYPE(uint64) | ||||
1085 | |||||
1086 | UNWRAP_TYPE(float32) | ||||
1087 | UNWRAP_TYPE(float64) | ||||
1088 | |||||
1089 | UNWRAP_TYPE(complex64) | ||||
1090 | UNWRAP_TYPE(complex128) | ||||
1091 | |||||
1092 | switch(sizeof(void*)) { | ||||
1093 | case 4: | ||||
1094 | tc_intp = tc_int32; | ||||
1095 | break; | ||||
1096 | case 8: | ||||
1097 | tc_intp = tc_int64; | ||||
1098 | break; | ||||
1099 | default: | ||||
1100 | PyErr_SetString(PyExc_AssertionError, "sizeof(void*) != {4, 8}"); | ||||
1101 | return NULL((void*)0); | ||||
1102 | } | ||||
1103 | |||||
1104 | #undef UNWRAP_TYPE | ||||
1105 | |||||
1106 | typecache = PyDict_New(); | ||||
1107 | ndarray_typecache = PyDict_New(); | ||||
1108 | structured_dtypes = PyDict_New(); | ||||
1109 | if (typecache == NULL((void*)0) || ndarray_typecache == NULL((void*)0) || | ||||
1110 | structured_dtypes == NULL((void*)0)) { | ||||
1111 | PyErr_SetString(PyExc_RuntimeError, "failed to create type cache"); | ||||
1112 | return NULL((void*)0); | ||||
1113 | } | ||||
1114 | |||||
1115 | fingerprint_hashtable = _Numba_hashtable_new(sizeof(int), | ||||
1116 | hash_writer, | ||||
1117 | compare_writer); | ||||
1118 | if (fingerprint_hashtable == NULL((void*)0)) { | ||||
1119 | PyErr_NoMemory(); | ||||
1120 | return NULL((void*)0); | ||||
1121 | } | ||||
1122 | |||||
1123 | /* initialize cached_arycode to all ones (in bits) */ | ||||
1124 | memset(cached_arycode, 0xFF, sizeof(cached_arycode)); | ||||
1125 | |||||
1126 | str_typeof_pyval = PyString_InternFromStringPyUnicode_InternFromString("typeof_pyval"); | ||||
1127 | str_value = PyString_InternFromStringPyUnicode_InternFromString("value"); | ||||
1128 | str_numba_type = PyString_InternFromStringPyUnicode_InternFromString("_numba_type_"); | ||||
1129 | if (!str_value || !str_typeof_pyval || !str_numba_type) | ||||
1130 | return NULL((void*)0); | ||||
1131 | |||||
1132 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | ||||
1133 | } |
1 | #ifndef PyObject_GetAttrString |
2 | PyObject* clang_analyzer_PyObject_New_Reference(); |
3 | PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name) { |
4 | return clang_analyzer_PyObject_New_Reference(); |
5 | } |
6 | #else |
7 | #warning "API PyObject_GetAttrString is defined as a macro." |
8 | #endif |