hyb
2025-12-31 6cdcd01f77e11b72c323603e27ebdb85b15223c9
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
 * This header file defines relevant features which:
 * - Require runtime inspection depending on the NumPy version.
 * - May be needed when compiling with an older version of NumPy to allow
 *   a smooth transition.
 *
 * As such, it is shipped with NumPy 2.0, but designed to be vendored in full
 * or parts by downstream projects.
 *
 * It must be included after any other includes.  `import_array()` must have
 * been called in the scope or version dependency will misbehave, even when
 * only `PyUFunc_` API is used.
 *
 * If required complicated defs (with inline functions) should be written as:
 *
 *     #if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
 *         Simple definition when NumPy 2.0 API is guaranteed.
 *     #else
 *         static inline definition of a 1.x compatibility shim
 *         #if NPY_ABI_VERSION < 0x02000000
 *            Make 1.x compatibility shim the public API (1.x only branch)
 *         #else
 *             Runtime dispatched version (1.x or 2.x)
 *         #endif
 *     #endif
 *
 * An internal build always passes NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
 */
 
#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_
 
/*
 * New macros for accessing real and complex part of a complex number can be
 * found in "npy_2_complexcompat.h".
 */
 
 
/*
 * This header is meant to be included by downstream directly for 1.x compat.
 * In that case we need to ensure that users first included the full headers
 * and not just `ndarraytypes.h`.
 */
 
#ifndef NPY_FEATURE_VERSION
  #error "The NumPy 2 compat header requires `import_array()` for which "  \
         "the `ndarraytypes.h` header include is not sufficient.  Please "  \
         "include it after `numpy/ndarrayobject.h` or similar.\n"  \
         "To simplify inclusion, you may use `PyArray_ImportNumPy()` " \
         "which is defined in the compat header and is lightweight (can be)."
#endif
 
#if NPY_ABI_VERSION < 0x02000000
  /*
   * Define 2.0 feature version as it is needed below to decide whether we
   * compile for both 1.x and 2.x (defining it guarantees 1.x only).
   */
  #define NPY_2_0_API_VERSION 0x00000012
  /*
   * If we are compiling with NumPy 1.x, PyArray_RUNTIME_VERSION so we
   * pretend the `PyArray_RUNTIME_VERSION` is `NPY_FEATURE_VERSION`.
   * This allows downstream to use `PyArray_RUNTIME_VERSION` if they need to.
   */
  #define PyArray_RUNTIME_VERSION NPY_FEATURE_VERSION
  /* Compiling on NumPy 1.x where these are the same: */
  #define PyArray_DescrProto PyArray_Descr
#endif
 
 
/*
 * Define a better way to call `_import_array()` to simplify backporting as
 * we now require imports more often (necessary to make ABI flexible).
 */
#ifdef import_array1
 
static inline int
PyArray_ImportNumPyAPI(void)
{
    if (NPY_UNLIKELY(PyArray_API == NULL)) {
        import_array1(-1);
    }
    return 0;
}
 
#endif  /* import_array1 */
 
 
/*
 * NPY_DEFAULT_INT
 *
 * The default integer has changed, `NPY_DEFAULT_INT` is available at runtime
 * for use as type number, e.g. `PyArray_DescrFromType(NPY_DEFAULT_INT)`.
 *
 * NPY_RAVEL_AXIS
 *
 * This was introduced in NumPy 2.0 to allow indicating that an axis should be
 * raveled in an operation. Before NumPy 2.0, NPY_MAXDIMS was used for this purpose.
 *
 * NPY_MAXDIMS
 *
 * A constant indicating the maximum number dimensions allowed when creating
 * an ndarray.
 *
 * NPY_NTYPES_LEGACY
 *
 * The number of built-in NumPy dtypes.
 */
#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
    #define NPY_DEFAULT_INT NPY_INTP
    #define NPY_RAVEL_AXIS NPY_MIN_INT
    #define NPY_MAXARGS 64
 
#elif NPY_ABI_VERSION < 0x02000000
    #define NPY_DEFAULT_INT NPY_LONG
    #define NPY_RAVEL_AXIS 32
    #define NPY_MAXARGS 32
 
    /* Aliases of 2.x names to 1.x only equivalent names */
    #define NPY_NTYPES NPY_NTYPES_LEGACY
    #define PyArray_DescrProto PyArray_Descr
    #define _PyArray_LegacyDescr PyArray_Descr
    /* NumPy 2 definition always works, but add it for 1.x only */
    #define PyDataType_ISLEGACY(dtype) (1)
