NumPy-源码解析-七十三-

42 阅读1小时+

NumPy 源码解析(七十三)

.\numpy\numpy\_core\src\multiarray\textreading\tokenize.h

#ifndef NUMPY_CORE_SRC_MULTIARRAY_TEXTREADING_TOKENIZE_H_
#define NUMPY_CORE_SRC_MULTIARRAY_TEXTREADING_TOKENIZE_H_

#include <Python.h>
#include "numpy/ndarraytypes.h"

#include "textreading/stream.h"
#include "textreading/parser_config.h"

#ifdef __cplusplus
extern "C" {
#endif

// 枚举定义不同的解析状态
typedef enum {
    /* Initialization of fields */
    TOKENIZE_INIT,                  // 初始化字段
    TOKENIZE_CHECK_QUOTED,          // 检查引号状态
    /* Main field parsing states */
    TOKENIZE_UNQUOTED,              // 未引用字段解析状态
    TOKENIZE_UNQUOTED_WHITESPACE,

.\numpy\numpy\_core\src\multiarray\usertypes.c

/*
  提供多维数组作为 Python 中的基本对象类型。

  基于原始的 Numeric 实现
  版权所有 (c) 1995, 1996, 1997 Jim Hugunin, hugunin@mit.edu

  同时也包含了许多 Numeric Python 开发者在 1995-2004 年间的贡献

  2005 年大幅修改,受 Numarray 启发

  作者:Travis Oliphant, oliphant@ee.byu.edu
  所属:Brigham Young University

  维护者邮箱:oliphant.travis@ieee.org

  Numarray 的设计思路(提供了指导)来自于
  Space Science Telescope Institute
  (J. Todd Miller, Perry Greenfield, Rick White)
*/
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>

#include "numpy/arrayobject.h"
#include "numpy/arrayscalars.h"

#include "npy_config.h"

#include "common.h"

#include "usertypes.h"
#include "dtypemeta.h"
#include "scalartypes.h"
#include "array_method.h"
#include "convert_datatype.h"
#include "dtype_traversal.h"
#include "legacy_dtype_implementation.h"


/* 
   NPY_NO_EXPORT 表示此函数不会导出到公共 API
   userdescrs 用于保存用户定义的数据描述符
*/
NPY_NO_EXPORT _PyArray_LegacyDescr **userdescrs = NULL;

/*
   功能:向整数数组添加新元素
   参数:p_types - 指向整数数组的指针
         insert - 要插入的整数值
   返回值:成功返回 0,内存分配失败返回 -1
*/
static int
_append_new(int **p_types, int insert)
{
    int n = 0;
    int *newtypes;
    int *types = *p_types;

    // 找到数组中的最后一个元素
    while (types[n] != NPY_NOTYPE) {
        n++;
    }
    // 重新分配内存,以添加新元素
    newtypes = (int *)realloc(types, (n + 2)*sizeof(int));
    if (newtypes == NULL) {
        PyErr_NoMemory(); // 内存分配失败,抛出内存错误异常
        return -1;
    }
    newtypes[n] = insert; // 在数组末尾添加新元素
    newtypes[n + 1] = NPY_NOTYPE;

    /* 替换传入的指针 */
    *p_types = newtypes;
    return 0;
}

/*
   默认的非零判断函数
   功能:检查数组中的元素是否存在非零值
   参数:ip - 数组元素的指针
         arr - 数组对象的指针
   返回值:存在非零元素返回 NPY_TRUE,否则返回 NPY_FALSE
*/
static npy_bool
_default_nonzero(void *ip, void *arr)
{
    int elsize = PyArray_ITEMSIZE(arr); // 获取数组元素的大小
    char *ptr = ip;
    while (elsize--) {
        if (*ptr++ != 0) { // 检查元素是否为非零
            return NPY_TRUE;
        }
    }
    return NPY_FALSE;
}

/*
   默认的复制和交换函数
   功能:将源数组的部分内容复制到目标数组,支持交换字节序
   参数:dst - 目标数组的起始地址
         dstride - 目标数组中相邻元素之间的字节偏移量
         src - 源数组的起始地址
         sstride - 源数组中相邻元素之间的字节偏移量
         n - 要复制的元素个数
         swap - 是否交换字节序的标志
         arr - 数组对象的指针
*/
static void
_default_copyswapn(void *dst, npy_intp dstride, void *src,
                   npy_intp sstride, npy_intp n, int swap, void *arr)
{
    npy_intp i;
    PyArray_CopySwapFunc *copyswap;
    char *dstptr = dst;
    char *srcptr = src;

    copyswap = PyDataType_GetArrFuncs(PyArray_DESCR(arr))->copyswap; // 获取复制和交换函数

    for (i = 0; i < n; i++) {
        copyswap(dstptr, srcptr, swap, arr); // 调用复制和交换函数
        dstptr += dstride; // 移动到下一个目标元素的位置
        srcptr += sstride; // 移动到下一个源元素的位置
    }
}

/*NUMPY_API
  初始化 arrfuncs 结构体,将所有函数指针初始化为 NULL
*/
NPY_NO_EXPORT void
PyArray_InitArrFuncs(PyArray_ArrFuncs *f)
{
    int i;

    for(i = 0; i < NPY_NTYPES_ABI_COMPATIBLE; i++) {
        f->cast[i] = NULL; // 将类型转换函数指针数组初始化为 NULL
    }
    f->getitem = NULL; // 获取元素函数指针初始化为 NULL
    f->setitem = NULL; // 设置元素函数指针初始化为 NULL
    f->copyswapn = NULL; // 复制和交换多个元素函数指针初始化为 NULL
    f->copyswap = NULL; // 复制和交换单个元素函数指针初始化为 NULL
    f->compare = NULL; // 比较函数指针初始化为 NULL
    f->argmax = NULL; // 最大值索引函数指针初始化为 NULL
    f->argmin = NULL; // 最小值索引函数指针初始化为 NULL
    f->dotfunc = NULL; // 点积函数指针初始化为 NULL
    f->scanfunc = NULL; // 扫描函数指针初始化为 NULL
    f->fromstr = NULL; // 字符串转数组函数指针初始化为 NULL
    f->nonzero = NULL; // 非零判断函数指针初始化为 NULL
    f->fill = NULL; // 填充函数指针初始化为 NULL
    f->fillwithscalar = NULL; // 使用标量填充函数指针初始化为 NULL
    for(i = 0; i < NPY_NSORTS; i++) {
        f->sort[i] = NULL; // 排序函数指针数组初始化为 NULL
        f->argsort[i] = NULL; // 获取排序索引函数指针数组初始化为 NULL
    }
    f->castdict = NULL; // 类型转换字典指针初始化为 NULL
    f->scalarkind = NULL; // 标量类型指针初始化为 NULL
    f->cancastscalarkindto = NULL; // 标量类型转换函数指针初始化为 NULL
    f->cancastto = NULL; // 类型转换函数指针初始化为 NULL
    f->_unused1 = NULL; // 未使用的字段1初始化为 NULL
    f->_unused2 = NULL; // 未使用的字段2初始化为 NULL
}
    f->_unused3 = NULL;


    // 将结构体指针 f 的成员变量 _unused3 设置为 NULL
/*
  返回与此类型相关联的类型编号 >=NPY_USERDEF。
  需要arraytypes.inc中定义的userdecrs表和PyArray_NUMUSER变量。
*/
/*NUMPY_API
 * 注册数据类型
 *
 * 从原型创建一个新的描述符。
 *
 * 该原型与NumPy 1.x ABI兼容,在1.x中将用作实际描述符。但由于ABI已更改,这在2.0中无法工作,
 * 我们将所有字段复制到新的结构体中。
 *
 * 成功注册后,代码必须使用`descr = PyArray_DescrFromType(num);`。这与1.x中的使用兼容。
 *
 * 此函数仅在2.x中复制所有内部引用。这应该是不相关的,因为任何内部引用都是不朽的。
*/
NPY_NO_EXPORT int
PyArray_RegisterDataType(PyArray_DescrProto *descr_proto)
{
    int typenum;
    int i;
    PyArray_ArrFuncs *f;

    /* 查看是否已经注册了此类型 */
    for (i = 0; i < NPY_NUMUSERTYPES; i++) {
        if (userdescrs[i]->type_num == descr_proto->type_num) {
            return descr_proto->type_num;
        }
    }
    typenum = NPY_USERDEF + NPY_NUMUSERTYPES;
    if (typenum >= NPY_VSTRING) {
        PyErr_SetString(PyExc_ValueError,
                "Too many user defined dtypes registered");
        return -1;
    }
    descr_proto->type_num = -1;
    if (PyDataType_ISUNSIZED(descr_proto)) {
        PyErr_SetString(PyExc_ValueError, "cannot register a" \
                        "flexible data-type");
        return -1;
    }
    f = descr_proto->f;
    if (f->nonzero == NULL) {
        f->nonzero = _default_nonzero;
    }
    if (f->copyswapn == NULL) {
        f->copyswapn = _default_copyswapn;
    }
    if (f->copyswap == NULL || f->getitem == NULL ||
        f->setitem == NULL) {
        PyErr_SetString(PyExc_ValueError, "a required array function"   \
                        " is missing.");
        return -1;
    }
    if (descr_proto->typeobj == NULL) {
        PyErr_SetString(PyExc_ValueError, "missing typeobject");
        return -1;
    }

    int use_void_clearimpl = 0;
    /*
     * 如果描述符的标志包含 NPY_ITEM_IS_POINTER 或 NPY_ITEM_REFCOUNT 标志位,
     * 表明用户自定义的数据类型实际上不能执行引用计数。然而,存在某些已有的
     * 手段(例如 xpress),它们使用了结构化的方法:
     *     dtype((xpress.var, [('variable', 'O')]))
     * 因此我们必须支持这种情况。但这样的结构必须是常量的(即在注册时固定,
     * 这是对于 `xpress` 而言的情况)。
     */
    use_void_clearimpl = 1;

    /*
     * 如果描述符的 names 或 fields 为 NULL,或者 fields 不是 PyDict 类型,
     * 则抛出错误。这是因为不支持使用 `NPY_ITEM_IS_POINTER` 或 `NPY_ITEM_REFCOUNT`
     * 的旧用户数据类型。只有在注册时硬编码了 names 和 fields 的结构化数据类型才能被创建。
     */
    if (descr_proto->names == NULL || descr_proto->fields == NULL ||
        !PyDict_CheckExact(descr_proto->fields)) {
        PyErr_Format(PyExc_ValueError,
                "Failed to register dtype for %S: Legacy user dtypes "
                "using `NPY_ITEM_IS_POINTER` or `NPY_ITEM_REFCOUNT` are "
                "unsupported.  It is possible to create such a dtype only "
                "if it is a structured dtype with names and fields "
                "hardcoded at registration time.\n"
                "Please contact the NumPy developers if this used to work "
                "but now fails.", descr_proto->typeobj);
        return -1;
    }

    /*
     * 扩展 userdescrs 数组,以便容纳新的用户数据类型描述符。
     * 如果内存分配失败,则返回内存错误。
     */
    userdescrs = realloc(userdescrs,
                         (NPY_NUMUSERTYPES+1)*sizeof(void *));
    if (userdescrs == NULL) {
        PyErr_SetString(PyExc_MemoryError, "RegisterDataType");
        return -1;
    }

    /*
     * 由于旧用户数据类型类无法具有名称(因为用户从未定义过名称),
     * 我们在这里为其创建一个名称。这些数据类型在本质上是静态类型。
     *
     * 注意:我们没有意图再次释放这段内存,因为这与静态类型定义的行为完全一致。
     */
    const char *scalar_name = descr_proto->typeobj->tp_name;

    /*
     * 为了获得一个合理的 __name__,我们必须仅获取名称,并忽略模块部分,
     * 这是因为静态类型在这方面受到限制(尽管这不是理想的,但在实践中并不是一个大问题)。
     * 这就是 Python 用于打印静态类型 __name__ 的方法。
     */
    const char *dot = strrchr(scalar_name, '.');
    if (dot) {
        scalar_name = dot + 1;
    }
    Py_ssize_t name_length = strlen(scalar_name) + 14;

    /*
     * 分配内存并格式化名称字符串,格式为 "numpy.dtype[类型名]"。
     * 如果内存分配失败,则返回内存错误。
     */
    char *name = PyMem_Malloc(name_length);
    if (name == NULL) {
        PyErr_NoMemory();
        return -1;
    }
    snprintf(name, name_length, "numpy.dtype[%s]", scalar_name);

    /*
     * 将用户提供的描述符结构体复制到一个新的结构体中。这样做是为了允许两者之间的布局不同。
     * 如果内存分配失败,则释放已分配的名称内存并返回内存错误。
     */
    _PyArray_LegacyDescr *descr = PyObject_Malloc(sizeof(_PyArray_LegacyDescr));
    if (descr == NULL) {
        PyMem_FREE(name);
        PyErr_NoMemory();
        return -1;
    }
    PyObject_INIT(descr, Py_TYPE(descr_proto));

    /*
     * 简单地按名称复制所有字段:
     * 增加类型对象的引用计数,设置类型对象和类型的种类。
     */
    Py_XINCREF(descr_proto->typeobj);
    descr->typeobj = descr_proto->typeobj;
    descr->kind = descr_proto->kind;
    // 将描述符的类型设置为原型描述符的类型
    descr->type = descr_proto->type;
    // 将描述符的字节顺序设置为原型描述符的字节顺序
    descr->byteorder = descr_proto->byteorder;
    // 将描述符的标志设置为原型描述符的标志
    descr->flags = descr_proto->flags;
    // 将描述符的元素大小设置为原型描述符的元素大小
    descr->elsize = descr_proto->elsize;
    // 将描述符的对齐方式设置为原型描述符的对齐方式
    descr->alignment = descr_proto->alignment;
    // 将描述符的子数组设置为原型描述符的子数组
    descr->subarray = descr_proto->subarray;
    // 增加原型描述符的字段的引用计数并将其赋给描述符的字段
    Py_XINCREF(descr_proto->fields);
    descr->fields = descr_proto->fields;
    // 增加原型描述符的名称的引用计数并将其赋给描述符的名称
    Py_XINCREF(descr_proto->names);
    descr->names = descr_proto->names;
    // 增加原型描述符的元数据的引用计数并将其赋给描述符的元数据
    Py_XINCREF(descr_proto->metadata);
    descr->metadata = descr_proto->metadata;
    // 如果原型描述符的 C 元数据不为空,则克隆它并赋给描述符的 C 元数据;否则置空描述符的 C 元数据
    if (descr_proto->c_metadata != NULL) {
        descr->c_metadata = NPY_AUXDATA_CLONE(descr_proto->c_metadata);
    }
    else {
        descr->c_metadata = NULL;
    }
    // 将描述符的哈希值置为无效值(假定字段未设置)
    descr->hash = -1;

    // 将描述符添加到用户描述符数组中,并增加用户描述符数量计数
    userdescrs[NPY_NUMUSERTYPES++] = descr;

    // 将描述符的类型编号设置为指定的类型编号
    descr->type_num = typenum;
    // 更新原型描述符的类型编号以便于检测重复注册
    descr_proto->type_num = typenum;
    // 尝试包装旧版本的描述符以处理遗留描述符,如果失败则进行回滚
    if (dtypemeta_wrap_legacy_descriptor(
            descr, descr_proto->f, &PyArrayDescr_Type, name, NULL) < 0) {
        descr->type_num = -1;
        NPY_NUMUSERTYPES--;
        // 覆盖描述符的类型,防止错误导致解除引用崩溃
        Py_SET_TYPE(descr, &PyArrayDescr_Type);
        Py_DECREF(descr);
        PyMem_Free(name);  // 只有在失败时释放名称
        return -1;
    }
    // 如果使用了 void_clearimpl,则设置相应的清除和零填充循环
    if (use_void_clearimpl) {
        // 设置清除循环函数指针
        NPY_DT_SLOTS(NPY_DTYPE(descr))->get_clear_loop = (
                (PyArrayMethod_GetTraverseLoop *)&npy_get_clear_void_and_legacy_user_dtype_loop);
        // 设置零填充循环函数指针
        NPY_DT_SLOTS(NPY_DTYPE(descr))->get_fill_zero_loop = (
                (PyArrayMethod_GetTraverseLoop *)&npy_get_zerofill_void_and_legacy_user_dtype_loop);
    }

    // 返回设置的类型编号
    return typenum;
/*
 * 检查是否已经使用新的转换实现机制缓存了转换。
 * 如果是,则不清空缓存(但是会默默地继续)。用户在使用后不应修改转换,
 * 但这可能在设置过程中意外发生(也可能从未发生)。参见 https://github.com/numpy/numpy/issues/20009
 */
static int _warn_if_cast_exists_already(
        PyArray_Descr *descr, int totype, char *funcname)
{
    // 从类型编号获取对应的数据类型元数据对象
    PyArray_DTypeMeta *to_DType = PyArray_DTypeFromTypeNum(totype);
    if (to_DType == NULL) {
        return -1;
    }
    // 从字典中获取对应转换实现的对象
    PyObject *cast_impl = PyDict_GetItemWithError(
            NPY_DT_SLOTS(NPY_DTYPE(descr))->castingimpls, (PyObject *)to_DType);
    Py_DECREF(to_DType);
    if (cast_impl == NULL) {
        if (PyErr_Occurred()) {
            return -1;
        }
    }
    else {
        // 如果获取到转换实现对象
        char *extra_msg;
        if (cast_impl == Py_None) {
            extra_msg = "the cast will continue to be considered impossible.";
        }
        else {
            extra_msg = "the previous definition will continue to be used.";
        }
        Py_DECREF(cast_impl);
        // 根据类型编号获取对应的描述符对象
        PyArray_Descr *to_descr = PyArray_DescrFromType(totype);
        // 发出运行时警告,说明转换注册/修改发生在使用后
        int ret = PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
                "A cast from %R to %R was registered/modified using `%s` "
                "after the cast had been used.  "
                "This registration will have (mostly) no effect: %s\n"
                "The most likely fix is to ensure that casts are the first "
                "thing initialized after dtype registration.  "
                "Please contact the NumPy developers with any questions!",
                descr, to_descr, funcname, extra_msg);
        Py_DECREF(to_descr);
        if (ret < 0) {
            return -1;
        }
    }
    return 0;
}

/*
 * NUMPY_API
 * 注册转换函数
 * 替换当前存储的任何函数。
 */
NPY_NO_EXPORT int
PyArray_RegisterCastFunc(PyArray_Descr *descr, int totype,
                         PyArray_VectorUnaryFunc *castfunc)
{
    PyObject *cobj, *key;
    int ret;

    // 检查类型编号是否有效
    if (totype >= NPY_NTYPES_LEGACY && !PyTypeNum_ISUSERDEF(totype)) {
        PyErr_SetString(PyExc_TypeError, "invalid type number.");
        return -1;
    }
    // 检查是否已经存在相同转换的警告
    if (_warn_if_cast_exists_already(
            descr, totype, "PyArray_RegisterCastFunc") < 0) {
        return -1;
    }

    // 如果类型编号小于 NPY_NTYPES_ABI_COMPATIBLE,直接设置转换函数
    if (totype < NPY_NTYPES_ABI_COMPATIBLE) {
        PyDataType_GetArrFuncs(descr)->cast[totype] = castfunc;
        return 0;
    }
    // 如果转换函数字典尚未初始化,初始化它
    if (PyDataType_GetArrFuncs(descr)->castdict == NULL) {
        PyDataType_GetArrFuncs(descr)->castdict = PyDict_New();
        if (PyDataType_GetArrFuncs(descr)->castdict == NULL) {
            return -1;
        }
    }
    // 创建用于作为字典键的 Python 整数对象
    key = PyLong_FromLong(totype);
    if (PyErr_Occurred()) {
        return -1;
    }
    // 创建转换函数对象的 Capsule 对象
    cobj = PyCapsule_New((void *)castfunc, NULL, NULL);
    if (cobj == NULL) {
        Py_DECREF(key);
        return -1;
    }
    # 调用 PyDataType_GetArrFuncs 函数获取描述符的数组函数字典(castdict),并向其中添加键值对
    ret = PyDict_SetItem(PyDataType_GetArrFuncs(descr)->castdict, key, cobj);
    # 减少键对象 key 的引用计数,可能会释放其内存
    Py_DECREF(key);
    # 减少值对象 cobj 的引用计数,可能会释放其内存
    Py_DECREF(cobj);
    # 返回 PyDict_SetItem 函数的执行结果,通常表示操作是否成功
    return ret;
/*NUMPY_API
 * Register a type number indicating that a descriptor can be cast
 * to it safely
 */
NPY_NO_EXPORT int
PyArray_RegisterCanCast(PyArray_Descr *descr, int totype,
                        NPY_SCALARKIND scalar)
{
    /*
     * 如果允许这样做,内置类型的类型转换查找表需要修改,
     * 因为对于它们,不会检查 cancastto。
     */
    if (!PyTypeNum_ISUSERDEF(descr->type_num) &&
                                        !PyTypeNum_ISUSERDEF(totype)) {
        PyErr_SetString(PyExc_ValueError,
                        "At least one of the types provided to "
                        "RegisterCanCast must be user-defined.");
        return -1;
    }
    if (_warn_if_cast_exists_already(
            descr, totype, "PyArray_RegisterCanCast") < 0) {
        return -1;
    }

    if (scalar == NPY_NOSCALAR) {
        /*
         * 使用 cancastto 进行注册
         * 这些列表一旦创建就不会被释放
         * —— 它们成为数据类型的一部分
         */
        if (PyDataType_GetArrFuncs(descr)->cancastto == NULL) {
            PyDataType_GetArrFuncs(descr)->cancastto = (int *)malloc(1*sizeof(int));
            if (PyDataType_GetArrFuncs(descr)->cancastto == NULL) {
                PyErr_NoMemory();
                return -1;
            }
            PyDataType_GetArrFuncs(descr)->cancastto[0] = NPY_NOTYPE;
        }
        return _append_new(&PyDataType_GetArrFuncs(descr)->cancastto, totype);
    }
    else {
        /* 使用 cancastscalarkindto 进行注册 */
        if (PyDataType_GetArrFuncs(descr)->cancastscalarkindto == NULL) {
            int i;
            PyDataType_GetArrFuncs(descr)->cancastscalarkindto =
                (int **)malloc(NPY_NSCALARKINDS* sizeof(int*));
            if (PyDataType_GetArrFuncs(descr)->cancastscalarkindto == NULL) {
                PyErr_NoMemory();
                return -1;
            }
            for (i = 0; i < NPY_NSCALARKINDS; i++) {
                PyDataType_GetArrFuncs(descr)->cancastscalarkindto[i] = NULL;
            }
        }
        if (PyDataType_GetArrFuncs(descr)->cancastscalarkindto[scalar] == NULL) {
            PyDataType_GetArrFuncs(descr)->cancastscalarkindto[scalar] =
                (int *)malloc(1*sizeof(int));
            if (PyDataType_GetArrFuncs(descr)->cancastscalarkindto[scalar] == NULL) {
                PyErr_NoMemory();
                return -1;
            }
            PyDataType_GetArrFuncs(descr)->cancastscalarkindto[scalar][0] =
                NPY_NOTYPE;
        }
        return _append_new(&PyDataType_GetArrFuncs(descr)->cancastscalarkindto[scalar], totype);
    }
}
// 定义 legacy_userdtype_common_dtype_function 函数,参数为两个 PyArray_DTypeMeta 类型的指针
legacy_userdtype_common_dtype_function(
        PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other)
{
    // 初始化 skind1 和 skind2 为 NPY_NOSCALAR
    int skind1 = NPY_NOSCALAR, skind2 = NPY_NOSCALAR, skind;

    // 如果 other 不是 legacy 类型,则可以始终退化为新样式类型
    if (!NPY_DT_is_legacy(other)) {
        // 增加 Py_NotImplemented 的引用计数,并返回 Py_NotImplemented 指针
        Py_INCREF(Py_NotImplemented);
        return (PyArray_DTypeMeta *)Py_NotImplemented;
    }
    
    // 推迟处理,以便只有一种类型处理转换
    if (cls->type_num < other->type_num) {
        // 增加 Py_NotImplemented 的引用计数,并返回 Py_NotImplemented 指针
        Py_INCREF(Py_NotImplemented);
        return (PyArray_DTypeMeta *)Py_NotImplemented;
    }

    // 检查是否可以安全地从一种类型转换为另一种类型
    if (PyArray_CanCastSafely(cls->type_num, other->type_num)) {
        // 增加 other 的引用计数,并返回 other 指针
        Py_INCREF(other);
        return other;
    }
    if (PyArray_CanCastSafely(other->type_num, cls->type_num)) {
        // 增加 cls 的引用计数,并返回 cls 指针
        Py_INCREF(cls);
        return cls;
    }

    /*
     * 以下代码曾是 PyArray_PromoteTypes() 的一部分。
     * 可以预期这段代码不会被使用。
     * 实际上,它允许将两种不同的用户定义类型提升为相同 "kind" 的 NumPy 类型。
     * 在实践中,由于 PyArray_EquivTypes(descr1, descr2) 的简化,使用与 NumPy 相同的 `kind` 从未可能。
     * 如果 kind 和元素大小匹配,则 PyArray_EquivTypes(descr1, descr2) 返回 True(例如,bfloat16 和 float16 将等效)。
     * 这个选项也非常难以理解,并且在示例中没有使用。
     */

    // 将 'kind' 字符转换为标量 kind
    switch (cls->singleton->kind) {
        case 'b':
            skind1 = NPY_BOOL_SCALAR;
            break;
        case 'u':
            skind1 = NPY_INTPOS_SCALAR;
            break;
        case 'i':
            skind1 = NPY_INTNEG_SCALAR;
            break;
        case 'f':
            skind1 = NPY_FLOAT_SCALAR;
            break;
        case 'c':
            skind1 = NPY_COMPLEX_SCALAR;
            break;
    }
    switch (other->singleton->kind) {
        case 'b':
            skind2 = NPY_BOOL_SCALAR;
            break;
        case 'u':
            skind2 = NPY_INTPOS_SCALAR;
            break;
        case 'i':
            skind2 = NPY_INTNEG_SCALAR;
            break;
        case 'f':
            skind2 = NPY_FLOAT_SCALAR;
            break;
        case 'c':
            skind2 = NPY_COMPLEX_SCALAR;
            break;
    }

    // 如果两者都是标量,可能会存在一种提升的可能性
    # 如果两个标量类型都不是 NPY_NOSCALAR
    if (skind1 != NPY_NOSCALAR && skind2 != NPY_NOSCALAR) {

        # 选择较大的标量类型作为起点
        skind = (skind1 > skind2) ? skind1 : skind2;
        
        # 根据较大标量类型确定最小的可以表示该类型的数据类型
        int ret_type_num = _npy_smallest_type_of_kind_table[skind];

        # 无限循环,直到找到合适的数据类型或者确认没有更大的类型
        for (;;) {

            # 如果没有该种类的更大数据类型,则尝试下一个更大的种类
            if (ret_type_num < 0) {
                ++skind;
                # 使用 -1 表示未找到更大的推广类型
                if (skind < NPY_NSCALARKINDS) {
                    ret_type_num = _npy_smallest_type_of_kind_table[skind];
                }
                else {
                    break;
                }
            }

            # 如果找到一个既能安全转换当前类的类型又能安全转换另一个类的类型,则完成
            if (PyArray_CanCastSafely(cls->type_num, ret_type_num) &&
                PyArray_CanCastSafely(other->type_num, ret_type_num)) {
                return PyArray_DTypeFromTypeNum(ret_type_num);
            }

            # 尝试当前种类的下一个更大的数据类型
            ret_type_num = _npy_next_larger_type_table[ret_type_num];
        }
    }

    # 如果两个标量类型中有任意一个是 NPY_NOSCALAR,则返回 Py_NotImplemented
    Py_INCREF(Py_NotImplemented);
    return (PyArray_DTypeMeta *)Py_NotImplemented;
/**
 * This function wraps a legacy cast into an array-method. This is mostly
 * used for legacy user-dtypes, but for example numeric to/from datetime
 * casts were only defined that way as well.
 *
 * @param from Source data type metadata for casting.
 * @param to Target data type metadata for casting.
 * @param casting Casting behavior specifier: `NPY_NO_CASTING` checks the legacy
 *        registered cast, otherwise uses the provided cast.
 */
NPY_NO_EXPORT int
PyArray_AddLegacyWrapping_CastingImpl(
        PyArray_DTypeMeta *from, PyArray_DTypeMeta *to, NPY_CASTING casting)
{
    // Determine the casting behavior if not explicitly provided
    if (casting < 0) {
        // Check if source and target types are the same
        if (from == to) {
            casting = NPY_NO_CASTING;
        }
        // Check for safe casting capability
        else if (PyArray_LegacyCanCastTypeTo(
                from->singleton, to->singleton, NPY_SAFE_CASTING)) {
            casting = NPY_SAFE_CASTING;
        }
        // Check for same-kind casting capability
        else if (PyArray_LegacyCanCastTypeTo(
                from->singleton, to->singleton, NPY_SAME_KIND_CASTING)) {
            casting = NPY_SAME_KIND_CASTING;
        }
        // Default to unsafe casting if no other options are suitable
        else {
            casting = NPY_UNSAFE_CASTING;
        }
    }

    // Prepare an array method specification for legacy casting
    PyArray_DTypeMeta *dtypes[2] = {from, to};
    PyArrayMethod_Spec spec = {
            /* Name is not actually used, but allows identifying these. */
            .name = "legacy_cast",
            .nin = 1,
            .nout = 1,
            .casting = casting,
            .dtypes = dtypes,
    };

    // Define method flags and slots based on whether types are identical or not
    if (from == to) {
        spec.flags = NPY_METH_REQUIRES_PYAPI | NPY_METH_SUPPORTS_UNALIGNED;
        // Define slots for identical type casting
        PyType_Slot slots[] = {
            {NPY_METH_get_loop, &legacy_cast_get_strided_loop},
            {NPY_METH_resolve_descriptors, &legacy_same_dtype_resolve_descriptors},
            {0, NULL}};
        spec.slots = slots;
        // Add the casting implementation using the specified method specification
        return PyArray_AddCastingImplementation_FromSpec(&spec, 1);
    }
    else {
        spec.flags = NPY_METH_REQUIRES_PYAPI;
        // Define slots for different type casting
        PyType_Slot slots[] = {
            {NPY_METH_get_loop, &legacy_cast_get_strided_loop},
            {NPY_METH_resolve_descriptors, &simple_cast_resolve_descriptors},
            {0, NULL}};
        spec.slots = slots;
        // Add the casting implementation using the specified method specification
        return PyArray_AddCastingImplementation_FromSpec(&spec, 1);
    }
}

.\numpy\numpy\_core\src\multiarray\usertypes.h

#ifndef NUMPY_CORE_SRC_MULTIARRAY_USERTYPES_H_
#define NUMPY_CORE_SRC_MULTIARRAY_USERTYPES_H_

#include "array_method.h"  // 包含另一个头文件 "array_method.h"

extern NPY_NO_EXPORT _PyArray_LegacyDescr **userdescrs;  // 声明一个名为 userdescrs 的外部全局变量,类型为 _PyArray_LegacyDescr**,在其他文件中可见

// 初始化数组函数指针数组结构体
NPY_NO_EXPORT void
PyArray_InitArrFuncs(PyArray_ArrFuncs *f);

// 注册能够进行类型转换的方法
NPY_NO_EXPORT int
PyArray_RegisterCanCast(PyArray_Descr *descr, int totype,
                        NPY_SCALARKIND scalar);

// 注册数据类型描述符
NPY_NO_EXPORT int
PyArray_RegisterDataType(PyArray_DescrProto *descr);

// 注册类型转换函数
NPY_NO_EXPORT int
PyArray_RegisterCastFunc(PyArray_Descr *descr, int totype,
                         PyArray_VectorUnaryFunc *castfunc);

// 用于确定两个用户定义数据类型的公共数据类型
NPY_NO_EXPORT PyArray_DTypeMeta *
legacy_userdtype_common_dtype_function(
        PyArray_DTypeMeta *cls, PyArray_DTypeMeta *other);

// 添加旧版包装的转换实现
NPY_NO_EXPORT int
PyArray_AddLegacyWrapping_CastingImpl(
        PyArray_DTypeMeta *from, PyArray_DTypeMeta *to, NPY_CASTING casting);

#endif  /* NUMPY_CORE_SRC_MULTIARRAY_USERTYPES_H_ */

.\numpy\numpy\_core\src\multiarray\vdot.c

/*
 * 定义宏,禁用已弃用的 NumPy API,并指定使用当前版本的 API
 * 定义宏,指示要包含 multiarray 模块
 */
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE

/*
 * 定义宏,确保在包含 Python.h 之前清理 PY_SSIZE_T 的定义
 * 包含 Python.h 头文件,提供 Python C API 的支持
 */
#define PY_SSIZE_T_CLEAN
#include <Python.h>

/*
 * 包含常用函数的头文件
 * 包含向量点积相关函数的头文件
 * 包含与 numpy 的 CBLAS 接口相关的头文件
 */
#include "common.h"
#include "vdot.h"
#include "npy_cblas.h"


/*
 * 所有数据假定是对齐的。
 * 计算复数浮点数向量点积的函数
 */
NPY_NO_EXPORT void
CFLOAT_vdot(char *ip1, npy_intp is1, char *ip2, npy_intp is2,
            char *op, npy_intp n, void *NPY_UNUSED(ignore))
{
#if defined(HAVE_CBLAS)
    // 计算每个输入向量的步长,确保对齐
    CBLAS_INT is1b = blas_stride(is1, sizeof(npy_cfloat));
    CBLAS_INT is2b = blas_stride(is2, sizeof(npy_cfloat));

    // 如果步长均合法,则使用 CBLAS 函数计算点积
    if (is1b && is2b) {
        // 使用双精度浮点数数组保持计算稳定性
        double sum[2] = {0., 0.};

        // 循环计算向量点积,使用块处理以提高效率
        while (n > 0) {
            // 确定当前处理的块大小
            CBLAS_INT chunk = n < NPY_CBLAS_CHUNK ? n : NPY_CBLAS_CHUNK;
            float tmp[2];

            // 调用 CBLAS 函数计算向量点积的实部和虚部
            CBLAS_FUNC(cblas_cdotc_sub)((CBLAS_INT)n, ip1, is1b, ip2, is2b, tmp);
            sum[0] += (double)tmp[0];
            sum[1] += (double)tmp[1];

            // 根据步长更新指针位置,准备处理下一个块
            ip1 += chunk * is1;
            ip2 += chunk * is2;
            n -= chunk;
        }

        // 将计算结果存入输出数组中
        ((float *)op)[0] = (float)sum[0];
        ((float *)op)[1] = (float)sum[1];
    }
    // 如果步长不合法,则使用简单的循环计算向量点积
    else
#endif
    {
        // 初始化实部和虚部的和
        float sumr = (float)0.0;
        float sumi = (float)0.0;
        npy_intp i;

        // 循环计算向量点积的实部和虚部
        for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
            // 提取每个向量元素的实部和虚部
            const float ip1r = ((float *)ip1)[0];
            const float ip1i = ((float *)ip1)[1];
            const float ip2r = ((float *)ip2)[0];
            const float ip2i = ((float *)ip2)[1];

            // 计算向量点积的实部和虚部
            sumr += ip1r * ip2r + ip1i * ip2i;
            sumi += ip1r * ip2i - ip1i * ip2r;
        }

        // 将计算结果存入输出数组中
        ((float *)op)[0] = sumr;
        ((float *)op)[1] = sumi;
    }
}


/*
 * 所有数据假定是对齐的。
 * 计算双精度复数向量点积的函数
 */
NPY_NO_EXPORT void
CDOUBLE_vdot(char *ip1, npy_intp is1, char *ip2, npy_intp is2,
             char *op, npy_intp n, void *NPY_UNUSED(ignore))
{
#if defined(HAVE_CBLAS)
    // 计算每个输入向量的步长,确保对齐
    CBLAS_INT is1b = blas_stride(is1, sizeof(npy_cdouble));
    CBLAS_INT is2b = blas_stride(is2, sizeof(npy_cdouble));

    // 如果步长均合法,则使用 CBLAS 函数计算点积
    if (is1b && is2b) {
        // 使用双精度浮点数数组保持计算稳定性
        double sum[2] = {0., 0.};

        // 循环计算向量点积,使用块处理以提高效率
        while (n > 0) {
            // 确定当前处理的块大小
            CBLAS_INT chunk = n < NPY_CBLAS_CHUNK ? n : NPY_CBLAS_CHUNK;
            double tmp[2];

            // 调用 CBLAS 函数计算向量点积的实部和虚部
            CBLAS_FUNC(cblas_zdotc_sub)((CBLAS_INT)n, ip1, is1b, ip2, is2b, tmp);
            sum[0] += (double)tmp[0];
            sum[1] += (double)tmp[1];

            // 根据步长更新指针位置,准备处理下一个块
            ip1 += chunk * is1;
            ip2 += chunk * is2;
            n -= chunk;
        }

        // 将计算结果存入输出数组中
        ((double *)op)[0] = (double)sum[0];
        ((double *)op)[1] = (double)sum[1];
    }
    // 如果步长不合法,则使用简单的循环计算向量点积
    else
#endif
    {
        // 初始化实部和虚部的总和为0
        double sumr = (double)0.0;
        double sumi = (double)0.0;
        // 循环迭代器
        npy_intp i;
    
        // 遍历从0到n的范围
        for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
            // 提取ip1和ip2的实部和虚部
            const double ip1r = ((double *)ip1)[0];
            const double ip1i = ((double *)ip1)[1];
            const double ip2r = ((double *)ip2)[0];
            const double ip2i = ((double *)ip2)[1];
    
            // 计算实部和虚部的加权和
            sumr += ip1r * ip2r + ip1i * ip2i;
            // 计算实部和虚部的差值
            sumi += ip1r * ip2i - ip1i * ip2r;
        }
        // 将累积的实部和虚部写入op的内存位置
        ((double *)op)[0] = sumr;
        ((double *)op)[1] = sumi;
    }
/*
 * 该函数计算复数向量的内积,并将结果存储在输出数组中。
 * 输入参数 ip1 和 ip2 是输入数组的指针,is1 和 is2 是它们的步长。
 * 输出参数 op 是输出数组的指针,n 是数组的长度。
 * ignore 参数未使用。
 */
NPY_NO_EXPORT void
CLONGDOUBLE_vdot(char *ip1, npy_intp is1, char *ip2, npy_intp is2,
                 char *op, npy_intp n, void *NPY_UNUSED(ignore))
{
    // 初始化实部和虚部的临时变量为0
    npy_longdouble tmpr = 0.0L;
    npy_longdouble tmpi = 0.0L;
    npy_intp i;

    // 循环计算复数向量的内积
    for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
        // 从输入数组中读取复数的实部和虚部
        const npy_longdouble ip1r = ((npy_longdouble *)ip1)[0];
        const npy_longdouble ip1i = ((npy_longdouble *)ip1)[1];
        const npy_longdouble ip2r = ((npy_longdouble *)ip2)[0];
        const npy_longdouble ip2i = ((npy_longdouble *)ip2)[1];

        // 计算复数向量的实部和虚部的内积
        tmpr += ip1r * ip2r + ip1i * ip2i;
        tmpi += ip1r * ip2i - ip1i * ip2r;
    }
    // 将计算结果存储到输出数组中
    ((npy_longdouble *)op)[0] = tmpr;
    ((npy_longdouble *)op)[1] = tmpi;
}

/*
 * 该函数计算对象数组的点积(dot product),并将结果存储在输出对象中。
 * 输入参数 ip1 和 ip2 是输入对象数组的指针,is1 和 is2 是它们的步长。
 * 输出参数 op 是输出对象的指针,n 是对象数组的长度。
 * ignore 参数未使用。
 */
NPY_NO_EXPORT void
OBJECT_vdot(char *ip1, npy_intp is1, char *ip2, npy_intp is2, char *op, npy_intp n,
            void *NPY_UNUSED(ignore))
{
    npy_intp i;
    PyObject *tmp0, *tmp1, *tmp2, *tmp = NULL;
    PyObject **tmp3;

    // 循环计算对象数组的点积
    for (i = 0; i < n; i++, ip1 += is1, ip2 += is2) {
        // 检查输入对象是否为空
        if ((*((PyObject **)ip1) == NULL) || (*((PyObject **)ip2) == NULL)) {
            tmp1 = Py_False;
            Py_INCREF(Py_False);  // 增加 Py_False 的引用计数
        }
        else {
            // 调用第一个对象的 conjugate 方法
            tmp0 = PyObject_CallMethod(*((PyObject **)ip1), "conjugate", NULL);
            if (tmp0 == NULL) {
                Py_XDECREF(tmp);  // 减少临时对象的引用计数
                return;
            }
            // 计算两个对象的乘积
            tmp1 = PyNumber_Multiply(tmp0, *((PyObject **)ip2));
            Py_DECREF(tmp0);  // 减少临时对象的引用计数
            if (tmp1 == NULL) {
                Py_XDECREF(tmp);  // 减少临时对象的引用计数
                return;
            }
        }
        // 更新临时对象的引用
        if (i == 0) {
            tmp = tmp1;
        }
        else {
            tmp2 = PyNumber_Add(tmp, tmp1);
            Py_XDECREF(tmp);  // 减少临时对象的引用计数
            Py_XDECREF(tmp1);  // 减少临时对象的引用计数
            if (tmp2 == NULL) {
                return;
            }
            tmp = tmp2;
        }
    }
    // 将最终的临时对象赋值给输出对象
    tmp3 = (PyObject**) op;
    tmp2 = *tmp3;
    *((PyObject **)op) = tmp;
    Py_XDECREF(tmp2);  // 减少临时对象的引用计数
}

.\numpy\numpy\_core\src\multiarray\vdot.h

#ifndef NUMPY_CORE_SRC_MULTIARRAY_VDOT_H_
#define NUMPY_CORE_SRC_MULTIARRAY_VDOT_H_

// 包含 "common.h" 头文件,这是当前头文件的依赖文件
#include "common.h"

// 声明 CFLOAT_vdot 函数,计算复数浮点数向量的点积
NPY_NO_EXPORT void
CFLOAT_vdot(char *, npy_intp, char *, npy_intp, char *, npy_intp, void *);

// 声明 CDOUBLE_vdot 函数,计算双精度浮点数向量的点积
NPY_NO_EXPORT void
CDOUBLE_vdot(char *, npy_intp, char *, npy_intp, char *, npy_intp, void *);

// 声明 CLONGDOUBLE_vdot 函数,计算长双精度浮点数向量的点积
NPY_NO_EXPORT void
CLONGDOUBLE_vdot(char *, npy_intp, char *, npy_intp, char *, npy_intp, void *);

// 声明 OBJECT_vdot 函数,计算对象类型向量的点积
NPY_NO_EXPORT void
OBJECT_vdot(char *, npy_intp, char *, npy_intp, char *, npy_intp, void *);

// 结束条件:关闭 NUMPY_CORE_SRC_MULTIARRAY_VDOT_H_ 宏定义
#endif  /* NUMPY_CORE_SRC_MULTIARRAY_VDOT_H_ */

.\numpy\numpy\_core\src\multiarray\_datetime.h

#ifndef NUMPY_CORE_SRC_MULTIARRAY__DATETIME_H_
#define NUMPY_CORE_SRC_MULTIARRAY__DATETIME_H_

// 外部声明 datetime 字符串数组,用于存储日期时间单元字符串
extern NPY_NO_EXPORT char const *_datetime_strings[NPY_DATETIME_NUMUNITS];

// 外部声明 _days_per_month_table,用于存储每月天数的表格
extern NPY_NO_EXPORT int _days_per_month_table[2][12];

// 导入 Python 中的 datetime 模块
NPY_NO_EXPORT void
numpy_pydatetime_import(void);

/*
 * 如果给定的年份是闰年则返回 1,否则返回 0。
 */
NPY_NO_EXPORT int
is_leapyear(npy_int64 year);

/*
 * 计算从 1970 年纪元开始到指定日期时间结构的天数偏移量。
 */
NPY_NO_EXPORT npy_int64
get_datetimestruct_days(const npy_datetimestruct *dts);

/*
 * 使用提供的元数据创建 datetime 或 timedelta 类型的 dtype。
 */
NPY_NO_EXPORT PyArray_Descr *
create_datetime_dtype(int type_num, PyArray_DatetimeMetaData *meta);

/*
 * 使用给定的单元创建 datetime 或 timedelta 类型的 dtype。
 */
NPY_NO_EXPORT PyArray_Descr *
create_datetime_dtype_with_unit(int type_num, NPY_DATETIMEUNIT unit);

/*
 * 返回 datetime dtype 中包含的 DateTimeMetaData 指针。
 */
NPY_NO_EXPORT PyArray_DatetimeMetaData *
get_datetime_metadata_from_dtype(PyArray_Descr *dtype);

/*
 * 在数组中查找与 datetime64 类型匹配的字符串类型。
 */
NPY_NO_EXPORT int
find_string_array_datetime64_type(PyArrayObject *arr,
        PyArray_DatetimeMetaData *meta);

/*
 * type1 和 type2 必须是 NPY_DATETIME 或 NPY_TIMEDELTA。
 * 应用类型提升规则,返回提升后的类型。
 */
NPY_NO_EXPORT PyArray_Descr *
datetime_type_promotion(PyArray_Descr *type1, PyArray_Descr *type2);

/*
 * 从 'datetime64[D]' 值中提取当前年份内的月份编号。1 表示一月,以此类推。
 */
NPY_NO_EXPORT int
days_to_month_number(npy_datetime days);

/*
 * 解析元数据字符串到元数据 C 结构中。
 * 成功返回 0,失败返回 -1。
 */
NPY_NO_EXPORT int
parse_datetime_metadata_from_metastr(char const *metastr, Py_ssize_t len,
                                    PyArray_DatetimeMetaData *out_meta);

/*
 * 将日期时间类型字符串解析为 dtype 描述符对象。
 * 'type' 字符串应为以 NULL 结尾的字符串,len 应为其长度。
 */
NPY_NO_EXPORT PyArray_Descr *
parse_dtype_from_datetime_typestr(char const *typestr, Py_ssize_t len);

/*
 * 将由 'str''len' 组成的子字符串转换为日期时间单元的枚举值。
 * 'metastr' 用于错误消息,可能为 NULL。
 * 成功返回 0,失败返回 -1。
 */
NPY_NO_EXPORT NPY_DATETIMEUNIT
parse_datetime_unit_from_string(char const *str, Py_ssize_t len, char const *metastr);

/*
 * 将除数转换为较小单位的倍数,用于日期时间元数据。
 * 'metastr' 用于错误消息,如果除数不适用,则可以为 NULL。
 * 成功返回 0,失败返回 -1。
 */
NPY_NO_EXPORT int
convert_datetime_divisor_to_multiple(PyArray_DatetimeMetaData *meta,
                                    int den, char const *metastr);

#endif  // NUMPY_CORE_SRC_MULTIARRAY__DATETIME_H_
/*
 * Determines whether the 'divisor' metadata divides evenly into
 * the 'dividend' metadata.
 */
NPY_NO_EXPORT npy_bool
datetime_metadata_divides(
                        PyArray_DatetimeMetaData *dividend,
                        PyArray_DatetimeMetaData *divisor,
                        int strict_with_nonlinear_units);



/*
 * This provides the casting rules for the DATETIME data type units.
 *
 * Notably, there is a barrier between 'date units' and 'time units'
 * for all but 'unsafe' casting.
 */
NPY_NO_EXPORT npy_bool
can_cast_datetime64_units(NPY_DATETIMEUNIT src_unit,
                          NPY_DATETIMEUNIT dst_unit,
                          NPY_CASTING casting);



/*
 * This provides the casting rules for the DATETIME data type metadata.
 */
NPY_NO_EXPORT npy_bool
can_cast_datetime64_metadata(PyArray_DatetimeMetaData *src_meta,
                             PyArray_DatetimeMetaData *dst_meta,
                             NPY_CASTING casting);



/*
 * This provides the casting rules for the TIMEDELTA data type units.
 *
 * Notably, there is a barrier between the nonlinear years and
 * months units, and all the other units.
 */
NPY_NO_EXPORT npy_bool
can_cast_timedelta64_units(NPY_DATETIMEUNIT src_unit,
                          NPY_DATETIMEUNIT dst_unit,
                          NPY_CASTING casting);



/*
 * This provides the casting rules for the TIMEDELTA data type metadata.
 */
NPY_NO_EXPORT npy_bool
can_cast_timedelta64_metadata(PyArray_DatetimeMetaData *src_meta,
                             PyArray_DatetimeMetaData *dst_meta,
                             NPY_CASTING casting);



/*
 * Computes the conversion factor to convert data with 'src_meta' metadata
 * into data with 'dst_meta' metadata.
 *
 * If overflow occurs, both out_num and out_denom are set to 0, but
 * no error is set.
 */
NPY_NO_EXPORT void
get_datetime_conversion_factor(PyArray_DatetimeMetaData *src_meta,
                                PyArray_DatetimeMetaData *dst_meta,
                                npy_int64 *out_num, npy_int64 *out_denom);



/*
 * Given a pointer to datetime metadata,
 * returns a tuple for pickling and other purposes.
 */
NPY_NO_EXPORT PyObject *
convert_datetime_metadata_to_tuple(PyArray_DatetimeMetaData *meta);



/*
 * Converts a metadata tuple into a datetime metadata C struct.
 *
 * Returns 0 on success, -1 on failure.
 */
NPY_NO_EXPORT int
convert_datetime_metadata_tuple_to_datetime_metadata(PyObject *tuple,
                                        PyArray_DatetimeMetaData *out_meta,
                                        npy_bool from_pickle);



/*
 * Gets a tzoffset in minutes by calling the fromutc() function on
 * the Python datetime.tzinfo object.
 */
NPY_NO_EXPORT int
get_tzoffset_from_pytzinfo(PyObject *timezone, npy_datetimestruct *dts);



/*
 * Converts an input object into datetime metadata. The input
 * may be either a string or a tuple.
 *
 * Returns 0 on success, -1 on failure.
 */
NPY_NO_EXPORT int
/*
 * 将 PyObject 转换为 datetime 元数据。
 * 返回值是一个 Unicode 对象的新引用。
 * 在错误时返回 NULL。
 *
 * 如果 'skip_brackets' 为 true,则跳过 '[]'。
 */
NPY_NO_EXPORT PyObject *
metastr_to_unicode(PyArray_DatetimeMetaData *meta, int skip_brackets);

/*
 * 将 PyObject * 转换为 datetime,支持所有支持的形式。
 *
 * 如果单位的元数据事先不知道,将 meta->base 设置为 -1,
 * 此函数将使用默认值或输入对象中的值填充 meta。
 *
 * 'casting' 参数用于控制接受的输入类型以及处理方式。
 * 例如,使用 'unsafe' casting,无法识别的输入将被转换为 'NaT' 而不是抛出错误,
 * 而使用 'safe' casting,如果输入中有任何精度将被丢弃,则会抛出错误。
 *
 * 错误时返回 -1,成功时返回 0。
 */
NPY_NO_EXPORT int
convert_pyobject_to_datetime(PyArray_DatetimeMetaData *meta, PyObject *obj,
                             NPY_CASTING casting, npy_datetime *out);

/*
 * 将 PyObject * 转换为 timedelta,支持所有支持的形式。
 *
 * 如果单位的元数据事先不知道,将 meta->base 设置为 -1,
 * 此函数将使用默认值或输入对象中的值填充 meta。
 *
 * 'casting' 参数用于控制接受的输入类型以及处理方式。
 * 例如,使用 'unsafe' casting,无法识别的输入将被转换为 'NaT' 而不是抛出错误,
 * 而使用 'safe' casting,如果输入中有任何精度将被丢弃,则会抛出错误。
 *
 * 错误时返回 -1,成功时返回 0。
 */
NPY_NO_EXPORT int
convert_pyobject_to_timedelta(PyArray_DatetimeMetaData *meta, PyObject *obj,
                              NPY_CASTING casting, npy_timedelta *out);

/*
 * 将 datetime 转换为 PyObject *。
 *
 * 对于天或更粗的单位,返回一个 datetime.date 对象。
 * 对于微秒或更粗的单位,返回一个 datetime.datetime 对象。
 * 对于精度高于微秒的单位,返回一个整数。
 */
NPY_NO_EXPORT PyObject *
convert_datetime_to_pyobject(npy_datetime dt, PyArray_DatetimeMetaData *meta);

/*
 * 将 timedelta 转换为 PyObject *。
 *
 * 如果是 Not-a-time,则返回字符串 "NaT"。
 * 对于微秒或更粗的单位,返回一个 datetime.timedelta 对象。
 * 对于精度高于微秒的单位,返回一个整数。
 */
NPY_NO_EXPORT PyObject *
convert_timedelta_to_pyobject(npy_timedelta td, PyArray_DatetimeMetaData *meta);

/*
 * 根据秒偏移调整 datetimestruct。假设当前值是有效的。
 */
NPY_NO_EXPORT void
add_seconds_to_datetimestruct(npy_datetimestruct *dts, int seconds);

/*
 * 根据分钟偏移调整 datetimestruct。假设当前值是有效的。
 */
NPY_NO_EXPORT void
add_minutes_to_datetimestruct(npy_datetimestruct *dts, int minutes);
/*
 * 在给定的 npy_datetimestruct 结构体上增加指定的分钟数
 */
add_minutes_to_datetimestruct(npy_datetimestruct *dts, int minutes);

/*
 * 检查两个 datetime 类型的描述符是否具有等效的元数据
 * 如果元数据匹配,则返回 true
 */
NPY_NO_EXPORT npy_bool
has_equivalent_datetime_metadata(PyArray_Descr *type1, PyArray_Descr *type2);

/*
 * 将单个 datetime 从 src_meta 元数据转换为 dst_meta 元数据
 * 成功时返回 0,失败时返回 -1
 */
NPY_NO_EXPORT int
cast_datetime_to_datetime(PyArray_DatetimeMetaData *src_meta,
                          PyArray_DatetimeMetaData *dst_meta,
                          npy_datetime src_dt,
                          npy_datetime *dst_dt);

/*
 * 将单个 timedelta 从 src_meta 元数据转换为 dst_meta 元数据
 * 成功时返回 0,失败时返回 -1
 */
NPY_NO_EXPORT int
cast_timedelta_to_timedelta(PyArray_DatetimeMetaData *src_meta,
                            PyArray_DatetimeMetaData *dst_meta,
                            npy_timedelta src_dt,
                            npy_timedelta *dst_dt);

/*
 * 检查对象是否最适合视为 Datetime 或 Timedelta
 * 如果是,则返回 true;否则返回 false
 */
NPY_NO_EXPORT npy_bool
is_any_numpy_datetime_or_timedelta(PyObject *obj);

/*
 * 实现特定于 datetime 的 arange 函数
 */
NPY_NO_EXPORT PyArrayObject *
datetime_arange(PyObject *start, PyObject *stop, PyObject *step,
                PyArray_Descr *dtype);

/*
 * 通过递归下降序列结构来检查给定 Python 对象中的所有对象
 * 返回基于数据的 datetime 或 timedelta 类型的描述符
 */
NPY_NO_EXPORT PyArray_Descr *
find_object_datetime_type(PyObject *obj, int type_num);

/*
 * 初始化 datetime 类型的强制转换规则
 * 成功时返回 0,失败时返回 -1
 */
NPY_NO_EXPORT int
PyArray_InitializeDatetimeCasts(void);

#endif  /* NUMPY_CORE_SRC_MULTIARRAY__DATETIME_H_ */

.\numpy\numpy\_core\src\npymath\arm64_exports.c

#if defined(__arm64__) && defined(__APPLE__)
#include <math.h>
/*
 * 对于 macOS arm64 平台,导出这些函数供 SciPy 使用。
 * SciPy 在 macOS arm64 上构建时,会下载 macOS x86_64 平台的 NumPy,
 * 并且链接器在无法使用 npymathlib.a 时不会报错。导入 numpy 会暴露这些外部函数。
 * 参考 https://github.com/numpy/numpy/issues/22673#issuecomment-1327520055
 *
 * 实际上,这个文件会作为主模块的一部分进行编译。
 */

// 计算反双曲正弦值
double npy_asinh(double x) {
    return asinh(x);
}

// 返回带有给定符号的 y 的值
double npy_copysign(double y, double x) {
    return copysign(y, x);
}

// 返回 log(1+x)
double npy_log1p(double x) {
    return log1p(x);
}

// 返回靠近 x 但大于 y 的浮点数
double npy_nextafter(double x, double y) {
    return nextafter(x, y);
}

#endif

.\numpy\numpy\_core\src\npymath\halffloat.cpp

#define NPY_NO_DEPRECATED_API NPY_API_VERSION
/*
 * 如果设置为1,转换过程中会尝试在需要时触发浮点系统的下溢、上溢和无效异常。
 */
#define NPY_HALF_GENERATE_OVERFLOW 1
#define NPY_HALF_GENERATE_INVALID 1

#include "numpy/halffloat.h"

#include "common.hpp"
/*
 ********************************************************************
 *                   HALF-PRECISION ROUTINES                        *
 ********************************************************************
 */

using namespace np;

/*
 * 将半精度浮点数转换为单精度浮点数
 */
float npy_half_to_float(npy_half h)
{
    return static_cast<float>(Half::FromBits(h));
}

/*
 * 将半精度浮点数转换为双精度浮点数
 */
double npy_half_to_double(npy_half h)
{
    return static_cast<double>(Half::FromBits(h));
}

/*
 * 将单精度浮点数转换为半精度浮点数
 */
npy_half npy_float_to_half(float f)
{
    return Half(f).Bits();
}

/*
 * 将双精度浮点数转换为半精度浮点数
 */
npy_half npy_double_to_half(double d)
{
    return Half(d).Bits();
}

/*
 * 判断半精度浮点数是否为零
 */
int npy_half_iszero(npy_half h)
{
    return (h&0x7fff) == 0;
}

/*
 * 判断半精度浮点数是否为NaN
 */
int npy_half_isnan(npy_half h)
{
    return Half::FromBits(h).IsNaN();
}

/*
 * 判断半精度浮点数是否为无穷大
 */
int npy_half_isinf(npy_half h)
{
    return ((h&0x7fffu) == 0x7c00u);
}

/*
 * 判断半精度浮点数是否为有限数
 */
int npy_half_isfinite(npy_half h)
{
    return ((h&0x7c00u) != 0x7c00u);
}

/*
 * 判断半精度浮点数的符号位是否为1(负数)
 */
int npy_half_signbit(npy_half h)
{
    return (h&0x8000u) != 0;
}

/*
 * 计算两个半精度浮点数之间的距离
 */
npy_half npy_half_spacing(npy_half h)
{
    npy_half ret;
    npy_uint16 h_exp = h&0x7c00u;
    npy_uint16 h_sig = h&0x03ffu;
    if (h_exp == 0x7c00u) {
#if NPY_HALF_GENERATE_INVALID
        npy_set_floatstatus_invalid();
#endif
        ret = NPY_HALF_NAN;
    } else if (h == 0x7bffu) {
#if NPY_HALF_GENERATE_OVERFLOW
        npy_set_floatstatus_overflow();
#endif
        ret = NPY_HALF_PINF;
    } else if ((h&0x8000u) && h_sig == 0) { /* 负数边界情况 */
        if (h_exp > 0x2c00u) { /* 如果结果是规格化的 */
            ret = h_exp - 0x2c00u;
        } else if(h_exp > 0x0400u) { /* 结果是次规格化的,但不是最小的 */
            ret = 1 << ((h_exp >> 10) - 2);
        } else {
            ret = 0x0001u; /* 最小的次规格化半精度浮点数 */
        }
    } else if (h_exp > 0x2800u) { /* 如果结果仍然是规格化的 */
        ret = h_exp - 0x2800u;
    } else if (h_exp > 0x0400u) { /* 结果是次规格化的,但不是最小的 */
        ret = 1 << ((h_exp >> 10) - 1);
    } else {
        ret = 0x0001u;
    }

    return ret;
}

/*
 * 返回一个半精度浮点数,其值与x相同,但其符号与y相同
 */
npy_half npy_half_copysign(npy_half x, npy_half y)
{
    return (x&0x7fffu) | (y&0x8000u);
}

/*
 * 返回x和y之间的下一个半精度浮点数
 */
npy_half npy_half_nextafter(npy_half x, npy_half y)
{
    npy_half ret;

    if (npy_half_isnan(x) || npy_half_isnan(y)) {
        ret = NPY_HALF_NAN;
    } else if (npy_half_eq_nonan(x, y)) {
        ret = x;
    } else if (npy_half_iszero(x)) {
        ret = (y&0x8000u) + 1; /* 最小的次规格化半精度浮点数 */
    } else if (!(x&0x8000u)) { /* x > 0 */
        if ((npy_int16)x > (npy_int16)y) { /* x > y */
            ret = x-1;
        } else {
            ret = x+1;
        }
    } else {
        // 如果 y 的符号位为 0 或者 x 的绝对值大于 y 的绝对值,则 x < y
        if (!(y&0x8000u) || (x&0x7fffu) > (y&0x7fffu)) { /* x < y */
            // 如果 x < y,则返回 x 减去 1
            ret = x-1;
        } else {
            // 否则返回 x 加上 1
            ret = x+1;
        }
    }
#if NPY_HALF_GENERATE_OVERFLOW
    // 如果结果溢出且输入值不是无穷大,则设置浮点数状态为溢出
    if (npy_half_isinf(ret) && npy_half_isfinite(x)) {
        npy_set_floatstatus_overflow();
    }
#endif

    // 返回计算结果
    return ret;
}

// 比较两个非 NaN 的 npy_half 类型的值是否相等
int npy_half_eq_nonan(npy_half h1, npy_half h2)
{
    return Half::FromBits(h1).Equal(Half::FromBits(h2));
}

// 比较两个 npy_half 类型的值是否相等
int npy_half_eq(npy_half h1, npy_half h2)
{
    return Half::FromBits(h1) == Half::FromBits(h2);
}

// 比较两个 npy_half 类型的值是否不相等
int npy_half_ne(npy_half h1, npy_half h2)
{
    return Half::FromBits(h1) != Half::FromBits(h2);
}

// 比较两个非 NaN 的 npy_half 类型的值是否 h1 小于 h2
int npy_half_lt_nonan(npy_half h1, npy_half h2)
{
    return Half::FromBits(h1).Less(Half::FromBits(h2));
}

// 比较两个 npy_half 类型的值是否 h1 小于 h2
int npy_half_lt(npy_half h1, npy_half h2)
{
    return Half::FromBits(h1) < Half::FromBits(h2);
}

// 比较两个 npy_half 类型的值是否 h1 大于 h2
int npy_half_gt(npy_half h1, npy_half h2)
{
    // 转换为 h2 < h1 的比较形式
    return npy_half_lt(h2, h1);
}

// 比较两个非 NaN 的 npy_half 类型的值是否 h1 小于等于 h2
int npy_half_le_nonan(npy_half h1, npy_half h2)
{
    return Half::FromBits(h1).LessEqual(Half::FromBits(h2));
}

// 比较两个 npy_half 类型的值是否 h1 小于等于 h2
int npy_half_le(npy_half h1, npy_half h2)
{
    return Half::FromBits(h1) <= Half::FromBits(h2);
}

// 比较两个 npy_half 类型的值是否 h1 大于等于 h2
int npy_half_ge(npy_half h1, npy_half h2)
{
    // 转换为 h2 <= h1 的比较形式
    return npy_half_le(h2, h1);
}

// 计算 npy_half 类型的 h1 除以 h2 的商和余数
npy_half npy_half_divmod(npy_half h1, npy_half h2, npy_half *modulus)
{
    float fh1 = npy_half_to_float(h1);
    float fh2 = npy_half_to_float(h2);
    float div, mod;

    // 执行浮点数的除法和取余操作
    div = npy_divmodf(fh1, fh2, &mod);
    // 将取余结果转换为 npy_half 类型
    *modulus = npy_float_to_half(mod);
    // 将商的结果转换为 npy_half 类型并返回
    return npy_float_to_half(div);
}


/*
 ********************************************************************
 *                     BIT-LEVEL CONVERSIONS                        *
 ********************************************************************
 */

// 将 npy_uint32 类型的浮点数位表示转换为 npy_uint16 类型的半精度浮点数位表示
npy_uint16 npy_floatbits_to_halfbits(npy_uint32 f)
{
    if constexpr (Half::kNativeConversion<float>) {
        // 如果支持本地浮点数转换,则执行转换
        return BitCast<uint16_t>(Half(BitCast<float>(f)));
    }
    else {
        // 否则使用私有方法执行转换
        return half_private::FromFloatBits(f);
    }
}

// 将 npy_uint64 类型的双精度浮点数位表示转换为 npy_uint16 类型的半精度浮点数位表示
npy_uint16 npy_doublebits_to_halfbits(npy_uint64 d)
{
    if constexpr (Half::kNativeConversion<double>) {
        // 如果支持本地浮点数转换,则执行转换
        return BitCast<uint16_t>(Half(BitCast<double>(d)));
    }
    else {
        // 否则使用私有方法执行转换
        return half_private::FromDoubleBits(d);
    }
}

// 将 npy_uint16 类型的半精度浮点数位表示转换为 npy_uint32 类型的浮点数位表示
npy_uint32 npy_halfbits_to_floatbits(npy_uint16 h)
{
    if constexpr (Half::kNativeConversion<float>) {
        // 如果支持本地浮点数转换,则执行转换
        return BitCast<uint32_t>(static_cast<float>(Half::FromBits(h)));
    }
    else {
        // 否则使用私有方法执行转换
        return half_private::ToFloatBits(h);
    }
}

// 将 npy_uint16 类型的半精度浮点数位表示转换为 npy_uint64 类型的双精度浮点数位表示
npy_uint64 npy_halfbits_to_doublebits(npy_uint16 h)
{
    if constexpr (Half::kNativeConversion<double>) {
        // 如果支持本地浮点数转换,则执行转换
        return BitCast<uint64_t>(static_cast<double>(Half::FromBits(h)));
    }
    else {
        // 否则使用私有方法执行转换
        return half_private::ToDoubleBits(h);
    }
}

.\numpy\numpy\_core\src\npymath\ieee754.cpp

/*
 * -*- c -*-
 *
 * Low-level routines related to IEEE-754 format
 */

/*
 * vim:syntax=c
 *
 * Low-level routines related to IEEE-754 format
 */

/*
 * The below code is provided for compilers which do not yet provide C11
 * compatibility (gcc 4.5 and older)
 */
#include "numpy/utils.h"

#include "npy_math_common.h"
#include "npy_math_private.h"

/*
 * FIXME: There is a lot of redundancy between _next* and npy_nextafter*.
 * refactor this at some point
 *
 * p >= 0, return x + nulp
 * p < 0, return x - nulp
 */
static double
_next(double x, int p)
{
    volatile double t;
    npy_int32 hx, hy, ix;
    npy_uint32 lx;

    EXTRACT_WORDS(hx, lx, x);
    ix = hx & 0x7fffffff; /* |x| */

    if (((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0)) /* x is nan */
        return x;
    if ((ix | lx) == 0) { /* x == 0 */
        if (p >= 0) {
            INSERT_WORDS(x, 0x0, 1); /* return +minsubnormal */
        }
        else {
            INSERT_WORDS(x, 0x80000000, 1); /* return -minsubnormal */
        }
        t = x * x;
        if (t == x)
            return t;
        else
            return x; /* raise underflow flag */
    }
    if (p < 0) { /* x -= ulp */
        if (lx == 0)
            hx -= 1;
        lx -= 1;
    }
    else { /* x += ulp */
        lx += 1;
        if (lx == 0)
            hx += 1;
    }
    hy = hx & 0x7ff00000;
    if (hy >= 0x7ff00000)
        return x + x;      /* overflow  */
    if (hy < 0x00100000) { /* underflow */
        t = x * x;
        if (t != x) { /* raise underflow flag */
            INSERT_WORDS(x, hx, lx);
            return x;
        }
    }
    INSERT_WORDS(x, hx, lx);
    return x;
}

/*
 * FIXME: There is a lot of redundancy between _next* and npy_nextafter*.
 * refactor this at some point
 *
 * p >= 0, return x + nulp
 * p < 0, return x - nulp
 */
static float
_next(float x, int p)
{
    volatile float t;
    npy_int32 hx, hy, ix;

    GET_FLOAT_WORD(hx, x);
    ix = hx & 0x7fffffff; /* |x| */

    if ((ix > 0x7f800000)) /* x is nan */
        return x;
    if (ix == 0) { /* x == 0 */
        if (p >= 0) {
            SET_FLOAT_WORD(x, 0x0 | 1); /* return +minsubnormal */
        }
        else {
            SET_FLOAT_WORD(x, 0x80000000 | 1); /* return -minsubnormal */
        }
        t = x * x;
        if (t == x)
            return t;
        else
            return x; /* raise underflow flag */
    }
    if (p < 0) { /* x -= ulp */
        hx -= 1;
    }
    else { /* x += ulp */
        hx += 1;
    }
    hy = hx & 0x7f800000;
    if (hy >= 0x7f800000)
        return x + x;      /* overflow  */
    if (hy < 0x00800000) { /* underflow */
        t = x * x;
        if (t != x) { /* raise underflow flag */
            SET_FLOAT_WORD(x, hx);
            return x;
        }
    }
    SET_FLOAT_WORD(x, hx);
    return x;
}

#if defined(HAVE_LDOUBLE_DOUBLE_DOUBLE_BE) || \
        defined(HAVE_LDOUBLE_DOUBLE_DOUBLE_LE)

/*
 * FIXME: this is ugly and untested. The asm part only works with gcc, and we
 * should consolidate the GET_LDOUBLE* / SET_LDOUBLE macros
 */
#define math_opt_barrier(x)    \
    ({                         \
        __typeof(x) __x = x;   \  # 定义一个临时变量 __x,类型与 x 相同,用于存储 x 的值
        __asm("" : "+m"(__x)); \  # 使用内联汇编语句,操作 __x 变量,"+m" 表示将 __x 视为内存输入输出操作数
        __x;                   \  # 返回 __x 变量的值
    })
/* 定义宏 math_force_eval(x),强制评估 x 的值 */
#define math_force_eval(x) __asm __volatile("" : : "m"(x))

/* 定义联合体 ieee854_long_double_shape_type,用于处理 IEEE 854 格式的长双精度浮点数 */
typedef union {
    npy_longdouble value;                 /* 长双精度浮点数值 */
    struct {
        npy_uint64 msw;                  /* 高位 64 位整数部分 */
        npy_uint64 lsw;                  /* 低位 64 位整数部分 */
    } parts64;
    struct {
        npy_uint32 w0, w1, w2, w3;       /* 32 位整数部分分解 */
    } parts32;
} ieee854_long_double_shape_type;

/* 从长双精度浮点数中获取两个 64 位整数 */
#define GET_LDOUBLE_WORDS64(ix0, ix1, d)     \
    do {                                     \
        ieee854_long_double_shape_type qw_u; \
        qw_u.value = (d);                    \
        (ix0) = qw_u.parts64.msw;            \
        (ix1) = qw_u.parts64.lsw;            \
    } while (0)

/* 将两个 64 位整数设置为长双精度浮点数 */
#define SET_LDOUBLE_WORDS64(d, ix0, ix1)     \
    do {                                     \
        ieee854_long_double_shape_type qw_u; \
        qw_u.parts64.msw = (ix0);            \
        qw_u.parts64.lsw = (ix1);            \
        (d) = qw_u.value;                    \
    } while (0)

/* 静态函数 _next,用于实现浮点数运算 */
static long double
_next(long double x, int p)
{
    npy_int64 hx, ihx, ilx;                 /* 高位和低位整数部分 */
    npy_uint64 lx;                          /* 无符号长整数部分 */
    npy_longdouble u;                       /* 长双精度浮点数 u */
    const npy_longdouble eps = exp2l(-105.); /* 0x1.0000000000000p-105L,用于计算精度 */

    GET_LDOUBLE_WORDS64(hx, lx, x);         /* 获取长双精度浮点数 x 的整数部分 */

    ihx = hx & 0x7fffffffffffffffLL;        /* 取 x 的绝对值的整数部分 */
    ilx = lx & 0x7fffffffffffffffLL;        /* 取 x 的绝对值的低位整数部分 */

    if (((ihx & 0x7ff0000000000000LL) == 0x7ff0000000000000LL) &&
        ((ihx & 0x000fffffffffffffLL) != 0)) {
        return x;                           /* 如果 x 是 NaN,则返回 x */
    }
    if (ihx == 0 && ilx == 0) {              /* 如果 x 等于 0 */
        SET_LDOUBLE_WORDS64(x, p, 0ULL);    /* 设置 x 为 +-minsubnormal */
        u = x * x;
        if (u == x) {
            return u;                       /* 如果 u 等于 x,则返回 u */
        }
        else {
            return x;                       /* 否则返回 x */
        }
    }

    if (p < 0) {                            /* 如果 p 小于 0 */
        if ((hx == 0xffefffffffffffffLL) && (lx == 0xfc8ffffffffffffeLL))
            return x + x;                   /* 如果溢出,返回 -inf */
        if (hx >= 0x7ff0000000000000LL) {   /* 如果 x 是无穷大 */
            SET_LDOUBLE_WORDS64(u, 0x7fefffffffffffffLL, 0x7c8ffffffffffffeLL);
            return u;                       /* 返回特定值 u */
        }
        if (ihx <= 0x0360000000000000LL) {  /* 如果 x 小于等于 LDBL_MIN */
            u = math_opt_barrier(x);        /* 对 x 进行数学优化屏障 */
            x -= LDBL_TRUE_MIN;             /* 减去 LDBL_TRUE_MIN */
            if (ihx < 0x0360000000000000LL || (hx > 0 && (npy_int64)lx <= 0) ||
                (hx < 0 && (npy_int64)lx > 1)) {
                u = u * u;
                math_force_eval(u);         /* 强制评估 u,触发下溢标志 */
            }
            return x;                       /* 返回 x */
        }
        if (ihx < 0x06a0000000000000LL) {   /* 如果 ulp 会变成非规格化数 */
            SET_LDOUBLE_WORDS64(u, (hx & 0x7ff0000000000000LL), 0ULL);
            u *= eps;                       /* u 乘以 eps */
        }
        else
            SET_LDOUBLE_WORDS64(
                    u, (hx & 0x7ff0000000000000LL) - 0x0690000000000000LL,
                    0ULL);
        return x - u;                       /* 返回 x - u */
    }


这段代码是关于处理长双精度浮点数的宏定义和函数实现,主要用于浮点数的精确计算和特殊情况处理。
    else { /* p >= 0, x += ulp */
        # 如果 p >= 0,意味着需要增加 ulp 到 x 上

        if ((hx == 0x7fefffffffffffffLL) && (lx == 0x7c8ffffffffffffeLL))
            # 如果 x 是正无穷大,返回 +inf
            return x + x; /* overflow, return +inf */

        if ((npy_uint64)hx >= 0xfff0000000000000ULL) {
            # 如果 x 是 NaN 或者无穷大,设置返回值为 NaN
            SET_LDOUBLE_WORDS64(u, 0xffefffffffffffffLL, 0xfc8ffffffffffffeLL);
            return u;
        }

        if (ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */
            # 如果 x 小于等于最小长双精度浮点数 LDBL_MIN

            u = math_opt_barrier(x);
            # 对 x 进行优化处理,可能是某种数学优化栅栏
            x += LDBL_TRUE_MIN;
            # 将 x 增加真实的最小长双精度浮点数

            if (ihx < 0x0360000000000000LL ||
                (hx > 0 && (npy_int64)lx < 0 && lx != 0x8000000000000001LL) ||
                (hx < 0 && (npy_int64)lx >= 0)) {
                # 如果 x 小于 LDBL_MIN 或者 (x 为正数且低位为负数且不是 -0.0L) 或者 (x 为负数且低位为正数)
                
                u = u * u;
                # 对 u 进行平方
                math_force_eval(u); /* raise underflow flag */
                # 强制评估 u,引发下溢标志
            }

            if (x == 0.0L)
                # 处理负的 LDBL_TRUE_MIN 情况
                x = -0.0L;

            return x;
            # 返回 x
        }

        if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
            # 如果 ulp 会导致非正常数(denormal)

            SET_LDOUBLE_WORDS64(u, (hx & 0x7ff0000000000000LL), 0ULL);
            # 将 u 设置为与 hx 的前 52 位相同,后面 52 位为 0
            u *= eps;
            # 将 u 乘以 eps
        }
        else {
            SET_LDOUBLE_WORDS64(
                    u, (hx & 0x7ff0000000000000LL) - 0x0690000000000000LL,
                    0ULL);
            # 将 u 设置为 hx 的前 52 位减去 0x0690000000000000LL,后面 52 位为 0
        }

        return x + u;
        # 返回 x 加上 u
    }
}
#else
static long double
_next(long double x, int p)
{
    volatile npy_longdouble t;  // 声明一个 volatile 类型的长双精浮点数 t,用于临时存储计算结果
    union IEEEl2bitsrep ux;     // 声明一个联合体 ux,用于存储长双精浮点数 x 的位表示

    ux.e = x;   // 将长双精浮点数 x 的值赋给联合体 ux 的位表示

    if ((GET_LDOUBLE_EXP(ux) == 0x7fff &&
         ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) | GET_LDOUBLE_MANL(ux)) != 0)) {
        return ux.e; /* x is nan */  // 如果 x 是 NaN,则直接返回 x
    }
    if (ux.e == 0.0) {
        SET_LDOUBLE_MANH(ux, 0); /* return +-minsubnormal */  // 设置 ux 的尾数部分为 +-minsubnormal
        SET_LDOUBLE_MANL(ux, 1);  // 将 ux 的尾数部分的低位设置为 1
        if (p >= 0) {
            SET_LDOUBLE_SIGN(ux, 0);  // 如果 p 大于等于 0,则设置 ux 的符号位为正号
        }
        else {
            SET_LDOUBLE_SIGN(ux, 1);  // 否则,设置 ux 的符号位为负号
        }
        t = ux.e * ux.e;  // 计算 ux.e 的平方,并将结果存储在 t 中
        if (t == ux.e) {
            return t;  // 如果 t 等于 ux.e,则返回 t
        }
        else {
            return ux.e; /* raise underflow flag */  // 否则,返回 ux.e,并可能引发下溢标志
        }
    }
    if (p < 0) { /* x -= ulp */  // 如果 p 小于 0,则表示 x 减去最后一个有效位
        if (GET_LDOUBLE_MANL(ux) == 0) {
            if ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) == 0) {
                SET_LDOUBLE_EXP(ux, GET_LDOUBLE_EXP(ux) - 1);  // 如果 ux 的尾数部分低位为 0,并且尾数部分高位去除掉了 LDBL_NBIT,那么将指数部分减 1
            }
            SET_LDOUBLE_MANH(ux, (GET_LDOUBLE_MANH(ux) - 1) |
                                         (GET_LDOUBLE_MANH(ux) & LDBL_NBIT));  // 将 ux 的尾数部分高位减 1,并保留 LDBL_NBIT
        }
        SET_LDOUBLE_MANL(ux, GET_LDOUBLE_MANL(ux) - 1);  // 将 ux 的尾数部分低位减 1
    }
    else { /* x += ulp */  // 否则,表示 x 加上最后一个有效位
        SET_LDOUBLE_MANL(ux, GET_LDOUBLE_MANL(ux) + 1);  // 将 ux 的尾数部分低位加 1
        if (GET_LDOUBLE_MANL(ux) == 0) {
            SET_LDOUBLE_MANH(ux, (GET_LDOUBLE_MANH(ux) + 1) |
                                         (GET_LDOUBLE_MANH(ux) & LDBL_NBIT));  // 如果 ux 的尾数部分低位变为 0,将 ux 的尾数部分高位加 1,并保留 LDBL_NBIT
            if ((GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT) == 0) {
                SET_LDOUBLE_EXP(ux, GET_LDOUBLE_EXP(ux) + 1);  // 如果 ux 的尾数部分高位去除掉了 LDBL_NBIT,则将指数部分加 1
            }
        }
    }
    if (GET_LDOUBLE_EXP(ux) == 0x7fff) {
        return ux.e + ux.e; /* overflow  */  // 如果 ux 的指数部分为 0x7fff,则返回 ux.e 的双倍,并可能引发溢出
    }
    if (GET_LDOUBLE_EXP(ux) == 0) { /* underflow */  // 如果 ux 的指数部分为 0,则表示发生下溢
        if (LDBL_NBIT) {
            SET_LDOUBLE_MANH(ux, GET_LDOUBLE_MANH(ux) & ~LDBL_NBIT);  // 如果 LDBL_NBIT 为真,则清除 ux 的尾数部分高位的 LDBL_NBIT
        }
        t = ux.e * ux.e;
        if (t != ux.e) { /* raise underflow flag */  // 如果 t 不等于 ux.e,则可能引发下溢标志
            return ux.e;
        }
    }

    return ux.e;  // 返回计算后的长双精浮点数值 ux.e
}
#endif

