NumPy-源码解析-四十九-

173 阅读1小时+

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

#ifndef NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_

// 包含必要的头文件:npy_common.h, npy_endian.h, npy_cpu.h, utils.h
#include "npy_common.h"
#include "npy_endian.h"
#include "npy_cpu.h"
#include "utils.h"

// 定义一个不导出的宏,用于内部使用
#define NPY_NO_EXPORT NPY_VISIBILITY_HIDDEN

// 根据编译时是否启用多线程(NPY_NO_SMP),确定是否允许使用线程
#if !NPY_NO_SMP
        #define NPY_ALLOW_THREADS 1
#else
        #define NPY_ALLOW_THREADS 0
#endif

// 如果编译环境不支持 __has_extension 宏,则定义为 0
#ifndef __has_extension
#define __has_extension(x) 0
#endif

/*
 * 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)
 */
// 定义静态分配的维度数组大小上限
#define NPY_MAXDIMS 64
// 不可改变的遗留迭代器的最大维度限制
#define NPY_MAXDIMS_LEGACY_ITERS 32
// NPY_MAXARGS 是版本相关的,定义在 npy_2_compat.h 中

/* Used for Converter Functions "O&" code in ParseTuple */
// 用于解析元组中 "O&" 类型参数的转换器函数返回状态
#define NPY_FAIL 0
#define NPY_SUCCEED 1

#endif  // NUMPY_CORE_INCLUDE_NUMPY_NDARRAYTYPES_H_
/* 枚举定义不同的 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,
};

/* 基本类型数组优先级 */
#define NPY_PRIORITY 0.0

/* 默认子类型优先级 */
#define NPY_SUBTYPE_PRIORITY 1.0

/* 默认标量优先级 */
#define NPY_SCALAR_PRIORITY -1000000.0

/* 浮点类型的数量(不包括 half) */
#define NPY_NUM_FLOATTYPE 3

/*
 * 这些字符对应于数组类型和 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;
#define NPY_NSORTS (NPY_STABLESORT + 1)


typedef enum {
        NPY_INTROSELECT=0               // 引导选择算法
} NPY_SELECTKIND;
#define NPY_NSELECTS (NPY_INTROSELECT + 1)


typedef enum {
        NPY_SEARCHLEFT=0,               // 向左搜索
        NPY_SEARCHRIGHT=1               // 向右搜索
} NPY_SEARCHSIDE;
#define NPY_NSEARCHSIDES (NPY_SEARCHRIGHT + 1)


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;
#define NPY_NSCALARKINDS (NPY_OBJECT_SCALAR + 1)

/* 用于指定数组内存布局或迭代顺序 */
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) */
#define NPY_DATETIME_NAT NPY_MIN_INT64

/*
 * 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
 */
#define NPY_DATETIME_MAX_ISO8601_STRLEN (21 + 3*5 + 1 + 3*6 + 6 + 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 兼容性,实际单位数比此值少一个
 */
#define NPY_DATETIME_NUMUNITS (NPY_FR_GENERIC + 1)
#define NPY_DATETIME_DEFAULTUNIT NPY_FR_GENERIC

/*
 * 工作日约定,用于将无效的工作日映射为有效的工作日
 */
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 */
#define NPY_AUXDATA_FREE(auxdata) \
    do { \
        if ((auxdata) != NULL) { \
            (auxdata)->free(auxdata); \
        } \
    } while(0)

#define NPY_AUXDATA_CLONE(auxdata) \
    ((auxdata)->clone(auxdata))



#define NPY_ERR(str) fprintf(stderr, #str); fflush(stderr);
#define NPY_ERR2(str) fprintf(stderr, str); fflush(stderr);



/*
* Macros to define how array, and dimension/strides data is
* allocated. These should be made private
*/

#define NPY_USE_PYMEM 1



#if NPY_USE_PYMEM == 1
/* use the Raw versions which are safe to call with the GIL released */
#define PyArray_malloc PyMem_RawMalloc
#define PyArray_free PyMem_RawFree
#define PyArray_realloc PyMem_RawRealloc
#else
#define PyArray_malloc malloc
#define PyArray_free free
#define PyArray_realloc realloc
#endif



/* Dimensions and strides */
#define PyDimMem_NEW(size)                                         \
    ((npy_intp *)PyArray_malloc(size*sizeof(npy_intp)))

#define PyDimMem_FREE(ptr) PyArray_free(ptr)

#define PyDimMem_RENEW(ptr,size)                                   \
        ((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. */
#define NPY_ITEM_REFCOUNT   0x01
/*
 * 定义了一些常量,用于描述数据类型的特征标志位。
 * 这些标志位用于指示数据类型的特性,如是否包含对象、是否需要初始化等。
 */
#define NPY_ITEM_HASOBJECT  0x01        /* Same as needing REFCOUNT */
#define NPY_LIST_PICKLE     0x02        /* Convert to list for pickling */
#define NPY_ITEM_IS_POINTER 0x04        /* The item is a POINTER  */
#define NPY_NEEDS_INIT      0x08        /* memory needs to be initialized for this data-type */
#define NPY_NEEDS_PYAPI     0x10        /* operations need Python C-API so don't give-up thread. */
#define NPY_USE_GETITEM     0x20        /* Use f.getitem when extracting elements of this data-type */
#define NPY_USE_SETITEM     0x40        /* Use f.setitem when setting creating 0-d array from this data-type.*/
#define NPY_ALIGNED_STRUCT  0x80        /* A sticky flag specifically for structured arrays */

/*
 * 这些标志位是针对全局数据类型的继承标志位,如果字段中的任何数据类型具有这些标志位,则其继承。
 */
#define NPY_FROM_FIELDS    (NPY_NEEDS_INIT | NPY_LIST_PICKLE | \
                            NPY_ITEM_REFCOUNT | NPY_NEEDS_PYAPI)

#define NPY_OBJECT_DTYPE_FLAGS (NPY_LIST_PICKLE | NPY_USE_GETITEM | \
                                NPY_ITEM_IS_POINTER | NPY_ITEM_REFCOUNT | \
                                NPY_NEEDS_INIT | NPY_NEEDS_PYAPI)

#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
/*
 * 如果 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;

#else  /* 兼容 1.x 和 2.x 的版本(仅共享字段): */

typedef struct _PyArray_Descr {
        PyObject_HEAD
        PyTypeObject *typeobj;
        char kind;
        char type;
        char byteorder;
        char _former_flags;
        int type_num;
} PyArray_Descr;

/* 要访问修改后的字段,请定义完整的 2.0 版本结构体: */

#endif
/*
 * 定义了一个名为 _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;

#endif  /* 1.x and 2.x compatible version */

/*
 * 半私有结构体 _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;
#if NPY_FEATURE_VERSION >= NPY_1_20_API_VERSION
    void *_buffer_info;  /* private buffer info, tagged to allow warning */
#endif
    /*
     * For malloc/calloc/realloc/free per object
     */
#if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION
    PyObject *mem_handler;
#endif
} PyArrayObject_fields;

