Skip to content

implement bits of numpy_helper in cython where possible #19450

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions pandas/_libs/src/numpy_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,6 @@ The full license is in the LICENSE file, distributed with this software.

PANDAS_INLINE npy_int64 get_nat(void) { return NPY_MIN_INT64; }

PANDAS_INLINE int is_integer_object(PyObject* obj) {
return (!PyBool_Check(obj)) && PyArray_IsIntegerScalar(obj);
}

PANDAS_INLINE int is_float_object(PyObject* obj) {
return (PyFloat_Check(obj) || PyArray_IsScalar(obj, Floating));
}
PANDAS_INLINE int is_complex_object(PyObject* obj) {
return (PyComplex_Check(obj) || PyArray_IsScalar(obj, ComplexFloating));
}

PANDAS_INLINE int is_bool_object(PyObject* obj) {
return (PyBool_Check(obj) || PyArray_IsScalar(obj, Bool));
}

PANDAS_INLINE int is_string_object(PyObject* obj) {
return (PyString_Check(obj) || PyUnicode_Check(obj));
}

PANDAS_INLINE int is_datetime64_object(PyObject* obj) {
return PyArray_IsScalar(obj, Datetime);
}

PANDAS_INLINE int is_timedelta64_object(PyObject* obj) {
return PyArray_IsScalar(obj, Timedelta);
}

PANDAS_INLINE int assign_value_1d(PyArrayObject* ap, Py_ssize_t _i,
PyObject* v) {
npy_intp i = (npy_intp)_i;
Expand Down Expand Up @@ -80,17 +53,4 @@ void set_array_not_contiguous(PyArrayObject* ao) {
ao->flags &= ~(NPY_C_CONTIGUOUS | NPY_F_CONTIGUOUS);
}

// If arr is zerodim array, return a proper array scalar (e.g. np.int64).
// Otherwise, return arr as is.
PANDAS_INLINE PyObject* unbox_if_zerodim(PyObject* arr) {
if (PyArray_IsZeroDim(arr)) {
PyObject* ret;
ret = PyArray_ToScalar(PyArray_DATA(arr), arr);
return ret;
} else {
Py_INCREF(arr);
return arr;
}
}

#endif // PANDAS__LIBS_SRC_NUMPY_HELPER_H_
89 changes: 80 additions & 9 deletions pandas/_libs/src/util.pxd
Original file line number Diff line number Diff line change
@@ -1,24 +1,76 @@
from numpy cimport ndarray
from numpy cimport ndarray, NPY_C_CONTIGUOUS, NPY_F_CONTIGUOUS
cimport numpy as cnp
cnp.import_array()

cimport cpython
from cpython cimport PyTypeObject

cdef extern from "Python.h":
# Note: importing extern-style allows us to declare these as nogil
# functions, whereas `from cpython cimport` does not.
bint PyUnicode_Check(object obj) nogil
bint PyString_Check(object obj) nogil
bint PyBool_Check(object obj) nogil
bint PyFloat_Check(object obj) nogil
bint PyComplex_Check(object obj) nogil
bint PyObject_TypeCheck(object obj, PyTypeObject* type) nogil


cdef extern from "numpy/arrayobject.h":
PyTypeObject PyFloatingArrType_Type

cdef extern from "numpy/ndarrayobject.h":
PyTypeObject PyTimedeltaArrType_Type
PyTypeObject PyDatetimeArrType_Type
PyTypeObject PyComplexFloatingArrType_Type
PyTypeObject PyBoolArrType_Type

bint PyArray_IsIntegerScalar(obj) nogil
bint PyArray_Check(obj) nogil

# --------------------------------------------------------------------
# Type Checking

cdef inline bint is_string_object(object obj) nogil:
return PyString_Check(obj) or PyUnicode_Check(obj)


cdef inline bint is_integer_object(object obj) nogil:
return not PyBool_Check(obj) and PyArray_IsIntegerScalar(obj)


cdef inline bint is_float_object(object obj) nogil:
return (PyFloat_Check(obj) or
(PyObject_TypeCheck(obj, &PyFloatingArrType_Type)))


cdef inline bint is_complex_object(object obj) nogil:
return (PyComplex_Check(obj) or
PyObject_TypeCheck(obj, &PyComplexFloatingArrType_Type))


cdef inline bint is_bool_object(object obj) nogil:
return (PyBool_Check(obj) or
PyObject_TypeCheck(obj, &PyBoolArrType_Type))


cdef inline bint is_timedelta64_object(object obj) nogil:
return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type)


cdef inline bint is_datetime64_object(object obj) nogil:
return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type)

# --------------------------------------------------------------------

cdef extern from "numpy_helper.h":
void set_array_not_contiguous(ndarray ao)

int is_integer_object(object)
int is_float_object(object)
int is_complex_object(object)
int is_bool_object(object)
int is_string_object(object)
int is_datetime64_object(object)
int is_timedelta64_object(object)
int assign_value_1d(ndarray, Py_ssize_t, object) except -1
cnp.int64_t get_nat()
object get_value_1d(ndarray, Py_ssize_t)
char *get_c_string(object) except NULL
object char_to_string(char*)
object unbox_if_zerodim(object arr)

ctypedef fused numeric:
cnp.int8_t
Expand Down Expand Up @@ -112,3 +164,22 @@ cdef inline bint _checknan(object val):

cdef inline bint is_period_object(object val):
return getattr(val, '_typ', '_typ') == 'period'


cdef inline object unbox_if_zerodim(object arr):
"""
If arr is zerodim array, return a proper array scalar (e.g. np.int64).
Otherwise, return arr as is.

Parameters
----------
arr : object

Returns
-------
result : object
"""
if cnp.PyArray_IsZeroDim(arr):
return cnp.PyArray_ToScalar(cnp.PyArray_DATA(arr), arr)
else:
return arr
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -686,8 +686,7 @@ def pxd(name):
ext.sources[0] = root + suffix

ujson_ext = Extension('pandas._libs.json',
depends=['pandas/_libs/src/ujson/lib/ultrajson.h',
'pandas/_libs/src/numpy_helper.h'],
depends=['pandas/_libs/src/ujson/lib/ultrajson.h'],
sources=(['pandas/_libs/src/ujson/python/ujson.c',
'pandas/_libs/src/ujson/python/objToJSON.c',
'pandas/_libs/src/ujson/python/JSONtoObj.c',
Expand Down