namespace {
template <typename T>
struct numeric_limits;

template <>
struct numeric_limits<float> {
    static const npy_float nan;  // 定义 float 类型的特殊值 nan
};
const npy_float numeric_limits<float>::nan = NPY_NANF;  // 初始化 float 类型的 nan

template <>
struct numeric_limits<double> {
    static const npy_double nan;  // 定义 double 类型的特殊值 nan
};
const npy_double numeric_limits<double>::nan = NPY_NAN;  // 初始化 double 类型的 nan

template <>
struct numeric_limits<long double> {
    static const npy_longdouble nan;  // 定义 long double 类型的特殊值 nan
};
const npy_longdouble numeric_limits<long double>::nan = NPY_NANL;  // 初始化 long double 类型的 nan
}  // namespace

template <typename type>
static type
_npy_spacing(type x)
{
    /* XXX: npy isnan/isinf may be optimized by bit twiddling */  // 提示可能通过位操作对 npy 的 isnan/isinf 进行优化
    if (npy_isinf(x)) {
        return numeric_limits<type>::nan;  // 如果 x 是无穷大,则返回该类型的 nan 值
    }

    return _next(x, 1) - x;  // 否则,返回 x 的下一个值减去 x 本身的差值
}

/*
 * Instantiation of C interface
 */