/*
 * To hide the implementation details, we only expose
 * the Python struct HEAD.
 */
#if !defined(NPY_NO_DEPRECATED_API) || \
    (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) */
#define PyArray_ISONESEGMENT(m) (PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS) || \
                                 PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS))


注释:  

/* 结构体定义结束 */

/* 定义 PyArrayNeighborhoodIterObject 结构体,继承自 PyObject */
/* PyArrayIterObject 的一部分:保持此精确顺序 */

/* 数组迭代器结构体的维度减一 */
/* 当前索引和总大小 */
/* N 维循环的坐标 */
/* ao->dimensions - 1 */
/* ao->strides 或虚拟值 */
/* 后退跨度 */
/* 形状因子 */
/* 指向 PyArrayObject 的指针 */
/* 指向当前项的指针 */
/* 表示数据是否连续的标志 */

/* 每个维度的边界 */
/* 每个维度的限制 */
/* 每个维度限制的大小 */
/* 数据转换函数指针 */

/* 新成员 */

/* 数组的维度 */
/* 数组的维度 */

/* 邻域点坐标相对于 _internal_iter 指向的点计算 */

/* 保留对常量填充值表示的引用 */

/* 操作模式 */
/*
 * 检查数组是否按 Fortran 风格存储(列优先),同时不应该按 C 风格存储(行优先)
 * 返回值:如果数组按 Fortran 风格存储则返回非零值,否则返回零
 */
#define PyArray_ISFORTRAN(m) (PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) && \
                             (!PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)))

/*
 * 如果数组按 Fortran 风格存储,返回 NPY_ARRAY_F_CONTIGUOUS,否则返回 0
 */
#define PyArray_FORTRAN_IF(m) ((PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) ? \
                               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;
}

#if NPY_FEATURE_VERSION >= NPY_1_22_API_VERSION
    /*
     * 返回数组的内存处理器对象(如果支持)
     */
    static inline NPY_RETURNS_BORROWED_REF PyObject *
    PyArray_HANDLER(PyArrayObject *arr)
    {
        return ((PyArrayObject_fields *)arr)->mem_handler;
    }
#endif

/*
 * 检查数组的数据类型是否为布尔型
 * 返回值:如果数组的数据类型为 NPY_BOOL,则返回非零值,否则返回零
 */
#define PyTypeNum_ISBOOL(type) ((type) == NPY_BOOL)
# 定义宏:检查数据类型是否为无符号整数类型
#define PyTypeNum_ISUNSIGNED(type) (((type) == NPY_UBYTE) ||   \
                                 ((type) == NPY_USHORT) ||     \
                                 ((type) == NPY_UINT) ||       \
                                 ((type) == NPY_ULONG) ||      \
                                 ((type) == NPY_ULONGLONG))

# 定义宏:检查数据类型是否为有符号整数类型
#define PyTypeNum_ISSIGNED(type) (((type) == NPY_BYTE) ||      \
                               ((type) == NPY_SHORT) ||        \
                               ((type) == NPY_INT) ||          \
                               ((type) == NPY_LONG) ||         \
                               ((type) == NPY_LONGLONG))

# 定义宏:检查数据类型是否为整数类型
#define PyTypeNum_ISINTEGER(type) (((type) >= NPY_BYTE) &&     \
                                ((type) <= NPY_ULONGLONG))

# 定义宏:检查数据类型是否为浮点数类型
#define PyTypeNum_ISFLOAT(type) ((((type) >= NPY_FLOAT) && \
                              ((type) <= NPY_LONGDOUBLE)) || \
                              ((type) == NPY_HALF))

# 定义宏:检查数据类型是否为数字类型(包括整数和浮点数)
#define PyTypeNum_ISNUMBER(type) (((type) <= NPY_CLONGDOUBLE) || \
                                  ((type) == NPY_HALF))

# 定义宏:检查数据类型是否为字符串类型(包括字节字符串和Unicode字符串)
#define PyTypeNum_ISSTRING(type) (((type) == NPY_STRING) ||    \
                                  ((type) == NPY_UNICODE))

# 定义宏:检查数据类型是否为复数类型
#define PyTypeNum_ISCOMPLEX(type) (((type) >= NPY_CFLOAT) &&   \
                                ((type) <= NPY_CLONGDOUBLE))

# 定义宏:检查数据类型是否为灵活类型(如字符串或Void类型)
#define PyTypeNum_ISFLEXIBLE(type) (((type) >=NPY_STRING) &&  \
                                    ((type) <=NPY_VOID))

# 定义宏:检查数据类型是否为日期时间类型
#define PyTypeNum_ISDATETIME(type) (((type) >=NPY_DATETIME) &&  \
                                    ((type) <=NPY_TIMEDELTA))

# 定义宏:检查数据类型是否为用户自定义类型
#define PyTypeNum_ISUSERDEF(type) (((type) >= NPY_USERDEF) && \
                                   ((type) < NPY_USERDEF+     \
                                    NPY_NUMUSERTYPES))

# 定义宏:检查数据类型是否为扩展类型(包括灵活类型和用户自定义类型)
#define PyTypeNum_ISEXTENDED(type) (PyTypeNum_ISFLEXIBLE(type) ||  \
                                    PyTypeNum_ISUSERDEF(type))

# 定义宏:检查数据类型是否为对象类型
#define PyTypeNum_ISOBJECT(type) ((type) == NPY_OBJECT)


# 定义宏:检查数据类型是否为传统(遗留)数据类型
#define PyDataType_ISLEGACY(dtype) ((dtype)->type_num < NPY_VSTRING && ((dtype)->type_num >= 0))

# 定义宏:检查数据类型是否为布尔类型
#define PyDataType_ISBOOL(obj) PyTypeNum_ISBOOL(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为无符号整数类型
#define PyDataType_ISUNSIGNED(obj) PyTypeNum_ISUNSIGNED(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为有符号整数类型
#define PyDataType_ISSIGNED(obj) PyTypeNum_ISSIGNED(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为整数类型
#define PyDataType_ISINTEGER(obj) PyTypeNum_ISINTEGER(((PyArray_Descr*)(obj))->type_num )

# 定义宏:检查数据类型是否为浮点数类型
#define PyDataType_ISFLOAT(obj) PyTypeNum_ISFLOAT(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为数字类型(包括整数和浮点数)
#define PyDataType_ISNUMBER(obj) PyTypeNum_ISNUMBER(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为字符串类型(包括字节字符串和Unicode字符串)
#define PyDataType_ISSTRING(obj) PyTypeNum_ISSTRING(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为复数类型
#define PyDataType_ISCOMPLEX(obj) PyTypeNum_ISCOMPLEX(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为灵活类型(如字符串或Void类型)
#define PyDataType_ISFLEXIBLE(obj) PyTypeNum_ISFLEXIBLE(((PyArray_Descr*)(obj))->type_num)

# 定义宏:检查数据类型是否为日期时间类型
#define PyDataType_ISDATETIME(obj) PyTypeNum_ISDATETIME(((PyArray_Descr*)(obj))->type_num)
/*
 * 定义了一系列用于检查和操作 NumPy 数组数据类型和标志的宏。
 */

