1
#define PY_SSIZE_T_CLEAN
2
#include <Python.h>
3
#include "structmember.h"
4

5

6
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
7
#define _MULTIARRAYMODULE
8
#include "numpy/ndarraytypes.h"
9
#include "numpy/arrayobject.h"
10

11
#include "abstractdtypes.h"
12
#include "array_coercion.h"
13
#include "common.h"
14

15

16
static PyArray_Descr *
17 1
discover_descriptor_from_pyint(
18
        PyArray_DTypeMeta *NPY_UNUSED(cls), PyObject *obj)
19
{
20
    assert(PyLong_Check(obj));
21
    /*
22
     * We check whether long is good enough. If not, check longlong and
23
     * unsigned long before falling back to `object`.
24
     */
25 1
    long long value = PyLong_AsLongLong(obj);
26 1
    if (error_converting(value)) {
27 1
        PyErr_Clear();
28
    }
29
    else {
30
        if (NPY_MIN_LONG <= value && value <= NPY_MAX_LONG) {
31 1
            return PyArray_DescrFromType(NPY_LONG);
32
        }
33
        return PyArray_DescrFromType(NPY_LONGLONG);
34
    }
35

36 1
    unsigned long long uvalue = PyLong_AsUnsignedLongLong(obj);
37 1
    if (uvalue == (unsigned long long)-1 && PyErr_Occurred()){
38 1
        PyErr_Clear();
39
    }
40
    else {
41 1
        return PyArray_DescrFromType(NPY_ULONGLONG);
42
    }
43

44 1
    return PyArray_DescrFromType(NPY_OBJECT);
45
}
46

47

48
static PyArray_Descr*
49 1
discover_descriptor_from_pyfloat(
50
        PyArray_DTypeMeta* NPY_UNUSED(cls), PyObject *obj)
51
{
52
    assert(PyFloat_CheckExact(obj));
53 1
    return PyArray_DescrFromType(NPY_DOUBLE);
54
}
55

56

57
static PyArray_Descr*
58 1
discover_descriptor_from_pycomplex(
59
        PyArray_DTypeMeta* NPY_UNUSED(cls), PyObject *obj)
60
{
61
    assert(PyComplex_CheckExact(obj));
62 1
    return PyArray_DescrFromType(NPY_COMPLEX128);
63
}
64

65