extern "C" {
npy_float
npy_spacingf(npy_float x)
{
    return _npy_spacing(x);  // 返回 float 类型的 npy_spacing 函数调用结果
}
npy_double
npy_spacing(npy_double x)
{
    return _npy_spacing(x);  // 返回 double 类型的 npy_spacing 函数调用结果
}
npy_longdouble
npy_spacingl(npy_longdouble x)
{
    return _npy_spacing(x);  // 返回 long double 类型的 npy_spacing 函数调用结果
}
}

extern "C" int
npy_clear_floatstatus()
{
    char x = 0;  // 声明一个 char 类型的变量 x,并初始化为 0
    # 调用函数 npy_clear_floatstatus_barrier,传入参数 x,并返回其结果。
    return npy_clear_floatstatus_barrier(&x);
extern "C" int
npy_get_floatstatus()
{
    // 定义一个字符变量 x 并初始化为 0
    char x = 0;
    // 调用 npy_get_floatstatus_barrier 函数,传入 x 的地址作为参数,并返回结果
    return npy_get_floatstatus_barrier(&x);
}


/* 
 * 用于浮点错误处理的通用 C99 代码。这些函数主要是因为 `fenv.h` 在 C89 中未标准化,
 * 因此它们提供了更好的可移植性。在 C99/C++11 中应该不再需要这些,可以直接从 `fenv.h` 中使用更多功能。
 */
#include <fenv.h>

/*
 * 根据 C99 标准,如果 FE_DIVBYZERO 等未支持,则可能不会提供。在这种情况下,NumPy 将无法正确报告这些错误,
 * 但我们仍应允许编译(无论测试是否通过)。通过在本地定义它们为 0,我们使它们成为无操作。例如,`musl` 仍定义所有这些函数(作为无操作):
 *     https://git.musl-libc.org/cgit/musl/tree/src/fenv/fenv.c
 * 并在其测试中执行类似的替换:
 *     http://nsz.repo.hu/git/?p=libc-test;a=blob;f=src/common/mtest.h;h=706c1ba23ea8989b17a2f72ed1a919e187c06b6a;hb=HEAD#l30
 */
#ifndef FE_DIVBYZERO
    #define FE_DIVBYZERO 0
#endif
#ifndef FE_OVERFLOW
    #define FE_OVERFLOW 0
#endif
#ifndef FE_UNDERFLOW
    #define FE_UNDERFLOW 0
#endif
#ifndef FE_INVALID
    #define FE_INVALID 0
#endif


extern "C" int
npy_get_floatstatus_barrier(char *param)
{
    // 使用 fetestexcept 函数获取当前浮点异常状态并存储在 fpstatus 中
    int fpstatus = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW |
                                FE_INVALID);
    /*
     * 通过使用 volatile,编译器无法重新排序此调用
     */
    // 如果传入的 param 不为 NULL,则声明一个 volatile 的字符变量 c,并使用 param 转换后的指针来初始化它
    if (param != NULL) {
        volatile char NPY_UNUSED(c) = *(char *)param;
    }

    // 根据 fpstatus 的位掩码,返回相应的浮点异常错误码
    return ((FE_DIVBYZERO & fpstatus) ? NPY_FPE_DIVIDEBYZERO : 0) |
           ((FE_OVERFLOW & fpstatus) ? NPY_FPE_OVERFLOW : 0) |
           ((FE_UNDERFLOW & fpstatus) ? NPY_FPE_UNDERFLOW : 0) |
           ((FE_INVALID & fpstatus) ? NPY_FPE_INVALID : 0);
}