#define PyDataType_ISUSERDEF(obj) PyTypeNum_ISUSERDEF(((PyArray_Descr*)(obj))->type_num)
// 检查给定数据类型对象是否为用户定义类型

#define PyDataType_ISEXTENDED(obj) PyTypeNum_ISEXTENDED(((PyArray_Descr*)(obj))->type_num)
// 检查给定数据类型对象是否为扩展类型

#define PyDataType_ISOBJECT(obj) PyTypeNum_ISOBJECT(((PyArray_Descr*)(obj))->type_num)
// 检查给定数据类型对象是否为对象类型

#define PyDataType_MAKEUNSIZED(dtype) ((dtype)->elsize = 0)
// 将给定数据类型对象标记为无大小,通常用于灵活数据类型

/*
 * 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 中定义

#define PyArray_ISBOOL(obj) PyTypeNum_ISBOOL(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为布尔类型

#define PyArray_ISUNSIGNED(obj) PyTypeNum_ISUNSIGNED(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为无符号整数类型

#define PyArray_ISSIGNED(obj) PyTypeNum_ISSIGNED(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为有符号整数类型

#define PyArray_ISINTEGER(obj) PyTypeNum_ISINTEGER(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为整数类型

#define PyArray_ISFLOAT(obj) PyTypeNum_ISFLOAT(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为浮点数类型

#define PyArray_ISNUMBER(obj) PyTypeNum_ISNUMBER(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为数字类型

#define PyArray_ISSTRING(obj) PyTypeNum_ISSTRING(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为字符串类型

#define PyArray_ISCOMPLEX(obj) PyTypeNum_ISCOMPLEX(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为复数类型

#define PyArray_ISFLEXIBLE(obj) PyTypeNum_ISFLEXIBLE(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为灵活数据类型

#define PyArray_ISDATETIME(obj) PyTypeNum_ISDATETIME(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为日期时间类型

#define PyArray_ISUSERDEF(obj) PyTypeNum_ISUSERDEF(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为用户定义类型

#define PyArray_ISEXTENDED(obj) PyTypeNum_ISEXTENDED(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为扩展类型

#define PyArray_ISOBJECT(obj) PyTypeNum_ISOBJECT(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为对象类型

#define PyArray_HASFIELDS(obj) PyDataType_HASFIELDS(PyArray_DESCR(obj))
// 检查给定数组对象是否具有字段描述符

/*
 * 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.
 */
#define PyArray_ISVARIABLE(obj) PyTypeNum_ISFLEXIBLE(PyArray_TYPE(obj))
// 检查给定数组对象的类型是否为可变长度类型

#define PyArray_SAFEALIGNEDCOPY(obj) (PyArray_ISALIGNED(obj) && !PyArray_ISVARIABLE(obj))
// 检查给定数组对象是否是对齐的且不是可变长度类型

#define NPY_LITTLE '<'
// 定义小端字节顺序符号

#define NPY_BIG '>'
// 定义大端字节顺序符号

#define NPY_NATIVE '='
// 定义本地字节顺序符号

#define NPY_SWAP 's'
// 定义交换字节顺序符号

#define NPY_IGNORE '|'
// 定义忽略字节顺序符号

#if NPY_BYTE_ORDER == NPY_BIG_ENDIAN
#define NPY_NATBYTE NPY_BIG
#define NPY_OPPBYTE NPY_LITTLE
#else
#define NPY_NATBYTE NPY_LITTLE
#define NPY_OPPBYTE NPY_BIG
#endif

#define PyArray_ISNBO(arg) ((arg) != NPY_OPPBYTE)
// 检查参数是否与本地字节顺序匹配

#define PyArray_IsNativeByteOrder PyArray_ISNBO
// 别名,检查参数是否与本地字节顺序匹配

#define PyArray_ISNOTSWAPPED(m) PyArray_ISNBO(PyArray_DESCR(m)->byteorder)
// 检查给定数组对象的描述符的字节顺序是否与本地字节顺序匹配

#define PyArray_ISBYTESWAPPED(m) (!PyArray_ISNOTSWAPPED(m))
// 检查给定数组对象是否具有交换字节顺序的描述符

#define PyArray_FLAGSWAP(m, flags) (PyArray_CHKFLAGS(m, flags) &&       \
                                    PyArray_ISNOTSWAPPED(m))
// 检查给定数组对象是否符合特定标志并且没有交换字节顺序

#define PyArray_ISCARRAY(m) PyArray_FLAGSWAP(m, NPY_ARRAY_CARRAY)
// 检查给定数组对象是否具有 C 风格数组标志

#define PyArray_ISCARRAY_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_CARRAY_RO)
// 检查给定数组对象是否具有只读 C 风格数组标志

#define PyArray_ISFARRAY(m) PyArray_FLAGSWAP(m, NPY_ARRAY_FARRAY)
// 检查给定数组对象是否具有 Fortran 风格数组标志

#define PyArray_ISFARRAY_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_FARRAY_RO)
// 检查给定数组对象是否具有只读 Fortran 风格数组标志

#define PyArray_ISBEHAVED(m) PyArray_FLAGSWAP(m, NPY_ARRAY_BEHAVED)
// 检查给定数组对象是否具有规范行为标志

#define PyArray_ISBEHAVED_RO(m) PyArray_FLAGSWAP(m, NPY_ARRAY_ALIGNED)
// 检查给定数组对象是否具有只读规范行为标志
/*
 * 宏定义:检查数据类型是否未交换字节序
 */
#define PyDataType_ISNOTSWAPPED(d) PyArray_ISNBO(((PyArray_Descr *)(d))->byteorder)

/*
 * 宏定义:检查数据类型是否已交换字节序
 */
#define PyDataType_ISBYTESWAPPED(d) (!PyDataType_ISNOTSWAPPED(d))

/************************************************************
 * 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.
 */
#if defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD
    /*
     * 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

#ifndef NPY_DEPRECATED_INCLUDES
#error "Should never include npy_*_*_deprecated_api directly."
#endif


// 如果未定义 NPY_DEPRECATED_INCLUDES 宏,则产生编译错误,要求不直接包含 npy_*_*_deprecated_api 文件
#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_1_7_DEPRECATED_API_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NPY_1_7_DEPRECATED_API_H_


// 如果未定义 NUMPY_CORE_INCLUDE_NUMPY_NPY_1_7_DEPRECATED_API_H_ 宏,则定义该宏,避免重复包含本文件


/* Emit a warning if the user did not specifically request the old API */
#ifndef NPY_NO_DEPRECATED_API
#if defined(_WIN32)
#define _WARN___STR2__(x) #x
#define _WARN___STR1__(x) _WARN___STR2__(x)
#define _WARN___LOC__ __FILE__ "(" _WARN___STR1__(__LINE__) ") : Warning Msg: "
#pragma message(_WARN___LOC__"Using deprecated NumPy API, disable it with " \
                         "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION")
#else
#warning "Using deprecated NumPy API, disable it with " \
         "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION"