#else
    #define NPY_DEFAULT_INT  \
        (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? NPY_INTP : NPY_LONG)
    #define NPY_RAVEL_AXIS  \
        (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? NPY_MIN_INT : 32)
    #define NPY_MAXARGS  \
        (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? 64 : 32)
#endif
 
 
/*
 * Access inline functions for descriptor fields.  Except for the first
 * few fields, these needed to be moved (elsize, alignment) for
 * additional space.  Or they are descriptor specific and are not generally
 * available anymore (metadata, c_metadata, subarray, names, fields).
 *
 * Most of these are defined via the `DESCR_ACCESSOR` macro helper.
 */
#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION || NPY_ABI_VERSION < 0x02000000
    /* Compiling for 1.x or 2.x only, direct field access is OK: */
 
    static inline void
    PyDataType_SET_ELSIZE(PyArray_Descr *dtype, npy_intp size)
    {
        dtype->elsize = size;
    }
 
    static inline npy_uint64
    PyDataType_FLAGS(const PyArray_Descr *dtype)
    {
    #if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
        return dtype->flags;
    #else
        return (unsigned char)dtype->flags;  /* Need unsigned cast on 1.x */
    #endif
    }
 
    #define DESCR_ACCESSOR(FIELD, field, type, legacy_only)    \
        static inline type                                     \
        PyDataType_##FIELD(const PyArray_Descr *dtype) {       \
            if (legacy_only && !PyDataType_ISLEGACY(dtype)) {  \
                return (type)0;                                \
            }                                                  \
            return ((_PyArray_LegacyDescr *)dtype)->field;     \
        }
#else  /* compiling for both 1.x and 2.x */
 
    static inline void
    PyDataType_SET_ELSIZE(PyArray_Descr *dtype, npy_intp size)
    {
        if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) {
            ((_PyArray_DescrNumPy2 *)dtype)->elsize = size;
        }
        else {
            ((PyArray_DescrProto *)dtype)->elsize = (int)size;
        }
    }
 
    static inline npy_uint64
    PyDataType_FLAGS(const PyArray_Descr *dtype)
    {
        if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) {
            return ((_PyArray_DescrNumPy2 *)dtype)->flags;
        }
        else {
            return (unsigned char)((PyArray_DescrProto *)dtype)->flags;
        }
    }
 
    /* Cast to LegacyDescr always fine but needed when `legacy_only` */
    #define DESCR_ACCESSOR(FIELD, field, type, legacy_only)        \
        static inline type                                         \
        PyDataType_##FIELD(const PyArray_Descr *dtype) {           \
            if (legacy_only && !PyDataType_ISLEGACY(dtype)) {      \
                return (type)0;                                    \
            }                                                      \
            if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) {  \
                return ((_PyArray_LegacyDescr *)dtype)->field;     \
            }                                                      \
            else {                                                 \
                return ((PyArray_DescrProto *)dtype)->field;       \
            }                                                      \
        }
#endif
 
DESCR_ACCESSOR(ELSIZE, elsize, npy_intp, 0)
DESCR_ACCESSOR(ALIGNMENT, alignment, npy_intp, 0)
DESCR_ACCESSOR(METADATA, metadata, PyObject *, 1)
DESCR_ACCESSOR(SUBARRAY, subarray, PyArray_ArrayDescr *, 1)
DESCR_ACCESSOR(NAMES, names, PyObject *, 1)
DESCR_ACCESSOR(FIELDS, fields, PyObject *, 1)
DESCR_ACCESSOR(C_METADATA, c_metadata, NpyAuxData *, 1)
 
#undef DESCR_ACCESSOR
 
 
#if !(defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD)
#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
    static inline PyArray_ArrFuncs *
    PyDataType_GetArrFuncs(const PyArray_Descr *descr)
    {
        return _PyDataType_GetArrFuncs(descr);
    }
#elif NPY_ABI_VERSION < 0x02000000
    static inline PyArray_ArrFuncs *
    PyDataType_GetArrFuncs(const PyArray_Descr *descr)
    {
        return descr->f;
    }
#else
    static inline PyArray_ArrFuncs *
    PyDataType_GetArrFuncs(const PyArray_Descr *descr)
    {
        if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) {
            return _PyDataType_GetArrFuncs(descr);
        }
        else {
            return ((PyArray_DescrProto *)descr)->f;
        }
    }
#endif
 
 
#endif  /* not internal build */
 
#endif  /* NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_ */