extern "C" int
npy_clear_floatstatus_barrier(char *param)
{
    /* 在 x86 上测试浮点状态比清除状态快 50-100 倍 */
    // 调用 npy_get_floatstatus_barrier 函数获取当前浮点异常状态并存储在 fpstatus 中
    int fpstatus = npy_get_floatstatus_barrier(param);
    // 如果 fpstatus 不为 0,则调用 feclearexcept 函数清除 FE_DIVBYZERO、FE_OVERFLOW、FE_UNDERFLOW 和 FE_INVALID 异常
    if (fpstatus != 0) {
        feclearexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INVALID);
    }

    // 返回 fpstatus
    return fpstatus;
}

extern "C" void
npy_set_floatstatus_divbyzero(void)
{
    // 调用 feraiseexcept 函数,设置 FE_DIVBYZERO 异常
    feraiseexcept(FE_DIVBYZERO);
}

extern "C" void
npy_set_floatstatus_overflow(void)
{
    // 调用 feraiseexcept 函数,设置 FE_OVERFLOW 异常
    feraiseexcept(FE_OVERFLOW);
}

extern "C" void
npy_set_floatstatus_underflow(void)
{
    // 调用 feraiseexcept 函数,设置 FE_UNDERFLOW 异常
    feraiseexcept(FE_UNDERFLOW);
}

extern "C" void
npy_set_floatstatus_invalid(void)
{
    // 调用 feraiseexcept 函数,设置 FE_INVALID 异常
    feraiseexcept(FE_INVALID);
}

.\numpy\numpy\_core\src\npymath\npy_math.c

/*
 * vim:syntax=c
 * This file is compiled into the npy_math library with externally visible
 * symbols, and the static and inline specifiers utilized in the npy_math
 * function definitions are switched off.
 */
// 设置 C 语法高亮,指定这个文件被编译为 npy_math 库,其中包含外部可见的符号
// 在 npy_math 函数定义中,关闭了 static 和 inline 修饰符的使用
#define NPY_INLINE_MATH 0
// 包含 npy_math_internal.h 头文件
#include "npy_math_internal.h"

.\numpy\numpy\_core\src\npymath\npy_math_common.h

/*
 * Common headers needed by every npy math compilation unit
 */
#include <Python.h>     // 包含 Python C API 的头文件
#include <math.h>       // 包含数学函数的头文件
#include <float.h>      // 包含浮点数特性的头文件

#include "npy_config.h"     // 包含 numpy 配置的头文件
#include "numpy/npy_math.h" // 包含 numpy 数学函数的头文件

.\numpy\numpy\_core\src\npymath\npy_math_private.h

/*
 *
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

/*
 * from: @(#)fdlibm.h 5.1 93/09/24
 * $FreeBSD$
 */

#ifndef _NPY_MATH_PRIVATE_H_
#define _NPY_MATH_PRIVATE_H_

#include <Python.h>
#ifdef __cplusplus
#include <cmath>
using std::isgreater;
using std::isless;
#else
#include <math.h>
#endif

#include "npy_config.h"
#include "npy_fpmath.h"

#include "numpy/npy_math.h"
#include "numpy/npy_endian.h"
#include "numpy/npy_common.h"

/*
 * The original fdlibm code used statements like:
 *      n0 = ((*(int*)&one)>>29)^1;             * index of high word *
 *      ix0 = *(n0+(int*)&x);                   * high word of x *
 *      ix1 = *((1-n0)+(int*)&x);               * low word of x *
 * to dig two 32 bit words out of the 64 bit IEEE floating point
 * value.  That is non-ANSI, and, moreover, the gcc instruction
 * scheduler gets it wrong.  We instead use the following macros.
 * Unlike the original code, we determine the endianness at compile
 * time, not at run time; I don't see much benefit to selecting
 * endianness at run time.
 */

/*
 * A union which permits us to convert between a double and two 32 bit
 * ints.
 */

/* XXX: not really, but we already make this assumption elsewhere. Will have to
 * fix this at some point */
#define IEEE_WORD_ORDER NPY_BYTE_ORDER

#if IEEE_WORD_ORDER == NPY_BIG_ENDIAN

typedef union
{
  double value;
  struct
  {
    npy_uint32 msw;
    npy_uint32 lsw;
  } parts;
} ieee_double_shape_type;

#endif

#if IEEE_WORD_ORDER == NPY_LITTLE_ENDIAN

typedef union
{
  double value;
  struct
  {
    npy_uint32 lsw;
    npy_uint32 msw;
  } parts;
} ieee_double_shape_type;

#endif

/* Get two 32 bit ints from a double.  */

#define EXTRACT_WORDS(ix0,ix1,d)                                \
do {                                                            \
  ieee_double_shape_type ew_u;                                  \
  ew_u.value = (d);                                             \
  (ix0) = ew_u.parts.msw;                                       \
  (ix1) = ew_u.parts.lsw;                                       \
} while (0)

/* Get the more significant 32 bit int from a double.  */

#define GET_HIGH_WORD(i,d)                                      \
do {                                                            \
  ieee_double_shape_type gh_u;                                  \
  gh_u.value = (d);                                             \
  (i) = gh_u.parts.msw;                                         \
} while (0)

/* Get the less significant 32 bit int from a double.  */

#define GET_LOW_WORD(i,d)                                       \
do {                                                            \
  ieee_double_shape_type gl_u;                                  \
  gl_u.value = (d);                                             \
  (i) = gl_u.parts.lsw;                                         \
} while (0)

#endif /* _NPY_MATH_PRIVATE_H_ */
/*
 * Set the low 32 bits of a double from an int value.
 */
#define SET_LOW_WORD(d,v)                                       \
do {                                                            \
  ieee_double_shape_type sl_u;                                  \
  sl_u.value = (d);                                             \
  sl_u.parts.lsw = (v);                                         \
  (d) = sl_u.value;                                             \
} while (0)

/*
 * Set the high 32 bits of a double from an int value.
 */
#define SET_HIGH_WORD(d,v)                                      \
do {                                                            \
  ieee_double_shape_type sh_u;                                  \
  sh_u.value = (d);                                             \
  sh_u.parts.msw = (v);                                         \
  (d) = sh_u.value;                                             \
} while (0)

/*
 * Set a double value from two 32-bit int values.
 */
#define INSERT_WORDS(d,ix0,ix1)                                 \
do {                                                            \
  ieee_double_shape_type iw_u;                                  \
  iw_u.parts.msw = (ix0);                                       \
  iw_u.parts.lsw = (ix1);                                       \
  (d) = iw_u.value;                                             \
} while (0)

/*
 * A union allowing conversion between a float and a 32-bit int.
 */
typedef union
{
  float value;
  /* FIXME: Assumes 32 bit int.  */
  npy_uint32 word;
} ieee_float_shape_type;

/*
 * Get a 32-bit int representation of a float value.
 */
#define GET_FLOAT_WORD(i,d)                                     \
do {                                                            \
  ieee_float_shape_type gf_u;                                   \
  gf_u.value = (d);                                             \
  (i) = gf_u.word;                                              \
} while (0)

/*
 * Set a float value from a 32-bit int representation.
 */
#define SET_FLOAT_WORD(d,i)                                     \
do {                                                            \
  ieee_float_shape_type sf_u;                                   \
  sf_u.word = (i);                                              \
  (d) = sf_u.value;                                             \
} while (0)

/*
 * Long double support
 */
#if defined(HAVE_LDOUBLE_INTEL_EXTENDED_12_BYTES_LE)
    /*
     * 定义一个类型别名 `IEEEl2bitsrep_part`,用于表示 Intel 扩展的 80 位浮点数的部分位表示
     * Bit representation is
     *          |  junk  |     s  |eeeeeeeeeeeeeee|mmmmmmmm................mmmmmmm|
     *          | 16 bits|  1 bit |    15 bits    |            64 bits            |
     *          |             a[2]                |     a[1]     |    a[0]        |
     *
     * 16 位 a[2] 中的更强的位是垃圾位
     */
    typedef npy_uint32 IEEEl2bitsrep_part;
    
    
    union IEEEl2bitsrep {
        npy_longdouble     e;       // 用长双精度浮点数表示的 IEEE 80 位浮点数
        IEEEl2bitsrep_part a[3];    // 用于访问 80 位浮点数各个部分的数组表示
    };
    
    #define LDBL_MANL_INDEX     0    // 低位部分在 a 数组中的索引
    #define LDBL_MANL_MASK      0xFFFFFFFF    // 低位部分的掩码
    #define LDBL_MANL_SHIFT     0    // 低位部分的位移
    
    #define LDBL_MANH_INDEX     1    // 高位部分在 a 数组中的索引
    #define LDBL_MANH_MASK      0xFFFFFFFF    // 高位部分的掩码
    #define LDBL_MANH_SHIFT     0    // 高位部分的位移
    
    #define LDBL_EXP_INDEX      2    // 指数部分在 a 数组中的索引
    #define LDBL_EXP_MASK       0x7FFF    // 指数部分的掩码
    #define LDBL_EXP_SHIFT      0    // 指数部分的位移
    
    #define LDBL_SIGN_INDEX     2    // 符号位在 a 数组中的索引
    #define LDBL_SIGN_MASK      0x8000    // 符号位的掩码
    #define LDBL_SIGN_SHIFT     15    // 符号位的位移
    
    #define LDBL_NBIT           0x80000000    // 用于检测 NaN 的位掩码
    
    typedef npy_uint32 ldouble_man_t;    // 用于表示长双精度浮点数低位部分的类型别名
    typedef npy_uint32 ldouble_exp_t;    // 用于表示长双精度浮点数指数部分的类型别名
    typedef npy_uint32 ldouble_sign_t;   // 用于表示长双精度浮点数符号部分的类型别名