#endif
#endif


// 如果未定义 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 */
#define NPY_CONTIGUOUS NPY_ARRAY_C_CONTIGUOUS
#define NPY_FORTRAN NPY_ARRAY_F_CONTIGUOUS


// 这些数组标志在 NumPy 1.7 中已弃用
#define NPY_CONTIGUOUS NPY_ARRAY_C_CONTIGUOUS  // NPY_CONTIGUOUS 等同于 NPY_ARRAY_C_CONTIGUOUS
#define NPY_FORTRAN NPY_ARRAY_F_CONTIGUOUS      // NPY_FORTRAN 等同于 NPY_ARRAY_F_CONTIGUOUS


/*
 * 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.
 */
#define NPY_AO PyArrayObject


// 在 NumPy 1.7 中已弃用此类快捷方式,不应出现在公共 API 中。
#define NPY_AO PyArrayObject  // NPY_AO 等同于 PyArrayObject


/*
 * 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:
 *
 *     #if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
 *         Simple definition when NumPy 2.0 API is guaranteed.
 *     #else
 *         static inline definition of a 1.x compatibility shim
 *         #if NPY_ABI_VERSION < 0x02000000
 *            Make 1.x compatibility shim the public API (1.x only branch)
 *         #else
 *             Runtime dispatched version (1.x or 2.x)
 *         #endif
 *     #endif
 *
 * An internal build always passes NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
 */

#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_

/*
 * New macros for accessing real and complex part of a complex number can be
 * found in "npy_2_complexcompat.h".
 */

/*
 * This header is meant to be included by downstream directly for 1.x compat.
 * In that case we need to ensure that users first included the full headers
 * and not just `ndarraytypes.h`.
 */

#ifndef NPY_FEATURE_VERSION
  #error "The NumPy 2 compat header requires `import_array()` for which "  \
         "the `ndarraytypes.h` header include is not sufficient.  Please "  \
         "include it after `numpy/ndarrayobject.h` or similar.\n"  \
         "To simplify inclusion, you may use `PyArray_ImportNumPy()` " \
         "which is defined in the compat header and is lightweight (can be)."
#endif

#if NPY_ABI_VERSION < 0x02000000
  /*
   * Define 2.0 feature version as it is needed below to decide whether we
   * compile for both 1.x and 2.x (defining it guarantees 1.x only).
   */
  #define NPY_2_0_API_VERSION 0x00000012
  /*
   * If we are compiling with NumPy 1.x, PyArray_RUNTIME_VERSION so we
   * pretend the `PyArray_RUNTIME_VERSION` is `NPY_FEATURE_VERSION`.
   * This allows downstream to use `PyArray_RUNTIME_VERSION` if they need to.
   */
  #define PyArray_RUNTIME_VERSION NPY_FEATURE_VERSION
  /* Compiling on NumPy 1.x where these are the same: */
  #define PyArray_DescrProto PyArray_Descr
#endif

/*
 * Define a better way to call `_import_array()` to simplify backporting as
 * we now require imports more often (necessary to make ABI flexible).
 */
#ifdef import_array1

static inline int
PyArray_ImportNumPyAPI()
{
    if (NPY_UNLIKELY(PyArray_API == NULL)) {
        import_array1(-1);
    }
    return 0;
}

#endif  /* import_array1 */

#endif  /* NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_ */
/*
 * 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 内置数据类型的数量,这是一个遗留的定义。
 */
#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
    #define NPY_DEFAULT_INT NPY_INTP
    #define NPY_RAVEL_AXIS NPY_MIN_INT
    #define NPY_MAXARGS 64

#elif NPY_ABI_VERSION < 0x02000000
    #define NPY_DEFAULT_INT NPY_LONG
    #define NPY_RAVEL_AXIS 32
    #define NPY_MAXARGS 32

    /* NumPy 1.x 兼容的别名 */
    #define NPY_NTYPES NPY_NTYPES_LEGACY
    #define PyArray_DescrProto PyArray_Descr
    #define _PyArray_LegacyDescr PyArray_Descr
    /* NumPy 2 定义适用于 NumPy 1.x */
    #define PyDataType_ISLEGACY(dtype) (1)
#else
    #define NPY_DEFAULT_INT  \
        (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? NPY_INTP : NPY_LONG)
    #define NPY_RAVEL_AXIS  \
        (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? -1 : 32)
    #define NPY_MAXARGS  \
        (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? 64 : 32)
#endif


/*
 * Access inline functions for descriptor fields.  Except for the first
 * few fields, these needed to be moved (elsize, alignment) for
 * additional space.  Or they are descriptor specific and are not generally
 * available anymore (metadata, c_metadata, subarray, names, fields).
 *
 * Most of these are defined via the `DESCR_ACCESSOR` macro helper.
 */