66
NPY_NO_EXPORT int
67 1
initialize_and_map_pytypes_to_dtypes()
68
{
69 1
    PyArrayAbstractObjDTypeMeta_Type.tp_base = &PyArrayDTypeMeta_Type;
70 1
    if (PyType_Ready(&PyArrayAbstractObjDTypeMeta_Type) < 0) {
71
        return -1;
72
    }
73 1
    ((PyTypeObject *)&PyArray_PyIntAbstractDType)->tp_base = &PyArrayDTypeMeta_Type;
74 1
    PyArray_PyIntAbstractDType.scalar_type = &PyLong_Type;
75 1
    if (PyType_Ready((PyTypeObject *)&PyArray_PyIntAbstractDType) < 0) {
76
        return -1;
77
    }
78 1
    ((PyTypeObject *)&PyArray_PyFloatAbstractDType)->tp_base = &PyArrayDTypeMeta_Type;
79 1
    PyArray_PyFloatAbstractDType.scalar_type = &PyFloat_Type;
80 1
    if (PyType_Ready((PyTypeObject *)&PyArray_PyFloatAbstractDType) < 0) {
81
        return -1;
82
    }
83 1
    ((PyTypeObject *)&PyArray_PyComplexAbstractDType)->tp_base = &PyArrayDTypeMeta_Type;
84 1
    PyArray_PyComplexAbstractDType.scalar_type = &PyComplex_Type;
85 1
    if (PyType_Ready((PyTypeObject *)&PyArray_PyComplexAbstractDType) < 0) {
86
        return -1;
87
    }
88

89
    /* Register the new DTypes for discovery */
90 1
    if (_PyArray_MapPyTypeToDType(
91
            &PyArray_PyIntAbstractDType, &PyLong_Type, NPY_FALSE) < 0) {
92
        return -1;
93
    }
94 1
    if (_PyArray_MapPyTypeToDType(
95
            &PyArray_PyFloatAbstractDType, &PyFloat_Type, NPY_FALSE) < 0) {
96
        return -1;
97
    }
98 1
    if (_PyArray_MapPyTypeToDType(
99
            &PyArray_PyComplexAbstractDType, &PyComplex_Type, NPY_FALSE) < 0) {
100
        return -1;
101
    }
102

103
    /*
104
     * Map str, bytes, and bool, for which we do not need abstract versions
105
     * to the NumPy DTypes. This is done here using the `is_known_scalar_type`
106
     * function.
107
     * TODO: The `is_known_scalar_type` function is considered preliminary,
108
     *       the same could be achieved e.g. with additional abstract DTypes.
109
     */
110
    PyArray_DTypeMeta *dtype;
111 1
    dtype = NPY_DTYPE(PyArray_DescrFromType(NPY_UNICODE));
112 1
    if (_PyArray_MapPyTypeToDType(dtype, &PyUnicode_Type, NPY_FALSE) < 0) {
113
        return -1;
114
    }
115

116 1
    dtype = NPY_DTYPE(PyArray_DescrFromType(NPY_STRING));
117 1
    if (_PyArray_MapPyTypeToDType(dtype, &PyBytes_Type, NPY_FALSE) < 0) {
118
        return -1;
119
    }
120 1
    dtype = NPY_DTYPE(PyArray_DescrFromType(NPY_BOOL));
121 1
    if (_PyArray_MapPyTypeToDType(dtype, &PyBool_Type, NPY_FALSE) < 0) {
122
        return -1;
123
    }
124

125 1
    return 0;
126
}
127

128

129

130
/* Note: This is currently largely not used, but will be required eventually. */
131
NPY_NO_EXPORT PyTypeObject PyArrayAbstractObjDTypeMeta_Type = {
132
        PyVarObject_HEAD_INIT(NULL, 0)
133
        .tp_name = "numpy._AbstractObjDTypeMeta",
134
        .tp_basicsize = sizeof(PyArray_DTypeMeta),
135
        .tp_flags = Py_TPFLAGS_DEFAULT,
136
        .tp_doc = "Helper MetaClass for value based casting AbstractDTypes.",
137
};
138

139
NPY_NO_EXPORT PyArray_DTypeMeta PyArray_PyIntAbstractDType = {{{
140
        PyVarObject_HEAD_INIT(&PyArrayAbstractObjDTypeMeta_Type, 0)
141
        .tp_basicsize = sizeof(PyArray_DTypeMeta),
142
        .tp_name = "numpy._PyIntBaseAbstractDType",
143
    },},
144
    .abstract = 1,
145
    .discover_descr_from_pyobject = discover_descriptor_from_pyint,
146
    .kind = 'i',
147
};
148

149
NPY_NO_EXPORT PyArray_DTypeMeta PyArray_PyFloatAbstractDType = {{{
150
        PyVarObject_HEAD_INIT(&PyArrayAbstractObjDTypeMeta_Type, 0)
151
        .tp_basicsize = sizeof(PyArray_DTypeMeta),
152
        .tp_name = "numpy._PyFloatBaseAbstractDType",
153
    },},
154
    .abstract = 1,
155
    .discover_descr_from_pyobject = discover_descriptor_from_pyfloat,
156
    .kind = 'f',
157
};
158

159
NPY_NO_EXPORT PyArray_DTypeMeta PyArray_PyComplexAbstractDType = {{{
160
        PyVarObject_HEAD_INIT(&PyArrayAbstractObjDTypeMeta_Type, 0)
161
        .tp_basicsize = sizeof(PyArray_DTypeMeta),
162
        .tp_name = "numpy._PyComplexBaseAbstractDType",
163
    },},
164
    .abstract = 1,
165
    .discover_descr_from_pyobject = discover_descriptor_from_pycomplex,
166
    .kind = 'c',
167
};
168

Read our documentation on viewing source code .

Loading