forked from pandas-dev/pandas
-
Notifications
You must be signed in to change notification settings - Fork 3
/
numpy_helper.h
204 lines (169 loc) · 4.68 KB
/
numpy_helper.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#include "Python.h"
#include "numpy/arrayobject.h"
#include "numpy/arrayscalars.h"
#include "helper.h"
#define PANDAS_FLOAT 0
#define PANDAS_INT 1
#define PANDAS_BOOL 2
#define PANDAS_STRING 3
#define PANDAS_OBJECT 4
#define PANDAS_DATETIME 5
PANDAS_INLINE int
infer_type(PyObject* obj) {
if (PyBool_Check(obj)) {
return PANDAS_BOOL;
}
else if (PyArray_IsIntegerScalar(obj)) {
return PANDAS_INT;
}
else if (PyArray_IsScalar(obj, Datetime)) {
return PANDAS_DATETIME;
}
else if (PyFloat_Check(obj) || PyArray_IsScalar(obj, Floating)) {
return PANDAS_FLOAT;
}
else if (PyString_Check(obj) || PyUnicode_Check(obj)) {
return PANDAS_STRING;
}
else {
return PANDAS_OBJECT;
}
}
PANDAS_INLINE npy_int64
get_nat(void) {
return NPY_MIN_INT64;
}
PANDAS_INLINE npy_datetime
get_datetime64_value(PyObject* obj) {
return ((PyDatetimeScalarObject*) obj)->obval;
}
PANDAS_INLINE npy_timedelta
get_timedelta64_value(PyObject* obj) {
return ((PyTimedeltaScalarObject*) obj)->obval;
}
PANDAS_INLINE int
is_integer_object(PyObject* obj) {
return (!PyBool_Check(obj)) && PyArray_IsIntegerScalar(obj);
// return 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;
char *item = (char *) PyArray_DATA(ap) + i * PyArray_STRIDE(ap, 0);
return PyArray_DESCR(ap)->f->setitem(v, item, ap);
}
PANDAS_INLINE PyObject*
get_value_1d(PyArrayObject* ap, Py_ssize_t i) {
char *item = (char *) PyArray_DATA(ap) + i * PyArray_STRIDE(ap, 0);
return PyArray_Scalar(item, PyArray_DESCR(ap), (PyObject*) ap);
}
PANDAS_INLINE char*
get_c_string(PyObject* obj) {
#if PY_VERSION_HEX >= 0x03000000
PyObject* enc_str = PyUnicode_AsEncodedString(obj, "utf-8", "error");
char *ret;
ret = PyBytes_AS_STRING(enc_str);
// TODO: memory leak here
// Py_XDECREF(enc_str);
return ret;
#else
return PyString_AsString(obj);
#endif
}
PANDAS_INLINE PyObject*
char_to_string(char* data) {
#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_FromString(data);
#else
return PyString_FromString(data);
#endif
}
// PANDAS_INLINE int
// is_string(PyObject* obj) {
// #if PY_VERSION_HEX >= 0x03000000
// return PyUnicode_Check(obj);
// #else
// return PyString_Check(obj);
// #endif
PyObject* sarr_from_data(PyArray_Descr *descr, int length, void* data) {
PyArrayObject *result;
npy_intp dims[1] = {length};
Py_INCREF(descr); // newfromdescr steals a reference to descr
result = (PyArrayObject*) PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims,
NULL, data, 0, NULL);
// Returned array doesn't own data by default
result->flags |= NPY_OWNDATA;
return (PyObject*) result;
}
void transfer_object_column(char *dst, char *src, size_t stride,
size_t length) {
int i;
size_t sz = sizeof(PyObject*);
for (i = 0; i < length; ++i)
{
// uninitialized data
// Py_XDECREF(*((PyObject**) dst));
memcpy(dst, src, sz);
Py_INCREF(*((PyObject**) dst));
src += sz;
dst += stride;
}
}
void set_array_owndata(PyArrayObject *ao) {
ao->flags |= NPY_OWNDATA;
}
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;
}
}
// PANDAS_INLINE PyObject*
// get_base_ndarray(PyObject* ap) {
// // if (!ap || (NULL == ap)) {
// // Py_RETURN_NONE;
// // }
// while (!PyArray_CheckExact(ap)) {
// ap = PyArray_BASE((PyArrayObject*) ap);
// if (ap == Py_None) Py_RETURN_NONE;
// }
// // PyArray_BASE is a borrowed reference
// if(ap) {
// Py_INCREF(ap);
// }
// return ap;
// }