#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION || NPY_ABI_VERSION < 0x02000000
    /* 编译环境为 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)
    {
    #if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
        // 返回数据类型描述符的标志位
        return dtype->flags;
    #else
        // 在 1.x 版本中,需要将标志位转换为无符号字符型
        return (unsigned char)dtype->flags;
    #endif
    }

    #define DESCR_ACCESSOR(FIELD, field, type, legacy_only)    \
        static inline type                                     \
        PyDataType_##FIELD(const PyArray_Descr *dtype) {       \
            if (legacy_only && !PyDataType_ISLEGACY(dtype)) {  \
                return (type)0;                                \
            }                                                  \
            // 返回数据类型描述符中指定字段的值
            return ((_PyArray_LegacyDescr *)dtype)->field;     \
        }
#else  /* 编译环境同时支持 1.x 和 2.x */

    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` */
    #define DESCR_ACCESSOR(FIELD, field, type, legacy_only)        \
        static inline type                                         \
        PyDataType_##FIELD(const PyArray_Descr *dtype) {           \
            // 如果 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;       \
            }                                                      \
        }
#endif

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*

#undef DESCR_ACCESSOR

#if !(defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD)
#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION
    static inline PyArray_ArrFuncs *
    PyDataType_GetArrFuncs(const PyArray_Descr *descr)
    {
        return _PyDataType_GetArrFuncs(descr);
    }
#elif NPY_ABI_VERSION < 0x02000000
    static inline PyArray_ArrFuncs *
    PyDataType_GetArrFuncs(const PyArray_Descr *descr)
    {
        return descr->f;
    }
#else
    static inline PyArray_ArrFuncs *
    PyDataType_GetArrFuncs(const PyArray_Descr *descr)
    {
        if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION) {
            return _PyDataType_GetArrFuncs(descr);
        }
        else {
            return ((PyArray_DescrProto *)descr)->f;
        }
    }
#endif

#endif  /* not internal build */

#endif  /* NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPAT_H_ */

.\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. */

#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPLEXCOMPAT_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NPY_2_COMPLEXCOMPAT_H_

#include <numpy/npy_math.h>  // 包含 numpy/npy_math.h 头文件,这里定义了新的宏

#ifndef NPY_CSETREALF
#define NPY_CSETREALF(c, r) (c)->real = (r)  // 定义宏 NPY_CSETREALF,设置复数结构体 c 的实部为 r
#endif
#ifndef NPY_CSETIMAGF
#define NPY_CSETIMAGF(c, i) (c)->imag = (i)  // 定义宏 NPY_CSETIMAGF,设置复数结构体 c 的虚部为 i
#endif
#ifndef NPY_CSETREAL
#define NPY_CSETREAL(c, r)  (c)->real = (r)  // 定义宏 NPY_CSETREAL,设置复数结构体 c 的实部为 r
#endif
#ifndef NPY_CSETIMAG
#define NPY_CSETIMAG(c, i)  (c)->imag = (i)  // 定义宏 NPY_CSETIMAG,设置复数结构体 c 的虚部为 i
#endif
#ifndef NPY_CSETREALL
#define NPY_CSETREALL(c, r) (c)->real = (r)  // 定义宏 NPY_CSETREALL,设置复数结构体 c 的实部为 r
#endif
#ifndef NPY_CSETIMAGL
#define NPY_CSETIMAGL(c, i) (c)->imag = (i)  // 定义宏 NPY_CSETIMAGL,设置复数结构体 c 的虚部为 i
#endif

#endif  // 结束条件编译指令

.\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.
 */

#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_

#include <Python.h>
#include <stdio.h>

#ifndef NPY_PY3K
#define NPY_PY3K 1
#endif

#include "numpy/npy_common.h"
#include "numpy/ndarrayobject.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * 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.
 */
#endif /* NPY_PY3K */

/* Py3 changes PySlice_GetIndicesEx' first argument's type to PyObject* */
#ifdef NPY_PY3K
#  define NpySlice_GetIndicesEx PySlice_GetIndicesEx
#else
#  define NpySlice_GetIndicesEx(op, nop, start, end, step, slicelength) \
    PySlice_GetIndicesEx((PySliceObject *)op, nop, start, end, step, slicelength)
#endif

#if PY_VERSION_HEX < 0x030900a4
    /* Introduced in https://github.com/python/cpython/commit/d2ec81a8c99796b51fb8c49b77a7fe369863226f */
    #define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0)
    /* Introduced in https://github.com/python/cpython/commit/b10dc3e7a11fcdb97e285882eba6da92594f90f9 */
    #define Py_SET_SIZE(obj, size) ((Py_SIZE(obj) = (size)), (void)0)
    /* Introduced in https://github.com/python/cpython/commit/c86a11221df7e37da389f9c6ce6e47ea22dc44ff */
#endif

#endif /* NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_ */
    #define Py_SET_REFCNT(obj, refcnt) ((Py_REFCNT(obj) = (refcnt)), (void)0)
#endif

#define Npy_EnterRecursiveCall(x) Py_EnterRecursiveCall(x)

/*
 * 定义宏:将 PyString 相关宏重定向到 PyBytes 相关宏
 */

#if defined(NPY_PY3K)

// 在 Python 3 中,将 PyString 相关宏重定向到 PyBytes 相关宏
#define PyString_Type PyBytes_Type
#define PyString_Check PyBytes_Check
#define PyStringObject PyBytesObject
#define PyString_FromString PyBytes_FromString
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#define PyString_AS_STRING PyBytes_AS_STRING
#define PyString_AsStringAndSize PyBytes_AsStringAndSize
#define PyString_FromFormat PyBytes_FromFormat
#define PyString_Concat PyBytes_Concat
#define PyString_ConcatAndDel PyBytes_ConcatAndDel
#define PyString_AsString PyBytes_AsString
#define PyString_GET_SIZE PyBytes_GET_SIZE
#define PyString_Size PyBytes_Size

// 同时,将 PyUnicode 相关宏也定义为 PyString 相关宏
#define PyUString_Type PyUnicode_Type
#define PyUString_Check PyUnicode_Check
#define PyUStringObject PyUnicodeObject
#define PyUString_FromString PyUnicode_FromString
#define PyUString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyUString_FromFormat PyUnicode_FromFormat
#define PyUString_Concat PyUnicode_Concat2
#define PyUString_ConcatAndDel PyUnicode_ConcatAndDel
#define PyUString_GET_SIZE PyUnicode_GET_SIZE
#define PyUString_Size PyUnicode_Size
#define PyUString_InternFromString PyUnicode_InternFromString
#define PyUString_Format PyUnicode_Format

// 定义宏:检查对象是否为基本字符串对象(PyString 或 PyBytes)
#define PyBaseString_Check(obj) (PyUnicode_Check(obj))

#else

// 在 Python 2 中,将 PyBytes 相关宏重定向到 PyString 相关宏
#define PyBytes_Type PyString_Type
#define PyBytes_Check PyString_Check
#define PyBytesObject PyStringObject
#define PyBytes_FromString PyString_FromString
#define PyBytes_FromStringAndSize PyString_FromStringAndSize
#define PyBytes_AS_STRING PyString_AS_STRING
#define PyBytes_AsStringAndSize PyString_AsStringAndSize
#define PyBytes_FromFormat PyString_FromFormat
#define PyBytes_Concat PyString_Concat
#define PyBytes_ConcatAndDel PyString_ConcatAndDel
#define PyBytes_AsString PyString_AsString
#define PyBytes_GET_SIZE PyString_GET_SIZE
#define PyBytes_Size PyString_Size

// 同时,将 PyUnicode 相关宏也定义为 PyString 相关宏
#define PyUString_Type PyString_Type
#define PyUString_Check PyString_Check
#define PyUStringObject PyStringObject
#define PyUString_FromString PyString_FromString
#define PyUString_FromStringAndSize PyString_FromStringAndSize
#define PyUString_FromFormat PyString_FromFormat
#define PyUString_Concat PyString_Concat
#define PyUString_ConcatAndDel PyString_ConcatAndDel
#define PyUString_GET_SIZE PyString_GET_SIZE
#define PyUString_Size PyString_Size
#define PyUString_InternFromString PyString_InternFromString
#define PyUString_Format PyString_Format

// 定义宏:检查对象是否为基本字符串对象(PyString)
#define PyBaseString_Check(obj) (PyBytes_Check(obj) || PyUnicode_Check(obj))

#endif /* NPY_PY3K */

/*
 * 定义宏:保护 CRT 调用,防止因为传递无效参数而导致的程序立即终止
 * 参见:https://bugs.python.org/issue23524
 */
#if defined _MSC_VER && _MSC_VER >= 1900

#include <stdlib.h>

extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler;
// 定义宏:进入抑制无效参数处理器的范围
#define NPY_BEGIN_SUPPRESS_IPH { _invalid_parameter_handler _Py_old_handler = \
    # 设置线程本地的无效参数处理函数为静默模式的无效参数处理函数
    _set_thread_local_invalid_parameter_handler(_Py_silent_invalid_parameter_handler);
/*
 * 定义 _WIN32 环境下的宏 NPY_BEGIN_SUPPRESS_IPH 和 NPY_END_SUPPRESS_IPH,
 * 这些宏用于暂时禁用 Windows 平台的无效参数处理程序
 */
#ifdef _WIN32
#define NPY_BEGIN_SUPPRESS_IPH \
    _set_thread_local_invalid_parameter_handler(_Py_old_handler);
#define NPY_END_SUPPRESS_IPH
#else
#define NPY_BEGIN_SUPPRESS_IPH
#define NPY_END_SUPPRESS_IPH
#endif /* _MSC_VER >= 1900 */

/*
 * 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 !defined(NPY_PY3K)
    if (PyFile_Check(file)) {
        return PyFile_AsFile(file);
    }
#endif

    /* 先刷新以确保数据按正确顺序写入文件 */
    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* 句柄 */
#ifdef _WIN32
    NPY_BEGIN_SUPPRESS_IPH
    handle = _fdopen(fd2, mode);
    NPY_END_SUPPRESS_IPH
#else
    handle = fdopen(fd2, mode);
#endif
    if (handle == NULL) {
        PyErr_SetString(PyExc_IOError,
                        "从 Python 文件对象获取 FILE* 句柄失败。如果是在构建 NumPy 时出现问题,可能是因为链接了错误的调试/发布运行时库");
        return NULL;
    }

    /* 记录原始的文件句柄位置 */
    *orig_pos = npy_ftell(handle);
}
    # 如果原始位置是 -1,则说明需要确定文件当前的位置信息

    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 !defined(NPY_PY3K)
    if (PyFile_Check(file)) {
        return 0;
    }
#endif

    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 !defined(NPY_PY3K)
    if (PyFile_Check(file)) {
        return 1;
    }
#endif
    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 支持这个功能 */
        #ifdef NPY_PY3K
            // 声明用于存储第二个异常的变量
            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);
        #endif
    }
    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 支持这种操作
        #ifdef NPY_PY3K
            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);
        #endif
    }
    else {
        // 恢复之前的异常状态
        PyErr_Restore(exc, val, tb);
    }
}

/*
 * PyObject_Cmp
 */
/* PyObject_Cmp 函数 */
#if defined(NPY_PY3K)
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;
    }
}
#endif

/*
 * 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

#ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_COMMON_H_
#define NUMPY_CORE_INCLUDE_NUMPY_NPY_COMMON_H_

/* 需要 Python.h 以使用 npy_intp、npy_uintp */
#include <Python.h>

/* numpyconfig.h 是自动生成的配置文件 */
#include "numpyconfig.h"
#ifdef HAVE_NPY_CONFIG_H
#include <npy_config.h>
#endif

/*
 * 在定义 npy_math 函数时使用 static inline 修饰符,
 * 允许编译器在可能时进行优化
 */
#ifndef NPY_INLINE_MATH
#if defined(NPY_INTERNAL_BUILD) && NPY_INTERNAL_BUILD
    #define NPY_INLINE_MATH 1
#else
    #define NPY_INLINE_MATH 0
#endif
#endif

/*
 * gcc 即使在 -O3 下也不会展开循环
 * 谨慎使用,现代 CPU 很少因此而加速
 */
#ifdef HAVE_ATTRIBUTE_OPTIMIZE_UNROLL_LOOPS
#define NPY_GCC_UNROLL_LOOPS \
    __attribute__((optimize("unroll-loops")))
#else
#define NPY_GCC_UNROLL_LOOPS
#endif

/* 最高的 gcc 优化级别,启用自动向量化 */
#ifdef HAVE_ATTRIBUTE_OPTIMIZE_OPT_3
#define NPY_GCC_OPT_3 __attribute__((optimize("O3")))
#else
#define NPY_GCC_OPT_3
#endif

/*
 * 标记一个参数(从1开始)不能为空且不会被检查
 * 如果函数检查为空,不要使用!!编译器将移除检查
 */
#ifdef HAVE_ATTRIBUTE_NONNULL
#define NPY_GCC_NONNULL(n) __attribute__((nonnull(n)))
#else
#define NPY_GCC_NONNULL(n)
#endif

/*
 * 给编译器一个提示,哪个分支更可能或更不可能发生,
 * 例如,罕见的错误情况:
 *
 * if (NPY_UNLIKELY(failure == 0))
 *    return NULL;
 *
 * 双重 !! 是为了将表达式(如 NULL)转换为布尔值,符合内置函数的需求
 */
#ifdef HAVE___BUILTIN_EXPECT
#define NPY_LIKELY(x) __builtin_expect(!!(x), 1)
#define NPY_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define NPY_LIKELY(x) (x)
#define NPY_UNLIKELY(x) (x)
#endif

#ifdef HAVE___BUILTIN_PREFETCH
/* 与 _mm_prefetch 不同,也适用于非 x86 平台 */
#define NPY_PREFETCH(x, rw, loc) __builtin_prefetch((x), (rw), (loc))
#else
#ifdef NPY_HAVE_SSE
/* _MM_HINT_ET[01] (rw = 1) 不支持,仅在 gcc >= 4.9 中可用 */
#define NPY_PREFETCH(x, rw, loc) _mm_prefetch((x), loc == 0 ? _MM_HINT_NTA : \
                                             (loc == 1 ? _MM_HINT_T2 : \
                                              (loc == 2 ? _MM_HINT_T1 : \
                                               (loc == 3 ? _MM_HINT_T0 : -1))))
#else
#define NPY_PREFETCH(x, rw,loc)
#endif
#endif

/* `NPY_INLINE` 为向后兼容性保留;应改用 `inline` */
#if defined(_MSC_VER) && !defined(__clang__)
    #define NPY_INLINE __inline
/* 用于处理 Windows 上的 clang-cl */
#elif defined(__GNUC__) || defined(__clang__)
    #if defined(__STRICT_ANSI__)
         #define NPY_INLINE __inline__
    #else
         #define NPY_INLINE inline
    #endif
#else
    #define NPY_INLINE
#endif

#ifdef _MSC_VER
    #define NPY_FINLINE static __forceinline
#elif defined(__GNUC__)
    #define NPY_FINLINE static inline __attribute__((always_inline))
#else
    // 定义一个宏 NPY_FINLINE,它展开为 static
#ifdef _MSC_VER
    // 如果编译器是 Microsoft Visual C++,定义为静态函数,禁止内联优化,使用__declspec(noinline)修饰
    #define NPY_NOINLINE static __declspec(noinline)
#elif defined(__GNUC__) || defined(__clang__)
    // 如果编译器是 GCC 或 Clang,定义为静态函数,禁止内联优化,使用__attribute__((noinline))修饰
    #define NPY_NOINLINE static __attribute__((noinline))
#else
    // 其他情况下,仅定义为静态函数
    #define NPY_NOINLINE static
#endif

#ifdef __cplusplus
    // 如果是 C++ 编译环境,定义为线程局部存储(thread_local)
    #define NPY_TLS thread_local
#elif defined(HAVE_THREAD_LOCAL)
    // 如果支持标准的线程局部存储,也定义为线程局部存储
    #define NPY_TLS thread_local
#elif defined(HAVE__THREAD_LOCAL)
    // 如果使用 _Thread_local 关键字支持线程局部存储
    #define NPY_TLS _Thread_local
#elif defined(HAVE___THREAD)
    // 如果支持 __thread 关键字的线程局部存储
    #define NPY_TLS __thread
#elif defined(HAVE___DECLSPEC_THREAD_)
    // 如果支持 __declspec(thread) 关键字的线程局部存储
    #define NPY_TLS __declspec(thread)
#else
    // 否则不进行任何特殊的线程局部存储定义
    #define NPY_TLS
#endif

#ifdef WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE
    // 如果定义了特定的返回借用引用的属性,使用 cpychecker_returns_borrowed_ref 修饰
  #define NPY_RETURNS_BORROWED_REF \
    __attribute__((cpychecker_returns_borrowed_ref))
#else
    // 否则不使用任何属性修饰
 #define NPY_RETURNS_BORROWED_REF
#endif

#ifdef WITH_CPYCHECKER_STEALS_REFERENCE_TO_ARG_ATTRIBUTE
    // 如果定义了特定的参数窃取引用的属性,使用 cpychecker_steals_reference_to_arg(n) 修饰
  #define NPY_STEALS_REF_TO_ARG(n) \
   __attribute__((cpychecker_steals_reference_to_arg(n)))
#else
    // 否则不使用任何属性修饰
 #define NPY_STEALS_REF_TO_ARG(n)
#endif

/* 64 bit file position support, also on win-amd64. Issue gh-2256 */
#if defined(_MSC_VER) && defined(_WIN64) && (_MSC_VER > 1400) || \
    defined(__MINGW32__) || defined(__MINGW64__)
    // 如果是在 Microsoft Visual C++ 编译环境下,并且是 64 位 Windows,或者在 MinGW 环境下
    #include <io.h>

    // 定义文件操作为 64 位版本的函数
    #define npy_fseek _fseeki64
    #define npy_ftell _ftelli64
    #define npy_lseek _lseeki64
    // 定义文件偏移量类型为 npy_int64
    #define npy_off_t npy_int64

    // 根据整数类型大小定义 Python 格式化字符串
    #if NPY_SIZEOF_INT == 8
        #define NPY_OFF_T_PYFMT "i"
    #elif NPY_SIZEOF_LONG == 8
        #define NPY_OFF_T_PYFMT "l"
    #elif NPY_SIZEOF_LONGLONG == 8
        #define NPY_OFF_T_PYFMT "L"
    #else
        #error Unsupported size for type off_t
    #endif
#else
#ifdef HAVE_FSEEKO
    // 如果支持 fseeko 函数,定义为 npy_fseek
    #define npy_fseek fseeko
#else
    // 否则定义为标准的 fseek 函数
    #define npy_fseek fseek
#endif
#ifdef HAVE_FTELLO
    // 如果支持 ftello 函数,定义为 npy_ftell
    #define npy_ftell ftello
#else
    // 否则定义为标准的 ftell 函数
    #define npy_ftell ftell
#endif
    // 包含系统类型头文件
    #include <sys/types.h>
    // 非 Windows 环境下包含unistd.h头文件
    #ifndef _WIN32
        #include <unistd.h>
    #endif
    // 定义文件偏移量类型为 off_t
    #define npy_lseek lseek
    #define npy_off_t off_t

    // 根据不同大小的 off_t 定义 Python 格式化字符串
    #if NPY_SIZEOF_OFF_T == NPY_SIZEOF_SHORT
        #define NPY_OFF_T_PYFMT "h"
    #elif NPY_SIZEOF_OFF_T == NPY_SIZEOF_INT
        #define NPY_OFF_T_PYFMT "i"
    #elif NPY_SIZEOF_OFF_T == NPY_SIZEOF_LONG
        #define NPY_OFF_T_PYFMT "l"
    #elif NPY_SIZEOF_OFF_T == NPY_SIZEOF_LONGLONG
        #define NPY_OFF_T_PYFMT "L"
    #else
        #error Unsupported size for type off_t
    #endif
#endif

/* 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 中未定义的大小
#define NPY_SIZEOF_CHAR 1
#define NPY_SIZEOF_BYTE 1
#define NPY_SIZEOF_DATETIME 8
#define NPY_SIZEOF_TIMEDELTA 8
#define NPY_SIZEOF_HALF 2
#define NPY_SIZEOF_CFLOAT NPY_SIZEOF_COMPLEX_FLOAT
#define NPY_SIZEOF_CDOUBLE NPY_SIZEOF_COMPLEX_DOUBLE
/* 定义 NPY_SIZEOF_CLONGDOUBLE 与 NPY_SIZEOF_COMPLEX_LONGDOUBLE 相等 */
#define NPY_SIZEOF_CLONGDOUBLE NPY_SIZEOF_COMPLEX_LONGDOUBLE

/* 如果 constchar 已定义,则取消定义 */
#ifdef constchar
#undef constchar
#endif

/* 定义 NPY_SSIZE_T_PYFMT 为 "n" */
#define NPY_SSIZE_T_PYFMT "n"

/* 将 constchar 定义为 char */
#define constchar char

/* 
 * NPY_INTP_FMT 注意:
 *      不同于其他的 NPY_*_FMT 宏,这些宏用于 PyOS_snprintf,
 *      NPY_INTP_FMT 用于 PyErr_Format 和 PyUnicode_FromFormat。
 *      这些函数使用不同的格式代码,根据 Python 文档进行了便携式指定。
 *      参见 issue gh-2388。
 */
#if NPY_SIZEOF_INTP == NPY_SIZEOF_LONG
        #define NPY_INTP NPY_LONG
        #define NPY_UINTP NPY_ULONG
        #define PyIntpArrType_Type PyLongArrType_Type
        #define PyUIntpArrType_Type PyULongArrType_Type
        #define NPY_MAX_INTP NPY_MAX_LONG
        #define NPY_MIN_INTP NPY_MIN_LONG
        #define NPY_MAX_UINTP NPY_MAX_ULONG
        #define NPY_INTP_FMT "ld"
#elif NPY_SIZEOF_INTP == NPY_SIZEOF_INT
        #define NPY_INTP NPY_INT
        #define NPY_UINTP NPY_UINT
        #define PyIntpArrType_Type PyIntArrType_Type
        #define PyUIntpArrType_Type PyUIntArrType_Type
        #define NPY_MAX_INTP NPY_MAX_INT
        #define NPY_MIN_INTP NPY_MIN_INT
        #define NPY_MAX_UINTP NPY_MAX_UINT
        #define NPY_INTP_FMT "d"
#elif defined(PY_LONG_LONG) && (NPY_SIZEOF_INTP == NPY_SIZEOF_LONGLONG)
        #define NPY_INTP NPY_LONGLONG
        #define NPY_UINTP NPY_ULONGLONG
        #define PyIntpArrType_Type PyLongLongArrType_Type
        #define PyUIntpArrType_Type PyULongLongArrType_Type
        #define NPY_MAX_INTP NPY_MAX_LONGLONG
        #define NPY_MIN_INTP NPY_MIN_LONGLONG
        #define NPY_MAX_UINTP NPY_MAX_ULONGLONG
        #define NPY_INTP_FMT "lld"
#else
    #error "Failed to correctly define NPY_INTP and NPY_UINTP"
#endif

/*
 * 一些平台未定义 bool、long long 或 long double。
 * 在这里进行处理。
 */
#define NPY_BYTE_FMT "hhd"
#define NPY_UBYTE_FMT "hhu"
#define NPY_SHORT_FMT "hd"
#define NPY_USHORT_FMT "hu"
#define NPY_INT_FMT "d"
#define NPY_UINT_FMT "u"
#define NPY_LONG_FMT "ld"
#define NPY_ULONG_FMT "lu"
#define NPY_HALF_FMT "g"
#define NPY_FLOAT_FMT "g"
#define NPY_DOUBLE_FMT "g"

#ifdef PY_LONG_LONG
typedef PY_LONG_LONG npy_longlong;
typedef unsigned PY_LONG_LONG npy_ulonglong;
#  ifdef _MSC_VER
#    define NPY_LONGLONG_FMT         "I64d"
#    define NPY_ULONGLONG_FMT        "I64u"
#  else
#    define NPY_LONGLONG_FMT         "lld"
#    define NPY_ULONGLONG_FMT        "llu"
#  endif
#  ifdef _MSC_VER
#    define NPY_LONGLONG_SUFFIX(x)   (x##i64)
#    define NPY_ULONGLONG_SUFFIX(x)  (x##Ui64)
#  else
#    define NPY_LONGLONG_SUFFIX(x)   (x##LL)
#    define NPY_ULONGLONG_SUFFIX(x)  (x##ULL)
#  endif
#else
typedef long npy_longlong;
typedef unsigned long npy_ulonglong;
#  define NPY_LONGLONG_SUFFIX(x)  (x##L)
#  define NPY_ULONGLONG_SUFFIX(x) (x##UL)
#endif

/* 定义 npy_bool 为 unsigned char,以及 NPY_FALSE 和 NPY_TRUE 的值 */
typedef unsigned char npy_bool;
#define NPY_FALSE 0
#define NPY_TRUE 1
/*
 * `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
