File: | _typeof.c |
Warning: | line 323, column 29 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 PyUnicode_AsEncodedString |
2 | PyObject* clang_analyzer_PyObject_New_Reference(); |
3 | PyObject* PyUnicode_AsEncodedString(PyObject *unicode, const char *encoding, const char *errors) { |
4 | return clang_analyzer_PyObject_New_Reference(); |
5 | } |
6 | #else |
7 | #warning "API PyUnicode_AsEncodedString is defined as a macro." |
8 | #endif |