#elif defined(HAVE_LDOUBLE_INTEL_EXTENDED_16_BYTES_LE)
    /*
     * Intel extended 80 bits precision, 16 bytes alignment.. Bit representation is
     *          |  junk  |     s  |eeeeeeeeeeeeeee|mmmmmmmm................mmmmmmm|
     *          | 16 bits|  1 bit |    15 bits    |            64 bits            |
     *          |             a[2]                |     a[1]     |    a[0]        |
     *
     * a[3] and 16 stronger bits of a[2] are junk
     */
    typedef npy_uint32 IEEEl2bitsrep_part;  // 定义IEEE长双精度类型的部分位表示

    union IEEEl2bitsrep {
        npy_longdouble     e;  // 使用长双精度类型的联合表示
        IEEEl2bitsrep_part a[4];  // 使用四个32位整数数组表示长双精度数的位
    };

    #define LDBL_MANL_INDEX     0  // 长双精度数低位的索引
    #define LDBL_MANL_MASK      0xFFFFFFFF  // 长双精度数低位的掩码
    #define LDBL_MANL_SHIFT     0  // 长双精度数低位的位移量

    #define LDBL_MANH_INDEX     1  // 长双精度数高位的索引
    #define LDBL_MANH_MASK      0xFFFFFFFF  // 长双精度数高位的掩码
    #define LDBL_MANH_SHIFT     0  // 长双精度数高位的位移量

    #define LDBL_EXP_INDEX      2  // 长双精度数指数部分的索引
    #define LDBL_EXP_MASK       0x7FFF  // 长双精度数指数部分的掩码
    #define LDBL_EXP_SHIFT      0  // 长双精度数指数部分的位移量

    #define LDBL_SIGN_INDEX     2  // 长双精度数符号位的索引
    #define LDBL_SIGN_MASK      0x8000  // 长双精度数符号位的掩码
    #define LDBL_SIGN_SHIFT     15  // 长双精度数符号位的位移量

    #define LDBL_NBIT           0x800000000  // 长双精度数N位的掩码

    typedef npy_uint32 ldouble_man_t;  // 长双精度数尾数的类型定义
    typedef npy_uint32 ldouble_exp_t;  // 长双精度数指数的类型定义
    typedef npy_uint32 ldouble_sign_t;  // 长双精度数符号的类型定义
#elif defined(HAVE_LDOUBLE_MOTOROLA_EXTENDED_12_BYTES_BE)
    /*
     * Motorola extended 80 bits precision. Bit representation is
     *          |     s  |eeeeeeeeeeeeeee|  junk  |mmmmmmmm................mmmmmmm|
     *          |  1 bit |    15 bits    | 16 bits|            64 bits            |
     *          |             a[0]                |     a[1]     |    a[2]        |
     *
     * 16 low bits of a[0] are junk
     */
    typedef npy_uint32 IEEEl2bitsrep_part;  // 定义IEEE长双精度类型的部分位表示

    union IEEEl2bitsrep {
        npy_longdouble     e;  // 使用长双精度类型的联合表示
        IEEEl2bitsrep_part a[3];  // 使用三个32位整数数组表示长双精度数的位
    };

    #define LDBL_MANL_INDEX     2  // 长双精度数低位的索引
    #define LDBL_MANL_MASK      0xFFFFFFFF  // 长双精度数低位的掩码
    #define LDBL_MANL_SHIFT     0  // 长双精度数低位的位移量

    #define LDBL_MANH_INDEX     1  // 长双精度数高位的索引
    #define LDBL_MANH_MASK      0xFFFFFFFF  // 长双精度数高位的掩码
    #define LDBL_MANH_SHIFT     0  // 长双精度数高位的位移量

    #define LDBL_EXP_INDEX      0  // 长双精度数指数部分的索引
    #define LDBL_EXP_MASK       0x7FFF0000  // 长双精度数指数部分的掩码
    #define LDBL_EXP_SHIFT      16  // 长双精度数指数部分的位移量

    #define LDBL_SIGN_INDEX     0  // 长双精度数符号位的索引
    #define LDBL_SIGN_MASK      0x80000000  // 长双精度数符号位的掩码
    #define LDBL_SIGN_SHIFT     31  // 长双精度数符号位的位移量

    #define LDBL_NBIT           0x80000000  // 长双精度数N位的掩码

    typedef npy_uint32 ldouble_man_t;  // 长双精度数尾数的类型定义
    typedef npy_uint32 ldouble_exp_t;  // 长双精度数指数的类型定义
    typedef npy_uint32 ldouble_sign_t;  // 长双精度数符号的类型定义
#elif defined(HAVE_LDOUBLE_IEEE_DOUBLE_BE)
    /* 64 bits IEEE double precision aligned on 16 bytes: used by ppc arch on
     * Mac OS X */

    /*
     * IEEE double precision. Bit representation is
     *          |  s  |eeeeeeeeeee|mmmmmmmm................mmmmmmm|
     *          |1 bit|  11 bits  |            52 bits            |
     *          |          a[0]         |         a[1]            |
     */
    typedef npy_uint32 IEEEl2bitsrep_part;  // 定义IEEE长双精度类型的部分位表示

    union IEEEl2bitsrep {
        npy_longdouble     e;  // 使用长双精度类型的联合表示
        IEEEl2bitsrep_part a[2];  // 使用两个32位整数数组表示长双精度数的位
    };

    #define LDBL_MANL_INDEX     1  // 长双精度数低位的索引
    # 定义长双精度浮点数的尾数掩码和位移量
    # 尾数掩码,用于提取尾数部分
    # 尾数位移量,用于右移操作提取尾数

    # 定义长双精度浮点数的指数索引、指数掩码和位移量
    # 指数索引,指数掩码用于提取指数部分
    # 指数掩码,用于提取指数部分
    # 指数位移量,用于右移操作提取指数部分

    # 定义长双精度浮点数的符号索引、符号掩码和位移量
    # 符号索引,符号掩码用于提取符号部分
    # 符号掩码,用于提取符号部分
    # 符号位移量,用于右移操作提取符号部分

    # 定义长双精度浮点数的最低有效位
    typedef npy_uint32 ldouble_man_t;  // 定义长双精度浮点数的尾数类型
    typedef npy_uint32 ldouble_exp_t;  // 定义长双精度浮点数的指数类型
    typedef npy_uint32 ldouble_sign_t; // 定义长双精度浮点数的符号类型
#elif defined(HAVE_LDOUBLE_IEEE_DOUBLE_LE)
    /*
     * 64 bits IEEE double precision, Little Endian.
     * 
     * IEEE double precision. Bit representation is
     *          |  s  |eeeeeeeeeee|mmmmmmmm................mmmmmmm|
     *          |1 bit|  11 bits  |            52 bits            |
     *          |          a[1]         |         a[0]            |
     */
    // 定义结构体,用于存储 IEEE 双精度浮点数的位表示
    typedef npy_uint32 IEEEl2bitsrep_part;

    // 联合体,允许以多种方式访问同一存储位置的数据
    union IEEEl2bitsrep {
        npy_longdouble     e;    // 长双精度浮点数
        IEEEl2bitsrep_part a[2]; // 用两个 32 位整数数组表示的位表示
    };

    // 定义尾数低位索引、掩码和位移量
    #define LDBL_MANL_INDEX     0
    #define LDBL_MANL_MASK      0xFFFFFFFF
    #define LDBL_MANL_SHIFT     0

    // 定义尾数高位索引、掩码和位移量
    #define LDBL_MANH_INDEX     1
    #define LDBL_MANH_MASK      0x000FFFFF
    #define LDBL_MANH_SHIFT     0

    // 定义指数索引、掩码和位移量
    #define LDBL_EXP_INDEX      1
    #define LDBL_EXP_MASK       0x7FF00000
    #define LDBL_EXP_SHIFT      20

    // 定义符号索引、掩码和位移量
    #define LDBL_SIGN_INDEX     1
    #define LDBL_SIGN_MASK      0x80000000
    #define LDBL_SIGN_SHIFT     31

    // 定义 NBIT 常量
    #define LDBL_NBIT           0x00000080

    // 定义长双精度浮点数的尾数、指数和符号类型
    typedef npy_uint32 ldouble_man_t;
    typedef npy_uint32 ldouble_exp_t;
    typedef npy_uint32 ldouble_sign_t;
    #define LDBL_EXP_MASK       0x7FFF000000000000
    #define LDBL_EXP_SHIFT      48
    
    # 定义长双精度浮点数的指数掩码和指数位移量
    # LDBL_EXP_MASK: 用于屏蔽长双精度浮点数的指数部分的掩码
    # LDBL_EXP_SHIFT: 指数部分在长双精度浮点数中的位移量
    
    
    #define LDBL_SIGN_INDEX     1
    #define LDBL_SIGN_MASK      0x8000000000000000
    #define LDBL_SIGN_SHIFT     63
    
    # 定义长双精度浮点数的符号索引、符号掩码和符号位移量
    # LDBL_SIGN_INDEX: 符号位在长双精度浮点数中的索引位置
    # LDBL_SIGN_MASK: 用于屏蔽长双精度浮点数的符号位的掩码
    # LDBL_SIGN_SHIFT: 符号位在长双精度浮点数中的位移量
    
    
    #define LDBL_NBIT           0
    
    # 定义长双精度浮点数的第一位(最高位)
    # LDBL_NBIT: 长双精度浮点数的最高位(最高有效位)
    
    typedef npy_uint64 ldouble_man_t;
    typedef npy_uint64 ldouble_exp_t;
    typedef npy_uint32 ldouble_sign_t;
    
    # 声明长双精度浮点数的尾数、指数和符号的数据类型
    # ldouble_man_t: 长双精度浮点数的尾数类型,为 64 位无符号整数
    # ldouble_exp_t: 长双精度浮点数的指数类型,为 64 位无符号整数
    # ldouble_sign_t: 长双精度浮点数的符号类型,为 32 位无符号整数
#if !defined(HAVE_LDOUBLE_IBM_DOUBLE_DOUBLE_BE) && \
    !defined(HAVE_LDOUBLE_IBM_DOUBLE_DOUBLE_LE)
/* Get the sign bit of x. x should be of type IEEEl2bitsrep */
#define GET_LDOUBLE_SIGN(x) \
    (((x).a[LDBL_SIGN_INDEX] & LDBL_SIGN_MASK) >> LDBL_SIGN_SHIFT)

/* Set the sign bit of x to v. x should be of type IEEEl2bitsrep */
#define SET_LDOUBLE_SIGN(x, v) \
  ((x).a[LDBL_SIGN_INDEX] =                                             \
   ((x).a[LDBL_SIGN_INDEX] & ~LDBL_SIGN_MASK) |                         \
   (((IEEEl2bitsrep_part)(v) << LDBL_SIGN_SHIFT) & LDBL_SIGN_MASK))

/* Get the exp bits of x. x should be of type IEEEl2bitsrep */
#define GET_LDOUBLE_EXP(x) \
    (((x).a[LDBL_EXP_INDEX] & LDBL_EXP_MASK) >> LDBL_EXP_SHIFT)

/* Set the exp bit of x to v. x should be of type IEEEl2bitsrep */
#define SET_LDOUBLE_EXP(x, v) \
  ((x).a[LDBL_EXP_INDEX] =                                              \
   ((x).a[LDBL_EXP_INDEX] & ~LDBL_EXP_MASK) |                           \
   (((IEEEl2bitsrep_part)(v) << LDBL_EXP_SHIFT) & LDBL_EXP_MASK))

/* Get the manl bits of x. x should be of type IEEEl2bitsrep */
#define GET_LDOUBLE_MANL(x) \
    (((x).a[LDBL_MANL_INDEX] & LDBL_MANL_MASK) >> LDBL_MANL_SHIFT)

/* Set the manl bit of x to v. x should be of type IEEEl2bitsrep */
#define SET_LDOUBLE_MANL(x, v) \
  ((x).a[LDBL_MANL_INDEX] =                                             \
   ((x).a[LDBL_MANL_INDEX] & ~LDBL_MANL_MASK) |                         \
   (((IEEEl2bitsrep_part)(v) << LDBL_MANL_SHIFT) & LDBL_MANL_MASK))

/* Get the manh bits of x. x should be of type IEEEl2bitsrep */
#define GET_LDOUBLE_MANH(x) \
    (((x).a[LDBL_MANH_INDEX] & LDBL_MANH_MASK) >> LDBL_MANH_SHIFT)

/* Set the manh bit of x to v. x should be of type IEEEl2bitsrep */
#define SET_LDOUBLE_MANH(x, v) \
    ((x).a[LDBL_MANH_INDEX] = \
     ((x).a[LDBL_MANH_INDEX] & ~LDBL_MANH_MASK) |                       \
     (((IEEEl2bitsrep_part)(v) << LDBL_MANH_SHIFT) & LDBL_MANH_MASK))
#endif /* !HAVE_LDOUBLE_DOUBLE_DOUBLE_* */

#endif /* !_NPY_MATH_PRIVATE_H_ */



/* 
   These macros define operations to manipulate specific bits within a structure
   representing a long double's internal bit layout. They are used when certain
   configurations for IBM's double-double long double format are not defined.
*/

/* 
   GET_LDOUBLE_SIGN(x): Retrieves the sign bit from the IEEEl2bitsrep structure x.

   SET_LDOUBLE_SIGN(x, v): Sets the sign bit of x to the value v (0 or 1).

   GET_LDOUBLE_EXP(x): Retrieves the exponent bits from the IEEEl2bitsrep structure x.

   SET_LDOUBLE_EXP(x, v): Sets the exponent bits of x to the value v.

   GET_LDOUBLE_MANL(x): Retrieves the lower part of the mantissa from the IEEEl2bitsrep structure x.

   SET_LDOUBLE_MANL(x, v): Sets the lower part of the mantissa of x to the value v.

   GET_LDOUBLE_MANH(x): Retrieves the higher part of the mantissa from the IEEEl2bitsrep structure x.

   SET_LDOUBLE_MANH(x, v): Sets the higher part of the mantissa of x to the value v.
*/

/*
   The #endif directives close conditional compilation blocks, checking for specific configurations
   of IBM's double-double long double format and preventing redefinition of these macros when those
   configurations are defined. The final #endif closes the conditional block started by #if.
*/

/*
   The final #endif closes a conditional block based on whether the header file _NPY_MATH_PRIVATE_H_ 
   is defined, ensuring proper inclusion of content based on preprocessor directives.
*/

.\numpy\numpy\_core\src\npysort\binsearch.cpp

/* -*- c -*- */

// 禁用已弃用的 NumPy API
#define NPY_NO_DEPRECATED_API NPY_API_VERSION

// 引入 NumPy 的数组类型和通用头文件
#include "numpy/ndarraytypes.h"
#include "numpy/npy_common.h"

// 引入排序和二分搜索相关的自定义头文件
#include "npy_binsearch.h"
#include "npy_sort.h"
#include "numpy_tag.h"

// 引入标准库头文件
#include <array>
#include <functional>  // 用于 std::less 和 std::less_equal

// binsearch 函数的搜索变体的枚举器
enum arg_t
{
    noarg,  // 无参数
    arg     // 有参数
};
enum side_t
{
    left,   // 左侧
    right   // 右侧
};

// 将枚举器映射到比较器的模板
template <class Tag, side_t side>
struct side_to_cmp;

// 左侧搜索比较器的特化
template <class Tag>
struct side_to_cmp<Tag, left> {
    static constexpr auto value = Tag::less;  // 使用 Tag 的 less 函数对象
};

// 右侧搜索比较器的特化
template <class Tag>
struct side_to_cmp<Tag, right> {
    static constexpr auto value = Tag::less_equal;  // 使用 Tag 的 less_equal 函数对象
};

// 将搜索方向映射到通用比较器的模板
template <side_t side>
struct side_to_generic_cmp;

// 左侧搜索通用比较器的特化
template <>
struct side_to_generic_cmp<left> {
    using type = std::less<int>;  // 使用 std::less 进行整数比较
};

// 右侧搜索通用比较器的特化
template <>
struct side_to_generic_cmp<right> {
    using type = std::less_equal<int>;  // 使用 std::less_equal 进行整数比较
};

/*
 *****************************************************************************
 **                            NUMERIC SEARCHES                             **
 *****************************************************************************
 */

// 泛型二分搜索函数的实现
template <class Tag, side_t side>
static void
binsearch(const char *arr, const char *key, char *ret, npy_intp arr_len,
          npy_intp key_len, npy_intp arr_str, npy_intp key_str,
          npy_intp ret_str, PyArrayObject *)
{
    using T = typename Tag::type;  // 使用 Tag 的类型 T
    auto cmp = side_to_cmp<Tag, side>::value;  // 获取比较器函数对象
    npy_intp min_idx = 0;
    npy_intp max_idx = arr_len;
    T last_key_val;

    if (key_len == 0) {
        return;  // 如果 key 长度为 0,则直接返回
    }
    last_key_val = *(const T *)key;  // 获取第一个 key 的值

    for (; key_len > 0; key_len--, key += key_str, ret += ret_str) {
        const T key_val = *(const T *)key;  // 获取当前 key 的值
        /*
         * 根据前一个 key 值更新索引,当 key 是有序的时候能显著提升搜索效率,
         * 但对于纯随机的情况略微降低速度。
         */
        if (cmp(last_key_val, key_val)) {
            max_idx = arr_len;  // 如果上一个 key 小于当前 key,则更新最大索引
        }
        else {
            min_idx = 0;  // 否则重置最小索引
            max_idx = (max_idx < arr_len) ? (max_idx + 1) : arr_len;  // 更新最大索引
        }

        last_key_val = key_val;  // 更新上一个 key 的值为当前 key

        while (min_idx < max_idx) {
            const npy_intp mid_idx = min_idx + ((max_idx - min_idx) >> 1);  // 计算中间索引
            const T mid_val = *(const T *)(arr + mid_idx * arr_str);  // 获取中间值
            if (cmp(mid_val, key_val)) {
                min_idx = mid_idx + 1;  // 更新最小索引
            }
            else {
                max_idx = mid_idx;  // 更新最大索引
            }
        }
        *(npy_intp *)ret = min_idx;  // 将结果存入 ret 中
    }
}