#define NPY_FLOAT16 NPY_HALF
// 定义 npy_half 为 npy_uint16
typedef npy_uint16 npy_half;
// 定义 npy_float16 为 npy_half
typedef npy_half npy_float16;

#if NPY_BITSOF_LONGDOUBLE == 32
#ifndef NPY_FLOAT32
// 定义 NPY_FLOAT32 为 NPY_LONGDOUBLE
#define NPY_FLOAT32 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX64 为 NPY_CLONGDOUBLE
#define 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
#define NPY_FLOAT32_FMT NPY_LONGDOUBLE_FMT
#define NPY_COMPLEX64_FMT NPY_CLONGDOUBLE_FMT
#endif
#elif NPY_BITSOF_LONGDOUBLE == 64
#ifndef NPY_FLOAT64
// 定义 NPY_FLOAT64 为 NPY_LONGDOUBLE
#define NPY_FLOAT64 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX128 为 NPY_CLONGDOUBLE
#define 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
#define NPY_FLOAT64_FMT NPY_LONGDOUBLE_FMT
#define NPY_COMPLEX128_FMT NPY_CLONGDOUBLE_FMT
#endif
#elif NPY_BITSOF_LONGDOUBLE == 80
#ifndef NPY_FLOAT80
// 定义 NPY_FLOAT80 为 NPY_LONGDOUBLE
#define NPY_FLOAT80 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX160 为 NPY_CLONGDOUBLE
#define 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
#define NPY_FLOAT80_FMT NPY_LONGDOUBLE_FMT
#define NPY_COMPLEX160_FMT NPY_CLONGDOUBLE_FMT
#endif
#elif NPY_BITSOF_LONGDOUBLE == 96
#ifndef NPY_FLOAT96
// 定义 NPY_FLOAT96 为 NPY_LONGDOUBLE
#define NPY_FLOAT96 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX192 为 NPY_CLONGDOUBLE
#define 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
#define NPY_FLOAT96_FMT NPY_LONGDOUBLE_FMT
#define NPY_COMPLEX192_FMT NPY_CLONGDOUBLE_FMT
#endif
#elif NPY_BITSOF_LONGDOUBLE == 128
#ifndef NPY_FLOAT128
// 定义 NPY_FLOAT128 为 NPY_LONGDOUBLE
#define NPY_FLOAT128 NPY_LONGDOUBLE
// 定义 NPY_COMPLEX256 为 NPY_CLONGDOUBLE
#define 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,则定义一系列与长双精度浮点数相关的宏和类型别名 */
#if NPY_BITSOF_LONGDOUBLE == 128
#define NPY_FLOAT128 NPY_LONGDOUBLE
#define NPY_COMPLEX256 NPY_CLONGDOUBLE
typedef npy_longdouble npy_float128;
typedef npy_clongdouble npy_complex256;
#define PyFloat128ScalarObject PyLongDoubleScalarObject
#define PyComplex256ScalarObject PyCLongDoubleScalarObject
#define PyFloat128ArrType_Type PyLongDoubleArrType_Type
#define PyComplex256ArrType_Type PyCLongDoubleArrType_Type
#define NPY_FLOAT128_FMT NPY_LONGDOUBLE_FMT
#define NPY_COMPLEX256_FMT NPY_CLONGDOUBLE_FMT
#endif

