diff options
-rw-r--r-- | numpy/core/code_generators/genapi.py | 1 | ||||
-rw-r--r-- | numpy/core/code_generators/numpy_api.py | 5 | ||||
-rw-r--r-- | numpy/core/src/multiarray/item_selection.c | 5 | ||||
-rw-r--r-- | numpy/core/src/multiarray/mapping.c | 4 | ||||
-rw-r--r-- | numpy/core/src/multiarray/na_object.c | 80 | ||||
-rw-r--r-- | numpy/core/src/multiarray/na_object.h | 18 |
6 files changed, 66 insertions, 47 deletions
diff --git a/numpy/core/code_generators/genapi.py b/numpy/core/code_generators/genapi.py index fdf043ddb..05f382240 100644 --- a/numpy/core/code_generators/genapi.py +++ b/numpy/core/code_generators/genapi.py @@ -44,6 +44,7 @@ API_FILES = [join('multiarray', 'array_assign_array.c'), join('multiarray', 'methods.c'), join('multiarray', 'multiarraymodule.c'), join('multiarray', 'na_mask.c'), + join('multiarray', 'na_object.c'), join('multiarray', 'nditer_api.c'), join('multiarray', 'nditer_constr.c'), join('multiarray', 'nditer_pywrap.c'), diff --git a/numpy/core/code_generators/numpy_api.py b/numpy/core/code_generators/numpy_api.py index 4d5d42074..ac5c12e24 100644 --- a/numpy/core/code_generators/numpy_api.py +++ b/numpy/core/code_generators/numpy_api.py @@ -337,6 +337,11 @@ multiarray_funcs_api = { 'PyArray_ReduceWrapper': 296, 'PyArray_RemoveAxesInPlace': 297, 'PyArray_DebugPrint': 298, + 'NpyNA_GetDType': 300, + 'NpyNA_IsMultiNA': 301, + 'NpyNA_GetPayload': 302, + 'NpyNA_FromObject': 303, + 'NpyNA_FromDTypeAndPayload': 304, } ufunc_types_api = { diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c index 120ed75f3..663567014 100644 --- a/numpy/core/src/multiarray/item_selection.c +++ b/numpy/core/src/multiarray/item_selection.c @@ -2343,9 +2343,8 @@ PyArray_MultiIndexGetItem(PyArrayObject *self, npy_intp *multi_index) return PyArray_DESCR(self)->f->getitem(data, self); } else { - return (PyObject *)NpyNA_FromDTypeAndMaskValue( - PyArray_DTYPE(self), - maskvalue, 0); + return (PyObject *)NpyNA_FromDTypeAndPayload( + PyArray_DTYPE(self), 0, 0); } } /* Case without an NA mask */ diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index c6e42905f..92c0429aa 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -1803,8 +1803,8 @@ array_subscript_nice(PyArrayObject *self, PyObject *op) (PyObject *)self); } else { - return (PyObject *)NpyNA_FromDTypeAndMaskValue( - PyArray_DESCR(self), (npy_mask)*maskna_item, 0); + return (PyObject *)NpyNA_FromDTypeAndPayload( + PyArray_DESCR(self), 0, 0); } } } diff --git a/numpy/core/src/multiarray/na_object.c b/numpy/core/src/multiarray/na_object.c index 3b52a7678..c356fb421 100644 --- a/numpy/core/src/multiarray/na_object.c +++ b/numpy/core/src/multiarray/na_object.c @@ -368,7 +368,45 @@ NpyNA_CombineNAWithObject(NpyNA *na, PyObject *obj) return (NpyNA *)ret; } -/* + +/*NUMPY_API + * + * Returns the *dtype* field of the NA object, which is NULL when + * the NA has no dtype. Does not raise an error. + */ +NPY_NO_EXPORT PyArray_Descr * +NpyNA_GetDType(NpyNA* na) +{ + NpyNA_fields *fna = (NpyNA_fields *)na; + return fna->dtype; +} + +/*NUMPY_API + * + * Returns true if the NA has a multi-NA payload, false otherwise. + */ +NPY_NO_EXPORT npy_bool +NpyNA_IsMultiNA(NpyNA* na) +{ + NpyNA_fields *fna = (NpyNA_fields *)na; + return fna->payload != NPY_NA_NOPAYLOAD; +} + +/*NUMPY_API + * + * Gets the multi-NA payload of the NA, or 0 if *na* doesn't have + * a multi-NA payload. + */ +NPY_NO_EXPORT int +NpyNA_GetPayload(NpyNA* na) +{ + NpyNA_fields *fna = (NpyNA_fields *)na; + return fna->payload == NPY_NA_NOPAYLOAD ? 0 : fna->payload; +} + + +/*NUMPY_API + * * Converts an object into an NA if possible. * * If 'suppress_error' is enabled, doesn't raise an error when something @@ -433,28 +471,22 @@ NpyNA_FromObject(PyObject *obj, int suppress_error) return NULL; } -/* - * Converts a dtype reference and mask value into an NA. +/*NUMPY_API + * + * Converts a dtype reference and payload value into an NA. * Doesn't steal the 'dtype' reference. Raises an error - * if 'maskvalue' represents an exposed mask. + * if the payload is invalid */ NPY_NO_EXPORT NpyNA * -NpyNA_FromDTypeAndMaskValue(PyArray_Descr *dtype, npy_mask maskvalue, - int multina) +NpyNA_FromDTypeAndPayload(PyArray_Descr *dtype, int multina, int payload) { NpyNA_fields *fna; - if (dtype == NULL && maskvalue == 0) { + if (dtype == NULL && multina == 0 && payload == 0) { Py_INCREF(Npy_NA); return (NpyNA *)Npy_NA; } - if (NpyMaskValue_IsExposed(maskvalue)) { - PyErr_SetString(PyExc_ValueError, - "Cannot convert exposed mask value into NA"); - return NULL; - } - fna = (NpyNA_fields *)na_new(&NpyNA_Type, NULL, NULL); if (fna == NULL) { return NULL; @@ -464,11 +496,17 @@ NpyNA_FromDTypeAndMaskValue(PyArray_Descr *dtype, npy_mask maskvalue, Py_XINCREF(fna->dtype); if (multina) { - fna->payload = NpyMaskValue_GetPayload(maskvalue); + if (payload < 0 || payload > 0x7f) { + PyErr_Format(PyExc_ValueError, + "Given NA payload, %d, is out of bounds [0, 128)", + payload); + Py_DECREF(fna); + } + fna->payload = (npy_uint8)payload; } - else if (NpyMaskValue_GetPayload(maskvalue) != 0) { + else if (payload != 0) { PyErr_SetString(PyExc_ValueError, - "Cannot convert mask value into NA without enabling multi-NA"); + "NA payload must be zero when multi-NA is disabled"); Py_DECREF(fna); return NULL; } @@ -482,14 +520,7 @@ NpyNA_FromDTypeAndMaskValue(PyArray_Descr *dtype, npy_mask maskvalue, NPY_NO_EXPORT npy_mask NpyNA_AsMaskValue(NpyNA *na) { - NpyNA_fields *fna = (NpyNA_fields *)na; - - if (fna->payload == NPY_NA_NOPAYLOAD) { - return 0; - } - else { - return NpyMaskValue_Create(0, fna->payload); - } + return NpyMaskValue_Create(0, NpyNA_GetPayload(na)); } /* An NA unary op simply passes along the same NA */ @@ -749,4 +780,5 @@ NPY_NO_EXPORT NpyNA_fields _Npy_NASingleton = { 1 /* is_singleton */ }; +/* This symbol is exported in the NumPy C API */ NPY_NO_EXPORT PyObject *Npy_NA = (PyObject *)&_Npy_NASingleton; diff --git a/numpy/core/src/multiarray/na_object.h b/numpy/core/src/multiarray/na_object.h index 48770cfc2..3e602ccdf 100644 --- a/numpy/core/src/multiarray/na_object.h +++ b/numpy/core/src/multiarray/na_object.h @@ -37,24 +37,6 @@ NPY_NO_EXPORT NpyNA * NpyNA_CombineNAWithObject(NpyNA *na, PyObject *obj); /* - * Converts an object into an NA if possible. - * - * If 'suppress_error' is enabled, doesn't raise an error when something - * isn't NA. - */ -NPY_NO_EXPORT NpyNA * -NpyNA_FromObject(PyObject *obj, int suppress_error); - -/* - * Converts a dtype reference and mask value into an NA. - * Doesn't steal the 'dtype' reference. Raises an error - * if 'maskvalue' represents an exposed mask. - */ -NPY_NO_EXPORT NpyNA * -NpyNA_FromDTypeAndMaskValue(PyArray_Descr *dtype, npy_mask maskvalue, - int multina); - -/* * Returns a mask value corresponding to the NA. */ NPY_NO_EXPORT npy_mask |