NumPy 源码解析(四十九)
.\numpy\numpy\_core\include\numpy\ndarrayobject.h
/*
* DON'T INCLUDE THIS DIRECTLY.
*/
#ifndef NUMPY_CORE_INCLUDE_NUMPY_NDARRAYOBJECT_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NDARRAYOBJECT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <Python.h>
#include "ndarraytypes.h"
#include "dtype_api.h"
/* Includes the "function" C-API -- these are all stored in a
list of pointers --- one for each file
The two lists are concatenated into one in multiarray.
They are available as import_array()
*/
#include "__multiarray_api.h"
/*
* Include any definitions which are defined differently for 1.x and 2.x
* (Symbols only available on 2.x are not there, but rather guarded.)
*/
#include "npy_2_compat.h"
/* C-API that requires previous API to be defined */
// 定义宏,检查对象是否为 PyArray_Descr 类型
#define PyArray_DescrCheck(op) PyObject_TypeCheck(op, &PyArrayDescr_Type)
// 定义宏,检查对象是否为 PyArray 类型
#define PyArray_Check(op) PyObject_TypeCheck(op, &PyArray_Type)
// 定义宏,精确检查对象是否为 PyArray 类型
#define PyArray_CheckExact(op) (((PyObject*)(op))->ob_type == &PyArray_Type)
// 定义宏,检查对象是否有数组接口类型
#define PyArray_HasArrayInterfaceType(op, type, context, out) \
((((out)=PyArray_FromStructInterface(op)) != Py_NotImplemented) || \
(((out)=PyArray_FromInterface(op)) != Py_NotImplemented) || \
(((out)=PyArray_FromArrayAttr(op, type, context)) != \
Py_NotImplemented))
// 定义宏,检查对象是否有数组接口
#define PyArray_HasArrayInterface(op, out) \
PyArray_HasArrayInterfaceType(op, NULL, NULL, out)
// 定义宏,检查对象是否为零维数组
#define PyArray_IsZeroDim(op) (PyArray_Check(op) && \
(PyArray_NDIM((PyArrayObject *)(op)) == 0))
// 定义宏,检查对象是否为标量
#define PyArray_IsScalar(obj, cls) \
(PyObject_TypeCheck(obj, &Py##cls##ArrType_Type))
// 定义宏,检查对象是否为标量或零维数组
#define PyArray_CheckScalar(m) (PyArray_IsScalar(m, Generic) || \
PyArray_IsZeroDim(m))
// 定义宏,检查对象是否为 Python 数字类型
#define PyArray_IsPythonNumber(obj) \
(PyFloat_Check(obj) || PyComplex_Check(obj) || \
PyLong_Check(obj) || PyBool_Check(obj))
// 定义宏,检查对象是否为整数标量
#define PyArray_IsIntegerScalar(obj) (PyLong_Check(obj) \
|| PyArray_IsScalar((obj), Integer))
// 定义宏,检查对象是否为 Python 标量类型
#define PyArray_IsPythonScalar(obj) \
(PyArray_IsPythonNumber(obj) || PyBytes_Check(obj) || \
PyUnicode_Check(obj))
// 定义宏,检查对象是否为任何类型的标量
#define PyArray_IsAnyScalar(obj) \
(PyArray_IsScalar(obj, Generic) || PyArray_IsPythonScalar(obj))
// 定义宏,检查对象是否为任何类型的标量或零维数组
#define PyArray_CheckAnyScalar(obj) (PyArray_IsPythonScalar(obj) || \
PyArray_CheckScalar(obj))
// 定义宏,获取对象的连续副本
#define PyArray_GETCONTIGUOUS(m) (PyArray_ISCONTIGUOUS(m) ? \
Py_INCREF(m), (m) : \
(PyArrayObject *)(PyArray_Copy(m)))
# 定义宏 PyArray_SAMESHAPE(a1,a2),用于比较两个数组的形状是否相同
#define PyArray_SAMESHAPE(a1,a2) ((PyArray_NDIM(a1) == PyArray_NDIM(a2)) && \
PyArray_CompareLists(PyArray_DIMS(a1), \
PyArray_DIMS(a2), \
PyArray_NDIM(a1)))
# 定义宏 PyArray_SIZE(m),计算数组 m 的总元素数
#define PyArray_SIZE(m) PyArray_MultiplyList(PyArray_DIMS(m), PyArray_NDIM(m))
# 定义宏 PyArray_NBYTES(m),计算数组 m 的总字节数
#define PyArray_NBYTES(m) (PyArray_ITEMSIZE(m) * PyArray_SIZE(m))
# 定义宏 PyArray_FROM_O(m),根据对象 m 创建一个 NumPy 数组
#define PyArray_FROM_O(m) PyArray_FromAny(m, NULL, 0, 0, 0, NULL)
# 定义宏 PyArray_FROM_OF(m,flags),根据对象 m 和标志 flags 创建一个 NumPy 数组
#define PyArray_FROM_OF(m,flags) PyArray_CheckFromAny(m, NULL, 0, 0, flags, \
NULL)
# 定义宏 PyArray_FROM_OT(m,type),根据对象 m 和数据类型 type 创建一个 NumPy 数组
#define PyArray_FROM_OT(m,type) PyArray_FromAny(m, \
PyArray_DescrFromType(type), 0, 0, 0, NULL)
# 定义宏 PyArray_FROM_OTF(m, type, flags),根据对象 m、数据类型 type 和标志 flags 创建一个 NumPy 数组
#define PyArray_FROM_OTF(m, type, flags) \
PyArray_FromAny(m, PyArray_DescrFromType(type), 0, 0, \
(((flags) & NPY_ARRAY_ENSURECOPY) ? \
((flags) | NPY_ARRAY_DEFAULT) : (flags)), NULL)
# 定义宏 PyArray_FROMANY(m, type, min, max, flags),根据对象 m、数据类型 type、最小深度 min、最大深度 max 和标志 flags 创建一个 NumPy 数组
#define PyArray_FROMANY(m, type, min, max, flags) \
PyArray_FromAny(m, PyArray_DescrFromType(type), min, max, \
(((flags) & NPY_ARRAY_ENSURECOPY) ? \
(flags) | NPY_ARRAY_DEFAULT : (flags)), NULL)
# 定义宏 PyArray_ZEROS(m, dims, type, is_f_order),创建一个元素类型为 type、形状为 dims、是否 F 风格的全零 NumPy 数组
#define PyArray_ZEROS(m, dims, type, is_f_order) \
PyArray_Zeros(m, dims, PyArray_DescrFromType(type), is_f_order)
# 定义宏 PyArray_EMPTY(m, dims, type, is_f_order),创建一个元素类型为 type、形状为 dims、是否 F 风格的空 NumPy 数组
#define PyArray_EMPTY(m, dims, type, is_f_order) \
PyArray_Empty(m, dims, PyArray_DescrFromType(type), is_f_order)
# 定义宏 PyArray_FILLWBYTE(obj, val),使用值 val 填充数组 obj 的每个字节
#define PyArray_FILLWBYTE(obj, val) memset(PyArray_DATA(obj), val, \
PyArray_NBYTES(obj))
# 定义宏 PyArray_ContiguousFromAny(op, type, min_depth, max_depth),从对象 op 创建一个连续的 NumPy 数组,元素类型为 type,最小深度 min_depth,最大深度 max_depth
#define PyArray_ContiguousFromAny(op, type, min_depth, max_depth) \
PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
max_depth, NPY_ARRAY_DEFAULT, NULL)
# 定义宏 PyArray_EquivArrTypes(a1, a2),比较两个数组 a1 和 a2 是否类型等效
#define PyArray_EquivArrTypes(a1, a2) \
PyArray_EquivTypes(PyArray_DESCR(a1), PyArray_DESCR(a2))
# 定义宏 PyArray_EquivByteorders(b1, b2),比较两个字节序 b1 和 b2 是否等效
#define PyArray_EquivByteorders(b1, b2) \
(((b1) == (b2)) || (PyArray_ISNBO(b1) == PyArray_ISNBO(b2)))
# 定义宏 PyArray_SimpleNew(nd, dims, typenum),简单地创建一个 NumPy 数组,元素类型为 typenum,形状为 dims,维度数为 nd
#define PyArray_SimpleNew(nd, dims, typenum) \
PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, NULL, 0, 0, NULL)
# 定义宏 PyArray_SimpleNewFromData(nd, dims, typenum, data),从给定的数据 data 创建一个 NumPy 数组,元素类型为 typenum,形状为 dims,维度数为 nd
#define PyArray_SimpleNewFromData(nd, dims, typenum, data) \
PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, \
data, 0, NPY_ARRAY_CARRAY, NULL)
# 定义宏 PyArray_SimpleNewFromDescr(nd, dims, descr),根据描述符 descr 创建一个 NumPy 数组,形状为 dims,维度数为 nd
#define PyArray_SimpleNewFromDescr(nd, dims, descr) \
PyArray_NewFromDescr(&PyArray_Type, descr, nd, dims, \
NULL, NULL, 0, NULL)
# 定义宏 PyArray_ToScalar(data, arr),将数据 data 转换为与数组 arr 兼容的标量
#define PyArray_ToScalar(data, arr) \
PyArray_Scalar(data, PyArray_DESCR(arr), (PyObject *)arr)
/* 这些宏可能在循环内部性能更高,因为避免了 obj 内部的解引用操作 */
/* 宏定义:根据给定索引 i 计算一维数组中的元素指针 */
#define PyArray_GETPTR1(obj, i) ((void *)(PyArray_BYTES(obj) + \
(i)*PyArray_STRIDES(obj)[0]))
/* 宏定义:根据给定索引 i, j 计算二维数组中的元素指针 */
#define PyArray_GETPTR2(obj, i, j) ((void *)(PyArray_BYTES(obj) + \
(i)*PyArray_STRIDES(obj)[0] + \
(j)*PyArray_STRIDES(obj)[1]))
/* 宏定义:根据给定索引 i, j, k 计算三维数组中的元素指针 */
#define PyArray_GETPTR3(obj, i, j, k) ((void *)(PyArray_BYTES(obj) + \
(i)*PyArray_STRIDES(obj)[0] + \
(j)*PyArray_STRIDES(obj)[1] + \
(k)*PyArray_STRIDES(obj)[2]))
/* 宏定义:根据给定索引 i, j, k, l 计算四维数组中的元素指针 */
#define PyArray_GETPTR4(obj, i, j, k, l) ((void *)(PyArray_BYTES(obj) + \
(i)*PyArray_STRIDES(obj)[0] + \
(j)*PyArray_STRIDES(obj)[1] + \
(k)*PyArray_STRIDES(obj)[2] + \
(l)*PyArray_STRIDES(obj)[3]))
/* 函数:丢弃写回备份(若存在) */
static inline void
PyArray_DiscardWritebackIfCopy(PyArrayObject *arr)
{
PyArrayObject_fields *fa = (PyArrayObject_fields *)arr;
if (fa && fa->base) {
if (fa->flags & NPY_ARRAY_WRITEBACKIFCOPY) {
PyArray_ENABLEFLAGS((PyArrayObject*)fa->base, NPY_ARRAY_WRITEABLE);
Py_DECREF(fa->base);
fa->base = NULL;
PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEBACKIFCOPY);
}
}
}
/* 宏定义:替换数组描述符 */
#define PyArray_DESCR_REPLACE(descr) do { \
PyArray_Descr *_new_; \
_new_ = PyArray_DescrNew(descr); \
Py_XDECREF(descr); \
descr = _new_; \
} while(0)
/* 宏定义:复制数组并保证连续性 */
#define PyArray_Copy(obj) PyArray_NewCopy(obj, NPY_CORDER)
/* 宏定义:从 Python 对象创建数组(保证数组行为和数组化) */
#define PyArray_FromObject(op, type, min_depth, max_depth) \
PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
max_depth, NPY_ARRAY_BEHAVED | \
NPY_ARRAY_ENSUREARRAY, NULL)
/* 宏定义:从 Python 对象创建连续数组 */
#define PyArray_ContiguousFromObject(op, type, min_depth, max_depth) \
PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
max_depth, NPY_ARRAY_DEFAULT | \
NPY_ARRAY_ENSUREARRAY, NULL)
/* 宏定义:从 Python 对象复制数组 */
#define PyArray_CopyFromObject(op, type, min_depth, max_depth) \
PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
max_depth, NPY_ARRAY_ENSURECOPY | \
NPY_ARRAY_DEFAULT | \
NPY_ARRAY_ENSUREARRAY, NULL)
/* 宏定义:将数组转换为指定类型 */
#define PyArray_Cast(mp, type_num) \
PyArray_CastToType(mp, PyArray_DescrFromType(type_num), 0)
/* 宏定义:在指定轴上采取数组元素 */
#define PyArray_Take(ap, items, axis) \
PyArray_TakeFrom(ap, items, axis, NULL, NPY_RAISE)
/*
定义一个宏,用于在数组中放置元素。此宏调用 PyArray_PutTo 函数,
将 items 和 values 放置到 ap 中,如果出现问题则会抛出异常。
*/
#define PyArray_Put(ap, items, values) \
PyArray_PutTo(ap, items, values, NPY_RAISE)
/*
检查字典中的某个键是否是元组的“标题”条目(即在字段字典中的重复条目)。
如果元组的长度不为3,则返回0。
否则,获取元组的第三个元素作为 title,然后比较 key 和 title 的对象身份。
如果它们相等,则返回1。
在 PyPy 版本下,由于字典键不总是保留对象身份,使用值比较作为备选方案。
*/
static inline int
NPY_TITLE_KEY_check(PyObject *key, PyObject *value)
{
PyObject *title;
if (PyTuple_Size(value) != 3) {
return 0;
}
title = PyTuple_GetItem(value, 2);
if (key == title) {
return 1;
}
#ifdef PYPY_VERSION
/*
* 在 PyPy 中,字典键并不总是保持对象身份。
* 因此,如果 key 和 title 都是 Unicode 对象,则通过值比较判断它们是否相等。
* 如果相等,则返回1;否则返回0。
*/
if (PyUnicode_Check(title) && PyUnicode_Check(key)) {
return PyUnicode_Compare(title, key) == 0 ? 1 : 0;
}
#endif
return 0;
}
/* 宏,用于向后兼容“if NPY_TITLE_KEY(key, value) { ...” 的旧代码 */
#define NPY_TITLE_KEY(key, value) (NPY_TITLE_KEY_check((key), (value)))
/*
定义一个宏 DEPRECATE,用于发出 DeprecationWarning 警告。
使用 PyErr_WarnEx 函数,警告消息为 msg,级别为 1。
*/
#define DEPRECATE(msg) PyErr_WarnEx(PyExc_DeprecationWarning,msg,1)
/*
定义一个宏 DEPRECATE_FUTUREWARNING,用于发出 FutureWarning 警告。
使用 PyErr_WarnEx 函数,警告消息为 msg,级别为 1。
*/
#define DEPRECATE_FUTUREWARNING(msg) PyErr_WarnEx(PyExc_FutureWarning,msg,1)
/*
* 这些宏和函数需要运行时版本检查,而这些检查只在 `npy_2_compat.h` 中定义。
* 因此它们不能成为 `ndarraytypes.h` 的一部分,后者试图自包含。
*/
/*
返回给定数组对象的元素大小(以字节为单位)。
通过 PyArrayObject 的 descr 成员访问 PyDataType_ELSIZE 宏得到结果。
*/
static inline npy_intp
PyArray_ITEMSIZE(const PyArrayObject *arr)
{
return PyDataType_ELSIZE(((PyArrayObject_fields *)arr)->descr);
}
/*
检查给定数据类型对象是否具有字段(即是否是传统的数据类型描述符且具有非空名称)。
使用 PyDataType_ISLEGACY 和 PyDataType_NAMES 宏来实现。
*/
#define PyDataType_HASFIELDS(obj) (PyDataType_ISLEGACY((PyArray_Descr*)(obj)) && PyDataType_NAMES((PyArray_Descr*)(obj)) != NULL)
/*
检查给定数据类型对象是否具有子数组。
使用 PyDataType_ISLEGACY 和 PyDataType_SUBARRAY 宏来实现。
*/
#define PyDataType_HASSUBARRAY(dtype) (PyDataType_ISLEGACY(dtype) && PyDataType_SUBARRAY(dtype) != NULL)
/*
检查给定数据类型对象是否为未定大小(即其元素大小为0且没有字段)。
*/
#define PyDataType_ISUNSIZED(dtype) ((dtype)->elsize == 0 && \
!PyDataType_HASFIELDS(dtype))
/*
检查给定数据类型对象是否具有特定标志。
使用 PyDataType_FLAGS 宏来获取标志位,然后与指定的标志进行比较。
*/
#define PyDataType_FLAGCHK(dtype, flag) \
((PyDataType_FLAGS(dtype) & (flag)) == (flag))
/*
检查给定数据类型对象是否具有引用计数。
使用 PyDataType_FLAGCHK 宏来检查 NPY_ITEM_REFCOUNT 标志位。
*/
#define PyDataType_REFCHK(dtype) \
PyDataType_FLAGCHK(dtype, NPY_ITEM_REFCOUNT)
/*
在处理给定数据类型对象时,开始线程(如果没有需要 Python API 支持的标志位)。
使用 NPY_BEGIN_THREADS 宏来启动线程。
*/
#define NPY_BEGIN_THREADS_DESCR(dtype) \
do {if (!(PyDataType_FLAGCHK((dtype), NPY_NEEDS_PYAPI))) \
NPY_BEGIN_THREADS;} while (0);
/*
在处理给定数据类型对象时,结束线程(如果没有需要 Python API 支持的标志位)。
使用 NPY_END_THREADS 宏来结束线程。
*/
#define NPY_END_THREADS_DESCR(dtype) \
do {if (!(PyDataType_FLAGCHK((dtype), NPY_NEEDS_PYAPI))) \
NPY_END_THREADS; } while (0);
/*
如果不是在 NPY_INTERNAL_BUILD 且 NPY_INTERNAL_BUILD 未定义时,
此处的内部副本现在在 `dtypemeta.h` 中定义。
*/
/*
* `PyArray_Scalar` 与此函数相同,但会将大多数 NumPy 类型转换为 Python 标量。
*/
static inline PyObject *
PyArray_GETITEM(const PyArrayObject *arr, const char *itemptr)
{
/*
使用 PyArrayObject 的 descr 成员来获取 PyDataType_GetArrFuncs 函数,
然后调用其 getitem 方法,以 itemptr 作为参数获取数组对象 arr 的元素。
*/
return PyDataType_GetArrFuncs(((PyArrayObject_fields *)arr)->descr)->getitem(
(void *)itemptr, (PyArrayObject *)arr);
}
/*
* SETITEM should only be used if it is known that the value is a scalar
* and of a type understood by the arrays dtype.
* Use `PyArray_Pack` if the value may be of a different dtype.
*/
static inline int
PyArray_SETITEM(PyArrayObject *arr, char *itemptr, PyObject *v)
{
// 获取数组描述符的类型函数集合,并调用其 setitem 方法设置值 v 到数组 arr 的指定位置 itemptr
return PyDataType_GetArrFuncs(((PyArrayObject_fields *)arr)->descr)->setitem(v, itemptr, arr);
}
#endif /* not internal */
#ifdef __cplusplus
}
#endif
#endif /* NUMPY_CORE_INCLUDE_NUMPY_NDARRAYOBJECT_H_ */
.\numpy\numpy\_core\include\numpy\ndarraytypes.h
// 包含必要的头文件:npy_common.h, npy_endian.h, npy_cpu.h, utils.h
// 定义一个不导出的宏,用于内部使用
// 根据编译时是否启用多线程(NPY_NO_SMP),确定是否允许使用线程
// 如果编译环境不支持 __has_extension 宏,则定义为 0
/*
* There are several places in the code where an array of dimensions
* is allocated statically. This is the size of that static
* allocation.
*
* The array creation itself could have arbitrary dimensions but all
* the places where static allocation is used would need to be changed
* to dynamic (including inside of several structures)
*
* As of NumPy 2.0, we strongly discourage the downstream use of NPY_MAXDIMS,
* but since auditing everything seems a big ask, define it as 64.
* A future version could:
* - Increase or remove the limit and require recompilation (like 2.0 did)
* - Deprecate or remove the macro but keep the limit (at basically any time)
*/
// 定义静态分配的维度数组大小上限
// 不可改变的遗留迭代器的最大维度限制
// NPY_MAXARGS 是版本相关的,定义在 npy_2_compat.h 中
/* Used for Converter Functions "O&" code in ParseTuple */
// 用于解析元组中 "O&" 类型参数的转换器函数返回状态
/* 枚举定义不同的 NumPy 数据类型 */
enum NPY_TYPES {
NPY_BOOL=0, /* 布尔型 */
NPY_BYTE, NPY_UBYTE, /* 有符号和无符号字节型 */
NPY_SHORT, NPY_USHORT, /* 有符号和无符号短整型 */
NPY_INT, NPY_UINT, /* 有符号和无符号整型 */
NPY_LONG, NPY_ULONG, /* 有符号和无符号长整型 */
NPY_LONGLONG, NPY_ULONGLONG, /* 有符号和无符号长长整型 */
NPY_FLOAT, NPY_DOUBLE, /* 单精度和双精度浮点型 */
NPY_LONGDOUBLE, /* 长双精度浮点型 */
NPY_CFLOAT, NPY_CDOUBLE,/* 单复数和双复数浮点型 */
NPY_CLONGDOUBLE, /* 长双复数浮点型 */
NPY_OBJECT=17, /* Python 对象 */
NPY_STRING, NPY_UNICODE,/* 字符串和Unicode类型 */
NPY_VOID, /* Void(空)类型 */
/* 以下为1.6版后添加的新类型,可能在2.0版中整合到以上类型中 */
NPY_DATETIME, NPY_TIMEDELTA, NPY_HALF,
NPY_CHAR, /* 不推荐使用,如果使用会报错 */
/* *legacy* 类型的数量 */
NPY_NTYPES_LEGACY=24,
/* 避免将来添加新类型时改变 */
NPY_NOTYPE=25,
NPY_USERDEF=256, /* 留出空间用于用户定义类型 */
/* 不包括1.6版后添加的新类型的类型数量 */
NPY_NTYPES_ABI_COMPATIBLE=21,
/*
* 2.0版后添加的新 DType,不共享传统布局
* VSTRING 是这些类型中的第一个,将来可能为用户定义 DType 开辟一个块
*/
NPY_VSTRING=2056,
};
/* 基本类型数组优先级 */
/* 默认子类型优先级 */
/* 默认标量优先级 */
/* 浮点类型的数量(不包括 half) */
/*
* 这些字符对应于数组类型和 struct 模块
*/
/*
* 定义了 Numpy 数组数据类型的字符表示和对应的枚举值
*/
enum NPY_TYPECHAR {
NPY_BOOLLTR = '?', // 布尔类型
NPY_BYTELTR = 'b', // 字节类型
NPY_UBYTELTR = 'B', // 无符号字节类型
NPY_SHORTLTR = 'h', // 短整型
NPY_USHORTLTR = 'H', // 无符号短整型
NPY_INTLTR = 'i', // 整型
NPY_UINTLTR = 'I', // 无符号整型
NPY_LONGLTR = 'l', // 长整型
NPY_ULONGLTR = 'L', // 无符号长整型
NPY_LONGLONGLTR = 'q', // 长长整型
NPY_ULONGLONGLTR = 'Q', // 无符号长长整型
NPY_HALFLTR = 'e', // 半精度浮点型
NPY_FLOATLTR = 'f', // 单精度浮点型
NPY_DOUBLELTR = 'd', // 双精度浮点型
NPY_LONGDOUBLELTR = 'g', // 长双精度浮点型
NPY_CFLOATLTR = 'F', // 复数类型(单精度)
NPY_CDOUBLELTR = 'D', // 复数类型(双精度)
NPY_CLONGDOUBLELTR = 'G', // 复数类型(长双精度)
NPY_OBJECTLTR = 'O', // Python 对象
NPY_STRINGLTR = 'S', // 字符串
NPY_DEPRECATED_STRINGLTR2 = 'a',// 废弃的字符串类型
NPY_UNICODELTR = 'U', // Unicode 字符串
NPY_VOIDLTR = 'V', // 任意数据类型(void)
NPY_DATETIMELTR = 'M', // 日期时间类型
NPY_TIMEDELTALTR = 'm', // 时间增量类型
NPY_CHARLTR = 'c', // 字符类型
/*
* 新的非遗留数据类型
*/
NPY_VSTRINGLTR = 'T', // 可变长度字符串
/*
* 注意,我们移除了 `NPY_INTPLTR`,因为我们将其定义
* 改为 'n',而不再使用 'p'。在大多数平台上,这是相同的整数。
* 对于与 `size_t` 相同大小的 `np.intp`,应该使用 'n',
* 而 'p' 仍然表示指针大小。
*
* 'p', 'P', 'n', 和 'N' 都是有效的,并在 `arraytypes.c.src` 中明确定义。
*/
/*
* 这些用于 dtype 的 '种类',而不是上面的 '类型码'。
*/
NPY_GENBOOLLTR ='b', // 通用布尔类型
NPY_SIGNEDLTR = 'i', // 有符号类型
NPY_UNSIGNEDLTR = 'u', // 无符号类型
NPY_FLOATINGLTR = 'f', // 浮点类型
NPY_COMPLEXLTR = 'c', // 复数类型
};
/*
* 改动可能会破坏 Numpy API 的兼容性,
* 因为会改变 PyArray_ArrFuncs 中的偏移量,因此需要小心。
* 在这里,我们重复使用 mergesort 插槽来实现任何类型的稳定排序,
* 实际实现将依赖于数据类型。
*/
typedef enum {
_NPY_SORT_UNDEFINED=-1, // 未定义的排序类型
NPY_QUICKSORT=0, // 快速排序
NPY_HEAPSORT=1, // 堆排序
NPY_MERGESORT=2, // 归并排序
NPY_STABLESORT=2, // 稳定排序
} NPY_SORTKIND;
typedef enum {
NPY_INTROSELECT=0 // 引导选择算法
} NPY_SELECTKIND;
typedef enum {
NPY_SEARCHLEFT=0, // 向左搜索
NPY_SEARCHRIGHT=1 // 向右搜索
} NPY_SEARCHSIDE;
typedef enum {
NPY_NOSCALAR=-1, // 非标量
NPY_BOOL_SCALAR, // 布尔标量
NPY_INTPOS_SCALAR, // 正整数标量
NPY_INTNEG_SCALAR, // 负整数标量
NPY_FLOAT_SCALAR, // 浮点数标量
NPY_COMPLEX_SCALAR, // 复数标量
NPY_OBJECT_SCALAR // 对象标量
} NPY_SCALARKIND;
/* 用于指定数组内存布局或迭代顺序 */
typedef enum {
/* 如果输入都是 Fortran,则使用 Fortran 顺序,否则使用 C 顺序 */
NPY_ANYORDER=-1, // 任意顺序
/* C 顺序 */
NPY_CORDER=0, // C 顺序
/* Fortran 顺序 */
NPY_FORTRANORDER=1, // Fortran 顺序
/* 尽可能接近输入的顺序 */
NPY_KEEPORDER=2 // 保持原顺序
} NPY_ORDER;
/* 用于指定在支持的操作中允许的类型转换 */
/*
* 定义枚举类型 NPY_CASTING,用于指定数组类型转换时的转换规则
*/
typedef enum {
_NPY_ERROR_OCCURRED_IN_CAST = -1,
/* 只允许相同类型的转换 */
NPY_NO_CASTING=0,
/* 允许相同和字节交换类型的转换 */
NPY_EQUIV_CASTING=1,
/* 只允许安全的转换 */
NPY_SAFE_CASTING=2,
/* 允许安全转换或者同种类型的转换 */
NPY_SAME_KIND_CASTING=3,
/* 允许任意类型的转换 */
NPY_UNSAFE_CASTING=4,
} NPY_CASTING;
/*
* 定义枚举类型 NPY_CLIPMODE,用于指定数组运算中的截断模式
*/
typedef enum {
NPY_CLIP=0,
NPY_WRAP=1,
NPY_RAISE=2
} NPY_CLIPMODE;
/*
* 定义枚举类型 NPY_CORRELATEMODE,用于指定相关运算的模式
*/
typedef enum {
NPY_VALID=0,
NPY_SAME=1,
NPY_FULL=2
} NPY_CORRELATEMODE;
/* DATETIME 类型的特殊值,表示非时间值 (NaT) */
/*
* DATETIME ISO 8601 字符串的最大长度上限
* YEAR: 21 (64-bit year)
* MONTH: 3
* DAY: 3
* HOURS: 3
* MINUTES: 3
* SECONDS: 3
* ATTOSECONDS: 1 + 3*6
* TIMEZONE: 5
* NULL TERMINATOR: 1
*/
/*
* 枚举类型 NPY_DATETIMEUNIT,定义了日期时间单位
* NPY_FR_ERROR = -1: 错误或未确定
* NPY_FR_Y = 0: 年
* NPY_FR_M = 1: 月
* NPY_FR_W = 2: 周
* NPY_FR_D = 4: 日
* NPY_FR_h = 5: 小时
* NPY_FR_m = 6: 分钟
* NPY_FR_s = 7: 秒
* NPY_FR_ms = 8: 毫秒
* NPY_FR_us = 9: 微秒
* NPY_FR_ns = 10: 纳秒
* NPY_FR_ps = 11: 皮秒
* NPY_FR_fs = 12: 飞秒
* NPY_FR_as = 13: 阿托秒
* NPY_FR_GENERIC = 14: 未限定单位,可以转换为任何单位
*/
typedef enum {
/* 强制为有符号的枚举类型,必须为 -1 以保持代码兼容性 */
NPY_FR_ERROR = -1, /* 错误或未确定 */
/* 有效单位开始 */
NPY_FR_Y = 0, /* 年 */
NPY_FR_M = 1, /* 月 */
NPY_FR_W = 2, /* 周 */
/* 1.6 版本中的 NPY_FR_B (值为 3) 的间隔 */
NPY_FR_D = 4, /* 日 */
NPY_FR_h = 5, /* 小时 */
NPY_FR_m = 6, /* 分钟 */
NPY_FR_s = 7, /* 秒 */
NPY_FR_ms = 8, /* 毫秒 */
NPY_FR_us = 9, /* 微秒 */
NPY_FR_ns = 10, /* 纳秒 */
NPY_FR_ps = 11, /* 皮秒 */
NPY_FR_fs = 12, /* 飞秒 */
NPY_FR_as = 13, /* 阿托秒 */
NPY_FR_GENERIC = 14 /* 未限定单位,可以转换为任何单位 */
} NPY_DATETIMEUNIT;
/*
* NPY_DATETIME_NUMUNITS 的定义,为了与 1.6 ABI 兼容性,实际单位数比此值少一个
*/
/*
* 工作日约定,用于将无效的工作日映射为有效的工作日
*/
typedef enum {
/* 前进到下一个工作日 */
NPY_BUSDAY_FORWARD,
NPY_BUSDAY_FOLLOWING = NPY_BUSDAY_FORWARD,
/* 后退到前一个工作日 */
NPY_BUSDAY_BACKWARD,
NPY_BUSDAY_PRECEDING = NPY_BUSDAY_BACKWARD,
/*
* 前进到下一个工作日,除非跨越月边界,否则后退
*/
NPY_BUSDAY_MODIFIEDFOLLOWING,
/*
* 后退到前一个工作日,除非跨越月边界,否则前进
*/
NPY_BUSDAY_MODIFIEDPRECEDING,
/* 在非工作日返回 NaT(Not a Time)值。 */
NPY_BUSDAY_NAT,
/* 在非工作日抛出异常。 */
NPY_BUSDAY_RAISE
} NPY_BUSDAY_ROLL;
/************************************************************
* NumPy Auxiliary Data for inner loops, sort functions, etc.
************************************************************/
/*
* When creating an auxiliary data struct, this should always appear
* as the first member, like this:
*
* typedef struct {
* NpyAuxData base;
* double constant;
* } constant_multiplier_aux_data;
*/
typedef struct NpyAuxData_tag NpyAuxData;
/* Function pointers for freeing or cloning auxiliary data */
typedef void (NpyAuxData_FreeFunc) (NpyAuxData *);
typedef NpyAuxData *(NpyAuxData_CloneFunc) (NpyAuxData *);
struct NpyAuxData_tag {
NpyAuxData_FreeFunc *free;
NpyAuxData_CloneFunc *clone;
/* To allow for a bit of expansion without breaking the ABI */
void *reserved[2];
};
/* Macros to use for freeing and cloning auxiliary data */
do { \
if ((auxdata) != NULL) { \
(auxdata)->free(auxdata); \
} \
} while(0)
((auxdata)->clone(auxdata))
/*
* Macros to define how array, and dimension/strides data is
* allocated. These should be made private
*/
/* use the Raw versions which are safe to call with the GIL released */
/* Dimensions and strides */
((npy_intp *)PyArray_malloc(size*sizeof(npy_intp)))
((npy_intp *)PyArray_realloc(ptr,size*sizeof(npy_intp)))
/* forward declaration */
struct _PyArray_Descr;
/* These must deal with unaligned and swapped data if necessary */
typedef PyObject * (PyArray_GetItemFunc) (void *, void *);
typedef int (PyArray_SetItemFunc)(PyObject *, void *, void *);
typedef void (PyArray_CopySwapNFunc)(void *, npy_intp, void *, npy_intp,
npy_intp, int, void *);
typedef void (PyArray_CopySwapFunc)(void *, void *, int, void *);
typedef npy_bool (PyArray_NonzeroFunc)(void *, void *);
/*
* These assume aligned and notswapped data -- a buffer will be used
* before or contiguous data will be obtained
*/
typedef int (PyArray_CompareFunc)(const void *, const void *, void *);
typedef int (PyArray_ArgFunc)(void*, npy_intp, npy_intp*, void *);
typedef void (PyArray_DotFunc)(void *, npy_intp, void *, npy_intp, void *,
npy_intp, void *);
/*
* 声明一个函数指针类型 PyArray_VectorUnaryFunc,接受四个参数:
* - void *: 指向输入数组的指针
* - void *: 指向输出数组的指针
* - npy_intp: 表示数组的长度或者维度
* - void *: 其他可能的参数
*/
typedef void (PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *,
void *);
/*
* 声明一个函数指针类型 PyArray_ScanFunc,接受四个参数:
* - FILE *: 指向文件的指针
* - void *: 指向数据的指针
* - char *: 分隔符参数(不再使用,保留为了向后兼容)
* - struct _PyArray_Descr *: 数组描述符结构体的指针
*/
typedef int (PyArray_ScanFunc)(FILE *fp, void *dptr,
char *ignore, struct _PyArray_Descr *);
/*
* 声明一个函数指针类型 PyArray_FromStrFunc,接受四个参数:
* - char *: 指向输入字符串的指针
* - void *: 指向数据的指针
* - char **: 指向结束位置的指针,用于指示解析的结束位置
* - struct _PyArray_Descr *: 数组描述符结构体的指针
*/
typedef int (PyArray_FromStrFunc)(char *s, void *dptr, char **endptr,
struct _PyArray_Descr *);
/*
* 声明一个函数指针类型 PyArray_FillFunc,接受三个参数:
* - void *: 指向数据的指针,用于填充数组
* - npy_intp: 表示数组的长度或者维度
* - void *: 其他可能的参数
*/
typedef int (PyArray_FillFunc)(void *, npy_intp, void *);
/*
* 声明一个函数指针类型 PyArray_SortFunc,接受三个参数:
* - void *: 指向数组的指针,表示要排序的数组
* - npy_intp: 表示数组的长度或者维度
* - void *: 其他可能的参数
*/
typedef int (PyArray_SortFunc)(void *, npy_intp, void *);
/*
* 声明一个函数指针类型 PyArray_ArgSortFunc,接受四个参数:
* - void *: 指向数组的指针,表示要排序的数组
* - npy_intp *: 指向整数数组的指针,用于存储排序后的索引
* - npy_intp: 表示数组的长度或者维度
* - void *: 其他可能的参数
*/
typedef int (PyArray_ArgSortFunc)(void *, npy_intp *, npy_intp, void *);
/*
* 声明一个函数指针类型 PyArray_FillWithScalarFunc,接受四个参数:
* - void *: 指向数据的指针,用于填充数组
* - npy_intp: 表示数组的长度或者维度
* - void *: 指向标量数据的指针,用于填充数组
* - void *: 其他可能的参数
*/
typedef int (PyArray_FillWithScalarFunc)(void *, npy_intp, void *, void *);
/*
* 声明一个函数指针类型 PyArray_ScalarKindFunc,接受一个参数:
* - void *: 指向数据的指针,表示要查询的标量类型
*/
typedef int (PyArray_ScalarKindFunc)(void *);
/*
* 定义一个结构体 PyArray_Dims,包含两个成员变量:
* - npy_intp *: 指向整数数组的指针,用于存储维度信息
* - int: 表示数组的维度数量
*/
typedef struct {
npy_intp *ptr;
int len;
} PyArray_Dims;
typedef struct {
/*
* Functions to cast to most other standard types
* Can have some NULL entries. The types
* DATETIME, TIMEDELTA, and HALF go into the castdict
* even though they are built-in.
*/
PyArray_VectorUnaryFunc *cast[NPY_NTYPES_ABI_COMPATIBLE];
/* The next four functions *cannot* be NULL */
/*
* Functions to get and set items with standard Python types
* -- not array scalars
*/
PyArray_GetItemFunc *getitem;
PyArray_SetItemFunc *setitem;
/*
* Copy and/or swap data. Memory areas may not overlap
* Use memmove first if they might
*/
PyArray_CopySwapNFunc *copyswapn;
PyArray_CopySwapFunc *copyswap;
/*
* Function to compare items
* Can be NULL
*/
PyArray_CompareFunc *compare;
/*
* Function to select largest
* Can be NULL
*/
PyArray_ArgFunc *argmax;
/*
* Function to compute dot product
* Can be NULL
*/
PyArray_DotFunc *dotfunc;
/*
* Function to scan an ASCII file and
* place a single value plus possible separator
* Can be NULL
*/
PyArray_ScanFunc *scanfunc;
/*
* Function to read a single value from a string
* and adjust the pointer; Can be NULL
*/
PyArray_FromStrFunc *fromstr;
/*
* Function to determine if data is zero or not
* If NULL a default version is
* used at Registration time.
*/
PyArray_NonzeroFunc *nonzero;
/*
* Used for arange. Should return 0 on success
* and -1 on failure.
* Can be NULL.
*/
PyArray_FillFunc *fill;
/*
* Function to fill arrays with scalar values
* Can be NULL
*/
PyArray_FillWithScalarFunc *fillwithscalar;
/*
* Sorting functions
* Can be NULL
*/
PyArray_SortFunc *sort[NPY_NSORTS];
PyArray_ArgSortFunc *argsort[NPY_NSORTS];
/*
* Dictionary of additional casting functions
* PyArray_VectorUnaryFuncs
* which can be populated to support casting
* to other registered types. Can be NULL
*/
PyObject *castdict;
/*
* Functions useful for generalizing
* the casting rules.
* Can be NULL;
*/
PyArray_ScalarKindFunc *scalarkind;
int **cancastscalarkindto;
int *cancastto;
void *_unused1;
void *_unused2;
void *_unused3;
/*
* Function to select smallest
* Can be NULL
*/
PyArray_ArgFunc *argmin;
} PyArray_ArrFuncs;
/* The item must be reference counted when it is inserted or extracted. */
/*
* 定义了一些常量,用于描述数据类型的特征标志位。
* 这些标志位用于指示数据类型的特性,如是否包含对象、是否需要初始化等。
*/
/*
* 这些标志位是针对全局数据类型的继承标志位,如果字段中的任何数据类型具有这些标志位,则其继承。
*/
NPY_ITEM_REFCOUNT | NPY_NEEDS_PYAPI)
NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT | \
NPY_NEEDS_INIT | NPY_NEEDS_PYAPI)
/*
* 如果 NumPy 版本符合 2.x 及以上,使用公共的 PyArray_Descr 结构体。
*/
typedef struct _PyArray_Descr {
PyObject_HEAD
/*
* typeobj 表示该类型的实例的类型对象,不应该有两个 type_number 指向相同的类型对象。
*/
PyTypeObject *typeobj;
/* 表示该类型的种类 */
char kind;
/* 表示该类型的唯一字符 */
char type;
/*
* '>' (big), '<' (little), '|' (not-applicable), 或 '=' (native),
* 表示字节顺序。
*/
char byteorder;
/* 旧的标志位字段(未使用),用于确保 type_num 是稳定的。 */
char _former_flags;
/* 表示该类型的数字 */
int type_num;
/* 用于特定 dtype 实例的标志位 */
npy_uint64 flags;
/* 该类型的元素大小(itemsize) */
npy_intp elsize;
/* 该类型所需的对齐方式 */
npy_intp alignment;
/* 元数据字典或 NULL */
PyObject *metadata;
/* 缓存的哈希值(如果尚未计算则为 -1) */
npy_hash_t hash;
/* 未使用的插槽(必须初始化为 NULL),用于将来的扩展 */
void *reserved_null[2];
} PyArray_Descr;
typedef struct _PyArray_Descr {
PyObject_HEAD
PyTypeObject *typeobj;
char kind;
char type;
char byteorder;
char _former_flags;
int type_num;
} PyArray_Descr;
/* 要访问修改后的字段,请定义完整的 2.0 版本结构体: */
/*
* 定义了一个名为 _PyArray_DescrNumPy2 的结构体,表示 NumPy 2.x 中的数组描述符。
* 此结构体包含了用于描述数组数据类型的各种字段和元数据。
* 是 NumPy 1.x 和 2.x 兼容版本的一部分。
*/
typedef struct {
PyObject_HEAD
PyTypeObject *typeobj; // 指向数组数据类型对象的指针
char kind; // 数据类型的种类
char type; // 数据类型的具体类型
char byteorder; // 数据的字节顺序
char _former_flags; // 先前的标志位
int type_num; // 数据类型的编号
npy_uint64 flags; // 数组描述符的标志
npy_intp elsize; // 每个数组元素的大小
npy_intp alignment; // 数组数据的对齐方式
PyObject *metadata; // 数组描述符的元数据
npy_hash_t hash; // 数组描述符的哈希值
void *reserved_null[2]; // 保留字段,暂未使用
} _PyArray_DescrNumPy2;
/*
* 半私有结构体 _PyArray_LegacyDescr,包含了遗留描述符的额外字段
* 在进行类型转换或访问之前必须检查 NPY_DT_is_legacy。
* 当运行在 1.x 版本时,结构体不是有效的公共 API 使用。
*/
typedef struct {
PyObject_HEAD
PyTypeObject *typeobj; // 指向数组数据类型对象的指针
char kind; // 数据类型的种类
char type; // 数据类型的具体类型
char byteorder; // 数据的字节顺序
char _former_flags; // 先前的标志位
int type_num; // 数据类型的编号
npy_uint64 flags; // 数组描述符的标志
npy_intp elsize; // 每个数组元素的大小
npy_intp alignment; // 数组数据的对齐方式
PyObject *metadata; // 数组描述符的元数据
npy_hash_t hash; // 数组描述符的哈希值
void *reserved_null[2]; // 保留字段,暂未使用
struct _arr_descr *subarray; // 子数组的描述符
PyObject *fields; // 数组字段的 Python 对象
PyObject *names; // 数组字段的名称
NpyAuxData *c_metadata; // C 风格的元数据
} _PyArray_LegacyDescr;
/*
* PyArray_DescrProto 结构体,未修改的 PyArray_Descr 结构体,与 NumPy 1.x 中的版本完全相同。
* 用作注册新的遗留数据类型的原型。
* 在 1.x 版本中,也用于访问用户代码中的字段。
*/
typedef struct {
PyObject_HEAD
PyTypeObject *typeobj; // 指向数组数据类型对象的指针
char kind; // 数据类型的种类
char type; // 数据类型的具体类型
char byteorder; // 数据的字节顺序
char flags; // 数组描述符的标志
int type_num; // 数据类型的编号
int elsize; // 每个数组元素的大小
int alignment; // 数组数据的对齐方式
struct _arr_descr *subarray; // 子数组的描述符
PyObject *fields; // 数组字段的 Python 对象
PyObject *names; // 数组字段的名称
PyArray_ArrFuncs *f; // 数组函数的指针
PyObject *metadata; // 数组描述符的元数据
NpyAuxData *c_metadata; // C 风格的元数据
npy_hash_t hash; // 数组描述符的哈希值
} PyArray_DescrProto;
typedef struct _arr_descr {
PyArray_Descr *base; // 数组的基本描述符
PyObject *shape; // 数组的形状,一个元组
} PyArray_ArrayDescr;
/*
* 数组数据的内存处理器结构体。
* free 函数的声明与 PyMemAllocatorEx 不同。
*/
typedef struct {
void *ctx; // 上下文指针
void* (*malloc) (void *ctx, size_t size); // 分配内存的函数指针
void* (*calloc) (void *ctx, size_t nelem, size_t elsize); // 分配并清零内存的函数指针
void* (*realloc) (void *ctx, void *ptr, size_t new_size); // 重新分配内存的函数指针
void (*free) (void *ctx, void *ptr, size_t size); // 释放内存的函数指针
/*
* 这是版本 1 的结尾。只能在此行之后添加新的字段。
*/
} PyDataMemAllocator;
typedef struct {
char name[127]; // 名称字符串,长度为 127,用于保持结构体对齐
uint8_t version; // 版本号,当前为 1
PyDataMemAllocator allocator; // 内存分配器结构体
} PyDataMem_Handler;
/*
* 主数组对象的结构体。
*
* 推荐使用下面定义的内联函数(如 PyArray_DATA 等)来访问此处的字段,
* 因为在多个版本中直接访问成员本身已经被弃用。
* 为了确保代码不使用已弃用的访问方式,
* 需要定义 NPY_NO_DEPRECATED_API 为 NPY_1_7_API_VERSION
* (或更高版本,如 NPY_1_8_API_VERSION)。
*/
/* This struct defines the fields of a PyArrayObject, which represents an array object in NumPy */
typedef struct tagPyArrayObject_fields {
PyObject_HEAD
/* Pointer to the raw data buffer */
char *data;
/* The number of dimensions, also called 'ndim' */
int nd;
/* The size in each dimension, also called 'shape' */
npy_intp *dimensions;
/*
* Number of bytes to jump to get to the
* next element in each dimension
*/
npy_intp *strides;
/*
* This object is decref'd upon
* deletion of array. Except in the
* case of WRITEBACKIFCOPY which has
* special handling.
*
* For views it points to the original
* array, collapsed so no chains of
* views occur.
*
* For creation from buffer object it
* points to an object that should be
* decref'd on deletion
*
* For WRITEBACKIFCOPY flag this is an
* array to-be-updated upon calling
* PyArray_ResolveWritebackIfCopy
*/
PyObject *base;
/* Pointer to type structure */
PyArray_Descr *descr;
/* Flags describing array -- see below */
int flags;
/* For weak references */
PyObject *weakreflist;
void *_buffer_info; /* private buffer info, tagged to allow warning */
/*
* For malloc/calloc/realloc/free per object
*/
PyObject *mem_handler;
} PyArrayObject_fields;
/*
* To hide the implementation details, we only expose
* the Python struct HEAD.
*/
(NPY_NO_DEPRECATED_API < NPY_1_7_API_VERSION)
/*
* Can't put this in npy_deprecated_api.h like the others.
* PyArrayObject field access is deprecated as of NumPy 1.7.
*/
typedef PyArrayObject_fields PyArrayObject;
#else
typedef struct tagPyArrayObject {
PyObject_HEAD
} PyArrayObject;
#endif
/*
* Removed 2020-Nov-25, NumPy 1.20
* #define NPY_SIZEOF_PYARRAYOBJECT (sizeof(PyArrayObject_fields))
*
* The above macro was removed as it gave a false sense of a stable ABI
* with respect to the structures size. If you require a runtime constant,
* you can use `PyArray_Type.tp_basicsize` instead. Otherwise, please
* see the PyArrayObject documentation or ask the NumPy developers for
* information on how to correctly replace the macro in a way that is
* compatible with multiple NumPy versions.
*/
/* Mirrors buffer object to ptr */
typedef struct {
PyObject_HEAD
PyObject *base;
void *ptr;
npy_intp len;
int flags;
} PyArray_Chunk;
typedef struct {
NPY_DATETIMEUNIT base;
int num;
} PyArray_DatetimeMetaData;
typedef struct {
NpyAuxData base;
PyArray_DatetimeMetaData meta;
} PyArray_DatetimeDTypeMetaData;
/*
* This structure contains an exploded view of a date-time value.
* NaT is represented by year == NPY_DATETIME_NAT.
*/
/*
* 定义了表示日期时间的结构体,包括年、月、日、时、分、秒、微秒、皮秒和阿秒
*/
typedef struct {
npy_int64 year;
npy_int32 month, day, hour, min, sec, us, ps, as;
} npy_datetimestruct;
/*
* 这个结构体在内部没有使用
*/
typedef struct {
npy_int64 day;
npy_int32 sec, us, ps, as;
} npy_timedeltastruct;
/*
* PyArray_FinalizeFunc 的类型定义,是一个指向函数的指针,接受一个 PyArrayObject 和一个 PyObject* 参数并返回 int
*/
typedef int (PyArray_FinalizeFunc)(PyArrayObject *, PyObject *);
/*
* 表示 C 风格连续的数组,即最后一个索引变化最快。数据元素紧挨着存储在一起。
* 可以在构造函数中请求此标志。
* 可以通过 PyArray_FLAGS(arr) 函数测试此标志。
*/
#define NPY_ARRAY_C_CONTIGUOUS 0x0001
/*
* 表示 Fortran 风格连续的数组,即第一个索引在内存中变化最快(strides 数组与 C 连续数组相反)。
* 可以在构造函数中请求此标志。
* 可以通过 PyArray_FLAGS(arr) 函数测试此标志。
*/
#define NPY_ARRAY_F_CONTIGUOUS 0x0002
/*
* 注意:所有的零维数组都是 C_CONTIGUOUS 和 F_CONTIGUOUS。
* 如果一个一维数组是 C_CONTIGUOUS,那么它也是 F_CONTIGUOUS。
* 多于一维的数组如果有零个或一个元素,则可以同时是 C_CONTIGUOUS 和 F_CONTIGUOUS。
* 高维数组的连续性标志与 `array.squeeze()` 相同;
* 当检查连续性时,具有 `array.shape[dimension] == 1` 的维度实际上被忽略。
*/
/*
* 如果设置了该标志,数组拥有其数据:在删除数组时会释放数据。
* 可以通过 PyArray_FLAGS(arr) 函数测试此标志。
*/
#define NPY_ARRAY_OWNDATA 0x0004
/*
* 从任意类型转换到数组时,无论是否安全都进行强制转换。
* 仅在各种 FromAny 函数的参数标志中使用。
*/
#define NPY_ARRAY_FORCECAST 0x0010
/*
* 总是复制数组。返回的数组总是连续的、对齐的和可写的。
* 参见:NPY_ARRAY_ENSURENOCOPY = 0x4000。
* 可以在构造函数中请求此标志。
*/
#define NPY_ARRAY_ENSURECOPY 0x0020
/*
* 确保返回的数组是基类 ndarray。
* 可以在构造函数中请求此标志。
*/
#define NPY_ARRAY_ENSUREARRAY 0x0040
/*
* 确保 strides 以元素大小为单位。对于某些记录数组的操作是必需的。
* 可以在构造函数中请求此标志。
*/
#define NPY_ARRAY_ELEMENTSTRIDES 0x0080
/*
* 数组数据按照类型存储的适当内存地址对齐。例如,整数数组(每个4字节)从4的倍数的内存地址开始。
* 可以在构造函数中请求此标志。
* 可以通过 PyArray_FLAGS(arr) 函数测试此标志。
*/
#define NPY_ARRAY_ALIGNED 0x0100
/*
* 数组数据具有本机字节顺序。
* 可以在构造函数中请求此标志。
*/
/*
* 定义了一系列 NumPy 数组的属性标志位
*/
#define NPY_ARRAY_NOTSWAPPED 0x0200
/*
* 数组数据可写
*
* 可以在构造函数中请求此标志位。
* 可以通过 PyArray_FLAGS(arr) 测试此标志位。
*/
#define NPY_ARRAY_WRITEABLE 0x0400
/*
* 如果设置了此标志位,那么 base 包含一个指向相同大小数组的指针,
* 在调用 PyArray_ResolveWritebackIfCopy 时应更新为当前数组的内容。
*
* 可以在构造函数中请求此标志位。
* 可以通过 PyArray_FLAGS(arr) 测试此标志位。
*/
#define NPY_ARRAY_WRITEBACKIFCOPY 0x2000
/*
* 在从对象/数组转换时禁止复制(结果是一个视图)
*
* 可以在构造函数中请求此标志位。
*/
#define NPY_ARRAY_ENSURENOCOPY 0x4000
/*
* 注意:在 multiarray/arrayobject.h 中还定义了从第 31 位开始的内部标志位。
*/
#define NPY_ARRAY_BEHAVED (NPY_ARRAY_ALIGNED | \
NPY_ARRAY_WRITEABLE)
#define NPY_ARRAY_BEHAVED_NS (NPY_ARRAY_ALIGNED | \
NPY_ARRAY_WRITEABLE | \
NPY_ARRAY_NOTSWAPPED)
#define NPY_ARRAY_CARRAY (NPY_ARRAY_C_CONTIGUOUS | \
NPY_ARRAY_BEHAVED)
#define NPY_ARRAY_CARRAY_RO (NPY_ARRAY_C_CONTIGUOUS | \
NPY_ARRAY_ALIGNED)
#define NPY_ARRAY_FARRAY (NPY_ARRAY_F_CONTIGUOUS | \
NPY_ARRAY_BEHAVED)
#define NPY_ARRAY_FARRAY_RO (NPY_ARRAY_F_CONTIGUOUS | \
NPY_ARRAY_ALIGNED)
#define NPY_ARRAY_DEFAULT (NPY_ARRAY_CARRAY)
#define NPY_ARRAY_IN_ARRAY (NPY_ARRAY_CARRAY_RO)
#define NPY_ARRAY_OUT_ARRAY (NPY_ARRAY_CARRAY)
#define NPY_ARRAY_INOUT_ARRAY (NPY_ARRAY_CARRAY)
#define NPY_ARRAY_INOUT_ARRAY2 (NPY_ARRAY_CARRAY | \
NPY_ARRAY_WRITEBACKIFCOPY)
#define NPY_ARRAY_IN_FARRAY (NPY_ARRAY_FARRAY_RO)
#define NPY_ARRAY_OUT_FARRAY (NPY_ARRAY_FARRAY)
#define NPY_ARRAY_INOUT_FARRAY (NPY_ARRAY_FARRAY)
#define NPY_ARRAY_INOUT_FARRAY2 (NPY_ARRAY_FARRAY | \
NPY_ARRAY_WRITEBACKIFCOPY)
#define NPY_ARRAY_UPDATE_ALL (NPY_ARRAY_C_CONTIGUOUS | \
NPY_ARRAY_F_CONTIGUOUS | \
NPY_ARRAY_ALIGNED)
/* 此标志位是数组接口的,不是 PyArrayObject 的 */
#define NPY_ARR_HAS_DESCR 0x0800
/*
* 内部缓冲区的大小,用于对齐。将 BUFSIZE 设为 npy_cdouble 的倍数 —— 通常为 16,以便对齐 ufunc 缓冲区
*/
#define NPY_MIN_BUFSIZE ((int)sizeof(npy_cdouble))
#define NPY_MAX_BUFSIZE (((int)sizeof(npy_cdouble))*1000000)
#define NPY_BUFSIZE 8192
/* 缓冲区压力测试大小: */
/*#define NPY_BUFSIZE 17*/
/*
* C API:包括宏和函数。这里定义了宏。
*/
#define PyArray_ISCONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_C_CONTIGUOUS)
/* 定义宏PyArray_ISWRITEABLE,检查数组是否可写 */
#define PyArray_ISWRITEABLE(m) PyArray_CHKFLAGS((m), NPY_ARRAY_WRITEABLE)
/* 定义宏PyArray_ISALIGNED,检查数组是否按对齐要求对齐 */
#define PyArray_ISALIGNED(m) PyArray_CHKFLAGS((m), NPY_ARRAY_ALIGNED)
/* 定义宏PyArray_IS_C_CONTIGUOUS,检查数组是否C顺序连续 */
#define PyArray_IS_C_CONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_C_CONTIGUOUS)
/* 定义宏PyArray_IS_F_CONTIGUOUS,检查数组是否Fortran顺序连续 */
#define PyArray_IS_F_CONTIGUOUS(m) PyArray_CHKFLAGS((m), NPY_ARRAY_F_CONTIGUOUS)
/* NPY_BEGIN_THREADS_DEF在某些地方使用,因此始终定义它 */
#define NPY_BEGIN_THREADS_DEF PyThreadState *_save=NULL;
#if NPY_ALLOW_THREADS
/* 如果允许线程,则定义以下线程相关宏 */
#define NPY_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
#define NPY_END_ALLOW_THREADS Py_END_ALLOW_THREADS
#define NPY_BEGIN_THREADS do {_save = PyEval_SaveThread();} while (0);
#define NPY_END_THREADS do { if (_save) \
{ PyEval_RestoreThread(_save); _save = NULL;} } while (0);
/* 根据循环大小阈值决定是否启用线程 */
#define NPY_BEGIN_THREADS_THRESHOLDED(loop_size) do { if ((loop_size) > 500) \
{ _save = PyEval_SaveThread();} } while (0);
/* 定义宏NPY_ALLOW_C_API_DEF,保护C API访问状态 */
#define NPY_ALLOW_C_API_DEF PyGILState_STATE __save__;
/* 进入C API访问状态 */
#define NPY_ALLOW_C_API do {__save__ = PyGILState_Ensure();} while (0);
/* 退出C API访问状态 */
#define NPY_DISABLE_C_API do {PyGILState_Release(__save__);} while (0);
#else
/* 如果不允许线程,则将所有线程相关宏置空 */
#define NPY_BEGIN_ALLOW_THREADS
#define NPY_END_ALLOW_THREADS
#define NPY_BEGIN_THREADS
#define NPY_END_THREADS
#define NPY_BEGIN_THREADS_THRESHOLDED(loop_size)
#define NPY_BEGIN_THREADS_DESCR(dtype)
#define NPY_END_THREADS_DESCR(dtype)
#define NPY_ALLOW_C_API_DEF
#define NPY_ALLOW_C_API
#define NPY_DISABLE_C_API
#endif
/**********************************
* The nditer object, added in 1.6
**********************************/
/* nditer对象的实际结构是内部细节 */
typedef struct NpyIter_InternalOnly NpyIter;
/* 可能被特殊化的迭代器函数指针 */
typedef int (NpyIter_IterNextFunc)(NpyIter *iter); /* 迭代到下一个函数 */
typedef void (NpyIter_GetMultiIndexFunc)(NpyIter *iter,
npy_intp *outcoords); /* 获取多索引 */
/*** 全局标志,可能被传递给迭代器构造函数 ***/
/* 跟踪代表C顺序的索引 */
#define NPY_ITER_C_INDEX 0x00000001
/* 跟踪代表Fortran顺序的索引 */
#define NPY_ITER_F_INDEX 0x00000002
/* 跟踪多索引 */
#define NPY_ITER_MULTI_INDEX 0x00000004
/* 外部用户代码执行1维最内层循环 */
#define NPY_ITER_EXTERNAL_LOOP 0x00000008
/* 将所有操作数转换为共同的数据类型 */
#define NPY_ITER_COMMON_DTYPE 0x00000010
/* 操作数可能持有引用,在迭代期间需要API访问 */
#define NPY_ITER_REFS_OK 0x00000020
/* 允许零大小的操作数,迭代检查IterSize为0 */
#define NPY_ITER_ZEROSIZE_OK 0x00000040
/* 允许归约(大小为0的步幅,但维度大小>1) */
#define NPY_ITER_REDUCE_OK 0x00000080
/* 启用子范围迭代 */
#define NPY_ITER_RANGED 0x00000100
/* 启用缓冲 */
/* 定义了一系列的常量,用于 NumPy 迭代器对象的配置 */
/* 全局标志位,指定迭代器的基本行为特征 */
#define NPY_ITER_BUFFERED 0x00000200
/* 当启用缓冲时,尽可能扩展内部循环 */
#define NPY_ITER_GROWINNER 0x00000400
/* 延迟分配缓冲区直到第一次 Reset* 调用 */
#define NPY_ITER_DELAY_BUFALLOC 0x00000800
/* 当指定 NPY_KEEPORDER 时,禁止反转负步幅轴 */
#define NPY_ITER_DONT_NEGATE_STRIDES 0x00001000
/*
* 如果输出操作数与其他操作数重叠(基于启发式方法,可能有误报但不会漏报),则进行临时复制以消除重叠。
*/
#define NPY_ITER_COPY_IF_OVERLAP 0x00002000
/*** 可传递给迭代器构造函数的每个操作数的标志 ***/
/* 操作数将被读取和写入 */
#define NPY_ITER_READWRITE 0x00010000
/* 操作数将只被读取 */
#define NPY_ITER_READONLY 0x00020000
/* 操作数将只被写入 */
#define NPY_ITER_WRITEONLY 0x00040000
/* 操作数的数据必须是本机字节顺序 */
#define NPY_ITER_NBO 0x00080000
/* 操作数的数据必须对齐 */
#define NPY_ITER_ALIGNED 0x00100000
/* 操作数的数据必须是连续的(在内部循环内) */
#define NPY_ITER_CONTIG 0x00200000
/* 可以复制操作数以满足要求 */
#define NPY_ITER_COPY 0x00400000
/* 可以使用 WRITEBACKIFCOPY 复制操作数以满足要求 */
#define NPY_ITER_UPDATEIFCOPY 0x00800000
/* 如果操作数为 NULL,则分配操作数 */
#define NPY_ITER_ALLOCATE 0x01000000
/* 如果分配了操作数,则不使用任何子类型 */
#define NPY_ITER_NO_SUBTYPE 0x02000000
/* 这是一个虚拟数组插槽,操作数为 NULL,但临时数据存在 */
#define NPY_ITER_VIRTUAL 0x04000000
/* 要求维度与迭代器维度完全匹配 */
#define NPY_ITER_NO_BROADCAST 0x08000000
/* 在此数组上使用掩码,影响缓冲区到数组的复制 */
#define NPY_ITER_WRITEMASKED 0x10000000
/* 此数组是所有 WRITEMASKED 操作数的掩码 */
#define NPY_ITER_ARRAYMASK 0x20000000
/* 假设迭代器顺序数据访问以应对 COPY_IF_OVERLAP */
#define NPY_ITER_OVERLAP_ASSUME_ELEMENTWISE 0x40000000
/* 全局标志的掩码 */
#define NPY_ITER_GLOBAL_FLAGS 0x0000ffff
/* 每个操作数的标志的掩码 */
#define NPY_ITER_PER_OP_FLAGS 0xffff0000
/*****************************
* 基本迭代器对象
*****************************/
/* 前向声明 */
typedef struct PyArrayIterObject_tag PyArrayIterObject;
/*
* 一个函数类型,用于将一组坐标转换为指向数据的指针
*/
typedef char* (*npy_iter_get_dataptr_t)(
PyArrayIterObject* iter, const npy_intp*);
/* 定义一个结构体 PyArrayIterObject_tag,用于实现数组迭代器 */
struct PyArrayIterObject_tag {
PyObject_HEAD /* Python 对象头部 */
int nd_m1; /* 数组维度数减一 */
npy_intp index, size; /* 当前索引和数组大小 */
npy_intp coordinates[NPY_MAXDIMS_LEGACY_ITERS];/* NPY_MAXDIMS_LEGACY_ITERS 维度的坐标 */
npy_intp dims_m1[NPY_MAXDIMS_LEGACY_ITERS]; /* 数组的维度数组减一 */
npy_intp strides[NPY_MAXDIMS_LEGACY_ITERS]; /* 数组的步幅或者虚拟的步幅 */
npy_intp backstrides[NPY_MAXDIMS_LEGACY_ITERS];/* 后退的步幅 */
npy_intp factors[NPY_MAXDIMS_LEGACY_ITERS]; /* 形状因子 */
PyArrayObject *ao; /* 指向 PyArrayObject 的指针 */
char *dataptr; /* 当前项的指针 */
npy_bool contiguous; /* 是否连续存储 */
npy_intp bounds[NPY_MAXDIMS_LEGACY_ITERS][2]; /* 边界数组 */
npy_intp limits[NPY_MAXDIMS_LEGACY_ITERS][2]; /* 限制数组 */
npy_intp limits_sizes[NPY_MAXDIMS_LEGACY_ITERS];/* 限制大小数组 */
npy_iter_get_dataptr_t translate; /* 获取数据指针的函数 */
} ;
/* 迭代器 API */
#define PyArrayIter_Check(op) PyObject_TypeCheck((op), &PyArrayIter_Type)
#define _PyAIT(it) ((PyArrayIterObject *)(it)) /* 将迭代器类型转换为 PyArrayIterObject 指针类型 */
#define PyArray_ITER_RESET(it) do { \
_PyAIT(it)->index = 0; \ /* 重置迭代器索引为 0 */
_PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao); \ /* 重置数据指针为数组数据的起始位置 */
memset(_PyAIT(it)->coordinates, 0, \
(_PyAIT(it)->nd_m1+1)*sizeof(npy_intp)); \ /* 将坐标数组清零 */
} while (0)
#define _PyArray_ITER_NEXT1(it) do { \
(it)->dataptr += _PyAIT(it)->strides[0]; \ /* 移动到下一个元素的位置 */
(it)->coordinates[0]++; \ /* 更新第一个维度的坐标 */
} while (0)
#define _PyArray_ITER_NEXT2(it) do { \
if ((it)->coordinates[1] < (it)->dims_m1[1]) { \ /* 如果第二个维度的坐标小于 dims_m1 中的值 */
(it)->coordinates[1]++; \ /* 更新第二个维度的坐标 */
(it)->dataptr += (it)->strides[1]; \ /* 移动到下一个元素的位置 */
} \
else { \
(it)->coordinates[1] = 0; \ /* 第二个维度的坐标重置为 0 */
(it)->coordinates[0]++; \ /* 更新第一个维度的坐标 */
(it)->dataptr += (it)->strides[0] - \
(it)->backstrides[1]; \ /* 移动到下一个元素的位置,考虑到第二个维度的步幅 */
} \
} while (0)
这些注释解释了给定的 C 语言结构体定义和宏定义,以及它们的功能和作用。
// 宏定义:PyArray_ITER_NEXT(it)
#define PyArray_ITER_NEXT(it) do { \
// 增加迭代器的索引
_PyAIT(it)->index++; \
// 如果维度数为 0,调用单维度迭代器的下一步函数
if (_PyAIT(it)->nd_m1 == 0) { \
_PyArray_ITER_NEXT1(_PyAIT(it)); \
} \
// 如果是连续存储的多维数组,增加数据指针以移动到下一个元素
else if (_PyAIT(it)->contiguous) \
_PyAIT(it)->dataptr += PyArray_ITEMSIZE(_PyAIT(it)->ao); \
// 如果是二维数组,调用双维度迭代器的下一步函数
else if (_PyAIT(it)->nd_m1 == 1) { \
_PyArray_ITER_NEXT2(_PyAIT(it)); \
} \
// 对于更高维度的数组,逐个维度增加坐标和数据指针
else { \
int __npy_i; \
for (__npy_i=_PyAIT(it)->nd_m1; __npy_i >= 0; __npy_i--) { \
if (_PyAIT(it)->coordinates[__npy_i] < \
_PyAIT(it)->dims_m1[__npy_i]) { \
_PyAIT(it)->coordinates[__npy_i]++; \
_PyAIT(it)->dataptr += \
_PyAIT(it)->strides[__npy_i]; \
break; \
} \
else { \
_PyAIT(it)->coordinates[__npy_i] = 0; \
_PyAIT(it)->dataptr -= \
_PyAIT(it)->backstrides[__npy_i]; \
} \
} \
} \
} while (0)
// 宏定义:PyArray_ITER_GOTO(it, destination)
#define PyArray_ITER_GOTO(it, destination) do { \
int __npy_i; \
// 将迭代器的索引重置为 0
_PyAIT(it)->index = 0; \
// 将数据指针定位到数组的起始位置
_PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao); \
// 遍历各维度,根据目标坐标调整数据指针和迭代器的坐标
for (__npy_i = _PyAIT(it)->nd_m1; __npy_i>=0; __npy_i--) { \
// 如果目标坐标为负数,转换为对应的非负坐标
if (destination[__npy_i] < 0) { \
destination[__npy_i] += \
_PyAIT(it)->dims_m1[__npy_i]+1; \
} \
// 根据目标坐标和步长调整数据指针
_PyAIT(it)->dataptr += destination[__npy_i] * \
_PyAIT(it)->strides[__npy_i]; \
// 设置迭代器的坐标为目标坐标
_PyAIT(it)->coordinates[__npy_i] = \
destination[__npy_i]; \
// 计算迭代器的索引,考虑各维度的步长和边界
_PyAIT(it)->index += destination[__npy_i] * \
( __npy_i==_PyAIT(it)->nd_m1 ? 1 : \
_PyAIT(it)->dims_m1[__npy_i+1]+1) ; \
} \
} while (0)
/*
* 宏定义:PyArray_ITER_GOTO1D(it, ind)
* 功能:将迭代器移动到一维数组中的指定索引位置
*/
#define PyArray_ITER_GOTO1D(it, ind) do { \
int __npy_i; \
npy_intp __npy_ind = (npy_intp)(ind); \ // 将输入的索引转换为 npy_intp 类型
if (__npy_ind < 0) __npy_ind += _PyAIT(it)->size; \ // 如果索引为负数,将其转换为正数
_PyAIT(it)->index = __npy_ind; \ // 设置迭代器的当前索引为 __npy_ind
if (_PyAIT(it)->nd_m1 == 0) { \ // 如果数组的维度为1
_PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao) + \ // 设置数据指针为数组的起始地址 + 索引 * 步长
__npy_ind * _PyAIT(it)->strides[0]; \
} \
else if (_PyAIT(it)->contiguous) \ // 如果数组是连续存储的
_PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao) + \ // 设置数据指针为数组的起始地址 + 索引 * 每个元素的字节大小
__npy_ind * PyArray_ITEMSIZE(_PyAIT(it)->ao); \
else { \ // 否则,数组不是连续存储的
_PyAIT(it)->dataptr = PyArray_BYTES(_PyAIT(it)->ao); \ // 设置数据指针为数组的起始地址
for (__npy_i = 0; __npy_i<=_PyAIT(it)->nd_m1; \
__npy_i++) { \ // 遍历数组的各维度
_PyAIT(it)->coordinates[__npy_i] = \ // 计算当前维度的坐标值
(__npy_ind / _PyAIT(it)->factors[__npy_i]); \
_PyAIT(it)->dataptr += \ // 根据坐标值和步长,计算数据指针的偏移量
(__npy_ind / _PyAIT(it)->factors[__npy_i]) \
* _PyAIT(it)->strides[__npy_i]; \
__npy_ind %= _PyAIT(it)->factors[__npy_i]; \ // 更新索引值以处理下一个维度
} \
} \
} while (0)
/*
* 宏定义:PyArray_ITER_DATA(it)
* 功能:获取迭代器当前指向的数据指针
*/
#define PyArray_ITER_DATA(it) ((void *)(_PyAIT(it)->dataptr))
/*
* 宏定义:PyArray_ITER_NOTDONE(it)
* 功能:检查迭代器是否未完成遍历
*/
#define PyArray_ITER_NOTDONE(it) (_PyAIT(it)->index < _PyAIT(it)->size)
/*
* 结构体定义:PyArrayMultiIterObject
* 功能:多数组迭代器对象
*/
typedef struct {
PyObject_HEAD
int numiter; // 迭代器的数量
npy_intp size; // 广播后的总大小
npy_intp index; // 当前索引
int nd; // 维度数
npy_intp dimensions[NPY_MAXDIMS_LEGACY_ITERS]; // 维度数组
/*
* Space for the individual iterators, do not specify size publicly
* to allow changing it more easily.
* One reason is that Cython uses this for checks and only allows
* growing structs (as of Cython 3.0.6). It also allows NPY_MAXARGS
* to be runtime dependent.
*/
#if (defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD)
PyArrayIterObject *iters[64]; // 迭代器对象数组,最大容量为64
#elif defined(__cplusplus)
/*
* C++ doesn't stricly support flexible members and gives compilers
* warnings (pedantic only), so we lie. We can't make it 64 because
* then Cython is unhappy (larger struct at runtime is OK smaller not).
*/
PyArrayIterObject *iters[32]; // 迭代器对象数组,最大容量为32(为了避免C++编译器警告)
#else
PyArrayIterObject *iters[]; // 迭代器对象数组,长度可变
#endif
} PyArrayMultiIterObject;
#define _PyMIT(m) ((PyArrayMultiIterObject *)(m))
#define PyArray_MultiIter_RESET(multi) do { \
int __npy_mi; \
_PyMIT(multi)->index = 0; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_RESET(_PyMIT(multi)->iters[__npy_mi]); \
} \
} while (0)
# 重置多重迭代器 `multi` 的状态,将其索引置为0,并逐个重置其包含的每个迭代器
#define PyArray_MultiIter_RESET(multi) do { \
int __npy_mi; \
_PyMIT(multi)->index = 0; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_RESET(_PyMIT(multi)->iters[__npy_mi]); \
} \
} while (0)
#define PyArray_MultiIter_NEXT(multi) do { \
int __npy_mi; \
_PyMIT(multi)->index++; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_NEXT(_PyMIT(multi)->iters[__npy_mi]); \
} \
} while (0)
# 将多重迭代器 `multi` 的索引递增,并逐个移动其包含的每个迭代器到下一个位置
#define PyArray_MultiIter_NEXT(multi) do { \
int __npy_mi; \
_PyMIT(multi)->index++; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_NEXT(_PyMIT(multi)->iters[__npy_mi]); \
} \
} while (0)
#define PyArray_MultiIter_GOTO(multi, dest) do { \
int __npy_mi; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_GOTO(_PyMIT(multi)->iters[__npy_mi], dest); \
} \
_PyMIT(multi)->index = _PyMIT(multi)->iters[0]->index; \
} while (0)
# 将多重迭代器 `multi` 中所有迭代器移动到目标位置 `dest`,并将多重迭代器的索引设置为第一个迭代器的当前索引
#define PyArray_MultiIter_GOTO(multi, dest) do { \
int __npy_mi; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_GOTO(_PyMIT(multi)->iters[__npy_mi], dest); \
} \
_PyMIT(multi)->index = _PyMIT(multi)->iters[0]->index; \
} while (0)
#define PyArray_MultiIter_GOTO1D(multi, ind) do { \
int __npy_mi; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_GOTO1D(_PyMIT(multi)->iters[__npy_mi], ind); \
} \
_PyMIT(multi)->index = _PyMIT(multi)->iters[0]->index; \
} while (0)
# 将多重迭代器 `multi` 中所有迭代器移动到一维索引 `ind` 指定的位置,并将多重迭代器的索引设置为第一个迭代器的当前索引
#define PyArray_MultiIter_GOTO1D(multi, ind) do { \
int __npy_mi; \
for (__npy_mi=0; __npy_mi < _PyMIT(multi)->numiter; __npy_mi++) { \
PyArray_ITER_GOTO1D(_PyMIT(multi)->iters[__npy_mi], ind); \
} \
_PyMIT(multi)->index = _PyMIT(multi)->iters[0]->index; \
} while (0)
#define PyArray_MultiIter_DATA(multi, i) \
((void *)(_PyMIT(multi)->iters[i]->dataptr))
# 返回多重迭代器 `multi` 中第 `i` 个迭代器当前指向的数据指针
#define PyArray_MultiIter_DATA(multi, i) \
((void *)(_PyMIT(multi)->iters[i]->dataptr))
#define PyArray_MultiIter_NEXTi(multi, i) \
PyArray_ITER_NEXT(_PyMIT(multi)->iters[i])
# 将多重迭代器 `multi` 中第 `i` 个迭代器移动到下一个位置
#define PyArray_MultiIter_NEXTi(multi, i) \
PyArray_ITER_NEXT(_PyMIT(multi)->iters[i])
#define PyArray_MultiIter_NOTDONE(multi) \
(_PyMIT(multi)->index < _PyMIT(multi)->size)
# 检查多重迭代器 `multi` 是否完成迭代,即索引是否小于其总大小
#define PyArray_MultiIter_NOTDONE(multi) \
(_PyMIT(multi)->index < _PyMIT(multi)->size)
static NPY_INLINE int
PyArray_MultiIter_NUMITER(PyArrayMultiIterObject *multi)
{
return multi->numiter;
}
# 返回多重迭代器 `multi` 中包含的迭代器数量
static NPY_INLINE int
PyArray_MultiIter_NUMITER(PyArrayMultiIterObject *multi)
{
return multi->numiter;
}
static NPY_INLINE npy_intp
PyArray_MultiIter_SIZE(PyArrayMultiIterObject *multi)
{
return multi->size;
}
# 返回多重迭代器 `multi` 的总大小
static NPY_INLINE npy_intp
PyArray_MultiIter_SIZE(PyArrayMultiIterObject *multi)
{
return multi->size;
}
static NPY_INLINE npy_intp
PyArray_MultiIter_INDEX(PyArrayMultiIterObject *multi)
{
return multi->index;
}
# 返回多重迭代器 `multi` 的当前索引
static NPY_INLINE npy_intp
PyArray_MultiIter_INDEX(PyArrayMultiIterObject *multi)
{
return multi->index;
}
static NPY_INLINE int
PyArray_MultiIter_NDIM(PyArrayMultiIterObject *multi)
{
return multi->nd;
}
# 返回多重迭代器 `multi` 涉及的数组维度数目
static NPY_INLINE int
PyArray_MultiIter_NDIM(PyArrayMultiIterObject *multi)
{
return multi->nd;
}
static NPY_INLINE npy_intp *
PyArray_MultiIter_DIMS(PyArrayMultiIterObject *multi)
{
return multi->dimensions;
}
# 返回多重迭代器 `multi` 涉及的数组维度
static NPY_INLINE npy_intp *
PyArray_MultiIter_DIMS(PyArrayMultiIterObject *multi)
{
return multi->dimensions;
}
static NPY_INLINE void **
PyArray_MultiIter_ITERS(PyArrayMultiIterObject *multi)
{
return (void**)multi->iters;
}
# 返回多重迭代器 `multi` 中迭代器对象数组的指针
static NPY_INLINE void **
PyArray_MultiIter_ITERS(PyArrayMultiIterObject *multi)
{
return (void**)multi->iters;
}
enum {
# 枚举的开始标记
enum {
# 定义常量:邻域迭代器使用零填充方式
NPY_NEIGHBORHOOD_ITER_ZERO_PADDING,
# 定义常量:邻域迭代器使用一填充方式
NPY_NEIGHBORHOOD_ITER_ONE_PADDING,
# 定义常量:邻域迭代器使用常量填充方式
NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING,
# 定义常量:邻域迭代器使用循环填充方式
NPY_NEIGHBORHOOD_ITER_CIRCULAR_PADDING,
# 定义常量:邻域迭代器使用镜像填充方式
NPY_NEIGHBORHOOD_ITER_MIRROR_PADDING
};
typedef struct {
PyObject_HEAD
/*
* PyArrayIterObject part: keep this in this exact order
*/
int nd_m1; /* number of dimensions - 1 */
npy_intp index, size; /* current index and total size */
npy_intp coordinates[NPY_MAXDIMS_LEGACY_ITERS]; /* N-dimensional loop coordinates */
npy_intp dims_m1[NPY_MAXDIMS_LEGACY_ITERS]; /* ao->dimensions - 1 */
npy_intp strides[NPY_MAXDIMS_LEGACY_ITERS]; /* ao->strides or fake */
npy_intp backstrides[NPY_MAXDIMS_LEGACY_ITERS]; /* how far to jump back */
npy_intp factors[NPY_MAXDIMS_LEGACY_ITERS]; /* shape factors */
PyArrayObject *ao; /* pointer to the PyArrayObject */
char *dataptr; /* pointer to current item */
npy_bool contiguous; /* flag indicating contiguous data */
npy_intp bounds[NPY_MAXDIMS_LEGACY_ITERS][2]; /* bounds for each dimension */
npy_intp limits[NPY_MAXDIMS_LEGACY_ITERS][2]; /* limits for each dimension */
npy_intp limits_sizes[NPY_MAXDIMS_LEGACY_ITERS]; /* size of limits for each dimension */
npy_iter_get_dataptr_t translate; /* function pointer to translate data */
/*
* New members
*/
npy_intp nd; /* number of dimensions */
/* Dimensions is the dimension of the array */
npy_intp dimensions[NPY_MAXDIMS_LEGACY_ITERS]; /* dimensions of the array */
/*
* Neighborhood points coordinates are computed relatively to the
* point pointed by _internal_iter
*/
PyArrayIterObject* _internal_iter; /* internal iterator object */
/*
* To keep a reference to the representation of the constant value
* for constant padding
*/
char* constant; /* constant padding representation */
int mode; /* mode of operation */
} PyArrayNeighborhoodIterObject;
/*
* Neighborhood iterator API
*/
/* General: those work for any mode */
/* Reset the neighborhood iterator */
static inline int
PyArrayNeighborhoodIter_Reset(PyArrayNeighborhoodIterObject* iter);
/* Move to the next neighborhood */
static inline int
PyArrayNeighborhoodIter_Next(PyArrayNeighborhoodIterObject* iter);
#if 0
/* Move to the next neighborhood (2D version) */
static inline int
PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter);
#endif
/*
* Include inline implementations - functions defined there are not
* considered public API
*/
#define NUMPY_CORE_INCLUDE_NUMPY__NEIGHBORHOOD_IMP_H_
#include "_neighborhood_iterator_imp.h"
#undef NUMPY_CORE_INCLUDE_NUMPY__NEIGHBORHOOD_IMP_H_
/* The default array type */
#define NPY_DEFAULT_TYPE NPY_DOUBLE
/* default integer type defined in npy_2_compat header */
/*
* All sorts of useful ways to look into a PyArrayObject. It is recommended
* to use PyArrayObject * objects instead of always casting from PyObject *,
* for improved type checking.
*
* In many cases here the macro versions of the accessors are deprecated,
* but can't be immediately changed to inline functions because the
* preexisting macros accept PyObject * and do automatic casts. Inline
* functions accepting PyArrayObject * provides for some compile-time
* checking of correctness when working with these objects in C.
*/
/* Check if array is one segment (contiguous) */
PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS))
注释:
/* 结构体定义结束 */
/* 定义 PyArrayNeighborhoodIterObject 结构体,继承自 PyObject */
/* PyArrayIterObject 的一部分:保持此精确顺序 */
/* 数组迭代器结构体的维度减一 */
/* 当前索引和总大小 */
/* N 维循环的坐标 */
/* ao->dimensions - 1 */
/* ao->strides 或虚拟值 */
/* 后退跨度 */
/* 形状因子 */
/* 指向 PyArrayObject 的指针 */
/* 指向当前项的指针 */
/* 表示数据是否连续的标志 */
/* 每个维度的边界 */
/* 每个维度的限制 */
/* 每个维度限制的大小 */
/* 数据转换函数指针 */
/* 新成员 */
/* 数组的维度 */
/* 数组的维度 */
/* 邻域点坐标相对于 _internal_iter 指向的点计算 */
/* 保留对常量填充值表示的引用 */
/* 操作模式 */
/*
* 检查数组是否按 Fortran 风格存储(列优先),同时不应该按 C 风格存储(行优先)
* 返回值:如果数组按 Fortran 风格存储则返回非零值,否则返回零
*/
(!PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)))
/*
* 如果数组按 Fortran 风格存储,返回 NPY_ARRAY_F_CONTIGUOUS,否则返回 0
*/
NPY_ARRAY_F_CONTIGUOUS : 0))
/*
* 返回数组的维度数
*/
static inline int
PyArray_NDIM(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->nd;
}
/*
* 返回数组的数据指针
*/
static inline void *
PyArray_DATA(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->data;
}
/*
* 返回数组的数据指针(以字符形式)
*/
static inline char *
PyArray_BYTES(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->data;
}
/*
* 返回数组的维度数组指针
*/
static inline npy_intp *
PyArray_DIMS(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->dimensions;
}
/*
* 返回数组的步幅数组指针
*/
static inline npy_intp *
PyArray_STRIDES(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->strides;
}
/*
* 返回数组的指定维度的大小
*/
static inline npy_intp
PyArray_DIM(const PyArrayObject *arr, int idim)
{
return ((PyArrayObject_fields *)arr)->dimensions[idim];
}
/*
* 返回数组的指定步幅
*/
static inline npy_intp
PyArray_STRIDE(const PyArrayObject *arr, int istride)
{
return ((PyArrayObject_fields *)arr)->strides[istride];
}
/*
* 返回数组的 base 对象
*/
static inline NPY_RETURNS_BORROWED_REF PyObject *
PyArray_BASE(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->base;
}
/*
* 返回数组的数据类型描述符
*/
static inline NPY_RETURNS_BORROWED_REF PyArray_Descr *
PyArray_DESCR(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->descr;
}
/*
* 返回数组的 flags 属性
*/
static inline int
PyArray_FLAGS(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->flags;
}
/*
* 返回数组的数据类型编号
*/
static inline int
PyArray_TYPE(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->descr->type_num;
}
/*
* 检查数组的 flags 是否包含指定的 flags
* 返回值:如果数组 flags 包含所有指定 flags,则返回非零值,否则返回零
*/
static inline int
PyArray_CHKFLAGS(const PyArrayObject *arr, int flags)
{
return (PyArray_FLAGS(arr) & flags) == flags;
}
/*
* 返回数组的数据类型描述符
*/
static inline PyArray_Descr *
PyArray_DTYPE(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->descr;
}
/*
* 返回数组的维度数组指针
*/
static inline npy_intp *
PyArray_SHAPE(const PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->dimensions;
}
/*
* 设置数组的指定 flags,不进行检查,假定用户知道自己在做什么
*/
static inline void
PyArray_ENABLEFLAGS(PyArrayObject *arr, int flags)
{
((PyArrayObject_fields *)arr)->flags |= flags;
}
/*
* 清除数组的指定 flags,不进行检查,假定用户知道自己在做什么
*/
static inline void
PyArray_CLEARFLAGS(PyArrayObject *arr, int flags)
{
((PyArrayObject_fields *)arr)->flags &= ~flags;
}
/*
* 返回数组的内存处理器对象(如果支持)
*/
static inline NPY_RETURNS_BORROWED_REF PyObject *
PyArray_HANDLER(PyArrayObject *arr)
{
return ((PyArrayObject_fields *)arr)->mem_handler;
}
/*
* 检查数组的数据类型是否为布尔型
* 返回值:如果数组的数据类型为 NPY_BOOL,则返回非零值,否则返回零
*/
((type) == NPY_USHORT) || \
((type) == NPY_UINT) || \
((type) == NPY_ULONG) || \
((type) == NPY_ULONGLONG))
((type) == NPY_SHORT) || \
((type) == NPY_INT) || \
((type) == NPY_LONG) || \
((type) == NPY_LONGLONG))
((type) <= NPY_ULONGLONG))
((type) <= NPY_LONGDOUBLE)) || \
((type) == NPY_HALF))
((type) == NPY_HALF))
((type) == NPY_UNICODE))
((type) <= NPY_CLONGDOUBLE))
((type) <=NPY_VOID))
((type) <=NPY_TIMEDELTA))
((type) < NPY_USERDEF+ \
NPY_NUMUSERTYPES))
PyTypeNum_ISUSERDEF(type))
/*
* 定义了一系列用于检查和操作 NumPy 数组数据类型和标志的宏。
*/
// 检查给定数据类型对象是否为用户定义类型
// 检查给定数据类型对象是否为扩展类型
// 检查给定数据类型对象是否为对象类型
// 将给定数据类型对象标记为无大小,通常用于灵活数据类型
/*
* PyDataType_* FLAGS, FLACHK, REFCHK, HASFIELDS, HASSUBARRAY, UNSIZED,
* SUBARRAY, NAMES, FIELDS, C_METADATA, and METADATA require version specific
* lookup and are defined in npy_2_compat.h.
*/
// 这些宏定义需要特定版本的查找,并在 npy_2_compat.h 中定义
// 检查给定数组对象的类型是否为布尔类型
// 检查给定数组对象的类型是否为无符号整数类型
// 检查给定数组对象的类型是否为有符号整数类型
// 检查给定数组对象的类型是否为整数类型
// 检查给定数组对象的类型是否为浮点数类型
// 检查给定数组对象的类型是否为数字类型
// 检查给定数组对象的类型是否为字符串类型
// 检查给定数组对象的类型是否为复数类型
// 检查给定数组对象的类型是否为灵活数据类型
// 检查给定数组对象的类型是否为日期时间类型
// 检查给定数组对象的类型是否为用户定义类型
// 检查给定数组对象的类型是否为扩展类型
// 检查给定数组对象的类型是否为对象类型
// 检查给定数组对象是否具有字段描述符
/*
* FIXME: This should check for a flag on the data-type that
* states whether or not it is variable length. Because the
* ISFLEXIBLE check is hard-coded to the built-in data-types.
*/
// 检查给定数组对象的类型是否为可变长度类型
// 检查给定数组对象是否是对齐的且不是可变长度类型
// 定义小端字节顺序符号
// 定义大端字节顺序符号
// 定义本地字节顺序符号
// 定义交换字节顺序符号
// 定义忽略字节顺序符号
// 检查参数是否与本地字节顺序匹配
// 别名,检查参数是否与本地字节顺序匹配
// 检查给定数组对象的描述符的字节顺序是否与本地字节顺序匹配
// 检查给定数组对象是否具有交换字节顺序的描述符
PyArray_ISNOTSWAPPED(m))
// 检查给定数组对象是否符合特定标志并且没有交换字节顺序
// 检查给定数组对象是否具有 C 风格数组标志
// 检查给定数组对象是否具有只读 C 风格数组标志
// 检查给定数组对象是否具有 Fortran 风格数组标志
// 检查给定数组对象是否具有只读 Fortran 风格数组标志
// 检查给定数组对象是否具有规范行为标志
// 检查给定数组对象是否具有只读规范行为标志
/*
* 宏定义:检查数据类型是否未交换字节序
*/
/*
* 宏定义:检查数据类型是否已交换字节序
*/
/************************************************************
* PyArray_CreateSortedStridePerm 中使用的结构体,从 1.7 版本开始引入。
************************************************************/
typedef struct {
npy_intp perm, stride;
} npy_stride_sort_item;
/************************************************************
* 存储在数组的 __array_struct__ 属性返回的 PyCapsule 中的结构体形式。
* 查看完整文档请参考 https://docs.scipy.org/doc/numpy/reference/arrays.interface.html
************************************************************/
typedef struct {
int two; /*
* 作为健全性检查,包含整数 2
*/
int nd; /* 维度数量 */
char typekind; /*
* 数组中的数据类型种类代码,对应于 typestr 的字符代码
*/
int itemsize; /* 每个元素的大小 */
int flags; /*
* 数据解释方式的标志位。有效的标志有 CONTIGUOUS (1),
* F_CONTIGUOUS (2), ALIGNED (0x100), NOTSWAPPED (0x200),
* WRITEABLE (0x400)。ARR_HAS_DESCR (0x800) 表示结构中有 arrdescr 字段
*/
npy_intp *shape; /*
* 长度为 nd 的形状信息数组
*/
npy_intp *strides; /* 长度为 nd 的步幅信息数组 */
void *data; /* 数组第一个元素的指针 */
PyObject *descr; /*
* 字段列表或 NULL(如果 flags 没有设置 ARR_HAS_DESCR 标志则忽略)
*/
} PyArrayInterface;
/****************************************
* NpyString
*
* NpyString API 使用的类型。
****************************************/
/*
* "packed" 编码字符串。访问字符串数据时必须先解包字符串。
*/
typedef struct npy_packed_static_string npy_packed_static_string;
/*
* 对打包字符串中数据的无修改只读视图。
*/
typedef struct npy_unpacked_static_string {
size_t size;
const char *buf;
} npy_static_string;
/*
* 处理静态字符串的堆分配。
*/
typedef struct npy_string_allocator npy_string_allocator;
typedef struct {
PyArray_Descr base;
// 表示空值的对象
PyObject *na_object;
// 标志,指示是否将任意对象强制转换为字符串
char coerce;
// 表示 na 对象是否类似于 NaN
char has_nan_na;
// 表示 na 对象是否为字符串
char has_string_na;
// 若非零,则表示此实例已被数组所拥有
char array_owned;
// 当需要默认字符串时使用的字符串数据
npy_static_string default_string;
// 若存在,表示缺失数据对象的名称
npy_static_string na_name;
// 分配器应当仅在获取 allocator_lock 后直接访问,
// 并在 allocator 不再需要时立即释放锁
npy_string_allocator *allocator;
/*
* PyArray_StringDTypeObject: This structure definition likely represents
* a data type object for string arrays in NumPy.
*/
/*
* PyArray_DTypeMeta related definitions:
*
* As of now, this API is preliminary and will be extended as necessary.
*/
/*
* The Structures defined in this block are currently considered
* private API and may change without warning!
* Part of this (at least the size) is expected to be public API without
* further modifications.
*/
/* TODO: Make this definition public in the API, as soon as it's settled */
/*
* PyArrayDTypeMeta_Type: This variable likely defines the type object
* for the meta information related to data types
* in NumPy arrays.
*/
/*
* PyArray_DTypeMeta: Structure defining metadata for NumPy data types.
* It extends PyHeapTypeObject and includes fields
* such as singleton, type_num, scalar_type, flags,
* dt_slots, and reserved, aimed at providing a stable
* ABI for static and opaque API usage.
*/
#endif /* NPY_INTERNAL_BUILD */
/*
* Use the keyword NPY_DEPRECATED_INCLUDES to ensure that the header files
* npy_*_*_deprecated_api.h are only included from here and nowhere else.
*/
#ifdef NPY_DEPRECATED_INCLUDES
#error "Do not use the reserved keyword NPY_DEPRECATED_INCLUDES."
#endif
#define NPY_DEPRECATED_INCLUDES
/*
* Conditional inclusion of deprecated API headers based on NumPy version.
* Includes npy_1_7_deprecated_api.h for versions below 1.7 unless deprecated
* APIs are explicitly disabled (NPY_NO_DEPRECATED_API).
*/
#if !defined(NPY_NO_DEPRECATED_API) || \
(NPY_NO_DEPRECATED_API < NPY_1_7_API_VERSION)
#include "npy_1_7_deprecated_api.h"
#endif
/*
* There is no file npy_1_8_deprecated_api.h since there are no additional
* deprecated API features in NumPy 1.8.
*
* Note to maintainers: insert code like the following in future NumPy
* versions.
*
* #if !defined(NPY_NO_DEPRECATED_API) || \
* (NPY_NO_DEPRECATED_API < NPY_1_9_API_VERSION)
* #include "npy_1_9_deprecated_api.h"
* #endif
*/
#undef NPY_DEPRECATED_INCLUDES
取消预处理器定义 NPY_DEPRECATED_INCLUDES,如果之前定义过的话。
.\numpy\numpy\_core\include\numpy\npy_1_7_deprecated_api.h
// 如果未定义 NPY_DEPRECATED_INCLUDES 宏,则产生编译错误,要求不直接包含 npy_*_*_deprecated_api 文件
// 如果未定义 NUMPY_CORE_INCLUDE_NUMPY_NPY_1_7_DEPRECATED_API_H_ 宏,则定义该宏,避免重复包含本文件
/* Emit a warning if the user did not specifically request the old API */
"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION")
"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION"
// 如果未定义 NPY_NO_DEPRECATED_API 宏,则生成编译警告,提示用户使用了已弃用的 NumPy API,并给出禁用方法
/*
* This header exists to collect all dangerous/deprecated NumPy API
* as of NumPy 1.7.
*
* This is an attempt to remove bad API, the proliferation of macros,
* and namespace pollution currently produced by the NumPy headers.
*/
// 本头文件用于收集 NumPy 1.7 中所有危险/已弃用的 API。
// 旨在清除糟糕的 API、宏的过度使用以及当前由 NumPy 头文件引起的命名空间污染。
/* These array flags are deprecated as of NumPy 1.7 */
// 这些数组标志在 NumPy 1.7 中已弃用
/*
* The consistent NPY_ARRAY_* names which don't pollute the NPY_*
* namespace were added in NumPy 1.7.
*
* These versions of the carray flags are deprecated, but
* probably should only be removed after two releases instead of one.
*/
#define NPY_C_CONTIGUOUS NPY_ARRAY_C_CONTIGUOUS
#define NPY_F_CONTIGUOUS NPY_ARRAY_F_CONTIGUOUS
#define NPY_OWNDATA NPY_ARRAY_OWNDATA
#define NPY_FORCECAST NPY_ARRAY_FORCECAST
#define NPY_ENSURECOPY NPY_ARRAY_ENSURECOPY
#define NPY_ENSUREARRAY NPY_ARRAY_ENSUREARRAY
#define NPY_ELEMENTSTRIDES NPY_ARRAY_ELEMENTSTRIDES
#define NPY_ALIGNED NPY_ARRAY_ALIGNED
#define NPY_NOTSWAPPED NPY_ARRAY_NOTSWAPPED
#define NPY_WRITEABLE NPY_ARRAY_WRITEABLE
#define NPY_BEHAVED NPY_ARRAY_BEHAVED
#define NPY_BEHAVED_NS NPY_ARRAY_BEHAVED_NS
#define NPY_CARRAY NPY_ARRAY_CARRAY
#define NPY_CARRAY_RO NPY_ARRAY_CARRAY_RO
#define NPY_FARRAY NPY_ARRAY_FARRAY
#define NPY_FARRAY_RO NPY_ARRAY_FARRAY_RO
#define NPY_DEFAULT NPY_ARRAY_DEFAULT
#define NPY_IN_ARRAY NPY_ARRAY_IN_ARRAY
#define NPY_OUT_ARRAY NPY_ARRAY_OUT_ARRAY
#define NPY_INOUT_ARRAY NPY_ARRAY_INOUT_ARRAY
#define NPY_IN_FARRAY NPY_ARRAY_IN_FARRAY
#define NPY_OUT_FARRAY NPY_ARRAY_OUT_FARRAY
#define NPY_INOUT_FARRAY NPY_ARRAY_INOUT_FARRAY
#define NPY_UPDATE_ALL NPY_ARRAY_UPDATE_ALL
// 在 NumPy 1.7 中添加了一致的 NPY_ARRAY_* 名称,避免了 NPY_* 命名空间的污染。
// 这些 carray 标志的版本已弃用,但可能应该在两个版本发布后移除,而不是一个版本。
/* This way of accessing the default type is deprecated as of NumPy 1.7 */
#define PyArray_DEFAULT NPY_DEFAULT_TYPE
// 在 NumPy 1.7 中已弃用这种访问默认类型的方式
#define PyArray_DEFAULT NPY_DEFAULT_TYPE // PyArray_DEFAULT 等同于 NPY_DEFAULT_TYPE
/*
* Deprecated as of NumPy 1.7, this kind of shortcut doesn't
* belong in the public API.
*/
// 在 NumPy 1.7 中已弃用此类快捷方式,不应出现在公共 API 中。
/*
* Deprecated as of NumPy 1.7, an all-lowercase macro doesn't
* belong in the public API.
*/
#define fortran fortran_
// 在 NumPy 1.7 中已弃用全部小写的宏,不应出现在公共 API 中。
#define fortran fortran_ // fortran 等同于 fortran_
/*
* NumPy 1.7 版本后已弃用,因为它是一个污染命名空间的宏定义。
*/
#define FORTRAN_IF PyArray_FORTRAN_IF
/* NumPy 1.7 版本后已弃用,datetime64 类型现在使用 c_metadata 替代 */
#define NPY_METADATA_DTSTR "__timeunit__"
/*
* NumPy 1.7 版本后已弃用。
* 原因:
* - 这些是用于 datetime 的,但没有 datetime 的 "namespace"。
* - 它们只是将 NPY_STR_<x> 转换为 "<x>",这只是将简单的东西变成了间接引用。
*/
#define NPY_STR_Y "Y"
#define NPY_STR_M "M"
#define NPY_STR_W "W"
#define NPY_STR_D "D"
#define NPY_STR_h "h"
#define NPY_STR_m "m"
#define NPY_STR_s "s"
#define NPY_STR_ms "ms"
#define NPY_STR_us "us"
#define NPY_STR_ns "ns"
#define NPY_STR_ps "ps"
#define NPY_STR_fs "fs"
#define NPY_STR_as "as"
#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_1_7_DEPRECATED_API_H_ */
注释:
.\numpy\numpy\_core\include\numpy\npy_2_compat.h
/*
* 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:
*
*
* Simple definition when NumPy 2.0 API is guaranteed.
*
* static inline definition of a 1.x compatibility shim
*
* Make 1.x compatibility shim the public API (1.x only branch)
*
* Runtime dispatched version (1.x or 2.x)
*
*
*
* An internal build always passes NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
*/
/*
* 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`.
*/
"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)."
/*
* 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).
*/
/*
* 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.
*/
/* Compiling on NumPy 1.x where these are the same: */
/*
* Define a better way to call `_import_array()` to simplify backporting as
* we now require imports more often (necessary to make ABI flexible).
*/
static inline int
PyArray_ImportNumPyAPI()
{
if (NPY_UNLIKELY(PyArray_API == NULL)) {
import_array1(-1);
}
return 0;
}
/*
* NPY_DEFAULT_INT
*
* 默认整数类型,根据 NumPy 的版本不同有不同的定义。在运行时可以用作类型编号,
* 例如 `PyArray_DescrFromType(NPY_DEFAULT_INT)`。
*
* NPY_RAVEL_AXIS
*
* 在 NumPy 2.0 中引入,用于指示在操作中应该展平(ravel)的轴。在 NumPy 2.0 之前,
* 使用 NPY_MAXDIMS 来表示相同的含义。
*
* NPY_MAXDIMS
*
* 表示创建 ndarray 时允许的最大维度数。
*
* NPY_NTYPES_LEGACY
*
* NumPy 内置数据类型的数量,这是一个遗留的定义。
*/
/* NumPy 1.x 兼容的别名 */
/* NumPy 2 定义适用于 NumPy 1.x */
(PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? NPY_INTP : NPY_LONG)
(PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? -1 : 32)
(PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? 64 : 32)
/*
* 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.
*/
/* 编译环境为 1.x 或 2.x,直接访问字段是允许的 */
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)
{
// 返回数据类型描述符的标志位
return dtype->flags;
// 在 1.x 版本中,需要将标志位转换为无符号字符型
return (unsigned char)dtype->flags;
}
static inline type \
PyDataType_
if (legacy_only && !PyDataType_ISLEGACY(dtype)) { \
return (type)0; \
} \
// 返回数据类型描述符中指定字段的值
return ((_PyArray_LegacyDescr *)dtype)->field; \
}
static inline void
PyDataType_SET_ELSIZE(PyArray_Descr *dtype, npy_intp size)
{
// 根据运行时版本决定设置 dtype 的元素大小
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)
{
// 根据运行时版本返回 dtype 的 flags 属性
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` */
static inline type \
PyDataType_
// 如果 legacy_only 为真且 dtype 不是遗留描述符,则返回默认值
if (legacy_only && !PyDataType_ISLEGACY(dtype)) { \
return (type)0;
}
// 根据运行时版本返回 dtype 的指定字段值
if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) { \
return ((_PyArray_LegacyDescr *)dtype)->field; \
} \
else { \
return ((PyArray_DescrProto *)dtype)->field; \
} \
}
DESCR_ACCESSOR(ELSIZE, elsize, npy_intp, 0)
// 定义描述符访问器,访问元素大小的描述符
DESCR_ACCESSOR(ALIGNMENT, alignment, npy_intp, 0)
// 定义描述符访问器,访问对齐方式的描述符
DESCR_ACCESSOR(METADATA, metadata, PyObject *, 1)
// 定义描述符访问器,访问元数据的描述符,数据类型为 PyObject*
DESCR_ACCESSOR(SUBARRAY, subarray, PyArray_ArrayDescr *, 1)
// 定义描述符访问器,访问子数组的描述符,数据类型为 PyArray_ArrayDescr*
DESCR_ACCESSOR(NAMES, names, PyObject *, 1)
// 定义描述符访问器,访问字段名称的描述符,数据类型为 PyObject*
DESCR_ACCESSOR(FIELDS, fields, PyObject *, 1)
// 定义描述符访问器,访问字段的描述符,数据类型为 PyObject*
DESCR_ACCESSOR(C_METADATA, c_metadata, NpyAuxData *, 1)
// 定义描述符访问器,访问 C 语言元数据的描述符,数据类型为 NpyAuxData*
static inline PyArray_ArrFuncs *
PyDataType_GetArrFuncs(const PyArray_Descr *descr)
{
return _PyDataType_GetArrFuncs(descr);
}
static inline PyArray_ArrFuncs *
PyDataType_GetArrFuncs(const PyArray_Descr *descr)
{
return descr->f;
}
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;
}
}
.\numpy\numpy\_core\include\numpy\npy_2_complexcompat.h
/* This header is designed to be copy-pasted into downstream packages, since it provides
a compatibility layer between the old C struct complex types and the new native C99
complex types. The new macros are in numpy/npy_math.h, which is why it is included here. */
.\numpy\numpy\_core\include\numpy\npy_3kcompat.h
/*
* This is a convenience header file providing compatibility utilities
* for supporting different minor versions of Python 3.
* It was originally used to support the transition from Python 2,
* hence the "3k" naming.
*
* If you want to use this for your own projects, it's recommended to make a
* copy of it. Although the stuff below is unlikely to change, we don't provide
* strong backwards compatibility guarantees at the moment.
*/
extern "C" {
/*
* PyInt -> PyLong
*/
/*
* This function converts a Python object to a C int, handling overflow cases.
* It mimics _PyLong_AsInt from Python's limited API, included for compatibility.
*/
static inline int
Npy__PyLong_AsInt(PyObject *obj)
{
int overflow;
long result = PyLong_AsLongAndOverflow(obj, &overflow);
/* INT_MAX and INT_MIN are defined in Python.h */
if (overflow || result > INT_MAX || result < INT_MIN) {
/* Sets an OverflowError if the Python int is too large for a C int */
PyErr_SetString(PyExc_OverflowError,
"Python int too large to convert to C int");
return -1;
}
return (int)result;
}
#if defined(NPY_PY3K)
/* Check if the given object is a PyInt (in Python 2) */
static inline int PyInt_Check(PyObject *op) {
int overflow = 0;
if (!PyLong_Check(op)) {
return 0;
}
PyLong_AsLongAndOverflow(op, &overflow);
return (overflow == 0);
}
/* Macros for compatibility with Python 3 */
#define PyInt_FromLong PyLong_FromLong
#define PyInt_AsLong PyLong_AsLong
#define PyInt_AS_LONG PyLong_AsLong
#define PyInt_AsSsize_t PyLong_AsSsize_t
#define PyNumber_Int PyNumber_Long
/* NOTE:
*
* Since the PyLong type is very different from the fixed-range PyInt,
* we don't define PyInt_Type -> PyLong_Type.
*/
/* Py3 changes PySlice_GetIndicesEx' first argument's type to PyObject* */
PySlice_GetIndicesEx((PySliceObject *)op, nop, start, end, step, slicelength)
/* Introduced in https://github.com/python/cpython/commit/d2ec81a8c99796b51fb8c49b77a7fe369863226f */
/* Introduced in https://github.com/python/cpython/commit/b10dc3e7a11fcdb97e285882eba6da92594f90f9 */
/* Introduced in https://github.com/python/cpython/commit/c86a11221df7e37da389f9c6ce6e47ea22dc44ff */
/*
* 定义宏:将 PyString 相关宏重定向到 PyBytes 相关宏
*/
// 在 Python 3 中,将 PyString 相关宏重定向到 PyBytes 相关宏
// 同时,将 PyUnicode 相关宏也定义为 PyString 相关宏
// 定义宏:检查对象是否为基本字符串对象(PyString 或 PyBytes)
// 在 Python 2 中,将 PyBytes 相关宏重定向到 PyString 相关宏
// 同时,将 PyUnicode 相关宏也定义为 PyString 相关宏
// 定义宏:检查对象是否为基本字符串对象(PyString)
/*
* 定义宏:保护 CRT 调用,防止因为传递无效参数而导致的程序立即终止
* 参见:https://bugs.python.org/issue23524
*/
extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler;
// 定义宏:进入抑制无效参数处理器的范围
_set_thread_local_invalid_parameter_handler(_Py_silent_invalid_parameter_handler);
/*
* 定义 _WIN32 环境下的宏 NPY_BEGIN_SUPPRESS_IPH 和 NPY_END_SUPPRESS_IPH,
* 这些宏用于暂时禁用 Windows 平台的无效参数处理程序
*/
_set_thread_local_invalid_parameter_handler(_Py_old_handler);
/*
* PyUnicode_ConcatAndDel 和 PyUnicode_Concat2 函数
*/
/*
* 将 right 参数连接到 left 参数指向的 Unicode 对象,并释放 right
*/
static inline void
PyUnicode_ConcatAndDel(PyObject **left, PyObject *right)
{
Py_SETREF(*left, PyUnicode_Concat(*left, right));
Py_DECREF(right);
}
/*
* 将 right 参数连接到 left 参数指向的 Unicode 对象
*/
static inline void
PyUnicode_Concat2(PyObject **left, PyObject *right)
{
Py_SETREF(*left, PyUnicode_Concat(*left, right));
}
/*
* PyFile_* 兼容性
*/
/*
* 获取表示 Python 对象所代表的文件的 FILE* 句柄
*/
static inline FILE*
npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos)
{
int fd, fd2, unbuf;
Py_ssize_t fd2_tmp;
PyObject *ret, *os, *io, *io_raw;
npy_off_t pos;
FILE *handle;
/* 对于 Python 2 的 PyFileObject,使用 PyFile_AsFile 返回 FILE* 句柄 */
if (PyFile_Check(file)) {
return PyFile_AsFile(file);
}
/* 先刷新以确保数据按正确顺序写入文件 */
ret = PyObject_CallMethod(file, "flush", "");
if (ret == NULL) {
return NULL;
}
Py_DECREF(ret);
fd = PyObject_AsFileDescriptor(file);
if (fd == -1) {
return NULL;
}
/*
* 需要 dup 句柄,因为最终要调用 fclose
*/
os = PyImport_ImportModule("os");
if (os == NULL) {
return NULL;
}
ret = PyObject_CallMethod(os, "dup", "i", fd);
Py_DECREF(os);
if (ret == NULL) {
return NULL;
}
fd2_tmp = PyNumber_AsSsize_t(ret, PyExc_IOError);
Py_DECREF(ret);
if (fd2_tmp == -1 && PyErr_Occurred()) {
return NULL;
}
if (fd2_tmp < INT_MIN || fd2_tmp > INT_MAX) {
PyErr_SetString(PyExc_IOError,
"从 os.dup() 获取 int 失败");
return NULL;
}
fd2 = (int)fd2_tmp;
/* 转换为 FILE* 句柄 */
NPY_BEGIN_SUPPRESS_IPH
handle = _fdopen(fd2, mode);
NPY_END_SUPPRESS_IPH
handle = fdopen(fd2, mode);
if (handle == NULL) {
PyErr_SetString(PyExc_IOError,
"从 Python 文件对象获取 FILE* 句柄失败。如果是在构建 NumPy 时出现问题,可能是因为链接了错误的调试/发布运行时库");
return NULL;
}
/* 记录原始的文件句柄位置 */
*orig_pos = npy_ftell(handle);
}
if (*orig_pos == -1) {
/* 导入 io 模块以确定是否使用了缓冲 */
io = PyImport_ImportModule("io");
if (io == NULL) {
// 如果导入失败,则关闭文件句柄并返回空指针
fclose(handle);
return NULL;
}
/* 文件对象实例的 RawIOBase 是无缓冲的 */
io_raw = PyObject_GetAttrString(io, "RawIOBase");
Py_DECREF(io);
if (io_raw == NULL) {
// 如果获取 RawIOBase 失败,则关闭文件句柄并返回空指针
fclose(handle);
return NULL;
}
// 检查文件是否是无缓冲的
unbuf = PyObject_IsInstance(file, io_raw);
Py_DECREF(io_raw);
if (unbuf == 1) {
// 如果文件是无缓冲的,则直接返回文件句柄
return handle;
}
else {
// 如果文件不是无缓冲的,设置异常并关闭文件句柄后返回空指针
PyErr_SetString(PyExc_IOError, "obtaining file position failed");
fclose(handle);
return NULL;
}
}
// 将原始句柄定位到 Python 端的位置
ret = PyObject_CallMethod(file, "tell", "");
if (ret == NULL) {
// 如果获取位置信息失败,则关闭文件句柄并返回空指针
fclose(handle);
return NULL;
}
pos = PyLong_AsLongLong(ret);
Py_DECREF(ret);
if (PyErr_Occurred()) {
// 如果发生异常,则关闭文件句柄并返回空指针
fclose(handle);
return NULL;
}
// 使用 npy_fseek 将文件定位到指定位置
if (npy_fseek(handle, pos, SEEK_SET) == -1) {
// 如果定位失败,则设置异常并关闭文件句柄后返回空指针
PyErr_SetString(PyExc_IOError, "seeking file failed");
fclose(handle);
return NULL;
}
// 返回文件句柄
return handle;
/*
* Close the dup-ed file handle, and seek the Python one to the current position
*/
static inline int
npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos)
{
int fd, unbuf;
PyObject *ret, *io, *io_raw;
npy_off_t position;
/* For Python 2 PyFileObject, do nothing */
if (PyFile_Check(file)) {
return 0;
}
position = npy_ftell(handle);
/* Close the FILE* handle */
fclose(handle);
/*
* Restore original file handle position, in order to not confuse
* Python-side data structures
*/
fd = PyObject_AsFileDescriptor(file);
if (fd == -1) {
return -1;
}
if (npy_lseek(fd, orig_pos, SEEK_SET) == -1) {
/* The io module is needed to determine if buffering is used */
io = PyImport_ImportModule("io");
if (io == NULL) {
return -1;
}
/* File object instances of RawIOBase are unbuffered */
io_raw = PyObject_GetAttrString(io, "RawIOBase");
Py_DECREF(io);
if (io_raw == NULL) {
return -1;
}
unbuf = PyObject_IsInstance(file, io_raw);
Py_DECREF(io_raw);
if (unbuf == 1) {
/* Succeed if the IO is unbuffered */
return 0;
}
else {
PyErr_SetString(PyExc_IOError, "seeking file failed");
return -1;
}
}
if (position == -1) {
PyErr_SetString(PyExc_IOError, "obtaining file position failed");
return -1;
}
/* Seek Python-side handle to the FILE* handle position */
ret = PyObject_CallMethod(file, "seek", NPY_OFF_T_PYFMT "i", position, 0);
if (ret == NULL) {
return -1;
}
Py_DECREF(ret);
return 0;
}
static inline int
npy_PyFile_Check(PyObject *file)
{
int fd;
/* For Python 2, check if it is a PyFileObject */
if (PyFile_Check(file)) {
return 1;
}
fd = PyObject_AsFileDescriptor(file);
if (fd == -1) {
PyErr_Clear();
return 0;
}
return 1;
}
static inline PyObject*
npy_PyFile_OpenFile(PyObject *filename, const char *mode)
{
PyObject *open;
open = PyDict_GetItemString(PyEval_GetBuiltins(), "open");
if (open == NULL) {
return NULL;
}
return PyObject_CallFunction(open, "Os", filename, mode);
}
static inline int
npy_PyFile_CloseFile(PyObject *file)
{
PyObject *ret;
ret = PyObject_CallMethod(file, "close", NULL);
if (ret == NULL) {
return -1;
}
Py_DECREF(ret);
return 0;
}
/* This is a copy of _PyErr_ChainExceptions
*/
static inline void
npy_PyErr_ChainExceptions(PyObject *exc, PyObject *val, PyObject *tb)
{
if (exc == NULL)
return;
}
if (PyErr_Occurred()) {
/* 只有 Python 3 支持这个功能 */
// 声明用于存储第二个异常的变量
PyObject *exc2, *val2, *tb2;
// 获取并清除第二个异常
PyErr_Fetch(&exc2, &val2, &tb2);
// 规范化当前异常
PyErr_NormalizeException(&exc, &val, &tb);
// 如果有 traceback 信息,则将其设置给当前异常
if (tb != NULL) {
PyException_SetTraceback(val, tb);
// 释放 traceback 对象的引用计数
Py_DECREF(tb);
}
// 释放当前异常对象的引用计数
Py_DECREF(exc);
// 规范化第二个异常
PyErr_NormalizeException(&exc2, &val2, &tb2);
// 将第二个异常设置为当前异常的上下文
PyException_SetContext(val2, val);
// 恢复第二个异常
PyErr_Restore(exc2, val2, tb2);
}
else {
// 恢复之前捕获的异常
PyErr_Restore(exc, val, tb);
}
/* This is a copy of _PyErr_ChainExceptions, with:
* - a minimal implementation for python 2
* - __cause__ used instead of __context__
*/
/* 这是 _PyErr_ChainExceptions 的副本,包括:
* - 用于 Python 2 的最小实现
* - 使用 __cause__ 而不是 __context__
*/
static inline void
npy_PyErr_ChainExceptionsCause(PyObject *exc, PyObject *val, PyObject *tb)
{
if (exc == NULL)
return;
// 检查当前是否有异常发生
if (PyErr_Occurred()) {
/* only py3 supports this anyway */
// 只有 Python 3 支持这种操作
PyObject *exc2, *val2, *tb2;
// 获取当前的异常信息
PyErr_Fetch(&exc2, &val2, &tb2);
// 规范化异常对象,确保是标准的异常对象
PyErr_NormalizeException(&exc, &val, &tb);
// 如果 traceback 不为空,则设置到异常值中,并释放 traceback 对象
if (tb != NULL) {
PyException_SetTraceback(val, tb);
Py_DECREF(tb);
}
// 释放旧的异常对象
Py_DECREF(exc);
// 再次规范化异常对象,确保是标准的异常对象
PyErr_NormalizeException(&exc2, &val2, &tb2);
// 将新异常对象作为原因设置给旧的异常对象
PyException_SetCause(val2, val);
// 恢复之前的异常状态
PyErr_Restore(exc2, val2, tb2);
}
else {
// 恢复之前的异常状态
PyErr_Restore(exc, val, tb);
}
}
/*
* PyObject_Cmp
*/
/* PyObject_Cmp 函数 */
static inline int
PyObject_Cmp(PyObject *i1, PyObject *i2, int *cmp)
{
int v;
// 比较 i1 < i2
v = PyObject_RichCompareBool(i1, i2, Py_LT);
if (v == 1) {
*cmp = -1;
return 1;
}
else if (v == -1) {
return -1;
}
// 比较 i1 > i2
v = PyObject_RichCompareBool(i1, i2, Py_GT);
if (v == 1) {
*cmp = 1;
return 1;
}
else if (v == -1) {
return -1;
}
// 比较 i1 == i2
v = PyObject_RichCompareBool(i1, i2, Py_EQ);
if (v == 1) {
*cmp = 0;
return 1;
}
else {
*cmp = 0;
return -1;
}
}
/*
* PyCObject functions adapted to PyCapsules.
*
* The main job here is to get rid of the improved error handling
* of PyCapsules. It's a shame...
*/
/* 适应于 PyCapsules 的 PyCObject 函数 */
static inline PyObject *
NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
{
// 创建一个 PyCapsule 对象,封装指针 ptr,使用 dtor 作为析构函数
PyObject *ret = PyCapsule_New(ptr, NULL, dtor);
// 如果创建失败,则清除当前的异常状态
if (ret == NULL) {
PyErr_Clear();
}
return ret;
}
static inline PyObject *
NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, void (*dtor)(PyObject *))
{
// 创建一个 PyCapsule 对象,封装指针 ptr,使用 dtor 作为析构函数
PyObject *ret = NpyCapsule_FromVoidPtr(ptr, dtor);
// 如果创建成功且设置 context 失败,则清除当前的异常状态并释放对象
if (ret != NULL && PyCapsule_SetContext(ret, context) != 0) {
PyErr_Clear();
Py_DECREF(ret);
ret = NULL;
}
return ret;
}
static inline void *
NpyCapsule_AsVoidPtr(PyObject *obj)
{
// 从 PyCapsule 对象中获取指针
void *ret = PyCapsule_GetPointer(obj, NULL);
// 如果获取失败,则清除当前的异常状态
if (ret == NULL) {
PyErr_Clear();
}
return ret;
}
static inline void *
NpyCapsule_GetDesc(PyObject *obj)
{
// 获取 PyCapsule 对象的 context
return PyCapsule_GetContext(obj);
}
static inline int
NpyCapsule_Check(PyObject *ptr)
{
// 检查对象是否为 PyCapsule 类型
return PyCapsule_CheckExact(ptr);
}
#ifdef __cplusplus
}
#endif
#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_ */
.\numpy\numpy\_core\include\numpy\npy_common.h
/* 需要 Python.h 以使用 npy_intp、npy_uintp */
/* numpyconfig.h 是自动生成的配置文件 */
/*
* 在定义 npy_math 函数时使用 static inline 修饰符,
* 允许编译器在可能时进行优化
*/
/*
* gcc 即使在 -O3 下也不会展开循环
* 谨慎使用,现代 CPU 很少因此而加速
*/
__attribute__((optimize("unroll-loops")))
/* 最高的 gcc 优化级别,启用自动向量化 */
/*
* 标记一个参数(从1开始)不能为空且不会被检查
* 如果函数检查为空,不要使用!!编译器将移除检查
*/
/*
* 给编译器一个提示,哪个分支更可能或更不可能发生,
* 例如,罕见的错误情况:
*
* if (NPY_UNLIKELY(failure == 0))
* return NULL;
*
* 双重 !! 是为了将表达式(如 NULL)转换为布尔值,符合内置函数的需求
*/
/* 与 _mm_prefetch 不同,也适用于非 x86 平台 */
/* _MM_HINT_ET[01] (rw = 1) 不支持,仅在 gcc >= 4.9 中可用 */
(loc == 1 ? _MM_HINT_T2 : \
(loc == 2 ? _MM_HINT_T1 : \
(loc == 3 ? _MM_HINT_T0 : -1))))
/* `NPY_INLINE` 为向后兼容性保留;应改用 `inline` */
/* 用于处理 Windows 上的 clang-cl */
// 定义一个宏 NPY_FINLINE,它展开为 static
// 如果编译器是 Microsoft Visual C++,定义为静态函数,禁止内联优化,使用__declspec(noinline)修饰
// 如果编译器是 GCC 或 Clang,定义为静态函数,禁止内联优化,使用__attribute__((noinline))修饰
// 其他情况下,仅定义为静态函数
// 如果是 C++ 编译环境,定义为线程局部存储(thread_local)
// 如果支持标准的线程局部存储,也定义为线程局部存储
// 如果使用 _Thread_local 关键字支持线程局部存储
// 如果支持 __thread 关键字的线程局部存储
// 如果支持 __declspec(thread) 关键字的线程局部存储
// 否则不进行任何特殊的线程局部存储定义
// 如果定义了特定的返回借用引用的属性,使用 cpychecker_returns_borrowed_ref 修饰
__attribute__((cpychecker_returns_borrowed_ref))
// 否则不使用任何属性修饰
// 如果定义了特定的参数窃取引用的属性,使用 cpychecker_steals_reference_to_arg(n) 修饰
__attribute__((cpychecker_steals_reference_to_arg(n)))
// 否则不使用任何属性修饰
/* 64 bit file position support, also on win-amd64. Issue gh-2256 */
defined(__MINGW32__) || defined(__MINGW64__)
// 如果是在 Microsoft Visual C++ 编译环境下,并且是 64 位 Windows,或者在 MinGW 环境下
// 定义文件操作为 64 位版本的函数
// 定义文件偏移量类型为 npy_int64
// 根据整数类型大小定义 Python 格式化字符串
// 如果支持 fseeko 函数,定义为 npy_fseek
// 否则定义为标准的 fseek 函数
// 如果支持 ftello 函数,定义为 npy_ftell
// 否则定义为标准的 ftell 函数
// 包含系统类型头文件
// 非 Windows 环境下包含unistd.h头文件
// 定义文件偏移量类型为 off_t
// 根据不同大小的 off_t 定义 Python 格式化字符串
/* enums for detected endianness */
// 枚举检测到的字节序类型
enum {
// 未知字节序
NPY_CPU_UNKNOWN_ENDIAN,
// 小端字节序
NPY_CPU_LITTLE,
// 大端字节序
NPY_CPU_BIG
};
/*
* This is to typedef npy_intp to the appropriate size for Py_ssize_t.
* (Before NumPy 2.0 we used Py_intptr_t and Py_uintptr_t from `pyport.h`.)
*/
// 将 npy_intp 定义为适合 Py_ssize_t 大小的类型
typedef Py_ssize_t npy_intp;
// 定义 npy_uintp 为 size_t 类型
typedef size_t npy_uintp;
/*
* Define sizes that were not defined in numpyconfig.h.
*/
// 定义在 numpyconfig.h 中未定义的大小
/* 定义 NPY_SIZEOF_CLONGDOUBLE 与 NPY_SIZEOF_COMPLEX_LONGDOUBLE 相等 */
/* 如果 constchar 已定义,则取消定义 */
/* 定义 NPY_SSIZE_T_PYFMT 为 "n" */
/* 将 constchar 定义为 char */
/*
* NPY_INTP_FMT 注意:
* 不同于其他的 NPY_*_FMT 宏,这些宏用于 PyOS_snprintf,
* NPY_INTP_FMT 用于 PyErr_Format 和 PyUnicode_FromFormat。
* 这些函数使用不同的格式代码,根据 Python 文档进行了便携式指定。
* 参见 issue gh-2388。
*/
/*
* 一些平台未定义 bool、long long 或 long double。
* 在这里进行处理。
*/
typedef PY_LONG_LONG npy_longlong;
typedef unsigned PY_LONG_LONG npy_ulonglong;
typedef long npy_longlong;
typedef unsigned long npy_ulonglong;
/* 定义 npy_bool 为 unsigned char,以及 NPY_FALSE 和 NPY_TRUE 的值 */
typedef unsigned char npy_bool;
/*
* `NPY_SIZEOF_LONGDOUBLE` isn't usually equal to sizeof(long double).
* In some certain cases, it may forced to be equal to sizeof(double)
* even against the compiler implementation and the same goes for
* `complex long double`.
*
* Therefore, avoid `long double`, use `npy_longdouble` instead,
* and when it comes to standard math functions make sure of using
* the double version when `NPY_SIZEOF_LONGDOUBLE` == `NPY_SIZEOF_DOUBLE`.
* For example:
* npy_longdouble *ptr, x;
* #if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE
* npy_longdouble r = modf(x, ptr);
* #else
* npy_longdouble r = modfl(x, ptr);
* #endif
*
* See https://github.com/numpy/numpy/issues/20348
*/
#if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE
#define NPY_LONGDOUBLE_FMT "g"
#define longdouble_t double
typedef double npy_longdouble;
#else
#define NPY_LONGDOUBLE_FMT "Lg"
#define longdouble_t long double
typedef long double npy_longdouble;
#endif
#ifndef Py_USING_UNICODE
#error Must use Python with unicode enabled.
#endif
typedef signed char npy_byte; // 有符号字符
typedef unsigned char npy_ubyte; // 无符号字符
typedef unsigned short npy_ushort; // 无符号短整型
typedef unsigned int npy_uint; // 无符号整型
typedef unsigned long npy_ulong; // 无符号长整型
/* These are for completeness */
typedef char npy_char; // 字符
typedef short npy_short; // 短整型
typedef int npy_int; // 整型
typedef long npy_long; // 长整型
typedef float npy_float; // 单精度浮点型
typedef double npy_double; // 双精度浮点型
typedef Py_hash_t npy_hash_t; // Python 哈希类型
#define NPY_SIZEOF_HASH_T NPY_SIZEOF_INTP // 哈希类型的大小
#if defined(__cplusplus)
typedef struct
{
double _Val[2]; // 双精度复数结构体
} npy_cdouble;
typedef struct
{
float _Val[2]; // 单精度复数结构体
} npy_cfloat;
typedef struct
{
long double _Val[2]; // 长双精度复数结构体
} npy_clongdouble;
#else
#include <complex.h>
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
typedef _Dcomplex npy_cdouble; // Microsoft Visual C++ 的双精度复数类型
typedef _Fcomplex npy_cfloat; // Microsoft Visual C++ 的单精度复数类型
typedef _Lcomplex npy_clongdouble; // Microsoft Visual C++ 的长双精度复数类型
#else /* !defined(_MSC_VER) || defined(__INTEL_COMPILER) */
typedef double _Complex npy_cdouble; // 标准复数类型的双精度
typedef float _Complex npy_cfloat; // 标准复数类型的单精度
typedef longdouble_t _Complex npy_clongdouble; // 标准复数类型的长双精度
#endif
#endif
/*
* numarray-style bit-width typedefs
*/
#define NPY_MAX_INT8 127 // 有符号 8 位整型最大值
#define NPY_MIN_INT8 -128 // 有符号 8 位整型最小值
#define NPY_MAX_UINT8 255 // 无符号 8 位整型最大值
#define NPY_MAX_INT16 32767 // 有符号 16 位整型最大值
#define NPY_MIN_INT16 -32768 // 有符号 16 位整型最小值
#define NPY_MAX_UINT16 65535 // 无符号 16 位整型最大值
#define NPY_MAX_INT32 2147483647 // 有符号 32 位整型最大值
#define NPY_MIN_INT32 (-NPY_MAX_INT32 - 1) // 有符号 32 位整型最小值
#define NPY_MAX_UINT32 4294967295U // 无符号 32 位整型最大值
#define NPY_MAX_INT64 NPY_LONGLONG_SUFFIX(9223372036854775807) // 有符号 64 位整型最大值
#define NPY_MIN_INT64 (-NPY_MAX_INT64 - NPY_LONGLONG_SUFFIX(1)) // 有符号 64 位整型最小值
#define NPY_MAX_UINT64 NPY_ULONGLONG_SUFFIX(18446744073709551615) // 无符号 64 位整型最大值
#define NPY_MAX_INT128 NPY_LONGLONG_SUFFIX(85070591730234615865843651857942052864) // 有符号 128 位整型最大值
#define NPY_MIN_INT128 (-NPY_MAX_INT128 - NPY_LONGLONG_SUFFIX(1)) // 有符号 128 位整型最小值
#define NPY_MAX_UINT128 NPY_ULONGLONG_SUFFIX(170141183460469231731687303715884105728) // 无符号 128 位整型最大值
#define NPY_MAX_INT256 NPY_LONGLONG_SUFFIX(57896044618658097711785492504343953926634992332820282019728792003956564819967) // 有符号 256 位整型最大值
#define NPY_MIN_INT256 (-NPY_MAX_INT256 - NPY_LONGLONG_SUFFIX(1)) // 有符号 256 位整型最小值
/* 定义最大的 256 位无符号整数,即 2^256 - 1 */
#define NPY_MAX_UINT256 NPY_ULONGLONG_SUFFIX(115792089237316195423570985008687907853269984665640564039457584007913129639935)
/* 定义最小日期时间和最大日期时间为 int64_t 类型的最小和最大值 */
#define NPY_MIN_DATETIME NPY_MIN_INT64
#define NPY_MAX_DATETIME NPY_MAX_INT64
/* 定义最小时间差和最大时间差为 int64_t 类型的最小和最大值 */
#define NPY_MIN_TIMEDELTA NPY_MIN_INT64
#define NPY_MAX_TIMEDELTA NPY_MAX_INT64
/* 需要根据每种类型找到位数,并相应地进行定义。
C 语言规定 sizeof(char) == 1
因此,仅使用 sizeof 关键字并不会有帮助。
看起来 Python 自身也经常使用 sizeof(char),这应该始终为 1。
思路:利用 CHAR_BIT,它应该告诉我们每个字符的位数。
*/
/* 包含平台定义 -- 这些在 C89/90 标准中 */
#include <limits.h>
/* 定义最大有符号字节和最小有符号字节 */
#define NPY_MAX_BYTE SCHAR_MAX
#define NPY_MIN_BYTE SCHAR_MIN
/* 定义最大无符号字节 */
#define NPY_MAX_UBYTE UCHAR_MAX
/* 定义最大有符号短整数和最小有符号短整数 */
#define NPY_MAX_SHORT SHRT_MAX
#define NPY_MIN_SHORT SHRT_MIN
/* 定义最大无符号短整数 */
#define NPY_MAX_USHORT USHRT_MAX
/* 定义最大有符号整数 */
#define NPY_MAX_INT INT_MAX
#ifndef INT_MIN
#define INT_MIN (-INT_MAX - 1)
#endif
/* 定义最小有符号整数 */
#define NPY_MIN_INT INT_MIN
/* 定义最大无符号整数 */
#define NPY_MAX_UINT UINT_MAX
/* 定义最大有符号长整数和最小有符号长整数 */
#define NPY_MAX_LONG LONG_MAX
#define NPY_MIN_LONG LONG_MIN
/* 定义最大无符号长整数 */
#define NPY_MAX_ULONG ULONG_MAX
/* 定义布尔类型的位数 */
#define NPY_BITSOF_BOOL (sizeof(npy_bool) * CHAR_BIT)
/* 定义字符类型的位数 */
#define NPY_BITSOF_CHAR CHAR_BIT
/* 定义字节类型的位数 */
#define NPY_BITSOF_BYTE (NPY_SIZEOF_BYTE * CHAR_BIT)
/* 定义短整数类型的位数 */
#define NPY_BITSOF_SHORT (NPY_SIZEOF_SHORT * CHAR_BIT)
/* 定义整数类型的位数 */
#define NPY_BITSOF_INT (NPY_SIZEOF_INT * CHAR_BIT)
/* 定义长整数类型的位数 */
#define NPY_BITSOF_LONG (NPY_SIZEOF_LONG * CHAR_BIT)
/* 定义长长整数类型的位数 */
#define NPY_BITSOF_LONGLONG (NPY_SIZEOF_LONGLONG * CHAR_BIT)
/* 定义整型指针类型的位数 */
#define NPY_BITSOF_INTP (NPY_SIZEOF_INTP * CHAR_BIT)
/* 定义半精度浮点数类型的位数 */
#define NPY_BITSOF_HALF (NPY_SIZEOF_HALF * CHAR_BIT)
/* 定义单精度浮点数类型的位数 */
#define NPY_BITSOF_FLOAT (NPY_SIZEOF_FLOAT * CHAR_BIT)
/* 定义双精度浮点数类型的位数 */
#define NPY_BITSOF_DOUBLE (NPY_SIZEOF_DOUBLE * CHAR_BIT)
/* 定义长双精度浮点数类型的位数 */
#define NPY_BITSOF_LONGDOUBLE (NPY_SIZEOF_LONGDOUBLE * CHAR_BIT)
/* 定义复数浮点数类型的位数 */
#define NPY_BITSOF_CFLOAT (NPY_SIZEOF_CFLOAT * CHAR_BIT)
/* 定义复数双精度浮点数类型的位数 */
#define NPY_BITSOF_CDOUBLE (NPY_SIZEOF_CDOUBLE * CHAR_BIT)
/* 定义复数长双精度浮点数类型的位数 */
#define NPY_BITSOF_CLONGDOUBLE (NPY_SIZEOF_CLONGDOUBLE * CHAR_BIT)
/* 定义日期时间类型的位数 */
#define NPY_BITSOF_DATETIME (NPY_SIZEOF_DATETIME * CHAR_BIT)
/* 定义时间差类型的位数 */
#define NPY_BITSOF_TIMEDELTA (NPY_SIZEOF_TIMEDELTA * CHAR_BIT)
/* 根据长整数类型的位数选择相应的整数类型 */
#if NPY_BITSOF_LONG == 8
#define NPY_INT8 NPY_LONG
#define NPY_UINT8 NPY_ULONG
typedef long npy_int8;
typedef unsigned long npy_uint8;
#define PyInt8ScalarObject PyLongScalarObject
#define PyInt8ArrType_Type PyLongArrType_Type
#define PyUInt8ScalarObject PyULongScalarObject
#define PyUInt8ArrType_Type PyULongArrType_Type
#define NPY_INT8_FMT NPY_LONG_FMT
#define NPY_UINT8_FMT NPY_ULONG_FMT
#elif NPY_BITSOF_LONG == 16
#define NPY_INT16 NPY_LONG
#define NPY_UINT16 NPY_ULONG
typedef long npy_int16;
typedef unsigned long npy_uint16;
#define PyInt16ScalarObject PyLongScalarObject
#define PyInt16ArrType_Type PyLongArrType_Type
#define PyUInt16ScalarObject PyULongScalarObject
#define PyUInt16ArrType_Type PyULongArrType_Type
# 如果 NPY_BITSOF_LONG 等于 16,定义整型和无符号整型为长长整型和无符号长长整型
# 否则,如果 NPY_BITSOF_LONG 等于 32,定义整型和无符号整型为长整型和无符号长整型
# 否则,如果 NPY_BITSOF_LONG 等于 64,定义整型和无符号整型为长整型和无符号长整型,并定义特定的 PyLong 相关对象和类型
# 否则,如果 NPY_BITSOF_LONG 等于 128,定义整型和无符号整型为长整型和无符号长整型,并定义特定的 PyLong 相关对象和类型
#ifdef NPY_BITSOF_LONGLONG
# 如果 NPY_BITSOF_LONGLONG 等于 8,定义整型和无符号整型为长长整型和无符号长长整型,并定义特定的 PyLong 相关对象和类型
# 否则,如果 NPY_BITSOF_LONGLONG 等于 16,定义整型和无符号整型为长长整型和无符号长长整型,并定义特定的 PyLong 相关对象和类型
# 否则,如果 NPY_BITSOF_LONGLONG 等于 32,定义整型和无符号整型为长整型和无符号长整型,并定义特定的 PyLong 相关对象和类型
# define PyInt32ScalarObject PyLongLongScalarObject
# define PyInt32ArrType_Type PyLongLongArrType_Type
# define PyUInt32ScalarObject PyULongLongScalarObject
# define PyUInt32ArrType_Type PyULongLongArrType_Type
# 定义宏,将32位整数类型的标量对象和数组类型重命名为64位整数类型的标量对象和数组类型
#define NPY_INT32_FMT NPY_LONGLONG_FMT
#define NPY_UINT32_FMT NPY_ULONGLONG_FMT
# 定义宏,将32位整数的格式字符串重命名为64位整数的格式字符串
# endif
# define NPY_MAX_LONGLONG NPY_MAX_INT32
# define NPY_MIN_LONGLONG NPY_MIN_INT32
# define NPY_MAX_ULONGLONG NPY_MAX_UINT32
# 如果定义了64位整数,定义64位整数的最大和最小值以及64位无符号整数的最大值
#elif NPY_BITSOF_LONGLONG == 64
# ifndef NPY_INT64
# define NPY_INT64 NPY_LONGLONG
# define NPY_UINT64 NPY_ULONGLONG
typedef npy_longlong npy_int64;
typedef npy_ulonglong npy_uint64;
# define PyInt64ScalarObject PyLongLongScalarObject
# define PyInt64ArrType_Type PyLongLongArrType_Type
# define PyUInt64ScalarObject PyULongLongScalarObject
# define PyUInt64ArrType_Type PyULongLongArrType_Type
#define NPY_INT64_FMT NPY_LONGLONG_FMT
#define NPY_UINT64_FMT NPY_ULONGLONG_FMT
# define MyPyLong_FromInt64 PyLong_FromLongLong
# define MyPyLong_AsInt64 PyLong_AsLongLong
# 定义64位整数类型和无符号整数类型,并重命名相应的标量对象和数组类型
# 定义64位整数类型和无符号整数类型的格式字符串
# 定义将Python长整型转换为64位整数和从64位整数获取Python长整型的宏
# endif
# define NPY_MAX_LONGLONG NPY_MAX_INT64
# define NPY_MIN_LONGLONG NPY_MIN_INT64
# define NPY_MAX_ULONGLONG NPY_MAX_UINT64
# 如果定义了128位整数,定义128位整数的最大和最小值以及128位无符号整数的最大值
#elif NPY_BITSOF_LONGLONG == 128
# ifndef NPY_INT128
# define NPY_INT128 NPY_LONGLONG
# define NPY_UINT128 NPY_ULONGLONG
typedef npy_longlong npy_int128;
typedef npy_ulonglong npy_uint128;
# define PyInt128ScalarObject PyLongLongScalarObject
# define PyInt128ArrType_Type PyLongLongArrType_Type
# define PyUInt128ScalarObject PyULongLongScalarObject
# define PyUInt128ArrType_Type PyULongLongArrType_Type
#define NPY_INT128_FMT NPY_LONGLONG_FMT
#define NPY_UINT128_FMT NPY_ULONGLONG_FMT
# endif
# define NPY_MAX_LONGLONG NPY_MAX_INT128
# define NPY_MIN_LONGLONG NPY_MIN_INT128
# define NPY_MAX_ULONGLONG NPY_MAX_UINT128
# 如果定义了256位整数,定义256位整数的最大和最小值以及256位无符号整数的最大值
#elif NPY_BITSOF_LONGLONG == 256
# define NPY_INT256 NPY_LONGLONG
# define NPY_UINT256 NPY_ULONGLONG
typedef npy_longlong npy_int256;
typedef npy_ulonglong npy_uint256;
# define PyInt256ScalarObject PyLongLongScalarObject
# define PyInt256ArrType_Type PyLongLongArrType_Type
# define PyUInt256ScalarObject PyULongLongScalarObject
# define PyUInt256ArrType_Type PyULongLongArrType_Type
#define NPY_INT256_FMT NPY_LONGLONG_FMT
#define NPY_UINT256_FMT NPY_ULONGLONG_FMT
# define NPY_MAX_LONGLONG NPY_MAX_INT256
# define NPY_MIN_LONGLONG NPY_MIN_INT256
# define NPY_MAX_ULONGLONG NPY_MAX_UINT256
# 如果定义了8位整数,定义8位整数的最大和最小值以及8位无符号整数的最大值
#endif
#if NPY_BITSOF_INT == 8
#ifndef NPY_INT8
#define NPY_INT8 NPY_INT
#define NPY_UINT8 NPY_UINT
typedef int npy_int8;
typedef unsigned int npy_uint8;
# define PyInt8ScalarObject PyIntScalarObject
# define PyInt8ArrType_Type PyIntArrType_Type
# define PyUInt8ScalarObject PyUIntScalarObject
# define PyUInt8ArrType_Type PyUIntArrType_Type
#define NPY_INT8_FMT NPY_INT_FMT
#define NPY_UINT8_FMT NPY_UINT_FMT
#endif
# 如果定义了16位整数,定义16位整数的最大和最小值以及16位无符号整数的最大值
#elif NPY_BITSOF_INT == 16
#ifndef NPY_INT16
#define NPY_INT16 NPY_INT
#ifdef NPY_BITSOF_SHORT == 8
#ifndef NPY_INT8
// 如果平台的 short 类型占用 8 比特,且未定义 NPY_INT8,则定义 NPY_INT8 和 NPY_UINT8
#define NPY_INT8 NPY_SHORT
#define NPY_UINT8 NPY_USHORT
// 定义 npy_int8 和 npy_uint8 类型别名为 short 和 unsigned short
typedef short npy_int8;
typedef unsigned short npy_uint8;
// 定义 PyInt8ScalarObject 和 PyUInt8ScalarObject 宏别名为 PyShortScalarObject 和 PyUShortScalarObject
# define PyInt8ScalarObject PyShortScalarObject
# define PyInt8ArrType_Type PyShortArrType_Type
# define PyUInt8ScalarObject PyUShortScalarObject
# define PyUInt8ArrType_Type PyUShortArrType_Type
// 定义 NPY_INT8_FMT 和 NPY_UINT8_FMT 宏别名为 NPY_SHORT_FMT 和 NPY_USHORT_FMT
#define NPY_INT8_FMT NPY_SHORT_FMT
#define NPY_UINT8_FMT NPY_USHORT_FMT
#endif
#elif NPY_BITSOF_SHORT == 16
#ifndef NPY_INT16
// 如果平台的 short 类型占用 16 比特,且未定义 NPY_INT16,则定义 NPY_INT16 和 NPY_UINT16
#define NPY_INT16 NPY_SHORT
#define NPY_UINT16 NPY_USHORT
// 定义 npy_int16 和 npy_uint16 类型别名为 short 和 unsigned short
typedef short npy_int16;
typedef unsigned short npy_uint16;
// 定义 PyInt16ScalarObject 和 PyUInt16ScalarObject 宏别名为 PyShortScalarObject 和 PyUShortScalarObject
# define PyInt16ScalarObject PyShortScalarObject
# define PyInt16ArrType_Type PyShortArrType_Type
# define PyUInt16ScalarObject PyUShortScalarObject
# define PyUInt16ArrType_Type PyUShortArrType_Type
// 定义 NPY_INT16_FMT 和 NPY_UINT16_FMT 宏别名为 NPY_SHORT_FMT 和 NPY_USHORT_FMT
#define NPY_INT16_FMT NPY_SHORT_FMT
#define NPY_UINT16_FMT NPY_USHORT_FMT
#endif
#elif NPY_BITSOF_SHORT == 32
#ifndef NPY_INT32
// 如果平台的 short 类型占用 32 比特,且未定义 NPY_INT32,则定义 NPY_INT32
#define NPY_INT32 NPY_SHORT
这段代码根据平台中 short 类型的位数(8、16、32 比特)定义了不同的数据类型和相关宏别名,以及格式化字符串宏。
#ifdef NPY_BITSOF_SHORT == 32
// 如果 NPY_BITSOF_SHORT 等于 32,则定义以下内容
#ifndef NPY_INT32
// 如果 NPY_INT32 未定义,则定义 NPY_INT32 和 NPY_UINT32 为 NPY_BYTE
#define NPY_INT32 NPY_BYTE
#define NPY_UINT32 NPY_UBYTE
// 定义 npy_int32 和 npy_uint32 为 signed char 和 unsigned char 类型
typedef signed char npy_int32;
typedef unsigned char npy_uint32;
typedef unsigned char npy_ucs4;
// 将 PyInt32ScalarObject, PyInt32ArrType_Type, PyUInt32ScalarObject, PyUInt32ArrType_Type 分别定义为 PyByteScalarObject 和 PyByteArrType_Type
#define PyInt32ScalarObject PyByteScalarObject
#define PyInt32ArrType_Type PyByteArrType_Type
#define PyUInt32ScalarObject PyUByteScalarObject
#define PyUInt32ArrType_Type PyUByteArrType_Type
// 定义 NPY_INT32_FMT 和 NPY_UINT32_FMT 为 NPY_BYTE_FMT
#define NPY_INT32_FMT NPY_BYTE_FMT
#define NPY_UINT32_FMT NPY_UBYTE_FMT
#endif
#endif
#define NPY_INT64 NPY_BYTE
// 将 NPY_INT64 定义为 NPY_BYTE
#define NPY_UINT64 NPY_UBYTE
// 将 NPY_UINT64 定义为 NPY_UBYTE
typedef signed char npy_int64;
// 定义 npy_int64 为有符号字符类型
typedef unsigned char npy_uint64;
// 定义 npy_uint64 为无符号字符类型
# define PyInt64ScalarObject PyByteScalarObject
// 将 PyInt64ScalarObject 定义为 PyByteScalarObject
# define PyInt64ArrType_Type PyByteArrType_Type
// 将 PyInt64ArrType_Type 定义为 PyByteArrType_Type
# define PyUInt64ScalarObject PyUByteScalarObject
// 将 PyUInt64ScalarObject 定义为 PyUByteScalarObject
# define PyUInt64ArrType_Type PyUByteArrType_Type
// 将 PyUInt64ArrType_Type 定义为 PyUByteArrType_Type
#define NPY_INT64_FMT NPY_BYTE_FMT
// 将 NPY_INT64_FMT 定义为 NPY_BYTE_FMT
#define NPY_UINT64_FMT NPY_UBYTE_FMT
// 将 NPY_UINT64_FMT 定义为 NPY_UBYTE_FMT
# define MyPyLong_FromInt64 PyLong_FromLong
// 将 MyPyLong_FromInt64 定义为 PyLong_FromLong
# define MyPyLong_AsInt64 PyLong_AsLong
// 将 MyPyLong_AsInt64 定义为 PyLong_AsLong
#endif
#elif NPY_BITSOF_CHAR == 128
#ifndef NPY_INT128
#define NPY_INT128 NPY_BYTE
// 如果 NPY_INT128 未定义,则将其定义为 NPY_BYTE
#define NPY_UINT128 NPY_UBYTE
// 如果 NPY_UINT128 未定义,则将其定义为 NPY_UBYTE
typedef signed char npy_int128;
// 定义 npy_int128 为有符号字符类型
typedef unsigned char npy_uint128;
// 定义 npy_uint128 为无符号字符类型
# define PyInt128ScalarObject PyByteScalarObject
// 将 PyInt128ScalarObject 定义为 PyByteScalarObject
# define PyInt128ArrType_Type PyByteArrType_Type
// 将 PyInt128ArrType_Type 定义为 PyByteArrType_Type
# define PyUInt128ScalarObject PyUByteScalarObject
// 将 PyUInt128ScalarObject 定义为 PyUByteScalarObject
# define PyUInt128ArrType_Type PyUByteArrType_Type
// 将 PyUInt128ArrType_Type 定义为 PyUByteArrType_Type
#define NPY_INT128_FMT NPY_BYTE_FMT
// 将 NPY_INT128_FMT 定义为 NPY_BYTE_FMT
#define NPY_UINT128_FMT NPY_UBYTE_FMT
// 将 NPY_UINT128_FMT 定义为 NPY_UBYTE_FMT
#endif
#endif
#if NPY_BITSOF_DOUBLE == 32
#ifndef NPY_FLOAT32
#define NPY_FLOAT32 NPY_DOUBLE
// 如果 NPY_FLOAT32 未定义,则将其定义为 NPY_DOUBLE
#define NPY_COMPLEX64 NPY_CDOUBLE
// 如果 NPY_COMPLEX64 未定义,则将其定义为 NPY_CDOUBLE
typedef double npy_float32;
// 定义 npy_float32 为双精度浮点类型
typedef npy_cdouble npy_complex64;
// 定义 npy_complex64 为复数类型 npy_cdouble
# define PyFloat32ScalarObject PyDoubleScalarObject
// 将 PyFloat32ScalarObject 定义为 PyDoubleScalarObject
# define PyComplex64ScalarObject PyCDoubleScalarObject
// 将 PyComplex64ScalarObject 定义为 PyCDoubleScalarObject
# define PyFloat32ArrType_Type PyDoubleArrType_Type
// 将 PyFloat32ArrType_Type 定义为 PyDoubleArrType_Type
# define PyComplex64ArrType_Type PyCDoubleArrType_Type
// 将 PyComplex64ArrType_Type 定义为 PyCDoubleArrType_Type
#define NPY_FLOAT32_FMT NPY_DOUBLE_FMT
// 将 NPY_FLOAT32_FMT 定义为 NPY_DOUBLE_FMT
#define NPY_COMPLEX64_FMT NPY_CDOUBLE_FMT
// 将 NPY_COMPLEX64_FMT 定义为 NPY_CDOUBLE_FMT
#endif
#elif NPY_BITSOF_DOUBLE == 64
#ifndef NPY_FLOAT64
#define NPY_FLOAT64 NPY_DOUBLE
// 如果 NPY_FLOAT64 未定义,则将其定义为 NPY_DOUBLE
#define NPY_COMPLEX128 NPY_CDOUBLE
// 如果 NPY_COMPLEX128 未定义,则将其定义为 NPY_CDOUBLE
typedef double npy_float64;
// 定义 npy_float64 为双精度浮点类型
typedef npy_cdouble npy_complex128;
// 定义 npy_complex128 为复数类型 npy_cdouble
# define PyFloat64ScalarObject PyDoubleScalarObject
// 将 PyFloat64ScalarObject 定义为 PyDoubleScalarObject
# define PyComplex128ScalarObject PyCDoubleScalarObject
// 将 PyComplex128ScalarObject 定义为 PyCDoubleScalarObject
# define PyFloat64ArrType_Type PyDoubleArrType_Type
// 将 PyFloat64ArrType_Type 定义为 PyDoubleArrType_Type
# define PyComplex128ArrType_Type PyCDoubleArrType_Type
// 将 PyComplex128ArrType_Type 定义为 PyCDoubleArrType_Type
#define NPY_FLOAT64_FMT NPY_DOUBLE_FMT
// 将 NPY_FLOAT64_FMT 定义为 NPY_DOUBLE_FMT
#define NPY_COMPLEX128_FMT NPY_CDOUBLE_FMT
// 将 NPY_COMPLEX128_FMT 定义为 NPY_CDOUBLE_FMT
#endif
#elif NPY_BITSOF_DOUBLE == 80
#ifndef NPY_FLOAT80
#define NPY_FLOAT80 NPY_DOUBLE
// 如果 NPY_FLOAT80 未定义,则将其定义为 NPY_DOUBLE
#define NPY_COMPLEX160 NPY_CDOUBLE
// 如果 NPY_COMPLEX160 未定义,则将其定义为 NPY_CDOUBLE
typedef double npy_float80;
// 定义 npy_float80 为双精度浮点类型
typedef npy_cdouble npy_complex160;
// 定义 npy_complex160 为复数类型 npy_cdouble
# define PyFloat80ScalarObject PyDoubleScalarObject
// 将 PyFloat80ScalarObject 定义为 PyDoubleScalarObject
# define PyComplex160ScalarObject PyCDoubleScalarObject
// 将 PyComplex160ScalarObject 定义为 PyCDoubleScalarObject
# define PyFloat80ArrType_Type PyDoubleArrType_Type
// 将 PyFloat80ArrType_Type 定义为 PyDoubleArrType_Type
# define PyComplex160ArrType_Type PyCDoubleArrType_Type
// 将 PyComplex160ArrType_Type 定义为 PyCDoubleArrType_Type
#define NPY_FLOAT80_FMT NPY_DOUBLE_FMT
// 将 NPY_FLOAT80_FMT 定义为 NPY_DOUBLE_FMT
#define NPY_COMPLEX160_FMT NPY_CDOUBLE_FMT
// 将 NPY_COMPLEX160_FMT 定义为 NPY_CDOUBLE_FMT
#endif
#elif NPY_BITSOF_DOUBLE == 96
#ifndef NPY_FLOAT96
#define NPY_FLOAT96 NPY_DOUBLE
// 如果 NPY_FLOAT96 未定义,则将其定义为 NPY_DOUBLE
#define NPY_COMPLEX192 NPY_CDOUBLE
// 如果 NPY_COMPLEX192 未定义,则将其定义为 NPY_CDOUBLE
typedef double npy_float96;
// 定义 npy_float96 为双精度浮点类型
typedef npy_cdouble npy_complex192;
// 定义 npy_complex192 为复数类型 npy_cdouble
# define PyFloat96ScalarObject PyDoubleScalarObject
// 将 PyFloat96ScalarObject 定义为 PyDoubleScalarObject
# define PyComplex192ScalarObject PyCDoubleScalarObject
// 将 PyComplex192ScalarObject 定义为 PyCDoubleScalarObject
# define PyFloat96ArrType_Type PyDoubleArrType_Type
// 将 PyFloat96ArrType_Type 定义为 PyDoubleArrType_Type
# define PyComplex192ArrType_Type PyCDoubleArrType_Type
// 将 PyComplex192ArrType_Type 定义为 PyCDoubleArrType_Type
#if NPY_BITSOF_FLOAT == 32
// 如果浮点数位数为32位
#ifndef NPY_FLOAT32
// 如果未定义NPY_FLOAT32
#define NPY_FLOAT32 NPY_FLOAT
// 定义NPY_FLOAT32为NPY_FLOAT
#define NPY_COMPLEX64 NPY_CFLOAT
// 定义NPY_COMPLEX64为NPY_CFLOAT
typedef float npy_float32;
// 定义npy_float32为float类型
typedef npy_cfloat npy_complex64;
// 定义npy_complex64为npy_cfloat类型
# define PyFloat32ScalarObject PyFloatScalarObject
// 定义PyFloat32ScalarObject为PyFloatScalarObject
# define PyComplex64ScalarObject PyCFloatScalarObject
// 定义PyComplex64ScalarObject为PyCFloatScalarObject
# define PyFloat32ArrType_Type PyFloatArrType_Type
// 定义PyFloat32ArrType_Type为PyFloatArrType_Type
# define PyComplex64ArrType_Type PyCFloatArrType_Type
// 定义PyComplex64ArrType_Type为PyCFloatArrType_Type
#define NPY_FLOAT32_FMT NPY_FLOAT_FMT
// 定义NPY_FLOAT32_FMT为NPY_FLOAT_FMT
#define NPY_COMPLEX64_FMT NPY_CFLOAT_FMT
// 定义NPY_COMPLEX64_FMT为NPY_CFLOAT_FMT
#endif
#elif NPY_BITSOF_FLOAT == 64
// 否则如果浮点数位数为64位
#ifndef NPY_FLOAT64
// 如果未定义NPY_FLOAT64
#define NPY_FLOAT64 NPY_FLOAT
// 定义NPY_FLOAT64为NPY_FLOAT
#define NPY_COMPLEX128 NPY_CFLOAT
// 定义NPY_COMPLEX128为NPY_CFLOAT
typedef float npy_float64;
// 定义npy_float64为float类型
typedef npy_cfloat npy_complex128;
// 定义npy_complex128为npy_cfloat类型
# define PyFloat64ScalarObject PyFloatScalarObject
// 定义PyFloat64ScalarObject为PyFloatScalarObject
# define PyComplex128ScalarObject PyCFloatScalarObject
// 定义PyComplex128ScalarObject为PyCFloatScalarObject
# define PyFloat64ArrType_Type PyFloatArrType_Type
// 定义PyFloat64ArrType_Type为PyFloatArrType_Type
# define PyComplex128ArrType_Type PyCFloatArrType_Type
// 定义PyComplex128ArrType_Type为PyCFloatArrType_Type
#define NPY_FLOAT64_FMT NPY_FLOAT_FMT
// 定义NPY_FLOAT64_FMT为NPY_FLOAT_FMT
#define NPY_COMPLEX128_FMT NPY_CFLOAT_FMT
// 定义NPY_COMPLEX128_FMT为NPY_CFLOAT_FMT
#endif
#elif NPY_BITSOF_FLOAT == 80
// 否则如果浮点数位数为80位
#ifndef NPY_FLOAT80
// 如果未定义NPY_FLOAT80
#define NPY_FLOAT80 NPY_FLOAT
// 定义NPY_FLOAT80为NPY_FLOAT
#define NPY_COMPLEX160 NPY_CFLOAT
// 定义NPY_COMPLEX160为NPY_CFLOAT
typedef float npy_float80;
// 定义npy_float80为float类型
typedef npy_cfloat npy_complex160;
// 定义npy_complex160为npy_cfloat类型
# define PyFloat80ScalarObject PyFloatScalarObject
// 定义PyFloat80ScalarObject为PyFloatScalarObject
# define PyComplex160ScalarObject PyCFloatScalarObject
// 定义PyComplex160ScalarObject为PyCFloatScalarObject
# define PyFloat80ArrType_Type PyFloatArrType_Type
// 定义PyFloat80ArrType_Type为PyFloatArrType_Type
# define PyComplex160ArrType_Type PyCFloatArrType_Type
// 定义PyComplex160ArrType_Type为PyCFloatArrType_Type
#define NPY_FLOAT80_FMT NPY_FLOAT_FMT
// 定义NPY_FLOAT80_FMT为NPY_FLOAT_FMT
#define NPY_COMPLEX160_FMT NPY_CFLOAT_FMT
// 定义NPY_COMPLEX160_FMT为NPY_CFLOAT_FMT
#endif
#elif NPY_BITSOF_FLOAT == 96
// 否则如果浮点数位数为96位
#ifndef NPY_FLOAT96
// 如果未定义NPY_FLOAT96
#define NPY_FLOAT96 NPY_FLOAT
// 定义NPY_FLOAT96为NPY_FLOAT
#define NPY_COMPLEX192 NPY_CFLOAT
// 定义NPY_COMPLEX192为NPY_CFLOAT
typedef float npy_float96;
// 定义npy_float96为float类型
typedef npy_cfloat npy_complex192;
// 定义npy_complex192为npy_cfloat类型
# define PyFloat96ScalarObject PyFloatScalarObject
// 定义PyFloat96ScalarObject为PyFloatScalarObject
# define PyComplex192ScalarObject PyCFloatScalarObject
// 定义PyComplex192ScalarObject为PyCFloatScalarObject
# define PyFloat96ArrType_Type PyFloatArrType_Type
// 定义PyFloat96ArrType_Type为PyFloatArrType_Type
# define PyComplex192ArrType_Type PyCFloatArrType_Type
// 定义PyComplex192ArrType_Type为PyCFloatArrType_Type
#define NPY_FLOAT96_FMT NPY_FLOAT_FMT
// 定义NPY_FLOAT96_FMT为NPY_FLOAT_FMT
#define NPY_COMPLEX192_FMT NPY_CFLOAT_FMT
// 定义NPY_COMPLEX192_FMT为NPY_CFLOAT_FMT
#endif
#elif NPY_BITSOF_FLOAT == 128
// 否则如果浮点数位数为128位
#ifndef NPY_FLOAT128
// 如果未定义NPY_FLOAT128
#define NPY_FLOAT128 NPY_FLOAT
// 定义NPY_FLOAT128为NPY_FLOAT
#define NPY_COMPLEX256 NPY_CFLOAT
// 定义NPY_COMPLEX256为NPY_CFLOAT
typedef float npy_float128;
// 定义npy_float128为float类型
typedef npy_cfloat npy_complex256;
// 定义npy_complex256为npy_cfloat类型
# define PyFloat128ScalarObject PyFloatScalarObject
// 定义PyFloat128ScalarObject为PyFloatScalarObject
# define PyComplex256ScalarObject PyCFloatScalarObject
// 定义PyComplex256ScalarObject为PyCFloatScalarObject
# define PyFloat128ArrType_Type PyFloatArrType_Type
// 定义PyFloat128ArrType_Type为PyFloatArrType_Type
/* define PyComplex256ArrType_Type PyCFloatArrType_Type
#define NPY_FLOAT128_FMT NPY_FLOAT_FMT
#define NPY_COMPLEX256_FMT NPY_CFLOAT_FMT
#endif
#endif
*/
/* half/float16 isn't a floating-point type in C */
// 定义 NPY_FLOAT16 为 NPY_HALF
// 定义 npy_half 为 npy_uint16
typedef npy_uint16 npy_half;
// 定义 npy_float16 为 npy_half
typedef npy_half npy_float16;
// 定义 NPY_FLOAT32 为 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX64 为 NPY_CLONGDOUBLE
// 定义 npy_float32 为 npy_longdouble
typedef npy_longdouble npy_float32;
// 定义 npy_complex64 为 npy_clongdouble
typedef npy_clongdouble npy_complex64;
// define PyFloat32ScalarObject PyLongDoubleScalarObject
// define PyComplex64ScalarObject PyCLongDoubleScalarObject
// define PyFloat32ArrType_Type PyLongDoubleArrType_Type
// define PyComplex64ArrType_Type PyCLongDoubleArrType_Type
// 定义 NPY_FLOAT64 为 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX128 为 NPY_CLONGDOUBLE
// 定义 npy_float64 为 npy_longdouble
typedef npy_longdouble npy_float64;
// 定义 npy_complex128 为 npy_clongdouble
typedef npy_clongdouble npy_complex128;
// define PyFloat64ScalarObject PyLongDoubleScalarObject
// define PyComplex128ScalarObject PyCLongDoubleScalarObject
// define PyFloat64ArrType_Type PyLongDoubleArrType_Type
// define PyComplex128ArrType_Type PyCLongDoubleArrType_Type
// 定义 NPY_FLOAT80 为 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX160 为 NPY_CLONGDOUBLE
// 定义 npy_float80 为 npy_longdouble
typedef npy_longdouble npy_float80;
// 定义 npy_complex160 为 npy_clongdouble
typedef npy_clongdouble npy_complex160;
// define PyFloat80ScalarObject PyLongDoubleScalarObject
// define PyComplex160ScalarObject PyCLongDoubleScalarObject
// define PyFloat80ArrType_Type PyLongDoubleArrType_Type
// define PyComplex160ArrType_Type PyCLongDoubleArrType_Type
// 定义 NPY_FLOAT96 为 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX192 为 NPY_CLONGDOUBLE
// 定义 npy_float96 为 npy_longdouble
typedef npy_longdouble npy_float96;
// 定义 npy_complex192 为 npy_clongdouble
typedef npy_clongdouble npy_complex192;
// define PyFloat96ScalarObject PyLongDoubleScalarObject
// define PyComplex192ScalarObject PyCLongDoubleScalarObject
// define PyFloat96ArrType_Type PyLongDoubleArrType_Type
// define PyComplex192ArrType_Type PyCLongDoubleArrType_Type
// 定义 NPY_FLOAT128 为 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX256 为 NPY_CLONGDOUBLE
// 定义 npy_float128 为 npy_longdouble
typedef npy_longdouble npy_float128;
// 定义 npy_complex256 为 npy_clongdouble
typedef npy_clongdouble npy_complex256;
// define PyFloat128ScalarObject PyLongDoubleScalarObject
// define PyComplex256ScalarObject PyCLongDoubleScalarObject
// define PyFloat128ArrType_Type PyLongDoubleArrType_Type
/* 如果 NPY_BITSOF_LONGDOUBLE 宏定义为 128,则定义一系列与长双精度浮点数相关的宏和类型别名 */
typedef npy_longdouble npy_float128;
typedef npy_clongdouble npy_complex256;
/* 如果 NPY_BITSOF_LONGDOUBLE 宏定义为 256,则定义一系列与长双精度浮点数相关的宏和类型别名 */
typedef npy_longdouble npy_float256;
typedef npy_clongdouble npy_complex512;
/* datetime 的类型定义 */
typedef npy_int64 npy_timedelta; // 定义 npy_timedelta 类型为 npy_int64
typedef npy_int64 npy_datetime; // 定义 npy_datetime 类型为 npy_int64
/* numarray 风格的位宽命名类型定义结束标志 */