/* 如果 NPY_BITSOF_LONGDOUBLE 宏定义为 256,则定义一系列与长双精度浮点数相关的宏和类型别名 */
#elif NPY_BITSOF_LONGDOUBLE == 256
#define NPY_FLOAT256 NPY_LONGDOUBLE
#define NPY_COMPLEX512 NPY_CLONGDOUBLE
typedef npy_longdouble npy_float256;
typedef npy_clongdouble npy_complex512;
#define PyFloat256ScalarObject PyLongDoubleScalarObject
#define PyComplex512ScalarObject PyCLongDoubleScalarObject
#define PyFloat256ArrType_Type PyLongDoubleArrType_Type
#define PyComplex512ArrType_Type PyCLongDoubleArrType_Type
#define NPY_FLOAT256_FMT NPY_LONGDOUBLE_FMT
#define NPY_COMPLEX512_FMT NPY_CLONGDOUBLE_FMT
#endif

/* datetime 的类型定义 */
typedef npy_int64 npy_timedelta;  // 定义 npy_timedelta 类型为 npy_int64
typedef npy_int64 npy_datetime;   // 定义 npy_datetime 类型为 npy_int64
#define NPY_DATETIME_FMT NPY_INT64_FMT  // 定义日期时间格式为 npy_int64 格式
#define NPY_TIMEDELTA_FMT NPY_INT64_FMT  // 定义时间间隔格式为 npy_int64 格式

/* numarray 风格的位宽命名类型定义结束标志 */
#endif  /* NUMPY_CORE_INCLUDE_NUMPY_NPY_COMMON_H_ */