// 带参数的泛型二分搜索函数的实现
template <class Tag, side_t side>
static int
argbinsearch(const char *arr, const char *key, const char *sort, char *ret,
             npy_intp arr_len, npy_intp key_len, npy_intp arr_str,
             npy_intp key_str, npy_intp sort_str, npy_intp ret_str,
             PyArrayObject *)
{
    using T = typename Tag::type;  // 使用 Tag 的类型 T
    auto cmp = side_to_cmp<Tag, side>::value;  // 获取比较器函数对象
    npy_intp min_idx = 0;  // 初始化最小索引为0,表示搜索范围的起始位置
    npy_intp max_idx = arr_len;  // 初始化最大索引为数组长度,表示搜索范围的结束位置
    T last_key_val;  // 声明变量用于存储上一个比较的关键值

    if (key_len == 0) {
        return 0;  // 如果关键字长度为0,直接返回0
    }
    last_key_val = *(const T *)key;  // 获取关键字的第一个元素作为初始的上一个关键值

    for (; key_len > 0; key_len--, key += key_str, ret += ret_str) {
        const T key_val = *(const T *)key;  // 获取当前关键字的值

        /*
         * 根据前一个关键字值更新索引范围,
         * 当关键字按顺序排列时,这样做可以显著提升搜索效率,
         * 但是对于完全随机的关键字会略微减慢速度。
         */
        if (cmp(last_key_val, key_val)) {
            max_idx = arr_len;  // 如果当前关键字与上一个不同,则更新最大索引为数组长度
        }
        else {
            min_idx = 0;  // 如果当前关键字与上一个相同,则重置最小索引为0
            max_idx = (max_idx < arr_len) ? (max_idx + 1) : arr_len;  // 并增加最大索引,但不超过数组长度
        }

        last_key_val = key_val;  // 更新上一个关键值为当前关键值

        while (min_idx < max_idx) {
            const npy_intp mid_idx = min_idx + ((max_idx - min_idx) >> 1);  // 计算中间索引位置
            const npy_intp sort_idx = *(npy_intp *)(sort + mid_idx * sort_str);  // 获取排序后的索引值
            T mid_val;

            if (sort_idx < 0 || sort_idx >= arr_len) {
                return -1;  // 如果排序索引超出有效范围,返回错误标志
            }

            mid_val = *(const T *)(arr + sort_idx * arr_str);  // 获取数组中排序后位置的值

            if (cmp(mid_val, key_val)) {
                min_idx = mid_idx + 1;  // 如果中间值小于关键值,更新最小索引为中间索引加一
            }
            else {
                max_idx = mid_idx;  // 否则更新最大索引为中间索引
            }
        }
        *(npy_intp *)ret = min_idx;  // 将最小索引值写入返回值中
    }
    return 0;  // 返回成功标志
/*
 * 使用模板函数实现二分查找算法,查找指定键在排序数组中的位置
 * 参数说明:
 * - arr: 输入数组的起始地址
 * - key: 要查找的键的起始地址
 * - ret: 返回的位置的地址
 * - arr_len: 数组的长度
 * - key_len: 键的长度(假设是键的长度,可能是用来迭代的计数器)
 * - arr_str: 数组中每个元素的步长(假设是元素之间的偏移量)
 * - key_str: 键中每个字符的步长(假设是字符之间的偏移量)
 * - ret_str: 返回位置指针每次迭代时的步长
 * - cmp: 用于比较元素的对象
 */
template <side_t side>
static void
npy_binsearch(const char *arr, const char *key, char *ret, npy_intp arr_len,
              npy_intp key_len, npy_intp arr_str, npy_intp key_str,
              npy_intp ret_str, PyArrayObject *cmp)
{
    // 使用模板元编程,根据边界方向选择相应的比较器类型
    using Cmp = typename side_to_generic_cmp<side>::type;
    // 获取用于比较元素的函数指针
    PyArray_CompareFunc *compare = PyDataType_GetArrFuncs(PyArray_DESCR(cmp))->compare;
    // 初始化二分查找的起始和结束位置
    npy_intp min_idx = 0;
    npy_intp max_idx = arr_len;
    // 记录上一个键的位置
    const char *last_key = key;

    // 循环遍历每个键
    for (; key_len > 0; key_len--, key += key_str, ret += ret_str) {
        /*
         * 当前键与上一个键进行比较,根据比较结果更新搜索范围的下界和上界
         * 当键有序时,根据上一个键的比较结果更新搜索范围,优化查找速度;
         * 当键是随机的时,可能会轻微减慢速度。
         */
        if (Cmp{}(compare(last_key, key, cmp), 0)) {
            max_idx = arr_len;
        }
        else {
            min_idx = 0;
            max_idx = (max_idx < arr_len) ? (max_idx + 1) : arr_len;
        }

        // 更新上一个键的位置
        last_key = key;

        // 二分查找算法
        while (min_idx < max_idx) {
            const npy_intp mid_idx = min_idx + ((max_idx - min_idx) >> 1);
            const char *arr_ptr = arr + mid_idx * arr_str;

            // 根据比较结果更新搜索范围
            if (Cmp{}(compare(arr_ptr, key, cmp), 0)) {
                min_idx = mid_idx + 1;
            }
            else {
                max_idx = mid_idx;
            }
        }
        // 将当前位置保存到返回位置的指针中
        *(npy_intp *)ret = min_idx;
    }
}

/*
 * 使用模板函数实现二分查找算法,查找指定键在排序数组中的位置
 * 参数说明:
 * - arr: 输入数组的起始地址
 * - key: 要查找的键的起始地址
 * - sort: 排序数组的起始地址(假设是排序数组,可能用于比较)
 * - ret: 返回的位置的地址
 * - arr_len: 数组的长度
 * - key_len: 键的长度(假设是键的长度,可能是用来迭代的计数器)
 * - arr_str: 数组中每个元素的步长(假设是元素之间的偏移量)
 * - key_str: 键中每个字符的步长(假设是字符之间的偏移量)
 * - sort_str: 排序数组中每个元素的步长(假设是元素之间的偏移量)
 * - ret_str: 返回位置指针每次迭代时的步长
 * - cmp: 用于比较元素的对象
 * 返回值:
 * - 返回找到的位置的索引,或者是否找到(假设是成功返回索引,失败返回-1)
 */
template <side_t side>
static int
npy_argbinsearch(const char *arr, const char *key, const char *sort, char *ret,
                 npy_intp arr_len, npy_intp key_len, npy_intp arr_str,
                 npy_intp key_str, npy_intp sort_str, npy_intp ret_str,
                 PyArrayObject *cmp)
{
    // 使用模板元编程,根据边界方向选择相应的比较器类型
    using Cmp = typename side_to_generic_cmp<side>::type;
    // 获取用于比较元素的函数指针
    PyArray_CompareFunc *compare = PyDataType_GetArrFuncs(PyArray_DESCR(cmp))->compare;
    // 初始化二分查找的起始和结束位置
    npy_intp min_idx = 0;
    npy_intp max_idx = arr_len;
    // 记录上一个键的位置
    const char *last_key = key;

    // 循环遍历每个键
    for (; key_len > 0; key_len--, key += key_str, ret += ret_str) {
        /*
         * 当前键与上一个键进行比较,根据比较结果更新搜索范围的下界和上界
         * 当键有序时,根据上一个键的比较结果更新搜索范围,优化查找速度;
         * 当键是随机的时,可能会轻微减慢速度。
         */
        if (Cmp{}(compare(last_key, key, cmp), 0)) {
            max_idx = arr_len;
        }
        else {
            min_idx = 0;
            max_idx = (max_idx < arr_len) ? (max_idx + 1) : arr_len;
        }

        // 更新上一个键的位置
        last_key = key;

        // 二分查找算法
        while (min_idx < max_idx) {
            const npy_intp mid_idx = min_idx + ((max_idx - min_idx) >> 1);
            const char *arr_ptr = arr + mid_idx * arr_str;

            // 根据比较结果更新搜索范围
            if (Cmp{}(compare(arr_ptr, key, cmp), 0)) {
                min_idx = mid_idx + 1;
            }
            else {
                max_idx = mid_idx;
            }
        }
        // 将当前位置保存到返回位置的指针中
        *(npy_intp *)ret = min_idx;
    }

    // 返回找到的位置的索引,或者是否找到(假设是成功返回索引,失败返回-1return (min_idx < arr_len && compare(arr + min_idx * arr_str, key, cmp) == 0) ? min_idx : -1;
}
    for (; key_len > 0; key_len--, key += key_str, ret += ret_str) {
        /*
         * 根据前一个键的比较结果更新索引,当键有序时,可以显著提升搜索速度,
         * 但对于完全随机的键略微降低速度。
         */
        
        // 根据最后一个键与当前键的比较结果,更新最大索引
        if (Cmp{}(compare(last_key, key, cmp), 0)) {
            max_idx = arr_len;
        }
        else {
            min_idx = 0;
            max_idx = (max_idx < arr_len) ? (max_idx + 1) : arr_len;
        }

        // 更新最后一个键为当前键
        last_key = key;

        // 二分查找在排序数组中定位键的位置
        while (min_idx < max_idx) {
            // 计算中间索引
            const npy_intp mid_idx = min_idx + ((max_idx - min_idx) >> 1);
            // 获取排序索引
            const npy_intp sort_idx = *(npy_intp *)(sort + mid_idx * sort_str);
            const char *arr_ptr;

            // 检查排序索引是否有效
            if (sort_idx < 0 || sort_idx >= arr_len) {
                return -1;
            }

            // 获取数组中的指针
            arr_ptr = arr + sort_idx * arr_str;

            // 比较数组中的值和当前键的大小
            if (Cmp{}(compare(arr_ptr, key, cmp), 0)) {
                // 更新最小索引以查找更大的键
                min_idx = mid_idx + 1;
            }
            else {
                // 更新最大索引以查找更小的键
                max_idx = mid_idx;
            }
        }
        
        // 将搜索结果写入返回数组中
        *(npy_intp *)ret = min_idx;
    }
    // 返回成功标志
    return 0;
/*
 *****************************************************************************
 **                             GENERATOR                                   **
 *****************************************************************************
 */

// 模板声明:二分搜索基类
template <arg_t arg>
struct binsearch_base;

// 特化模板:针对具有参数的情况(arg != noarg)
template <>
struct binsearch_base<arg> {
    // 定义函数指针类型
    using function_type = PyArray_ArgBinSearchFunc *;
    
    // 值类型结构体定义
    struct value_type {
        int typenum;  // 类型编号
        function_type binsearch[NPY_NSEARCHSIDES];  // 二分搜索函数指针数组
    };
    
    // 生成二分搜索映射表的静态方法
    template <class... Tags>
    static constexpr std::array<value_type, sizeof...(Tags)>
    make_binsearch_map(npy::taglist<Tags...>)
    {
        // 返回由标签列表生成的值类型数组
        return std::array<value_type, sizeof...(Tags)>{
                value_type{Tags::type_value,
                           {(function_type)&argbinsearch<Tags, left>,
                            (function_type)argbinsearch<Tags, right>}}...};
    }
    
    // 静态成员:无参数的二分搜索函数指针数组
    static constexpr std::array<function_type, 2> npy_map = {
            (function_type)&npy_argbinsearch<left>,
            (function_type)&npy_argbinsearch<right>};
};

// 初始化静态成员:无参数的二分搜索函数指针数组
constexpr std::array<binsearch_base<arg>::function_type, 2>
        binsearch_base<arg>::npy_map;

// 特化模板:针对无参数的情况(arg == noarg)
template <>
struct binsearch_base<noarg> {
    // 定义函数指针类型
    using function_type = PyArray_BinSearchFunc *;
    
    // 值类型结构体定义
    struct value_type {
        int typenum;  // 类型编号
        function_type binsearch[NPY_NSEARCHSIDES];  // 二分搜索函数指针数组
    };
    
    // 生成二分搜索映射表的静态方法
    template <class... Tags>
    static constexpr std::array<value_type, sizeof...(Tags)>
    make_binsearch_map(npy::taglist<Tags...>)
    {
        // 返回由标签列表生成的值类型数组
        return std::array<value_type, sizeof...(Tags)>{
                value_type{Tags::type_value,
                           {(function_type)&binsearch<Tags, left>,
                            (function_type)binsearch<Tags, right>}}...};
    }
    
    // 静态成员:有参数的二分搜索函数指针数组
    static constexpr std::array<function_type, 2> npy_map = {
            (function_type)&npy_binsearch<left>,
            (function_type)&npy_binsearch<right>};
};

// 初始化静态成员:有参数的二分搜索函数指针数组
constexpr std::array<binsearch_base<noarg>::function_type, 2>
        binsearch_base<noarg>::npy_map;

// 处理所有二分搜索变体的生成
template <arg_t arg>
struct binsearch_t : binsearch_base<arg> {
    // 继承基类的 make_binsearch_map 方法
    using binsearch_base<arg>::make_binsearch_map;
    // 定义值类型为基类的值类型
    using value_type = typename binsearch_base<arg>::value_type;

    // 定义标签列表类型
    using taglist = npy::taglist<
            /* If adding new types, make sure to keep them ordered by type num
             */
            npy::bool_tag, npy::byte_tag, npy::ubyte_tag, npy::short_tag,
            npy::ushort_tag, npy::int_tag, npy::uint_tag, npy::long_tag,
            npy::ulong_tag, npy::longlong_tag, npy::ulonglong_tag,
            npy::float_tag, npy::double_tag, npy::longdouble_tag, 
            npy::cfloat_tag, npy::cdouble_tag, npy::clongdouble_tag, 
            npy::datetime_tag, npy::timedelta_tag, npy::half_tag>;

    // 静态成员:标签列表映射表
    static constexpr std::array<value_type, taglist::size> map =
            make_binsearch_map(taglist());
};

// 模板声明:二分搜索变体
template <arg_t arg>
/*
 * 用于存储二进制搜索函数的映射表,具体类型和大小由模板参数arg决定
 */
constexpr std::array<typename binsearch_t<arg>::value_type,
                     binsearch_t<arg>::taglist::size>
        binsearch_t<arg>::map;

/*
 * 获取特定类型arg的二进制搜索函数,根据dtype和side参数返回相应的函数指针
 */
template <arg_t arg>
static inline typename binsearch_t<arg>::function_type
_get_binsearch_func(PyArray_Descr *dtype, NPY_SEARCHSIDE side)
{
    // 使用binsearch_t<arg>简化类型名称
    using binsearch = binsearch_t<arg>;
    // 获取映射表的大小
    npy_intp nfuncs = binsearch::map.size();
    // 初始化搜索范围的下界和上界
    npy_intp min_idx = 0;
    npy_intp max_idx = nfuncs;
    // 获取dtype的类型编号
    int type = dtype->type_num;

    // 检查side参数是否有效,若无效则返回NULL
    if ((int)side >= (int)NPY_NSEARCHSIDES) {
        return NULL;
    }

    /*
     * 使用二分搜索算法查找符合dtype类型的二进制搜索函数
     */
    while (min_idx < max_idx) {
        // 计算中间索引
        npy_intp mid_idx = min_idx + ((max_idx - min_idx) >> 1);

        // 根据类型编号比较映射表中的元素,调整搜索范围
        if (binsearch::map[mid_idx].typenum < type) {
            min_idx = mid_idx + 1;
        }
        else {
            max_idx = mid_idx;
        }
    }

    // 如果找到对应dtype类型的函数,则返回该函数指针
    if (min_idx < nfuncs && binsearch::map[min_idx].typenum == type) {
        return binsearch::map[min_idx].binsearch[side];
    }

    // 若未找到对应dtype类型的函数,且dtype具有比较功能,则返回通用的二进制搜索函数
    if (PyDataType_GetArrFuncs(dtype)->compare) {
        return binsearch::npy_map[side];
    }

    // 若以上条件都不满足,则返回NULL
    return NULL;
}

/*
 *****************************************************************************
 **                            C INTERFACE                                  **
 *****************************************************************************
 */

extern "C" {
    // 返回无参数版本(noarg)的二进制搜索函数
    NPY_NO_EXPORT PyArray_BinSearchFunc *
    get_binsearch_func(PyArray_Descr *dtype, NPY_SEARCHSIDE side)
    {
        return _get_binsearch_func<noarg>(dtype, side);
    }

    // 返回带参数版本(arg)的二进制搜索函数
    NPY_NO_EXPORT PyArray_ArgBinSearchFunc *
    get_argbinsearch_func(PyArray_Descr *dtype, NPY_SEARCHSIDE side)
    {
        return _get_binsearch_func<arg>(dtype, side);
    }
}

.\numpy\numpy\_core\src\npysort\heapsort.cpp

/*
 * The purpose of this module is to add faster sort functions
 * that are type-specific.  This is done by altering the
 * function table for the builtin descriptors.
 *
 * These sorting functions are copied almost directly from numarray
 * with a few modifications (complex comparisons compare the imaginary
 * part if the real parts are equal, for example), and the names
 * are changed.
 *
 * The original sorting code is due to Charles R. Harris who wrote
 * it for numarray.
 */

/*
 * Quick sort is usually the fastest, but the worst case scenario can
 * be slower than the merge and heap sorts.  The merge sort requires
 * extra memory and so for large arrays may not be useful.
 *
 * The merge sort is *stable*, meaning that equal components
 * are unmoved from their entry versions, so it can be used to
 * implement lexicographic sorting on multiple keys.
 *
 * The heap sort is included for completeness.
 */

#define NPY_NO_DEPRECATED_API NPY_API_VERSION

#include "npy_sort.h"              /* 包含排序相关的头文件 */
#include "npysort_common.h"        /* 包含排序通用的头文件 */
#include "numpy_tag.h"             /* 包含 numpy 标签相关的头文件 */

#include "npysort_heapsort.h"      /* 包含堆排序的头文件 */

#include <cstdlib>                 /* 包含标准库函数 */

#define NOT_USED NPY_UNUSED(unused) /* 定义一个宏,表示未使用的变量 */
#define PYA_QS_STACK 100            /* 定义快速排序的堆栈大小 */
#define SMALL_QUICKSORT 15          /* 定义快速排序的阈值 */
#define SMALL_MERGESORT 20          /* 定义归并排序的阈值 */
#define SMALL_STRING 16             /* 定义字符串的阈值 */


/*
 *****************************************************************************
 **                             GENERIC SORT                                **
 *****************************************************************************
 */

NPY_NO_EXPORT int
npy_heapsort(void *start, npy_intp num, void *varr)
{
    PyArrayObject *arr = (PyArrayObject *)varr;   /* 将输入转换为 PyArrayObject 类型 */
    npy_intp elsize = PyArray_ITEMSIZE(arr);      /* 获取数组元素的大小 */
    PyArray_CompareFunc *cmp = PyDataType_GetArrFuncs(PyArray_DESCR(arr))->compare;  /* 获取比较函数 */

    if (elsize == 0) {
        return 0;  /* 如果元素大小为0,无需排序 */
    }

    char *tmp = (char *)malloc(elsize);  /* 分配临时空间 */
    char *a = (char *)start - elsize;     /* 起始位置 */

    npy_intp i, j, l;

    if (tmp == NULL) {
        return -NPY_ENOMEM;  /* 如果内存分配失败,返回内存不足错误 */
    }

    for (l = num >> 1; l > 0; --l) {
        GENERIC_COPY(tmp, a + l * elsize, elsize);  /* 复制元素到临时空间 */
        for (i = l, j = l << 1; j <= num;) {
            if (j < num &&
                cmp(a + j * elsize, a + (j + 1) * elsize, arr) < 0) {
                ++j;  /* 如果右边元素比较大,移动到下一个 */
            }
            if (cmp(tmp, a + j * elsize, arr) < 0) {
                GENERIC_COPY(a + i * elsize, a + j * elsize, elsize);  /* 复制元素 */
                i = j;  /* 更新位置 */
                j += j; /* 增加步长 */
            }
            else {
                break;  /* 跳出循环 */
            }
        }
        GENERIC_COPY(a + i * elsize, tmp, elsize);  /* 复制元素 */
    }
    // 循环执行直到 num 变为 1
    for (; num > 1;) {
        // 将 a[num * elsize] 处的元素复制到 tmp 中
        GENERIC_COPY(tmp, a + num * elsize, elsize);
        // 将 a[elsize] 处的元素复制到 a[num * elsize] 处
        GENERIC_COPY(a + num * elsize, a + elsize, elsize);
        // num 减少 1
        num -= 1;
        // 开始堆排序的调整过程
        for (i = 1, j = 2; j <= num;) {
            // 比较 a[j * elsize] 和 a[(j + 1) * elsize],选择较大的
            if (j < num &&
                cmp(a + j * elsize, a + (j + 1) * elsize, arr) < 0) {
                ++j;
            }
            // 如果 tmp 小于 a[j * elsize],则进行元素交换
            if (cmp(tmp, a + j * elsize, arr) < 0) {
                GENERIC_COPY(a + i * elsize, a + j * elsize, elsize);
                i = j;
                j += j;  // j 的增加方式有误,应该为 j *= 2
            }
            else {
                break;
            }
        }
        // 将 tmp 复制到 a[i * elsize] 处
        GENERIC_COPY(a + i * elsize, tmp, elsize);
    }

    // 释放 tmp 所占用的内存
    free(tmp);
    // 返回 0 表示排序完成
    return 0;
}

NPY_NO_EXPORT int
npy_aheapsort(void *vv, npy_intp *tosort, npy_intp n, void *varr)
{
    // 将输入指针 vv 转换为 char 类型,这样可以按字节访问数据
    char *v = (char *)vv;
    // 将输入指针 varr 转换为 PyArrayObject 类型,以便访问 NumPy 数组的信息和方法
    PyArrayObject *arr = (PyArrayObject *)varr;
    // 计算数组元素的大小(以字节为单位)
    npy_intp elsize = PyArray_ITEMSIZE(arr);
    // 获取 NumPy 数组的比较函数指针,用于比较数组元素
    PyArray_CompareFunc *cmp = PyDataType_GetArrFuncs(PyArray_DESCR(arr))->compare;
    // 定义指向排序后索引数组的指针 a,进行堆排序需要偏移一位
    npy_intp *a, i, j, l, tmp;

    /* The array needs to be offset by one for heapsort indexing */
    // 对排序索引数组 tosort 进行偏移,使其能正确用于堆排序
    a = tosort - 1;

    // 建立最大堆
    for (l = n >> 1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l << 1; j <= n;) {
            // 比较子节点和父节点的值,并根据需要交换它们,以维持堆的性质
            if (j < n &&
                cmp(v + a[j] * elsize, v + a[j + 1] * elsize, arr) < 0) {
                ++j;
            }
            if (cmp(v + tmp * elsize, v + a[j] * elsize, arr) < 0) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    // 堆排序
    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            // 比较子节点和父节点的值,并根据需要交换它们,以维持堆的性质
            if (j < n &&
                cmp(v + a[j] * elsize, v + a[j + 1] * elsize, arr) < 0) {
                ++j;
            }
            if (cmp(v + tmp * elsize, v + a[j] * elsize, arr) < 0) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    // 堆排序完成,返回 0 表示成功
    return 0;
}

/***************************************
 * C > C++ dispatch
 ***************************************/

// 布尔类型的堆排序特化模板实例化及函数定义
template NPY_NO_EXPORT int
heapsort_<npy::bool_tag, npy_bool>(npy_bool *, npy_intp);
NPY_NO_EXPORT int
heapsort_bool(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    // 调用布尔类型的堆排序函数并返回结果
    return heapsort_<npy::bool_tag>((npy_bool *)start, n);
}

// 字节类型的堆排序特化模板实例化及函数定义
template NPY_NO_EXPORT int
heapsort_<npy::byte_tag, npy_byte>(npy_byte *, npy_intp);
NPY_NO_EXPORT int
heapsort_byte(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    // 调用字节类型的堆排序函数并返回结果
    return heapsort_<npy::byte_tag>((npy_byte *)start, n);
}

// 无符号字节类型的堆排序特化模板实例化及函数定义
template NPY_NO_EXPORT int
heapsort_<npy::ubyte_tag, npy_ubyte>(npy_ubyte *, npy_intp);
NPY_NO_EXPORT int
heapsort_ubyte(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    // 调用无符号字节类型的堆排序函数并返回结果
    return heapsort_<npy::ubyte_tag>((npy_ubyte *)start, n);
}

// 短整型类型的堆排序特化模板实例化及函数定义
template NPY_NO_EXPORT int
heapsort_<npy::short_tag, npy_short>(npy_short *, npy_intp);
NPY_NO_EXPORT int
heapsort_short(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    // 调用短整型类型的堆排序函数并返回结果
    return heapsort_<npy::short_tag>((npy_short *)start, n);
}

// 无符号短整型类型的堆排序特化模板实例化及函数定义
template NPY_NO_EXPORT int
heapsort_<npy::ushort_tag, npy_ushort>(npy_ushort *, npy_intp);
NPY_NO_EXPORT int
heapsort_ushort(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    // 调用无符号短整型类型的堆排序函数并返回结果
    return heapsort_<npy::ushort_tag>((npy_ushort *)start, n);
}

// 整型类型的堆排序特化模板实例化及函数定义
template NPY_NO_EXPORT int
heapsort_<npy::int_tag, npy_int>(npy_int *, npy_intp);
NPY_NO_EXPORT int
heapsort_int(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    // 调用整型类型的堆排序函数并返回结果
    return heapsort_<npy::int_tag>((npy_int *)start, n);
}

// 模板函数的声明部分截至此处
template NPY_NO_EXPORT int
heapsort_<npy::uint_tag, npy_uint>(npy_uint *, npy_intp);
# 声明一个模板函数 heapsort_,用于对无符号整数数组进行堆排序

NPY_NO_EXPORT int
heapsort_uint(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对无符号整数数组进行堆排序,并返回排序结果
    return heapsort_<npy::uint_tag>((npy_uint *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::long_tag, npy_long>(npy_long *, npy_intp);
# 声明一个模板函数 heapsort_,用于对长整型数组进行堆排序

NPY_NO_EXPORT int
heapsort_long(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对长整型数组进行堆排序,并返回排序结果
    return heapsort_<npy::long_tag>((npy_long *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::ulong_tag, npy_ulong>(npy_ulong *, npy_intp);
# 声明一个模板函数 heapsort_,用于对无符号长整型数组进行堆排序

NPY_NO_EXPORT int
heapsort_ulong(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对无符号长整型数组进行堆排序,并返回排序结果
    return heapsort_<npy::ulong_tag>((npy_ulong *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::longlong_tag, npy_longlong>(npy_longlong *, npy_intp);
# 声明一个模板函数 heapsort_,用于对长长整型数组进行堆排序

NPY_NO_EXPORT int
heapsort_longlong(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对长长整型数组进行堆排序,并返回排序结果
    return heapsort_<npy::longlong_tag>((npy_longlong *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::ulonglong_tag, npy_ulonglong>(npy_ulonglong *, npy_intp);
# 声明一个模板函数 heapsort_,用于对无符号长长整型数组进行堆排序

NPY_NO_EXPORT int
heapsort_ulonglong(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对无符号长长整型数组进行堆排序,并返回排序结果
    return heapsort_<npy::ulonglong_tag>((npy_ulonglong *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::half_tag, npy_half>(npy_half *, npy_intp);
# 声明一个模板函数 heapsort_,用于对半精度浮点数数组进行堆排序

NPY_NO_EXPORT int
heapsort_half(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对半精度浮点数数组进行堆排序,并返回排序结果
    return heapsort_<npy::half_tag>((npy_half *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::float_tag, npy_float>(npy_float *, npy_intp);
# 声明一个模板函数 heapsort_,用于对单精度浮点数数组进行堆排序

NPY_NO_EXPORT int
heapsort_float(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对单精度浮点数数组进行堆排序,并返回排序结果
    return heapsort_<npy::float_tag>((npy_float *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::double_tag, npy_double>(npy_double *, npy_intp);
# 声明一个模板函数 heapsort_,用于对双精度浮点数数组进行堆排序

NPY_NO_EXPORT int
heapsort_double(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对双精度浮点数数组进行堆排序,并返回排序结果
    return heapsort_<npy::double_tag>((npy_double *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::longdouble_tag, npy_longdouble>(npy_longdouble *, npy_intp);
# 声明一个模板函数 heapsort_,用于对长双精度浮点数数组进行堆排序

NPY_NO_EXPORT int
heapsort_longdouble(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对长双精度浮点数数组进行堆排序,并返回排序结果
    return heapsort_<npy::longdouble_tag>((npy_longdouble *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::cfloat_tag, npy_cfloat>(npy_cfloat *, npy_intp);
# 声明一个模板函数 heapsort_,用于对复数浮点数数组进行堆排序

NPY_NO_EXPORT int
heapsort_cfloat(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对复数浮点数数组进行堆排序,并返回排序结果
    return heapsort_<npy::cfloat_tag>((npy_cfloat *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::cdouble_tag, npy_cdouble>(npy_cdouble *, npy_intp);
# 声明一个模板函数 heapsort_,用于对复数双精度浮点数数组进行堆排序

NPY_NO_EXPORT int
heapsort_cdouble(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对复数双精度浮点数数组进行堆排序,并返回排序结果
    return heapsort_<npy::cdouble_tag>((npy_cdouble *)start, n);
}

template NPY_NO_EXPORT int
heapsort_<npy::clongdouble_tag, npy_clongdouble>(npy_clongdouble *, npy_intp);
# 声明一个模板函数 heapsort_,用于对复数长双精度浮点数数组进行堆排序

NPY_NO_EXPORT int
heapsort_clongdouble(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    # 调用具体化的 heapsort_ 函数来对复数长双精度浮点数数组进行堆排序,并返回排序结果
    return heapsort_<npy::clongdouble_tag>((npy_clongdouble *)start, n);
}
//cpp
// 声明一个模板函数,用于对日期时间类型进行堆排序,函数参数为日期时间数组和数组长度
template NPY_NO_EXPORT int heapsort_<npy::datetime_tag, npy_datetime>(npy_datetime *, npy_intp);

// 实现对日期时间类型进行堆排序的函数,函数参数为起始地址、数组长度和一个未使用的参数(varr)
NPY_NO_EXPORT int heapsort_datetime(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    // 调用模板函数 heapsort_<npy::datetime_tag> 进行堆排序,返回排序后的结果
    return heapsort_<npy::datetime_tag>((npy_datetime *)start, n);
}

// 类似地,声明一个模板函数,用于对时间差类型进行堆排序
template NPY_NO_EXPORT int heapsort_<npy::timedelta_tag, npy_timedelta>(npy_timedelta *, npy_intp);

// 实现对时间差类型进行堆排序的函数,参数和用法与上一个函数相似
NPY_NO_EXPORT int heapsort_timedelta(void *start, npy_intp n, void *NPY_UNUSED(varr))
{
    return heapsort_<npy::timedelta_tag>((npy_timedelta *)start, n);
}

// 声明一个模板函数,用于对布尔类型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::bool_tag, npy_bool>(npy_bool *vv, npy_intp *tosort, npy_intp n);

// 实现对布尔类型进行堆排序的函数,参数和用法与上一个函数相似
NPY_NO_EXPORT int aheapsort_bool(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::bool_tag>((npy_bool *)vv, tosort, n);
}

// 类似地,声明模板函数和实现函数,用于对字节类型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::byte_tag, npy_byte>(npy_byte *vv, npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int aheapsort_byte(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::byte_tag>((npy_byte *)vv, tosort, n);
}

// 对无符号字节类型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::ubyte_tag, npy_ubyte>(npy_ubyte *vv, npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int aheapsort_ubyte(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::ubyte_tag>((npy_ubyte *)vv, tosort, n);
}

// 对短整型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::short_tag, npy_short>(npy_short *vv, npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int aheapsort_short(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::short_tag>((npy_short *)vv, tosort, n);
}

// 对无符号短整型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::ushort_tag, npy_ushort>(npy_ushort *vv, npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int aheapsort_ushort(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::ushort_tag>((npy_ushort *)vv, tosort, n);
}

// 对整型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::int_tag, npy_int>(npy_int *vv, npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int aheapsort_int(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::int_tag>((npy_int *)vv, tosort, n);
}

// 对无符号整型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::uint_tag, npy_uint>(npy_uint *vv, npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int aheapsort_uint(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::uint_tag>((npy_uint *)vv, tosort, n);
}

// 对长整型进行堆排序
template NPY_NO_EXPORT int aheapsort_<npy::long_tag, npy_long>(npy_long *vv, npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int aheapsort_long(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::long_tag>((npy_long *)vv, tosort, n);
}
# 实例化模板,对无符号长整型数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::ulong_tag, npy_ulong>(npy_ulong *vv, npy_intp *tosort,
                                      npy_intp n);
# 声明对无符号长整型数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_ulong(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::ulong_tag>((npy_ulong *)vv, tosort, n);
}

# 实例化模板,对长长整型数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::longlong_tag, npy_longlong>(npy_longlong *vv, npy_intp *tosort,
                                            npy_intp n);
# 声明对长长整型数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_longlong(void *vv, npy_intp *tosort, npy_intp n,
                   void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::longlong_tag>((npy_longlong *)vv, tosort, n);
}

# 实例化模板,对无符号长长整型数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::ulonglong_tag, npy_ulonglong>(npy_ulonglong *vv,
                                              npy_intp *tosort, npy_intp n);
# 声明对无符号长长整型数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_ulonglong(void *vv, npy_intp *tosort, npy_intp n,
                    void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::ulonglong_tag>((npy_ulonglong *)vv, tosort, n);
}

# 实例化模板,对半精度浮点数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::half_tag, npy_half>(npy_half *vv, npy_intp *tosort,
                                    npy_intp n);
# 声明对半精度浮点数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_half(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::half_tag>((npy_half *)vv, tosort, n);
}

# 实例化模板,对单精度浮点数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::float_tag, npy_float>(npy_float *vv, npy_intp *tosort,
                                      npy_intp n);
# 声明对单精度浮点数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_float(void *vv, npy_intp *tosort, npy_intp n, void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::float_tag>((npy_float *)vv, tosort, n);
}

# 实例化模板,对双精度浮点数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::double_tag, npy_double>(npy_double *vv, npy_intp *tosort,
                                        npy_intp n);
# 声明对双精度浮点数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_double(void *vv, npy_intp *tosort, npy_intp n,
                 void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::double_tag>((npy_double *)vv, tosort, n);
}

# 实例化模板,对长双精度浮点数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::longdouble_tag, npy_longdouble>(npy_longdouble *vv,
                                                npy_intp *tosort, npy_intp n);
# 声明对长双精度浮点数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_longdouble(void *vv, npy_intp *tosort, npy_intp n,
                     void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::longdouble_tag>((npy_longdouble *)vv, tosort, n);
}

# 实例化模板,对复数浮点数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::cfloat_tag, npy_cfloat>(npy_cfloat *vv, npy_intp *tosort,
                                        npy_intp n);
# 声明对复数浮点数组进行堆排序的函数
NPY_NO_EXPORT int
aheapsort_cfloat(void *vv, npy_intp *tosort, npy_intp n,
                 void *NPY_UNUSED(varr))
{
    return aheapsort_<npy::cfloat_tag>((npy_cfloat *)vv, tosort, n);
}

# 实例化模板,对复数双精度浮点数组进行堆排序
template NPY_NO_EXPORT int
aheapsort_<npy::cdouble_tag, npy_cdouble>(npy_cdouble *vv, npy_intp *tosort,
                                          npy_intp n);
# 声明对复数双精度浮点数组进行堆排序的函数
// 调用模板函数 aheapsort_,对 void 类型的数组进行堆排序,并返回排序后的结果
aheapsort_cdouble(void *vv, npy_intp *tosort, npy_intp n,
                  void *NPY_UNUSED(varr))
{
    // 调用特化的 aheapsort_ 函数,处理 npy_cdouble 类型的数据
    return aheapsort_<npy::cdouble_tag>((npy_cdouble *)vv, tosort, n);
}

// 显式实例化模板函数 aheapsort_,处理 npy_clongdouble 类型的数组排序
template NPY_NO_EXPORT int
aheapsort_<npy::clongdouble_tag, npy_clongdouble>(npy_clongdouble *vv,
                                                  npy_intp *tosort,
                                                  npy_intp n);
NPY_NO_EXPORT int
// 对 void 类型的数组进行堆排序,返回排序后的结果
aheapsort_clongdouble(void *vv, npy_intp *tosort, npy_intp n,
                      void *NPY_UNUSED(varr))
{
    // 调用特化的 aheapsort_ 函数,处理 npy_clongdouble 类型的数据
    return aheapsort_<npy::clongdouble_tag>((npy_clongdouble *)vv, tosort, n);
}

// 显式实例化模板函数 aheapsort_,处理 npy_datetime 类型的数组排序
template NPY_NO_EXPORT int
aheapsort_<npy::datetime_tag, npy_datetime>(npy_datetime *vv, npy_intp *tosort,
                                            npy_intp n);
NPY_NO_EXPORT int
// 对 void 类型的数组进行堆排序,返回排序后的结果
aheapsort_datetime(void *vv, npy_intp *tosort, npy_intp n,
                   void *NPY_UNUSED(varr))
{
    // 调用特化的 aheapsort_ 函数,处理 npy_datetime 类型的数据
    return aheapsort_<npy::datetime_tag>((npy_datetime *)vv, tosort, n);
}

// 显式实例化模板函数 aheapsort_,处理 npy_timedelta 类型的数组排序
template NPY_NO_EXPORT int
aheapsort_<npy::timedelta_tag, npy_timedelta>(npy_timedelta *vv,
                                              npy_intp *tosort, npy_intp n);
NPY_NO_EXPORT int
// 对 void 类型的数组进行堆排序,返回排序后的结果
aheapsort_timedelta(void *vv, npy_intp *tosort, npy_intp n,
                    void *NPY_UNUSED(varr))
{
    // 调用特化的 aheapsort_ 函数,处理 npy_timedelta 类型的数据
    return aheapsort_<npy::timedelta_tag>((npy_timedelta *)vv, tosort, n);
}

// 对 void 类型的数组进行堆排序,使用 string_heapsort_ 函数处理 npy::string_tag 类型的数据
NPY_NO_EXPORT int
heapsort_string(void *start, npy_intp n, void *varr)
{
    return string_heapsort_<npy::string_tag>((npy_char *)start, n, varr);
}

// 对 void 类型的数组进行堆排序,使用 string_heapsort_ 函数处理 npy::unicode_tag 类型的数据
NPY_NO_EXPORT int
heapsort_unicode(void *start, npy_intp n, void *varr)
{
    return string_heapsort_<npy::unicode_tag>((npy_ucs4 *)start, n, varr);
}

// 对 void 类型的数组进行堆排序,使用 string_aheapsort_ 函数处理 npy::string_tag 类型的数据
NPY_NO_EXPORT int
aheapsort_string(void *vv, npy_intp *tosort, npy_intp n, void *varr)
{
    return string_aheapsort_<npy::string_tag>((npy_char *)vv, tosort, n, varr);
}

// 对 void 类型的数组进行堆排序,使用 string_aheapsort_ 函数处理 npy::unicode_tag 类型的数据
NPY_NO_EXPORT int
aheapsort_unicode(void *vv, npy_intp *tosort, npy_intp n, void *varr)
{
    return string_aheapsort_<npy::unicode_tag>((npy_ucs4 *)vv, tosort, n,
                                               varr);
}

.\numpy\numpy\_core\src\npysort\heapsort.hpp

#ifndef NUMPY_SRC_COMMON_NPYSORT_HEAPSORT_HPP
#define NUMPY_SRC_COMMON_NPYSORT_HEAPSORT_HPP

#include "common.hpp"

namespace np::sort {

template <typename T>
inline bool LessThan(const T &a, const T &b)
{
    // 比较函数,根据类型 T 的不同,进行不同的比较操作
    if constexpr (std::is_floating_point_v<T>) {
        // 如果 T 是浮点数类型,则考虑 NaN 的情况进行比较
        return a < b || (b != b && a == a);
    }
    else if constexpr(std::is_same_v<T, Half>) {
        // 如果 T 是 Half 类型,则调用其自定义的 Less 方法进行比较
        bool a_nn = !a.IsNaN();
        return b.IsNaN() ? a_nn : a_nn && a.Less(b);
    }
    else {
        // 对于其他类型 T,直接进行常规的小于比较
        return a < b;
    }
}

// NUMERIC SORTS
template <typename T>
inline void Heap(T *start, SSize n)
{
    SSize i, j, l;
    // 堆排序需要将数组的索引偏移一位,以符合堆的索引规则
    T tmp, *a = start - 1;

    // 自上而下建堆过程
    for (l = n >> 1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l << 1; j <= n;) {
            if (j < n && LessThan(a[j], a[j + 1])) {
                j += 1;
            }
            if (LessThan(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    // 堆排序的下沉调整过程
    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && LessThan(a[j], a[j + 1])) {
                j++;
            }
            if (LessThan(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }
}
} // namespace np::sort
#endif

.\numpy\numpy\_core\src\npysort\highway_qsort.dispatch.cpp

#include "highway_qsort.hpp"
#include "hwy/contrib/sort/vqsort-inl.h"

// 定义宏,指定只使用静态版本的 VQSort
#define VQSORT_ONLY_STATIC 1

// 定义模板函数 DISPATCH_VQSORT,用于生成特定类型的 QSort 函数
#define DISPATCH_VQSORT(TYPE) \
template<> void NPY_CPU_DISPATCH_CURFX(QSort)(TYPE *arr, intptr_t size) \
{ \
    // 调用 HWY 命名空间中的 VQSortStatic 函数,对数组进行升序排序
    hwy::HWY_NAMESPACE::VQSortStatic(arr, size, hwy::SortAscending()); \
} \

namespace np { namespace highway { namespace qsort_simd {

    // 实例化 DISPATCH_VQSORT 模板函数,针对不同的数据类型
    DISPATCH_VQSORT(int32_t)
    DISPATCH_VQSORT(uint32_t)
    DISPATCH_VQSORT(int64_t)
    DISPATCH_VQSORT(uint64_t)
    DISPATCH_VQSORT(double)
    DISPATCH_VQSORT(float)

} } } // np::highway::qsort_simd

.\numpy\numpy\_core\src\npysort\highway_qsort.hpp

#ifndef NUMPY_SRC_COMMON_NPYSORT_HWY_SIMD_QSORT_HPP
#define NUMPY_SRC_COMMON_NPYSORT_HWY_SIMD_QSORT_HPP

// 如果未定义 NUMPY_SRC_COMMON_NPYSORT_HWY_SIMD_QSORT_HPP 宏,则包含该头文件,以防止多次包含


#include "common.hpp"

// 包含 common.hpp 头文件,引入通用的常量、函数和数据结构定义


namespace np { namespace highway { namespace qsort_simd {

// 命名空间声明:np -> highway -> qsort_simd,用于组织 qsort_simd 相关的函数和数据结构


#ifndef NPY_DISABLE_OPTIMIZATION
    #include "highway_qsort.dispatch.h"
#endif

// 如果未定义 NPY_DISABLE_OPTIMIZATION 宏,则包含 highway_qsort.dispatch.h 头文件,该文件可能包含了针对 QSort 和 QSelect 函数的优化版本的声明和定义


NPY_CPU_DISPATCH_DECLARE(template <typename T> void QSort, (T *arr, npy_intp size))
NPY_CPU_DISPATCH_DECLARE(template <typename T> void QSelect, (T* arr, npy_intp num, npy_intp kth))

// 使用 NPY_CPU_DISPATCH_DECLARE 宏声明 QSort 和 QSelect 函数模板,这些函数用于对数组进行排序和选择操作


#ifndef NPY_DISABLE_OPTIMIZATION
    #include "highway_qsort_16bit.dispatch.h"
#endif

// 如果未定义 NPY_DISABLE_OPTIMIZATION 宏,则包含 highway_qsort_16bit.dispatch.h 头文件,该文件可能包含了针对 QSort 和 QSelect 函数在 16 位数据类型上的优化版本的声明和定义


NPY_CPU_DISPATCH_DECLARE(template <typename T> void QSort, (T *arr, npy_intp size))
NPY_CPU_DISPATCH_DECLARE(template <typename T> void QSelect, (T* arr, npy_intp num, npy_intp kth))

// 使用 NPY_CPU_DISPATCH_DECLARE 宏声明另一组 QSort 和 QSelect 函数模板,针对 16 位数据类型


} } } // np::highway::qsort_simd

// 命名空间封闭:结束 np -> highway -> qsort_simd 命名空间的声明


#endif // NUMPY_SRC_COMMON_NPYSORT_HWY_SIMD_QSORT_HPP

// 结束 NUMPY_SRC_COMMON_NPYSORT_HWY_SIMD_QSORT_HPP 头文件的条件编译指令

.\numpy\numpy\_core\src\npysort\highway_qsort_16bit.dispatch.cpp

// 包含自定义的排序头文件 "highway_qsort.hpp"
#include "highway_qsort.hpp"
// 定义宏 VQSORT_ONLY_STATIC 为 1,用于特定的静态排序
#define VQSORT_ONLY_STATIC 1
// 包含高速公路库中的排序实现头文件 "hwy/contrib/sort/vqsort-inl.h"
#include "hwy/contrib/sort/vqsort-inl.h"

// 包含自定义的快速排序头文件 "quicksort.hpp"
#include "quicksort.hpp"

// 命名空间声明:np -> highway -> qsort_simd
namespace np { namespace highway { namespace qsort_simd {

// 模板特化:处理半精度浮点数数组的 QSort 函数
template<> void NPY_CPU_DISPATCH_CURFX(QSort)(Half *arr, intptr_t size)
{
    // 如果支持半精度浮点数操作
#if HWY_HAVE_FLOAT16
    // 调用高速公路库中的静态向量化排序,对半精度浮点数数组 arr 进行升序排序
    hwy::HWY_NAMESPACE::VQSortStatic(reinterpret_cast<hwy::float16_t*>(arr), size, hwy::SortAscending());
// 如果不支持半精度浮点数操作
#else
    // 调用自定义的快速排序,对半精度浮点数数组 arr 进行排序
    sort::Quick(arr, size);
#endif
}

// 模板特化:处理无符号 16 位整数数组的 QSort 函数
template<> void NPY_CPU_DISPATCH_CURFX(QSort)(uint16_t *arr, intptr_t size)
{
    // 调用高速公路库中的静态向量化排序,对无符号 16 位整数数组 arr 进行升序排序
    hwy::HWY_NAMESPACE::VQSortStatic(arr, size, hwy::SortAscending());
}

// 模板特化:处理有符号 16 位整数数组的 QSort 函数
template<> void NPY_CPU_DISPATCH_CURFX(QSort)(int16_t *arr, intptr_t size)
{
    // 调用高速公路库中的静态向量化排序,对有符号 16 位整数数组 arr 进行升序排序
    hwy::HWY_NAMESPACE::VQSortStatic(arr, size, hwy::SortAscending());
}

} } } // np::highway::qsort_simd

.\numpy\numpy\_core\src\npysort\mergesort.cpp

/*
 * The purpose of this module is to add faster sort functions
 * that are type-specific.  This is done by altering the
 * function table for the builtin descriptors.
 *
 * These sorting functions are copied almost directly from numarray
 * with a few modifications (complex comparisons compare the imaginary
 * part if the real parts are equal, for example), and the names
 * are changed.
 *
 * The original sorting code is due to Charles R. Harris who wrote
 * it for numarray.
 */

/*
 * Quick sort is usually the fastest, but the worst case scenario can
 * be slower than the merge and heap sorts.  The merge sort requires
 * extra memory and so for large arrays may not be useful.
 *
 * The merge sort is *stable*, meaning that equal components
 * are unmoved from their entry versions, so it can be used to
 * implement lexicographic sorting on multiple keys.
 *
 * The heap sort is included for completeness.
 */

#define NPY_NO_DEPRECATED_API NPY_API_VERSION

#include "npy_sort.h"               // Include header for sorting functions
#include "npysort_common.h"         // Include header for common sorting utilities
#include "numpy_tag.h"              // Include header for numpy tags (type descriptors)

#include <cstdlib>                  // Standard library for memory allocation

#define NOT_USED NPY_UNUSED(unused) // Macro to indicate unused variables
#define PYA_QS_STACK 100            // Constant for quicksort stack size
#define SMALL_QUICKSORT 15          // Threshold for small quicksort
#define SMALL_MERGESORT 20          // Threshold for small mergesort
#define SMALL_STRING 16             // Threshold for small string sorting

/*
 *****************************************************************************
 **                            NUMERIC SORTS                                **
 *****************************************************************************
 */

template <typename Tag, typename type>
static void
mergesort0_(type *pl, type *pr, type *pw)
{
    type vp, *pi, *pj, *pk, *pm;

    if (pr - pl > SMALL_MERGESORT) {
        /* merge sort */
        pm = pl + ((pr - pl) >> 1);                 // Calculate middle point
        mergesort0_<Tag>(pl, pm, pw);               // Recursively sort left half
        mergesort0_<Tag>(pm, pr, pw);               // Recursively sort right half
        for (pi = pw, pj = pl; pj < pm;) {          // Copy elements to workspace
            *pi++ = *pj++;
        }
        pi = pw + (pm - pl);                        // Set insertion point in workspace
        pj = pw;
        pk = pl;
        while (pj < pi && pm < pr) {                // Merge sorted halves
            if (Tag::less(*pm, *pj)) {              // Compare using custom tag less function
                *pk++ = *pm++;
            }
            else {
                *pk++ = *pj++;
            }
        }
        while (pj < pi) {                           // Copy remaining elements from workspace
            *pk++ = *pj++;
        }
    }
    else {
        /* insertion sort */
        for (pi = pl + 1; pi < pr; ++pi) {          // Iterate through elements
            vp = *pi;
            pj = pi;
            pk = pi - 1;
            while (pj > pl && Tag::less(vp, *pk)) { // Perform insertion sort
                *pj-- = *pk--;
            }
            *pj = vp;
        }
    }
}

template <typename Tag, typename type>
NPY_NO_EXPORT int
mergesort_(type *start, npy_intp num)
{
    type *pl, *pr, *pw;

    pl = start;
    pr = pl + num;
    pw = (type *)malloc((num / 2) * sizeof(type));  // Allocate workspace
    if (pw == NULL) {
        return -NPY_ENOMEM;                       // Return error if allocation fails
    }
    mergesort0_<Tag>(pl, pr, pw);                 // Call mergesort function

    free(pw);                                      // Free allocated workspace
    return 0;                                      // Return success
}

template <typename Tag, typename type>
static void
amergesort0_(npy_intp *pl, npy_intp *pr, type *v, npy_intp *pw)
{
    type vp;
    npy_intp vi, *pi, *pj, *pk, *pm;
    if (pr - pl > SMALL_MERGESORT) {
        /* 如果待排序的子数组长度大于预设的小数组长度,使用归并排序 */

        // 计算中间位置
        pm = pl + ((pr - pl) >> 1);

        // 对左半部分进行归并排序
        amergesort0_<Tag>(pl, pm, v, pw);

        // 对右半部分进行归并排序
        amergesort0_<Tag>(pm, pr, v, pw);

        // 合并两个有序子数组
        for (pi = pw, pj = pl; pj < pm;) {
            *pi++ = *pj++;
        }

        // 设置合并后的起始位置
        pi = pw + (pm - pl);
        pj = pw;
        pk = pl;

        // 合并左右两个子数组
        while (pj < pi && pm < pr) {
            if (Tag::less(v[*pm], v[*pj])) {
                *pk++ = *pm++;
            }
            else {
                *pk++ = *pj++;
            }
        }

        // 处理剩余的元素
        while (pj < pi) {
            *pk++ = *pj++;
        }
    }
    else {
        /* 如果待排序的子数组长度不大于预设的小数组长度,使用插入排序 */

        // 插入排序
        for (pi = pl + 1; pi < pr; ++pi) {
            vi = *pi;
            vp = v[vi];
            pj = pi;
            pk = pi - 1;

            // 寻找合适的插入位置
            while (pj > pl && Tag::less(vp, v[*pk])) {
                *pj-- = *pk--;
            }

            // 插入元素
            *pj = vi;
        }
    }
}

template <typename Tag, typename type>
NPY_NO_EXPORT int
amergesort_(type *v, npy_intp *tosort, npy_intp num)
{
    npy_intp *pl, *pr, *pw;

    pl = tosort;                    // 初始化指向排序数组的起始位置
    pr = pl + num;                  // 初始化指向排序数组的结束位置的下一个位置
    pw = (npy_intp *)malloc((num / 2) * sizeof(npy_intp));   // 分配临时空间,用于归并排序中的工作数组
    if (pw == NULL) {               // 如果分配失败,则返回内存不足错误码
        return -NPY_ENOMEM;
    }
    amergesort0_<Tag>(pl, pr, v, pw);   // 调用归并排序的实现函数
    free(pw);                       // 释放临时工作数组的内存空间

    return 0;                       // 返回排序成功
}

/*
 
 *****************************************************************************
 **                             STRING SORTS                                **
 *****************************************************************************
 */

template <typename Tag, typename type>
static void
mergesort0_(type *pl, type *pr, type *pw, type *vp, size_t len)
{
    type *pi, *pj, *pk, *pm;

    if ((size_t)(pr - pl) > SMALL_MERGESORT * len) {   // 如果数组长度大于指定值,执行归并排序
        /* merge sort */
        pm = pl + (((pr - pl) / len) >> 1) * len;      // 计算中间位置并取整作为分割点
        mergesort0_<Tag>(pl, pm, pw, vp, len);         // 递归调用归并排序左半部分
        mergesort0_<Tag>(pm, pr, pw, vp, len);         // 递归调用归并排序右半部分
        Tag::copy(pw, pl, pm - pl);                   // 复制左半部分到临时工作数组
        pi = pw + (pm - pl);
        pj = pw;
        pk = pl;
        while (pj < pi && pm < pr) {                   // 归并两个有序数组
            if (Tag::less(pm, pj, len)) {              // 如果右半部分元素小于左半部分元素
                Tag::copy(pk, pm, len);                // 将右半部分元素复制到原数组
                pm += len;
                pk += len;
            }
            else {
                Tag::copy(pk, pj, len);                // 将左半部分元素复制到原数组
                pj += len;
                pk += len;
            }
        }
        Tag::copy(pk, pj, pi - pj);                    // 处理剩余的元素
    }
    else {
        /* insertion sort */                          // 如果数组长度小于等于指定值,执行插入排序
        for (pi = pl + len; pi < pr; pi += len) {      // 从第二个元素开始,依次将元素插入已排序的序列中
            Tag::copy(vp, pi, len);                   // 备份当前元素
            pj = pi;
            pk = pi - len;
            while (pj > pl && Tag::less(vp, pk, len)) {   // 向前比较并移动元素,保持序列有序
                Tag::copy(pj, pk, len);
                pj -= len;
                pk -= len;
            }
            Tag::copy(pj, vp, len);                   // 将备份的元素插入到正确的位置
        }
    }
}

template <typename Tag, typename type>
static int
string_mergesort_(type *start, npy_intp num, void *varr)
{
    PyArrayObject *arr = (PyArrayObject *)varr;
    size_t elsize = PyArray_ITEMSIZE(arr);
    size_t len = elsize / sizeof(type);
    type *pl, *pr, *pw, *vp;
    int err = 0;

    /* Items that have zero size don't make sense to sort */
    if (elsize == 0) {                              // 如果元素大小为0,直接返回排序成功
        return 0;
    }

    pl = start;                                      // 初始化指向排序数组的起始位置
    pr = pl + num * len;                             // 初始化指向排序数组的结束位置的下一个位置
    pw = (type *)malloc((num / 2) * elsize);          // 分配临时空间,用于归并排序中的工作数组
    if (pw == NULL) {                                // 如果分配失败,则返回内存不足错误码
        err = -NPY_ENOMEM;
        goto fail_0;
    }
    vp = (type *)malloc(elsize);                     // 分配临时空间,用于备份当前元素
    if (vp == NULL) {                                // 如果分配失败,则返回内存不足错误码
        err = -NPY_ENOMEM;
        goto fail_1;
    }
    mergesort0_<Tag>(pl, pr, pw, vp, len);           // 调用归并排序的实现函数

    free(vp);                                        // 释放临时备份元素的内存空间
fail_1:
    free(pw);                                        // 释放临时工作数组的内存空间
fail_0:
    return err;                                      // 返回排序的结果
}

template <typename Tag, typename type>
static void
amergesort0_(npy_intp *pl, npy_intp *pr, type *v, npy_intp *pw, size_t len)
{
    type *vp;
    npy_intp vi, *pi, *pj, *pk, *pm;
    if (pr - pl > SMALL_MERGESORT) {
        /* 如果子数组长度大于SMALL_MERGESORT,执行归并排序 */

        // 计算中间点
        pm = pl + ((pr - pl) >> 1);

        // 递归调用归并排序,对左半部分进行排序
        amergesort0_<Tag>(pl, pm, v, pw, len);
        
        // 递归调用归并排序,对右半部分进行排序
        amergesort0_<Tag>(pm, pr, v, pw, len);

        // 将左右两部分合并到临时数组pw中
        for (pi = pw, pj = pl; pj < pm;) {
            *pi++ = *pj++;
        }

        // 初始化指针pi指向合并后的起始位置
        pi = pw + (pm - pl);
        pj = pw;
        pk = pl;

        // 归并左右两部分,根据排序规则决定元素存放位置
        while (pj < pi && pm < pr) {
            if (Tag::less(v + (*pm) * len, v + (*pj) * len, len)) {
                *pk++ = *pm++;
            }
            else {
                *pk++ = *pj++;
            }
        }

        // 处理剩余元素
        while (pj < pi) {
            *pk++ = *pj++;
        }
    }
    else {
        /* 如果子数组长度不大于SMALL_MERGESORT,执行插入排序 */

        // 使用插入排序对当前子数组进行排序
        for (pi = pl + 1; pi < pr; ++pi) {
            vi = *pi;  // 当前待插入的值
            vp = v + vi * len;  // 对应的数据起始地址
            pj = pi;  // 待比较位置
            pk = pi - 1;  // 前一个位置

            // 向前比较并移动元素,直到找到插入位置
            while (pj > pl && Tag::less(vp, v + (*pk) * len, len)) {
                *pj-- = *pk--;
            }
            
            // 插入当前值到正确位置
            *pj = vi;
        }
    }


这段代码实现了一个通用的归并排序算法,其中根据子数组长度选择使用归并排序或插入排序。
}

template <typename Tag, typename type>
static int
string_amergesort_(type *v, npy_intp *tosort, npy_intp num, void *varr)
{
    PyArrayObject *arr = (PyArrayObject *)varr;  // 将void指针转换为PyArrayObject类型
    size_t elsize = PyArray_ITEMSIZE(arr);  // 计算数组元素的大小
    size_t len = elsize / sizeof(type);  // 计算数组中元素的个数
    npy_intp *pl, *pr, *pw;  // 定义指向npy_intp类型的指针

    /* Items that have zero size don't make sense to sort */
    if (elsize == 0) {
        return 0;  // 如果元素大小为0,返回0
    }

    pl = tosort;  // 初始化排序起始位置为tosort
    pr = pl + num;  // 初始化排序结束位置为tosort + num
    pw = (npy_intp *)malloc((num / 2) * sizeof(npy_intp));  // 分配内存给pw
    if (pw == NULL) {
        return -NPY_ENOMEM;  // 如果内存分配失败,返回内存不足错误码
    }
    amergesort0_<Tag>(pl, pr, v, pw, len);  // 调用模板函数进行排序
    free(pw);  // 释放pw指向的内存空间

    return 0;  // 返回0表示成功
}

/*
 *****************************************************************************
 **                             GENERIC SORT                                **
 *****************************************************************************
 */

static void
npy_mergesort0(char *pl, char *pr, char *pw, char *vp, npy_intp elsize,
               PyArray_CompareFunc *cmp, PyArrayObject *arr)
{
    char *pi, *pj, *pk, *pm;  // 定义指向字符的指针

    if (pr - pl > SMALL_MERGESORT * elsize) {
        /* merge sort */
        pm = pl + (((pr - pl) / elsize) >> 1) * elsize;  // 计算中间点pm
        npy_mergesort0(pl, pm, pw, vp, elsize, cmp, arr);  // 递归调用归并排序左半部分
        npy_mergesort0(pm, pr, pw, vp, elsize, cmp, arr);  // 递归调用归并排序右半部分
        GENERIC_COPY(pw, pl, pm - pl);  // 复制左半部分到pw中
        pi = pw + (pm - pl);  // 初始化pi为pw + (pm - pl)
        pj = pw;  // 初始化pj为pw
        pk = pl;  // 初始化pk为pl
        while (pj < pi && pm < pr) {
            if (cmp(pm, pj, arr) < 0) {  // 如果pm < pj,则复制pm到pk位置
                GENERIC_COPY(pk, pm, elsize);
                pm += elsize;
                pk += elsize;
            }
            else {  // 否则,复制pj到pk位置
                GENERIC_COPY(pk, pj, elsize);
                pj += elsize;
                pk += elsize;
            }
        }
        GENERIC_COPY(pk, pj, pi - pj);  // 复制剩余的元素到pk位置
    }
    else {
        /* insertion sort */
        for (pi = pl + elsize; pi < pr; pi += elsize) {  // 插入排序
            GENERIC_COPY(vp, pi, elsize);
            pj = pi;
            pk = pi - elsize;
            while (pj > pl && cmp(vp, pk, arr) < 0) {
                GENERIC_COPY(pj, pk, elsize);
                pj -= elsize;
                pk -= elsize;
            }
            GENERIC_COPY(pj, vp, elsize);
        }
    }
}

NPY_NO_EXPORT int
npy_mergesort(void *start, npy_intp num, void *varr)
{
    PyArrayObject *arr = (PyArrayObject *)varr;  // 将void指针转换为PyArrayObject类型
    npy_intp elsize = PyArray_ITEMSIZE(arr);  // 计算数组元素的大小
    PyArray_CompareFunc *cmp = PyDataType_GetArrFuncs(PyArray_DESCR(arr))->compare;  // 获取比较函数
    char *pl = (char *)start;  // 初始化数组起始位置
    char *pr = pl + num * elsize;  // 初始化数组结束位置
    char *pw;
    char *vp;
    int err = -NPY_ENOMEM;

    /* Items that have zero size don't make sense to sort */
    if (elsize == 0) {
        return 0;  // 如果元素大小为0,返回0
    }

    pw = (char *)malloc((num >> 1) * elsize);  // 分配内存给pw
    vp = (char *)malloc(elsize);  // 分配内存给vp

    if (pw != NULL && vp != NULL) {
        npy_mergesort0(pl, pr, pw, vp, elsize, cmp, arr);  // 调用归并排序函数
        err = 0;  // 表示排序成功
    }

    free(vp);  // 释放vp指向的内存空间
    free(pw);  // 释放pw指向的内存空间

    return err;  // 返回错误码或者0表示成功
}

static void
/* 
 * 使用合并排序算法对数组进行排序,其中包含以下参数:
 * - pl: 数组的左边界指针
 * - pr: 数组的右边界指针
 * - v: 指向数据的指针
 * - pw: 临时数组的指针,用于存储排序过程中的中间结果
 * - elsize: 元素大小
 * - cmp: 比较函数指针,用于比较数组元素
 * - arr: NumPy 数组对象指针,包含排序数据的描述信息
 */
npy_amergesort0(npy_intp *pl, npy_intp *pr, char *v, npy_intp *pw,
                npy_intp elsize, PyArray_CompareFunc *cmp, PyArrayObject *arr)
{
    char *vp;
    npy_intp vi, *pi, *pj, *pk, *pm;

    if (pr - pl > SMALL_MERGESORT) {
        /* 使用合并排序 */
        pm = pl + ((pr - pl) >> 1);
        npy_amergesort0(pl, pm, v, pw, elsize, cmp, arr);
        npy_amergesort0(pm, pr, v, pw, elsize, cmp, arr);
        for (pi = pw, pj = pl; pj < pm;) {
            *pi++ = *pj++;
        }
        pi = pw + (pm - pl);
        pj = pw;
        pk = pl;
        while (pj < pi && pm < pr) {
            if (cmp(v + (*pm) * elsize, v + (*pj) * elsize, arr) < 0) {
                *pk++ = *pm++;
            }
            else {
                *pk++ = *pj++;
            }
        }
        while (pj < pi) {
            *pk++ = *pj++;
        }
    }
    else {
        /* 使用插入排序 */
        for (pi = pl + 1; pi < pr; ++pi) {
            vi = *pi;
            vp = v + vi * elsize;
            pj = pi;
            pk = pi - 1;
            while (pj > pl && cmp(vp, v + (*pk) * elsize, arr) < 0) {
                *pj-- = *pk--;
            }
            *pj = vi;
        }
    }
}

/* 
 * 使用合并排序算法对数组进行排序的入口函数。
 * 其中包含以下参数:
 * - v: 指向数组的指针
 * - tosort: 指向要排序的元素的指针数组
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针
 * 返回值:
 * - 0:排序成功
 * - -NPY_ENOMEM:内存分配失败
 */
NPY_NO_EXPORT int
npy_amergesort(void *v, npy_intp *tosort, npy_intp num, void *varr)
{
    PyArrayObject *arr = (PyArrayObject *)varr;
    npy_intp elsize = PyArray_ITEMSIZE(arr);
    PyArray_CompareFunc *cmp = PyDataType_GetArrFuncs(PyArray_DESCR(arr))->compare;
    npy_intp *pl, *pr, *pw;

    /* 如果元素大小为0,则没有意义进行排序 */
    if (elsize == 0) {
        return 0;
    }

    pl = tosort;
    pr = pl + num;
    pw = (npy_intp *)malloc((num >> 1) * sizeof(npy_intp));
    if (pw == NULL) {
        return -NPY_ENOMEM;
    }
    npy_amergesort0(pl, pr, (char *)v, pw, elsize, cmp, arr);
    free(pw);

    return 0;
}

/***************************************
 * C > C++ 调度
 ***************************************/

/* 
 * 对布尔类型数组使用合并排序的函数
 * - start: 指向布尔类型数组的指针
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针(未使用)
 */
NPY_NO_EXPORT int
mergesort_bool(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    return mergesort_<npy::bool_tag>((npy_bool *)start, num);
}

/* 
 * 对字节类型数组使用合并排序的函数
 * - start: 指向字节类型数组的指针
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针(未使用)
 */
NPY_NO_EXPORT int
mergesort_byte(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    return mergesort_<npy::byte_tag>((npy_byte *)start, num);
}

/* 
 * 对无符号字节类型数组使用合并排序的函数
 * - start: 指向无符号字节类型数组的指针
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针(未使用)
 */
NPY_NO_EXPORT int
mergesort_ubyte(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    return mergesort_<npy::ubyte_tag>((npy_ubyte *)start, num);
}

/* 
 * 对短整型数组使用合并排序的函数
 * - start: 指向短整型数组的指针
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针(未使用)
 */
NPY_NO_EXPORT int
mergesort_short(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    return mergesort_<npy::short_tag>((npy_short *)start, num);
}

/* 
 * 对无符号短整型数组使用合并排序的函数
 * - start: 指向无符号短整型数组的指针
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针(未使用)
 */
NPY_NO_EXPORT int
mergesort_ushort(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    return mergesort_<npy::ushort_tag>((npy_ushort *)start, num);
}

/* 
 * 对整型数组使用合并排序的函数
 * - start: 指向整型数组的指针
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针(未使用)
 */
NPY_NO_EXPORT int
mergesort_int(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    return mergesort_<npy::int_tag>((npy_int *)start, num);
}

/* 
 * 对无符号整型数组使用合并排序的函数
 * - start: 指向无符号整型数组的指针
 * - num: 要排序的元素数量
 * - varr: 指向 NumPy 数组对象的指针(未使用)
 */
NPY_NO_EXPORT int
mergesort_uint(void *start, npy_intp num, void *NPY_UNUSED(varr)))
{
    // mergesort_uint 函数尚未完成
    return 0;
}
    // 调用 mergesort_<npy::uint_tag> 函数,对给定的数组进行归并排序,并返回排序后的结果。
    return mergesort_<npy::uint_tag>((npy_uint *)start, num);
NPY_NO_EXPORT int
mergesort_long(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::long_tag 进行排序,返回排序结果
    return mergesort_<npy::long_tag>((npy_long *)start, num);
}

NPY_NO_EXPORT int
mergesort_ulong(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::ulong_tag 进行排序,返回排序结果
    return mergesort_<npy::ulong_tag>((npy_ulong *)start, num);
}

NPY_NO_EXPORT int
mergesort_longlong(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::longlong_tag 进行排序,返回排序结果
    return mergesort_<npy::longlong_tag>((npy_longlong *)start, num);
}

NPY_NO_EXPORT int
mergesort_ulonglong(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::ulonglong_tag 进行排序,返回排序结果
    return mergesort_<npy::ulonglong_tag>((npy_ulonglong *)start, num);
}

NPY_NO_EXPORT int
mergesort_half(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::half_tag 进行排序,返回排序结果
    return mergesort_<npy::half_tag>((npy_half *)start, num);
}

NPY_NO_EXPORT int
mergesort_float(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::float_tag 进行排序,返回排序结果
    return mergesort_<npy::float_tag>((npy_float *)start, num);
}

NPY_NO_EXPORT int
mergesort_double(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::double_tag 进行排序,返回排序结果
    return mergesort_<npy::double_tag>((npy_double *)start, num);
}

NPY_NO_EXPORT int
mergesort_longdouble(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::longdouble_tag 进行排序,返回排序结果
    return mergesort_<npy::longdouble_tag>((npy_longdouble *)start, num);
}

NPY_NO_EXPORT int
mergesort_cfloat(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::cfloat_tag 进行排序,返回排序结果
    return mergesort_<npy::cfloat_tag>((npy_cfloat *)start, num);
}

NPY_NO_EXPORT int
mergesort_cdouble(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::cdouble_tag 进行排序,返回排序结果
    return mergesort_<npy::cdouble_tag>((npy_cdouble *)start, num);
}

NPY_NO_EXPORT int
mergesort_clongdouble(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::clongdouble_tag 进行排序,返回排序结果
    return mergesort_<npy::clongdouble_tag>((npy_clongdouble *)start, num);
}

NPY_NO_EXPORT int
mergesort_datetime(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::datetime_tag 进行排序,返回排序结果
    return mergesort_<npy::datetime_tag>((npy_datetime *)start, num);
}

NPY_NO_EXPORT int
mergesort_timedelta(void *start, npy_intp num, void *NPY_UNUSED(varr))
{
    // 调用模板函数 mergesort_,使用 npy::timedelta_tag 进行排序,返回排序结果
    return mergesort_<npy::timedelta_tag>((npy_timedelta *)start, num);
}

NPY_NO_EXPORT int
amergesort_bool(void *start, npy_intp *tosort, npy_intp num,
                void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,使用 npy::bool_tag 进行排序,返回排序结果
    return amergesort_<npy::bool_tag>((npy_bool *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_byte(void *start, npy_intp *tosort, npy_intp num,
                void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,使用 npy::byte_tag 进行排序,返回排序结果
    return amergesort_<npy::byte_tag>((npy_byte *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_ubyte(void *start, npy_intp *tosort, npy_intp num,
                 void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,使用 npy::ubyte_tag 进行排序,返回排序结果
    return amergesort_<npy::ubyte_tag>((npy_ubyte *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_short(void *start, npy_intp *tosort, npy_intp num,
                 void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,使用 npy::short_tag 进行排序,返回排序结果
    return amergesort_<npy::short_tag>((npy_short *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_ushort(void *start, npy_intp *tosort, npy_intp num,
                  void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,使用 npy::ushort_tag 进行排序,返回排序结果
    return amergesort_<npy::ushort_tag>((npy_ushort *)start, tosort, num);
}


以上是给定代码的注释。
    # 调用amergesort_<npy::ushort_tag>函数,传入参数并返回结果
    return amergesort_<npy::ushort_tag>((npy_ushort *)start, tosort, num);
NPY_NO_EXPORT int
amergesort_int(void *start, npy_intp *tosort, npy_intp num,
               void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理整数类型的排序,返回排序完成的状态
    return amergesort_<npy::int_tag>((npy_int *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_uint(void *start, npy_intp *tosort, npy_intp num,
                void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理无符号整数类型的排序,返回排序完成的状态
    return amergesort_<npy::uint_tag>((npy_uint *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_long(void *start, npy_intp *tosort, npy_intp num,
                void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理长整型的排序,返回排序完成的状态
    return amergesort_<npy::long_tag>((npy_long *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_ulong(void *start, npy_intp *tosort, npy_intp num,
                 void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理无符号长整型的排序,返回排序完成的状态
    return amergesort_<npy::ulong_tag>((npy_ulong *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_longlong(void *start, npy_intp *tosort, npy_intp num,
                    void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理长长整型的排序,返回排序完成的状态
    return amergesort_<npy::longlong_tag>((npy_longlong *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_ulonglong(void *start, npy_intp *tosort, npy_intp num,
                     void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理无符号长长整型的排序,返回排序完成的状态
    return amergesort_<npy::ulonglong_tag>((npy_ulonglong *)start, tosort,
                                           num);
}

NPY_NO_EXPORT int
amergesort_half(void *start, npy_intp *tosort, npy_intp num,
                void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理半精度浮点数的排序,返回排序完成的状态
    return amergesort_<npy::half_tag>((npy_half *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_float(void *start, npy_intp *tosort, npy_intp num,
                 void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理单精度浮点数的排序,返回排序完成的状态
    return amergesort_<npy::float_tag>((npy_float *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_double(void *start, npy_intp *tosort, npy_intp num,
                  void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理双精度浮点数的排序,返回排序完成的状态
    return amergesort_<npy::double_tag>((npy_double *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_longdouble(void *start, npy_intp *tosort, npy_intp num,
                      void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理长双精度浮点数的排序,返回排序完成的状态
    return amergesort_<npy::longdouble_tag>((npy_longdouble *)start, tosort,
                                            num);
}

NPY_NO_EXPORT int
amergesort_cfloat(void *start, npy_intp *tosort, npy_intp num,
                  void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理复数浮点数(单精度)的排序,返回排序完成的状态
    return amergesort_<npy::cfloat_tag>((npy_cfloat *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_cdouble(void *start, npy_intp *tosort, npy_intp num,
                   void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理复数浮点数(双精度)的排序,返回排序完成的状态
    return amergesort_<npy::cdouble_tag>((npy_cdouble *)start, tosort, num);
}

NPY_NO_EXPORT int
amergesort_clongdouble(void *start, npy_intp *tosort, npy_intp num,
                       void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理复数浮点数(长双精度)的排序,返回排序完成的状态
    return amergesort_<npy::clongdouble_tag>((npy_clongdouble *)start, tosort,
                                             num);
}

NPY_NO_EXPORT int
amergesort_datetime(void *start, npy_intp *tosort, npy_intp num,
                    void *NPY_UNUSED(varr))
{
    // 调用模板函数 amergesort_,以处理日期时间类型的排序,返回排序完成的状态
    return amergesort_<npy::datetime_tag>((npy_datetime *)start, tosort, num);
}
# 定义一个不导出的函数,使用 amergesort 算法对 timedelta 类型的数据进行排序
NPY_NO_EXPORT int
amergesort_timedelta(void *start, npy_intp *tosort, npy_intp num,
                     void *NPY_UNUSED(varr))
{
    // 调用 amergesort_ 函数,对应 timedelta 类型的排序算法
    return amergesort_<npy::timedelta_tag>((npy_timedelta *)start, tosort,
                                           num);
}

# 定义一个不导出的函数,使用 mergesort 算法对 string 类型的数据进行排序
NPY_NO_EXPORT int
mergesort_string(void *start, npy_intp num, void *varr)
{
    // 调用 string_mergesort_ 函数,对应 string 类型的 mergesort 排序算法
    return string_mergesort_<npy::string_tag>((npy_char *)start, num, varr);
}

# 定义一个不导出的函数,使用 mergesort 算法对 unicode 类型的数据进行排序
NPY_NO_EXPORT int
mergesort_unicode(void *start, npy_intp num, void *varr)
{
    // 调用 string_mergesort_ 函数,对应 unicode 类型的 mergesort 排序算法
    return string_mergesort_<npy::unicode_tag>((npy_ucs4 *)start, num, varr);
}

# 定义一个不导出的函数,使用 amergesort 算法对 string 类型的数据进行排序
NPY_NO_EXPORT int
amergesort_string(void *v, npy_intp *tosort, npy_intp num, void *varr)
{
    // 调用 string_amergesort_ 函数,对应 string 类型的 amergesort 排序算法
    return string_amergesort_<npy::string_tag>((npy_char *)v, tosort, num,
                                               varr);
}

# 定义一个不导出的函数,使用 amergesort 算法对 unicode 类型的数据进行排序
NPY_NO_EXPORT int
amergesort_unicode(void *v, npy_intp *tosort, npy_intp num, void *varr)
{
    // 调用 string_amergesort_ 函数,对应 unicode 类型的 amergesort 排序算法
    return string_amergesort_<npy::unicode_tag>((npy_ucs4 *)v, tosort, num,
                                                varr);
}