| 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 |