NumPy-源码解析-八十二-

46 阅读1小时+

NumPy 源码解析(八十二)

.\numpy\numpy\_core\tests\test_errstate.py

# 导入 pytest 模块,用于编写和运行测试用例
import pytest
# 导入 sysconfig 模块,用于访问 Python 系统配置信息
import sysconfig

# 导入 numpy 库,并将其命名为 np
import numpy as np
# 从 numpy.testing 模块中导入断言函数 assert_、assert_raises 和 IS_WASM
from numpy.testing import assert_, assert_raises, IS_WASM

# 检测是否为 ARM EABI 系统上的软浮点模拟,若是则标记为 True
hosttype = sysconfig.get_config_var('HOST_GNU_TYPE')
arm_softfloat = False if hosttype is None else hosttype.endswith('gnueabi')

# 定义测试类 TestErrstate
class TestErrstate:
    # 标记为 pytest 的测试用例,并在 WASM 环境下跳过此测试
    @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
    # 在 ARM 软浮点问题存在时跳过此测试,并说明原因
    @pytest.mark.skipif(arm_softfloat,
                        reason='platform/cpu issue with FPU (gh-413,-15562)')
    # 测试无效操作错误处理
    def test_invalid(self):
        # 进入上下文管理器,设置所有错误都抛出,下溢时忽略
        with np.errstate(all='raise', under='ignore'):
            # 创建一个负数数组
            a = -np.arange(3)
            # 在无效操作(如负数的平方根)时忽略错误
            with np.errstate(invalid='ignore'):
                np.sqrt(a)
            # 预期下面的操作会引发浮点数错误
            with assert_raises(FloatingPointError):
                np.sqrt(a)

    # 标记为 pytest 的测试用例,并在 WASM 环境下跳过此测试
    @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
    # 在 ARM 软浮点问题存在时跳过此测试,并说明原因
    @pytest.mark.skipif(arm_softfloat,
                        reason='platform/cpu issue with FPU (gh-15562)')
    # 测试除零错误处理
    def test_divide(self):
        # 进入上下文管理器,设置所有错误都抛出,下溢时忽略
        with np.errstate(all='raise', under='ignore'):
            # 创建一个负数数组
            a = -np.arange(3)
            # 在除零操作时忽略错误
            with np.errstate(divide='ignore'):
                a // 0
            # 预期下面的操作会引发浮点数错误
            with assert_raises(FloatingPointError):
                a // 0
            # 预期下面的操作会引发浮点数错误,参见 gh-15562
            with assert_raises(FloatingPointError):
                a // a

    # 测试错误回调函数
    def test_errcall(self):
        # 定义一个计数器函数 foo
        count = 0
        def foo(*args):
            nonlocal count
            count += 1

        # 获取当前的错误回调函数
        olderrcall = np.geterrcall()
        # 进入上下文管理器,设置错误回调函数为 foo
        with np.errstate(call=foo):
            # 验证当前错误回调函数为 foo
            assert np.geterrcall() is foo
            # 进入嵌套上下文管理器,设置错误回调函数为 None
            with np.errstate(call=None):
                # 验证当前错误回调函数为 None
                assert np.geterrcall() is None
        # 验证退出上下文管理器后恢复原来的错误回调函数
        assert np.geterrcall() is olderrcall
        # 验证计数器值为 0
        assert count == 0

        # 进入上下文管理器,设置错误回调函数为 foo,并处理无效操作
        with np.errstate(call=foo, invalid="call"):
            np.array(np.inf) - np.array(np.inf)

        # 验证计数器值增加到 1
        assert count == 1

    # 测试错误状态的装饰器功能
    def test_errstate_decorator(self):
        # 使用 errstate 装饰器,设置所有错误都忽略
        @np.errstate(all='ignore')
        def foo():
            # 创建一个负数数组
            a = -np.arange(3)
            # 在除零操作时忽略错误
            a // 0
            
        # 调用 foo 函数
        foo()

    # 测试错误状态进入一次性
    def test_errstate_enter_once(self):
        # 创建一个错误状态对象,设置无效操作时警告
        errstate = np.errstate(invalid="warn")
        # 进入上下文管理器
        with errstate:
            pass

        # 试图第二次进入错误状态上下文管理器时,预期会引发类型错误异常
        with pytest.raises(TypeError,
                match="Cannot enter `np.errstate` twice"):
            with errstate:
                pass

    # 标记为 pytest 的测试用例,并在 WASM 环境下跳过此测试
    @pytest.mark.skipif(IS_WASM, reason="wasm doesn't support asyncio")
    def test_asyncio_safe(self):
        # 引入 asyncio 库,如果缺失则跳过测试
        # Pyodide/wasm 不支持 asyncio。如果测试出现问题,应该大量跳过或者以不同方式运行。
        asyncio = pytest.importorskip("asyncio")

        @np.errstate(invalid="ignore")
        def decorated():
            # 被装饰的非异步函数(异步函数不能被装饰)
            assert np.geterr()["invalid"] == "ignore"

        async def func1():
            decorated()
            await asyncio.sleep(0.1)
            decorated()

        async def func2():
            with np.errstate(invalid="raise"):
                assert np.geterr()["invalid"] == "raise"
                await asyncio.sleep(0.125)
                assert np.geterr()["invalid"] == "raise"

        # 又一个有趣的实验:第三个函数使用不同的错误状态
        async def func3():
            with np.errstate(invalid="print"):
                assert np.geterr()["invalid"] == "print"
                await asyncio.sleep(0.11)
                assert np.geterr()["invalid"] == "print"

        async def main():
            # 同时运行所有三个函数多次:
            await asyncio.gather(
                    func1(), func2(), func3(), func1(), func2(), func3(),
                    func1(), func2(), func3(), func1(), func2(), func3())

        # 创建一个新的事件循环
        loop = asyncio.new_event_loop()
        with np.errstate(invalid="warn"):
            # 运行主函数
            asyncio.run(main())
            assert np.geterr()["invalid"] == "warn"

        # 最终确认错误状态应该为默认的 "warn"
        assert np.geterr()["invalid"] == "warn"
        # 关闭事件循环
        loop.close()

.\numpy\numpy\_core\tests\test_extint128.py

# 引入必要的模块和库
import itertools  # 提供迭代工具的函数
import contextlib  # 上下文管理器的支持
import operator  # 操作符函数的模块
import pytest  # 测试框架

import numpy as np  # 数组和数值计算工具
import numpy._core._multiarray_tests as mt  # NumPy内部的多维数组测试函数

from numpy.testing import assert_raises, assert_equal  # 断言函数,用于测试

# 定义常量
INT64_MAX = np.iinfo(np.int64).max  # int64类型的最大值
INT64_MIN = np.iinfo(np.int64).min  # int64类型的最小值
INT64_MID = 2**32  # int64类型的中间值

# int128不是二进制补码,符号位是单独的
INT128_MAX = 2**128 - 1  # int128类型的最大值
INT128_MIN = -INT128_MAX  # int128类型的最小值
INT128_MID = 2**64  # int128类型的中间值

# 定义不同类型的整数值列表
INT64_VALUES = (
    [INT64_MIN + j for j in range(20)] +  # int64类型的最小值附近的20个值
    [INT64_MAX - j for j in range(20)] +  # int64类型的最大值附近的20个值
    [INT64_MID + j for j in range(-20, 20)] +  # int64类型的中间值附近的40个值
    [2*INT64_MID + j for j in range(-20, 20)] +  # 2倍int64类型的中间值附近的40个值
    [INT64_MID//2 + j for j in range(-20, 20)] +  # int64类型中间值的一半附近的40个值
    list(range(-70, 70))  # -70到69的整数值
)

INT128_VALUES = (
    [INT128_MIN + j for j in range(20)] +  # int128类型的最小值附近的20个值
    [INT128_MAX - j for j in range(20)] +  # int128类型的最大值附近的20个值
    [INT128_MID + j for j in range(-20, 20)] +  # int128类型的中间值附近的40个值
    [2*INT128_MID + j for j in range(-20, 20)] +  # 2倍int128类型的中间值附近的40个值
    [INT128_MID//2 + j for j in range(-20, 20)] +  # int128类型中间值的一半附近的40个值
    list(range(-70, 70)) +  # -70到69的整数值
    [False]  # 表示负零的特殊值
)

INT64_POS_VALUES = [x for x in INT64_VALUES if x > 0]  # int64类型的正整数值列表

@contextlib.contextmanager
def exc_iter(*args):
    """
    创建一个上下文管理器,用于迭代*args的笛卡尔积,如果发生异常,则添加当前迭代的信息。
    """

    value = [None]  # 存储当前迭代的值

    def iterate():
        for v in itertools.product(*args):
            value[0] = v
            yield v

    try:
        yield iterate()  # 返回迭代器对象
    except Exception:
        import traceback
        msg = "At: %r\n%s" % (repr(value[0]),
                              traceback.format_exc())
        raise AssertionError(msg)  # 抛出断言异常,带有追踪信息

def test_safe_binop():
    # 测试安全算术运算函数

    ops = [
        (operator.add, 1),  # 加法操作符和对应的操作码
        (operator.sub, 2),  # 减法操作符和对应的操作码
        (operator.mul, 3)   # 乘法操作符和对应的操作码
    ]

    with exc_iter(ops, INT64_VALUES, INT64_VALUES) as it:
        for xop, a, b in it:
            pyop, op = xop
            c = pyop(a, b)  # 执行Python操作

            if not (INT64_MIN <= c <= INT64_MAX):  # 如果结果超出int64类型范围
                assert_raises(OverflowError, mt.extint_safe_binop, a, b, op)  # 断言应该引发溢出错误
            else:
                d = mt.extint_safe_binop(a, b, op)  # 调用扩展整数安全算术函数
                if c != d:
                    # assert_equal 函数速度较慢
                    assert_equal(d, c)  # 断言结果应该相等

def test_to_128():
    with exc_iter(INT64_VALUES) as it:
        for a, in it:
            b = mt.extint_to_128(a)  # 调用转换为int128的函数
            if a != b:
                assert_equal(b, a)  # 断言结果应该相等

def test_to_64():
    with exc_iter(INT128_VALUES) as it:
        for a, in it:
            if not (INT64_MIN <= a <= INT64_MAX):
                assert_raises(OverflowError, mt.extint_to_64, a)  # 断言应该引发溢出错误
            else:
                b = mt.extint_to_64(a)  # 调用转换为int64的函数
                if a != b:
                    assert_equal(b, a)  # 断言结果应该相等

def test_mul_64_64():
    with exc_iter(INT64_VALUES, INT64_VALUES) as it:
        for a, b in it:
            c = a * b
            d = mt.extint_mul_64_64(a, b)  # 调用int64乘法函数
            if c != d:
                assert_equal(d, c)  # 断言结果应该相等

def test_add_128():
    # 使用异常迭代器处理 INT128_VALUES 和 INT128_VALUES,获取迭代器对象
    with exc_iter(INT128_VALUES, INT128_VALUES) as it:
        # 遍历迭代器,每次迭代获取 a 和 b
        for a, b in it:
            # 计算 a + b 的结果
            c = a + b
            # 检查结果是否在 INT128_MIN 和 INT128_MAX 范围内
            if not (INT128_MIN <= c <= INT128_MAX):
                # 如果结果超出范围,断言抛出 OverflowError 异常,确保函数 mt.extint_add_128 能正确处理溢出
                assert_raises(OverflowError, mt.extint_add_128, a, b)
            else:
                # 如果结果在范围内,调用 mt.extint_add_128 计算结果 d
                d = mt.extint_add_128(a, b)
                # 断言计算结果 d 等于预期结果 c
                if c != d:
                    assert_equal(d, c)
# 测试函数:对给定的 INT128_VALUES 迭代器进行测试
def test_sub_128():
    # 使用 exc_iter 上下文管理器,迭代 INT128_VALUES 中的元素对 (a, b)
    with exc_iter(INT128_VALUES, INT128_VALUES) as it:
        for a, b in it:
            # 计算 a - b
            c = a - b
            # 检查是否 c 在 INT128_MIN 和 INT128_MAX 范围内
            if not (INT128_MIN <= c <= INT128_MAX):
                # 如果不在范围内,预期会引发 OverflowError 异常,调用 mt.extint_sub_128(a, b)
                assert_raises(OverflowError, mt.extint_sub_128, a, b)
            else:
                # 如果在范围内,调用 mt.extint_sub_128(a, b) 计算结果 d
                d = mt.extint_sub_128(a, b)
                # 检查计算结果是否与预期结果 c 相等
                if c != d:
                    assert_equal(d, c)


# 测试函数:对给定的 INT128_VALUES 迭代器进行测试
def test_neg_128():
    # 使用 exc_iter 上下文管理器,迭代 INT128_VALUES 中的元素 a
    with exc_iter(INT128_VALUES) as it:
        for a, in it:
            # 计算 -a
            b = -a
            # 调用 mt.extint_neg_128(a) 计算结果 c
            c = mt.extint_neg_128(a)
            # 检查计算结果是否与预期结果 b 相等
            if b != c:
                assert_equal(c, b)


# 测试函数:对给定的 INT128_VALUES 迭代器进行测试
def test_shl_128():
    # 使用 exc_iter 上下文管理器,迭代 INT128_VALUES 中的元素 a
    with exc_iter(INT128_VALUES) as it:
        for a, in it:
            # 根据 a 的正负情况计算左移结果 b
            if a < 0:
                b = -(((-a) << 1) & (2**128-1))
            else:
                b = (a << 1) & (2**128-1)
            # 调用 mt.extint_shl_128(a) 计算结果 c
            c = mt.extint_shl_128(a)
            # 检查计算结果是否与预期结果 b 相等
            if b != c:
                assert_equal(c, b)


# 测试函数:对给定的 INT128_VALUES 迭代器进行测试
def test_shr_128():
    # 使用 exc_iter 上下文管理器,迭代 INT128_VALUES 中的元素 a
    with exc_iter(INT128_VALUES) as it:
        for a, in it:
            # 根据 a 的正负情况计算右移结果 b
            if a < 0:
                b = -((-a) >> 1)
            else:
                b = a >> 1
            # 调用 mt.extint_shr_128(a) 计算结果 c
            c = mt.extint_shr_128(a)
            # 检查计算结果是否与预期结果 b 相等
            if b != c:
                assert_equal(c, b)


# 测试函数:对给定的 INT128_VALUES 迭代器进行测试
def test_gt_128():
    # 使用 exc_iter 上下文管理器,迭代 INT128_VALUES 中的元素对 (a, b)
    with exc_iter(INT128_VALUES, INT128_VALUES) as it:
        for a, b in it:
            # 计算 a 是否大于 b,结果为布尔值 c
            c = a > b
            # 调用 mt.extint_gt_128(a, b) 计算结果 d
            d = mt.extint_gt_128(a, b)
            # 检查计算结果是否与预期结果 c 相等
            if c != d:
                assert_equal(d, c)


# 测试函数:对给定的 INT128_VALUES 和 INT64_POS_VALUES 迭代器进行测试
@pytest.mark.slow
def test_divmod_128_64():
    with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it:
        for a, b in it:
            # 根据 a 和 b 计算 divmod 结果 c 和 cr
            if a >= 0:
                c, cr = divmod(a, b)
            else:
                c, cr = divmod(-a, b)
                c = -c
                cr = -cr

            # 调用 mt.extint_divmod_128_64(a, b) 计算结果 d, dr
            d, dr = mt.extint_divmod_128_64(a, b)

            # 检查计算结果是否符合预期
            if c != d or d != dr or b * d + dr != a:
                assert_equal(d, c)
                assert_equal(dr, cr)
                assert_equal(b * d + dr, a)


# 测试函数:对给定的 INT128_VALUES 和 INT64_POS_VALUES 迭代器进行测试
def test_floordiv_128_64():
    with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it:
        for a, b in it:
            # 计算 a 除以 b 的整数除法结果 c
            c = a // b
            # 调用 mt.extint_floordiv_128_64(a, b) 计算结果 d
            d = mt.extint_floordiv_128_64(a, b)

            # 检查计算结果是否与预期结果 c 相等
            if c != d:
                assert_equal(d, c)


# 测试函数:对给定的 INT128_VALUES 和 INT64_POS_VALUES 迭代器进行测试
def test_ceildiv_128_64():
    with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it:
        for a, b in it:
            # 计算 a 除以 b 的向上取整除法结果 c
            c = (a + b - 1) // b
            # 调用 mt.extint_ceildiv_128_64(a, b) 计算结果 d
            d = mt.extint_ceildiv_128_64(a, b)

            # 检查计算结果是否与预期结果 c 相等
            if c != d:
                assert_equal(d, c)

.\numpy\numpy\_core\tests\test_function_base.py

import sys  # 导入sys模块,用于系统相关的操作

import pytest  # 导入pytest模块,用于编写和运行测试用例

import numpy as np  # 导入NumPy库,用于科学计算
from numpy import (
    logspace, linspace, geomspace, dtype, array, arange, isnan,  # 导入NumPy的各种函数和类
    ndarray, sqrt, nextafter, stack, errstate
    )
from numpy._core import sctypes  # 导入NumPy内部的_core模块中的sctypes函数
from numpy._core.function_base import add_newdoc  # 导入NumPy内部的function_base模块中的add_newdoc函数
from numpy.testing import (  # 导入NumPy的测试模块中的各种断言函数
    assert_, assert_equal, assert_raises, assert_array_equal, assert_allclose,
    IS_PYPY
    )


class PhysicalQuantity(float):
    def __new__(cls, value):  # 物理量类,继承自float,用于带单位的数值计算
        return float.__new__(cls, value)

    def __add__(self, x):  # 重载加法运算符,确保操作数是PhysicalQuantity类型
        assert_(isinstance(x, PhysicalQuantity))
        return PhysicalQuantity(float(x) + float(self))

    __radd__ = __add__  # 右加法的实现与左加法相同

    def __sub__(self, x):  # 重载减法运算符,确保操作数是PhysicalQuantity类型
        assert_(isinstance(x, PhysicalQuantity))
        return PhysicalQuantity(float(self) - float(x))

    def __rsub__(self, x):  # 右减法的实现与左减法相反
        assert_(isinstance(x, PhysicalQuantity))
        return PhysicalQuantity(float(x) - float(self))

    def __mul__(self, x):  # 重载乘法运算符,确保操作数是PhysicalQuantity类型
        return PhysicalQuantity(float(x) * float(self))

    __rmul__ = __mul__  # 右乘法的实现与左乘法相同

    def __div__(self, x):  # 重载除法运算符,确保操作数是PhysicalQuantity类型
        return PhysicalQuantity(float(self) / float(x))

    def __rdiv__(self, x):  # 右除法的实现与左除法相反
        return PhysicalQuantity(float(x) / float(self))


class PhysicalQuantity2(ndarray):  # 物理量2类,继承自NumPy的ndarray类
    __array_priority__ = 10  # 设定数组优先级为10,用于运算符重载的优先级设置


class TestLogspace:

    def test_basic(self):  # 测试logspace基本功能
        y = logspace(0, 6)  # 生成指数等间隔的数组
        assert_(len(y) == 50)  # 断言生成数组长度为50
        y = logspace(0, 6, num=100)  # 指定生成100个点的指数等间隔数组
        assert_(y[-1] == 10 ** 6)  # 断言最后一个元素为10^6
        y = logspace(0, 6, endpoint=False)  # 不包含结束点的指数等间隔数组
        assert_(y[-1] < 10 ** 6)  # 断言最后一个元素小于10^6
        y = logspace(0, 6, num=7)  # 指定生成7个点的指数等间隔数组
        assert_array_equal(y, [1, 10, 100, 1e3, 1e4, 1e5, 1e6])  # 断言生成数组与预期数组相等

    def test_start_stop_array(self):  # 测试接受数组作为起始和结束点的logspace功能
        start = array([0., 1.])  # 起始点数组
        stop = array([6., 7.])  # 结束点数组
        t1 = logspace(start, stop, 6)  # 生成指数等间隔数组,起始和结束点分别为数组元素
        t2 = stack([logspace(_start, _stop, 6)
                    for _start, _stop in zip(start, stop)], axis=1)  # 使用zip函数生成多维数组
        assert_equal(t1, t2)  # 断言两个数组相等
        t3 = logspace(start, stop[0], 6)  # 使用数组和标量生成指数等间隔数组
        t4 = stack([logspace(_start, stop[0], 6)
                    for _start in start], axis=1)  # 使用列表推导式生成多维数组
        assert_equal(t3, t4)  # 断言两个数组相等
        t5 = logspace(start, stop, 6, axis=-1)  # 指定轴向生成指数等间隔数组
        assert_equal(t5, t2.T)  # 断言生成数组与转置后的多维数组相等

    @pytest.mark.parametrize("axis", [0, 1, -1])
    def test_base_array(self, axis: int):  # 测试接受数组作为基数的logspace功能
        start = 1  # 起始点
        stop = 2  # 结束点
        num = 6  # 生成点数
        base = array([1, 2])  # 基数数组
        t1 = logspace(start, stop, num=num, base=base, axis=axis)  # 生成指定基数的指数等间隔数组
        t2 = stack(
            [logspace(start, stop, num=num, base=_base) for _base in base],  # 使用列表推导式生成多维数组
            axis=(axis + 1) % t1.ndim,  # 指定轴向堆叠数组
        )
        assert_equal(t1, t2)  # 断言两个数组相等

    @pytest.mark.parametrize("axis", [0, 1, -1])
    # 测试以数组中的元素作为 stop 参数时的 logspace 函数
    def test_stop_base_array(self, axis: int):
        # 设定起始值
        start = 1
        # 用数组指定 stop 值
        stop = array([2, 3])
        # 指定数量
        num = 6
        # 用数组指定 base 值
        base = array([1, 2])
        # 调用 logspace 函数,生成第一个数组 t1
        t1 = logspace(start, stop, num=num, base=base, axis=axis)
        # 通过列表推导式生成第二个数组 t2,其中用到了不同的 stop 和 base
        t2 = stack(
            [logspace(start, _stop, num=num, base=_base)
             for _stop, _base in zip(stop, base)],
            axis=(axis + 1) % t1.ndim,
        )
        # 断言 t1 和 t2 应该相等
        assert_equal(t1, t2)

    # 测试不同 dtype 参数对 logspace 函数的影响
    def test_dtype(self):
        # 测试 dtype='float32'
        y = logspace(0, 6, dtype='float32')
        assert_equal(y.dtype, dtype('float32'))
        # 测试 dtype='float64'
        y = logspace(0, 6, dtype='float64')
        assert_equal(y.dtype, dtype('float64'))
        # 测试 dtype='int32'
        y = logspace(0, 6, dtype='int32')
        assert_equal(y.dtype, dtype('int32'))

    # 测试物理量对象 PhysicalQuantity 作为参数时的 logspace 函数
    def test_physical_quantities(self):
        # 创建两个物理量对象
        a = PhysicalQuantity(1.0)
        b = PhysicalQuantity(5.0)
        # 断言 logspace(a, b) 应该等同于 logspace(1.0, 5.0)
        assert_equal(logspace(a, b), logspace(1.0, 5.0))

    # 测试视图为 PhysicalQuantity2 类型的数组作为参数时的 logspace 函数
    def test_subclass(self):
        # 创建两个视图为 PhysicalQuantity2 的数组
        a = array(1).view(PhysicalQuantity2)
        b = array(7).view(PhysicalQuantity2)
        # 调用 logspace 函数,生成第一个数组 ls
        ls = logspace(a, b)
        # 断言 ls 应该是 PhysicalQuantity2 类型的对象
        assert type(ls) is PhysicalQuantity2
        # 断言 ls 应该等同于 logspace(1.0, 7.0)
        assert_equal(ls, logspace(1.0, 7.0))
        # 再次调用 logspace 函数,用 1 作为参数,生成第二个数组 ls
        ls = logspace(a, b, 1)
        # 断言 ls 应该是 PhysicalQuantity2 类型的对象
        assert type(ls) is PhysicalQuantity2
        # 断言 ls 应该等同于 logspace(1.0, 7.0, 1)
        assert_equal(ls, logspace(1.0, 7.0, 1))
# 定义一个测试类 TestGeomspace,用于测试 geomspace 函数的各种情况
class TestGeomspace:

    # 测试 geomspace 函数的基本用法
    def test_basic(self):
        # 默认参数情况下生成从 1 到 1e6 的等比数列,长度为 50
        y = geomspace(1, 1e6)
        assert_(len(y) == 50)

        # 指定生成长度为 100 的等比数列,确保最后一个元素等于 1e6
        y = geomspace(1, 1e6, num=100)
        assert_(y[-1] == 10 ** 6)

        # 不包括终点的等比数列,确保最后一个元素小于 1e6
        y = geomspace(1, 1e6, endpoint=False)
        assert_(y[-1] < 10 ** 6)

        # 指定生成长度为 7 的等比数列,验证生成的数列与预期的一致
        y = geomspace(1, 1e6, num=7)
        assert_array_equal(y, [1, 10, 100, 1e3, 1e4, 1e5, 1e6])

        # 测试非常规情况下的等比数列生成
        y = geomspace(8, 2, num=3)
        assert_allclose(y, [8, 4, 2])  # 确保数列的近似相等性
        assert_array_equal(y.imag, 0)  # 确保数列的虚部全部为零

        # 负数范围内的等比数列生成,验证生成的数列与预期的一致
        y = geomspace(-1, -100, num=3)
        assert_array_equal(y, [-1, -10, -100])
        assert_array_equal(y.imag, 0)

        y = geomspace(-100, -1, num=3)
        assert_array_equal(y, [-100, -10, -1])
        assert_array_equal(y.imag, 0)

    # 测试边界条件,确保生成的数列的起始点和终点与指定的起始点和终点完全一致
    def test_boundaries_match_start_and_stop_exactly(self):
        start = 0.3
        stop = 20.3

        # 测试只生成一个数的情况,确保生成的数等于指定的起始点
        y = geomspace(start, stop, num=1)
        assert_equal(y[0], start)

        # 测试不包括终点的情况下,生成只有一个数,确保生成的数等于指定的起始点
        y = geomspace(start, stop, num=1, endpoint=False)
        assert_equal(y[0], start)

        # 测试生成长度为 3 的数列,确保第一个数等于起始点,最后一个数等于终点
        y = geomspace(start, stop, num=3)
        assert_equal(y[0], start)
        assert_equal(y[-1], stop)

        # 测试不包括终点的情况下,生成长度为 3 的数列,确保第一个数等于起始点
        y = geomspace(start, stop, num=3, endpoint=False)
        assert_equal(y[0], start)

    # 测试在数列内部含有 NaN 值的情况
    def test_nan_interior(self):
        # 忽略无效值错误,生成长度为 4 的数列,确保第一个数和最后一个数正确,中间的数全部为 NaN
        with errstate(invalid='ignore'):
            y = geomspace(-3, 3, num=4)

        assert_equal(y[0], -3.0)
        assert_(isnan(y[1:-1]).all())  # 确保中间的数全部为 NaN
        assert_equal(y[3], 3.0)

        # 同样的情况下,不包括终点的数列,确保生成的数列的第一个数正确,中间的数全部为 NaN
        with errstate(invalid='ignore'):
            y = geomspace(-3, 3, num=4, endpoint=False)

        assert_equal(y[0], -3.0)
        assert_(isnan(y[1:]).all())  # 确保中间的数全部为 NaN
    def test_complex(self):
        # 测试复数情况

        # 纯虚数情况
        y = geomspace(1j, 16j, num=5)
        assert_allclose(y, [1j, 2j, 4j, 8j, 16j])
        assert_array_equal(y.real, 0)

        y = geomspace(-4j, -324j, num=5)
        assert_allclose(y, [-4j, -12j, -36j, -108j, -324j])
        assert_array_equal(y.real, 0)

        y = geomspace(1+1j, 1000+1000j, num=4)
        assert_allclose(y, [1+1j, 10+10j, 100+100j, 1000+1000j])

        y = geomspace(-1+1j, -1000+1000j, num=4)
        assert_allclose(y, [-1+1j, -10+10j, -100+100j, -1000+1000j])

        # 对数螺线情况
        y = geomspace(-1, 1, num=3, dtype=complex)
        assert_allclose(y, [-1, 1j, +1])

        y = geomspace(0+3j, -3+0j, 3)
        assert_allclose(y, [0+3j, -3/sqrt(2)+3j/sqrt(2), -3+0j])
        y = geomspace(0+3j, 3+0j, 3)
        assert_allclose(y, [0+3j, 3/sqrt(2)+3j/sqrt(2), 3+0j])
        y = geomspace(-3+0j, 0-3j, 3)
        assert_allclose(y, [-3+0j, -3/sqrt(2)-3j/sqrt(2), 0-3j])
        y = geomspace(0+3j, -3+0j, 3)
        assert_allclose(y, [0+3j, -3/sqrt(2)+3j/sqrt(2), -3+0j])
        y = geomspace(-2-3j, 5+7j, 7)
        assert_allclose(y, [-2-3j, -0.29058977-4.15771027j,
                            2.08885354-4.34146838j, 4.58345529-3.16355218j,
                            6.41401745-0.55233457j, 6.75707386+3.11795092j,
                            5+7j])

        # 类型转换应防止 -5 变成 NaN
        y = geomspace(3j, -5, 2)
        assert_allclose(y, [3j, -5])
        y = geomspace(-5, 3j, 2)
        assert_allclose(y, [-5, 3j])

    def test_complex_shortest_path(self):
        # 测试最短对数螺线路径,参见 gh-25644
        x = 1.2 + 3.4j
        y = np.exp(1j*(np.pi-.1)) * x
        z = np.geomspace(x, y, 5)
        expected = np.array([1.2 + 3.4j, -1.47384 + 3.2905616j,
                        -3.33577588 + 1.36842949j, -3.36011056 - 1.30753855j,
                        -1.53343861 - 3.26321406j])
        np.testing.assert_array_almost_equal(z, expected)


    def test_dtype(self):
        # 测试不同数据类型

        y = geomspace(1, 1e6, dtype='float32')
        assert_equal(y.dtype, dtype('float32'))
        y = geomspace(1, 1e6, dtype='float64')
        assert_equal(y.dtype, dtype('float64'))
        y = geomspace(1, 1e6, dtype='int32')
        assert_equal(y.dtype, dtype('int32'))

        # 原生数据类型
        y = geomspace(1, 1e6, dtype=float)
        assert_equal(y.dtype, dtype('float64'))
        y = geomspace(1, 1e6, dtype=complex)
        assert_equal(y.dtype, dtype('complex128'))
    def test_start_stop_array_scalar(self):
        # 定义整数类型的数组边界
        lim1 = array([120, 100], dtype="int8")
        lim2 = array([-120, -100], dtype="int8")
        # 定义无符号短整型数组边界
        lim3 = array([1200, 1000], dtype="uint16")
        # 创建等比数列,使用 lim1 数组中的边界值
        t1 = geomspace(lim1[0], lim1[1], 5)
        # 创建等比数列,使用 lim2 数组中的边界值
        t2 = geomspace(lim2[0], lim2[1], 5)
        # 创建等比数列,使用 lim3 数组中的边界值
        t3 = geomspace(lim3[0], lim3[1], 5)
        # 创建等比数列,使用浮点数边界值
        t4 = geomspace(120.0, 100.0, 5)
        # 创建等比数列,使用负浮点数边界值
        t5 = geomspace(-120.0, -100.0, 5)
        # 创建等比数列,使用浮点数边界值
        t6 = geomspace(1200.0, 1000.0, 5)

        # 断言比较 t1 和 t4,相对误差容差为 1e-2
        assert_allclose(t1, t4, rtol=1e-2)
        # 断言比较 t2 和 t5,相对误差容差为 1e-2
        assert_allclose(t2, t5, rtol=1e-2)
        # 断言比较 t3 和 t6,相对误差容差为 1e-5
        assert_allclose(t3, t6, rtol=1e-5)

    def test_start_stop_array(self):
        # 定义包含特殊情况的起始数组
        start = array([1.e0, 32., 1j, -4j, 1+1j, -1])
        # 定义包含特殊情况的结束数组
        stop = array([1.e4, 2., 16j, -324j, 10000+10000j, 1])
        # 创建多个等比数列,每对起始和结束值生成一个列,组合成 t1
        t1 = geomspace(start, stop, 5)
        # 使用 zip 将 start 和 stop 中的每对元素作为参数传递给 geomspace,创建 t2
        t2 = stack([geomspace(_start, _stop, 5)
                    for _start, _stop in zip(start, stop)], axis=1)
        # 断言 t1 等于 t2
        assert_equal(t1, t2)
        # 创建多个等比数列,每个起始值与同一个结束值生成一个列,组合成 t3
        t3 = geomspace(start, stop[0], 5)
        # 使用 zip 将 start 中的每个元素与 stop[0] 作为参数传递给 geomspace,创建 t4
        t4 = stack([geomspace(_start, stop[0], 5)
                    for _start in start], axis=1)
        # 断言 t3 等于 t4
        assert_equal(t3, t4)
        # 创建多个等比数列,每对起始和结束值生成一个列,并沿着轴反转,组合成 t5
        t5 = geomspace(start, stop, 5, axis=-1)
        # 断言 t5 等于 t2 的转置
        assert_equal(t5, t2.T)

    def test_physical_quantities(self):
        # 创建物理量对象 a 和 b
        a = PhysicalQuantity(1.0)
        b = PhysicalQuantity(5.0)
        # 断言 geomspace(a, b) 等于 geomspace(1.0, 5.0)
        assert_equal(geomspace(a, b), geomspace(1.0, 5.0))

    def test_subclass(self):
        # 创建 PhysicalQuantity2 类型的数组 a 和 b
        a = array(1).view(PhysicalQuantity2)
        b = array(7).view(PhysicalQuantity2)
        # 使用 geomspace(a, b) 创建等比数列 gs
        gs = geomspace(a, b)
        # 断言 gs 的类型是 PhysicalQuantity2
        assert type(gs) is PhysicalQuantity2
        # 断言 gs 等于 geomspace(1.0, 7.0)
        assert_equal(gs, geomspace(1.0, 7.0))
        # 使用 geomspace(a, b, 1) 创建等比数列 gs
        gs = geomspace(a, b, 1)
        # 断言 gs 的类型是 PhysicalQuantity2
        assert type(gs) is PhysicalQuantity2
        # 断言 gs 等于 geomspace(1.0, 7.0, 1)

    def test_bounds(self):
        # 断言调用 geomspace(0, 10) 会引发 ValueError 异常
        assert_raises(ValueError, geomspace, 0, 10)
        # 断言调用 geomspace(10, 0) 会引发 ValueError 异常
        assert_raises(ValueError, geomspace, 10, 0)
        # 断言调用 geomspace(0, 0) 会引发 ValueError 异常
        assert_raises(ValueError, geomspace, 0, 0)
    # 定义一个名为 TestLinspace 的测试类
class TestLinspace:

    # 定义测试基本功能的方法
    def test_basic(self):
        # 调用 linspace 函数生成等间隔的数列 y,长度为 50
        y = linspace(0, 10)
        # 断言 y 的长度为 50
        assert_(len(y) == 50)
        # 再次调用 linspace 函数生成等间隔的数列 y,包括终点值 10,数量为 100
        y = linspace(2, 10, num=100)
        # 断言 y 的最后一个值为 10
        assert_(y[-1] == 10)
        # 再次调用 linspace 函数生成等间隔的数列 y,不包括终点值 10
        y = linspace(2, 10, endpoint=False)
        # 断言 y 的最后一个值小于 10
        assert_(y[-1] < 10)
        # 使用 assert_raises 断言 ValueError 是否会被引发
        assert_raises(ValueError, linspace, 0, 10, num=-1)

    # 定义测试边界情况的方法
    def test_corner(self):
        # 调用 linspace 函数生成等间隔的数列 y,包括起点和终点值,数量为 1
        y = list(linspace(0, 1, 1))
        # 断言 y 应为 [0.0]
        assert_(y == [0.0], y)
        # 使用 assert_raises 断言 TypeError 是否会被引发
        assert_raises(TypeError, linspace, 0, 1, num=2.5)

    # 定义测试数据类型的方法
    def test_type(self):
        # 调用 linspace 函数生成等间隔的数列,数量为 0,获取其数据类型
        t1 = linspace(0, 1, 0).dtype
        # 调用 linspace 函数生成等间隔的数列,数量为 1,获取其数据类型
        t2 = linspace(0, 1, 1).dtype
        # 调用 linspace 函数生成等间隔的数列,数量为 2,获取其数据类型
        t3 = linspace(0, 1, 2).dtype
        # 断言 t1 与 t2 相等
        assert_equal(t1, t2)
        # 断言 t2 与 t3 相等
        assert_equal(t2, t3)

    # 定义测试数据类型参数的方法
    def test_dtype(self):
        # 调用 linspace 函数生成等间隔的浮点数数列,数据类型为 'float32'
        y = linspace(0, 6, dtype='float32')
        # 断言 y 的数据类型为 'float32'
        assert_equal(y.dtype, dtype('float32'))
        # 调用 linspace 函数生成等间隔的浮点数数列,数据类型为 'float64'
        y = linspace(0, 6, dtype='float64')
        # 断言 y 的数据类型为 'float64'
        assert_equal(y.dtype, dtype('float64'))
        # 调用 linspace 函数生成等间隔的整数数列,数据类型为 'int32'
        y = linspace(0, 6, dtype='int32')
        # 断言 y 的数据类型为 'int32'
        assert_equal(y.dtype, dtype('int32'))

    # 定义测试使用数组、标量作为起始和结束值的方法
    def test_start_stop_array_scalar(self):
        # 创建包含两个元素的 int8 类型数组 lim1 和 lim2
        lim1 = array([-120, 100], dtype="int8")
        lim2 = array([120, -100], dtype="int8")
        # 创建包含两个元素的 uint16 类型数组 lim3
        lim3 = array([1200, 1000], dtype="uint16")
        # 调用 linspace 函数生成 lim1[0] 到 lim1[1] 之间的等间隔数列,数量为 5
        t1 = linspace(lim1[0], lim1[1], 5)
        # 调用 linspace 函数生成 lim2[0] 到 lim2[1] 之间的等间隔数列,数量为 5
        t2 = linspace(lim2[0], lim2[1], 5)
        # 调用 linspace 函数生成 lim3[0] 到 lim3[1] 之间的等间隔数列,数量为 5
        t3 = linspace(lim3[0], lim3[1], 5)
        # 调用 linspace 函数生成 -120.0 到 100.0 之间的等间隔数列,数量为 5
        t4 = linspace(-120.0, 100.0, 5)
        # 调用 linspace 函数生成 120.0 到 -100.0 之间的等间隔数列,数量为 5
        t5 = linspace(120.0, -100.0, 5)
        # 调用 linspace 函数生成 1200.0 到 1000.0 之间的等间隔数列,数量为 5
        t6 = linspace(1200.0, 1000.0, 5)
        # 断言 t1 与 t4 相等
        assert_equal(t1, t4)
        # 断言 t2 与 t5 相等
        assert_equal(t2, t5)
        # 断言 t3 与 t6 相等
        assert_equal(t3, t6)

    # 定义测试使用数组作为起始和结束值的方法
    def test_start_stop_array(self):
        # 创建包含两个元素的 int8 类型数组 start 和 stop
        start = array([-120, 120], dtype="int8")
        stop = array([100, -100], dtype="int8")
        # 调用 linspace 函数分别以 start 和 stop 中的每个元素作为起始和结束值生成等间隔数列,数量为 5
        t1 = linspace(start, stop, 5)
        # 使用 stack 函数将生成的数列按列堆叠成二维数组 t2
        t2 = stack([linspace(_start, _stop, 5)
                    for _start, _stop in zip(start, stop)], axis=1)
        # 断言 t1 与 t2 相等
        assert_equal(t1, t2)
        # 调用 linspace 函数以 start 中的每个元素作为起始值,stop[0] 作为结束值生成等间隔数列,数量为 5
        t3 = linspace(start, stop[0], 5)
        # 使用 stack 函数将生成的数列按列堆叠成二维数组 t4
        t4 = stack([linspace(_start, stop[0], 5)
                    for _start in start], axis=1)
        # 断言 t3 与 t4 相等
        assert_equal(t3, t4)
        # 调用 linspace 函数以 start 和 stop 中的每个元素作为起始和结束值生成等间隔数列,数量为 5,按行堆叠成二维数组 t5
        t5 = linspace(start, stop, 5, axis=-1)
        # 断言 t5 与 t2 的转置相等
        assert_equal(t5, t2.T)

    # 定义测试生成复数数列的方法
    def test_complex(self):
        # 调用 linspace 函数生成复数数列 lim1,起始值为 1+2j,结束值为 3+4j,数量为 5
        lim1 = linspace(1 + 2j, 3 + 4j, 5)
        # 创建期望的复数数列 t1
        t1 = array([1.0+2.j, 1.5+2.5j,  2.0+3j, 2.5+3.5j, 3.0+4j])
        # 调用 linspace 函数生成复数数列 lim2,起始值为 1j,结束值为 10,数量为 5
        lim2 = linspace(1j, 10, 5)
        # 创建期望的复数数列 t2
        t2 = array([0.0+1.j, 2.5+0.75j, 5.0+0.5j, 7
    def test_array_interface(self):
        # 回归测试,用于检查 https://github.com/numpy/numpy/pull/6659
        # 确保 start/stop 可以是实现了 __array_interface__ 并且可以转换为数值标量的对象

        class Arrayish:
            """
            支持 __array_interface__ 的通用对象,因此理论上可以转换为数值标量,
            但不被认为是数值型,同时也支持浮点数乘法。

            数据应该是一个实现了缓冲区接口的对象,至少包含 4 个字节。
            """

            def __init__(self, data):
                self._data = data

            @property
            def __array_interface__(self):
                return {'shape': (), 'typestr': '<i4', 'data': self._data,
                        'version': 3}

            def __mul__(self, other):
                # 对于这个测试,任何乘法都是一个恒等操作 :)
                return self

        one = Arrayish(array(1, dtype='<i4'))
        five = Arrayish(array(5, dtype='<i4'))

        assert_equal(linspace(one, five), linspace(1, 5))

    def test_denormal_numbers(self):
        # 回归测试,用于检查 gh-5437。在使用 ICC 编译时可能会失败,因为 ICC 会将非规格化数变为零
        for ftype in sctypes['float']:
            stop = nextafter(ftype(0), ftype(1)) * 5  # 一个非规格化数
            assert_(any(linspace(0, stop, 10, endpoint=False, dtype=ftype)))

    def test_equivalent_to_arange(self):
        for j in range(1000):
            assert_equal(linspace(0, j, j+1, dtype=int),
                         arange(j+1, dtype=int))

    def test_retstep(self):
        for num in [0, 1, 2]:
            for ept in [False, True]:
                y = linspace(0, 1, num, endpoint=ept, retstep=True)
                assert isinstance(y, tuple) and len(y) == 2
                if num == 2:
                    y0_expect = [0.0, 1.0] if ept else [0.0, 0.5]
                    assert_array_equal(y[0], y0_expect)
                    assert_equal(y[1], y0_expect[1])
                elif num == 1 and not ept:
                    assert_array_equal(y[0], [0.0])
                    assert_equal(y[1], 1.0)
                else:
                    assert_array_equal(y[0], [0.0][:num])
                    assert isnan(y[1])

    def test_object(self):
        start = array(1, dtype='O')
        stop = array(2, dtype='O')
        y = linspace(start, stop, 3)
        assert_array_equal(y, array([1., 1.5, 2.]))
                    
    def test_round_negative(self):
        y = linspace(-1, 3, num=8, dtype=int)
        t = array([-1, -1, 0, 0, 1, 1, 2, 3], dtype=int)
        assert_array_equal(y, t)
    # 定义一个测试函数,测试在 any_step_zero 为 True 且 _mult_inplace 为 False 的情况下的行为
    def test_any_step_zero_and_not_mult_inplace(self):
        # 创建起始点数组,包含两个浮点数元素 [0.0, 1.0]
        start = array([0.0, 1.0])
        # 创建结束点数组,包含两个浮点数元素 [2.0, 1.0]
        stop = array([2.0, 1.0])
        # 使用 linspace 函数生成介于 start 和 stop 之间的均匀分布的数组,数组长度为 3
        y = linspace(start, stop, 3)
        # 使用 assert_array_equal 函数断言 y 的值等于预期的二维数组 [[0.0, 1.0], [1.0, 1.0], [2.0, 1.0]]
        assert_array_equal(y, array([[0.0, 1.0], [1.0, 1.0], [2.0, 1.0]]))
# 定义一个名为 TestAdd_newdoc 的测试类
class TestAdd_newdoc:

    # 用 pytest.mark.skipif 装饰器标记此测试,如果 Python 是以 -OO 优化模式运行,则跳过
    @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO")
    # 用 pytest.mark.xfail 装饰器标记此测试,如果是在 PyPy 上运行,则标记为预期失败
    @pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc")
    # 定义一个测试方法 test_add_doc
    def test_add_doc(self):
        # 断言:验证 np.add_newdoc 成功地附加了文档字符串
        tgt = "Current flat index into the array."
        assert_equal(np._core.flatiter.index.__doc__[:len(tgt)], tgt)
        # 断言:验证 np._core.ufunc.identity 的文档字符串长度大于 300
        assert_(len(np._core.ufunc.identity.__doc__) > 300)
        # 断言:验证 np.lib._index_tricks_impl.mgrid 的文档字符串长度大于 300
        assert_(len(np.lib._index_tricks_impl.mgrid.__doc__) > 300)

    # 用 pytest.mark.skipif 装饰器标记此测试,如果 Python 是以 -OO 优化模式运行,则跳过
    @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO")
    # 定义另一个测试方法 test_errors_are_ignored
    def test_errors_are_ignored(self):
        # 获取 np._core.flatiter.index 的当前文档字符串
        prev_doc = np._core.flatiter.index.__doc__
        # 添加一个新文档字符串到 "numpy._core" 模块的 "flatiter" 类的 "index" 方法
        add_newdoc("numpy._core", "flatiter", ("index", "bad docstring"))
        # 断言:验证 np._core.flatiter.index 的文档字符串没有改变
        assert prev_doc == np._core.flatiter.index.__doc__

.\numpy\numpy\_core\tests\test_getlimits.py

# 导入警告模块,用于处理警告信息
import warnings
# 导入 numpy 库
import numpy as np
# 导入 pytest 模块,用于编写和运行测试
import pytest
# 从 numpy._core 模块导入 finfo 和 iinfo 类
from numpy._core import finfo, iinfo
# 导入 half、single、double、longdouble 类型
from numpy import half, single, double, longdouble
# 导入 numpy.testing 模块中的断言函数
from numpy.testing import assert_equal, assert_, assert_raises
# 从 numpy._core.getlimits 模块中导入 _discovered_machar 和 _float_ma 函数

##################################################

# 定义 TestPythonFloat 测试类,测试 float 类型的 finfo 对象
class TestPythonFloat:
    # 测试 finfo 对象是否为单例
    def test_singleton(self):
        # 获取 float 类型的 finfo 对象
        ftype = finfo(float)
        # 再次获取 float 类型的 finfo 对象
        ftype2 = finfo(float)
        # 断言两个 finfo 对象的内存地址相同
        assert_equal(id(ftype), id(ftype2))

# 定义 TestHalf 测试类,测试 half 类型的 finfo 对象
class TestHalf:
    # 测试 finfo 对象是否为单例
    def test_singleton(self):
        # 获取 half 类型的 finfo 对象
        ftype = finfo(half)
        # 再次获取 half 类型的 finfo 对象
        ftype2 = finfo(half)
        # 断言两个 finfo 对象的内存地址相同
        assert_equal(id(ftype), id(ftype2))

# 定义 TestSingle 测试类,测试 single 类型的 finfo 对象
class TestSingle:
    # 测试 finfo 对象是否为单例
    def test_singleton(self):
        # 获取 single 类型的 finfo 对象
        ftype = finfo(single)
        # 再次获取 single 类型的 finfo 对象
        ftype2 = finfo(single)
        # 断言两个 finfo 对象的内存地址相同
        assert_equal(id(ftype), id(ftype2))

# 定义 TestDouble 测试类,测试 double 类型的 finfo 对象
class TestDouble:
    # 测试 finfo 对象是否为单例
    def test_singleton(self):
        # 获取 double 类型的 finfo 对象
        ftype = finfo(double)
        # 再次获取 double 类型的 finfo 对象
        ftype2 = finfo(double)
        # 断言两个 finfo 对象的内存地址相同
        assert_equal(id(ftype), id(ftype2))

# 定义 TestLongdouble 测试类,测试 longdouble 类型的 finfo 对象
class TestLongdouble:
    # 测试 finfo 对象是否为单例
    def test_singleton(self):
        # 获取 longdouble 类型的 finfo 对象
        ftype = finfo(longdouble)
        # 再次获取 longdouble 类型的 finfo 对象
        ftype2 = finfo(longdouble)
        # 断言两个 finfo 对象的内存地址相同
        assert_equal(id(ftype), id(ftype2))

# 定义一个辅助函数 assert_finfo_equal,用于断言两个 finfo 实例具有相同的属性值
def assert_finfo_equal(f1, f2):
    # 断言两个 finfo 实例在所有指定属性上的值相同
    for attr in ('bits', 'eps', 'epsneg', 'iexp', 'machep',
                 'max', 'maxexp', 'min', 'minexp', 'negep', 'nexp',
                 'nmant', 'precision', 'resolution', 'tiny',
                 'smallest_normal', 'smallest_subnormal'):
        assert_equal(getattr(f1, attr), getattr(f2, attr),
                     f'finfo instances {f1} and {f2} differ on {attr}')

# 定义一个辅助函数 assert_iinfo_equal,用于断言两个 iinfo 实例具有相同的属性值
def assert_iinfo_equal(i1, i2):
    # 断言两个 iinfo 实例在所有指定属性上的值相同
    for attr in ('bits', 'min', 'max'):
        assert_equal(getattr(i1, attr), getattr(i2, attr),
                     f'iinfo instances {i1} and {i2} differ on {attr}')

# 定义 TestFinfo 测试类,测试 finfo 对象的基本功能
class TestFinfo:
    # 测试基本的 finfo 功能
    def test_basic(self):
        # 定义一个包含不同数据类型的列表
        dts = list(zip(['f2', 'f4', 'f8', 'c8', 'c16'],
                       [np.float16, np.float32, np.float64, np.complex64,
                        np.complex128]))
        # 遍历列表中的每一对数据类型
        for dt1, dt2 in dts:
            # 断言两个不同数据类型的 finfo 实例具有相同的属性值
            assert_finfo_equal(finfo(dt1), finfo(dt2))

        # 断言当传入无效数据类型 'i4' 时会抛出 ValueError 异常
        assert_raises(ValueError, finfo, 'i4')

    # 测试 finfo 对象的回归测试 (Regression Test) - gh23108
    def test_regression_gh23108(self):
        # np.float32(1.0) 和 np.float64(1.0) 具有相同的哈希值,并且在 == 运算符下相等
        f1 = np.finfo(np.float32(1.0))
        f2 = np.finfo(np.float64(1.0))
        # 断言 f1 和 f2 不相等
        assert f1 != f2

    # 测试 finfo 对象的回归测试 (Regression Test) - gh23867
    def test_regression_gh23867(self):
        # 定义一个具有 dtype 属性的非可哈希对象
        class NonHashableWithDtype:
            __hash__ = None
            dtype = np.dtype('float32')
  
        x = NonHashableWithDtype()
        # 断言 np.finfo(x) 与 np.finfo(x.dtype) 相等
        assert np.finfo(x) == np.finfo(x.dtype)

# 定义 TestIinfo 测试类,用于测试整数信息对象 iinfo
class TestIinfo:
    # 定义一个测试方法,用于测试基本功能
    def test_basic(self):
        # 创建一个包含数据类型和对应的numpy数据类型的元组列表
        dts = list(zip(['i1', 'i2', 'i4', 'i8',
                   'u1', 'u2', 'u4', 'u8'],
                  [np.int8, np.int16, np.int32, np.int64,
                   np.uint8, np.uint16, np.uint32, np.uint64]))
        # 遍历元组列表,分别使用 assert_iinfo_equal 函数对数据类型信息进行断言比较
        for dt1, dt2 in dts:
            assert_iinfo_equal(iinfo(dt1), iinfo(dt2))

        # 使用 assert_raises 函数验证调用 iinfo('f4') 会引发 ValueError 异常
        assert_raises(ValueError, iinfo, 'f4')

    # 定义一个测试方法,用于测试无符号整数类型的最大值计算
    def test_unsigned_max(self):
        # 获取numpy支持的所有无符号整数类型
        types = np._core.sctypes['uint']
        # 遍历每种类型
        for T in types:
            # 在忽略溢出的错误状态下,计算当前类型 T 的最大值
            with np.errstate(over="ignore"):
                max_calculated = T(0) - T(1)
            # 断言 iinfo(T).max 等于上面计算得到的最大值
            assert_equal(iinfo(T).max, max_calculated)
class TestRepr:
    # 测试 np.iinfo 函数的输出是否符合预期
    def test_iinfo_repr(self):
        expected = "iinfo(min=-32768, max=32767, dtype=int16)"
        assert_equal(repr(np.iinfo(np.int16)), expected)

    # 测试 np.finfo 函数的输出是否符合预期
    def test_finfo_repr(self):
        expected = "finfo(resolution=1e-06, min=-3.4028235e+38," + \
                   " max=3.4028235e+38, dtype=float32)"
        assert_equal(repr(np.finfo(np.float32)), expected)


def test_instances():
    # 测试在数值实例上使用 iinfo 和 finfo 是否与对应类型的结果一致
    for c in [int, np.int16, np.int32, np.int64]:
        class_iinfo = iinfo(c)
        instance_iinfo = iinfo(c(12))

        assert_iinfo_equal(class_iinfo, instance_iinfo)

    for c in [float, np.float16, np.float32, np.float64]:
        class_finfo = finfo(c)
        instance_finfo = finfo(c(1.2))
        assert_finfo_equal(class_finfo, instance_finfo)

    # 测试当传入不合法参数时是否抛出 ValueError 异常
    with pytest.raises(ValueError):
        iinfo(10.)

    with pytest.raises(ValueError):
        iinfo('hi')

    with pytest.raises(ValueError):
        finfo(np.int64(1))


def assert_ma_equal(discovered, ma_like):
    # 检查 MachAr 类对象是否与计算出的 MachAr 实例相同
    for key, value in discovered.__dict__.items():
        assert_equal(value, getattr(ma_like, key))
        if hasattr(value, 'shape'):
            assert_equal(value.shape, getattr(ma_like, key).shape)
            assert_equal(value.dtype, getattr(ma_like, key).dtype)


def test_known_types():
    # 测试对已知类型编译参数是否正确
    for ftype, ma_like in ((np.float16, _float_ma[16]),
                           (np.float32, _float_ma[32]),
                           (np.float64, _float_ma[64])):
        assert_ma_equal(_discovered_machar(ftype), ma_like)
    # 抑制对 PPC 平台上双倍精度发现的警告
    with np.errstate(all='ignore'):
        ld_ma = _discovered_machar(np.longdouble)
    bytes = np.dtype(np.longdouble).itemsize
    if (ld_ma.it, ld_ma.maxexp) == (63, 16384) and bytes in (12, 16):
        # 80 位扩展精度
        assert_ma_equal(ld_ma, _float_ma[80])
    elif (ld_ma.it, ld_ma.maxexp) == (112, 16384) and bytes == 16:
        # IEE 754 128 位
        assert_ma_equal(ld_ma, _float_ma[128])


def test_subnormal_warning():
    """测试是否会引发次正常为零的警告"""
    with np.errstate(all='ignore'):
        ld_ma = _discovered_machar(np.longdouble)
    bytes = np.dtype(np.longdouble).itemsize
    # 使用 `warnings` 模块捕获警告信息
    with warnings.catch_warnings(record=True) as w:
        # 设置警告过滤器,始终显示警告
        warnings.simplefilter('always')
        # 如果 ld_ma.it 等于 63,ld_ma.maxexp 等于 16384,且 bytes 是 12 或 16
        if (ld_ma.it, ld_ma.maxexp) == (63, 16384) and bytes in (12, 16):
            # 对于80位扩展精度的情况
            ld_ma.smallest_subnormal
            # 断言:期望没有警告被触发
            assert len(w) == 0
        # 如果 ld_ma.it 等于 112,ld_ma.maxexp 等于 16384,且 bytes 是 16
        elif (ld_ma.it, ld_ma.maxexp) == (112, 16384) and bytes == 16:
            # 对于 IEEE 754 128位的情况
            ld_ma.smallest_subnormal
            # 断言:期望没有警告被触发
            assert len(w) == 0
        else:
            # 对于双倍精度的情况
            ld_ma.smallest_subnormal
            # 提示:这个测试可能在某些平台上失败
            assert len(w) == 0
# 定义一个测试函数,用于验证 np.finfo 函数对所有类型的浮点数和复数返回合理的结果
def test_plausible_finfo():
    # 遍历所有浮点数和复数类型,包括浮点数和复数的子类型
    for ftype in np._core.sctypes['float'] + np._core.sctypes['complex']:
        # 调用 np.finfo 函数获取特定类型的信息
        info = np.finfo(ftype)
        # 断言该类型的尾数位数大于1
        assert_(info.nmant > 1)
        # 断言该类型的最小指数小于-1
        assert_(info.minexp < -1)
        # 断言该类型的最大指数大于1
        assert_(info.maxexp > 1)

.\numpy\numpy\_core\tests\test_half.py

# 导入 platform 模块,用于获取平台信息
import platform
# 导入 pytest 模块,用于编写和运行测试用例
import pytest

# 导入 numpy 库,并分别导入其中的 uint16, float16, float32, float64 数据类型
import numpy as np
from numpy import uint16, float16, float32, float64
# 导入 numpy.testing 模块中的 assert_, assert_equal, _OLD_PROMOTION, IS_WASM 方法
from numpy.testing import assert_, assert_equal, _OLD_PROMOTION, IS_WASM

# 定义一个函数 assert_raises_fpe,用于验证是否引发浮点异常
def assert_raises_fpe(strmatch, callable, *args, **kwargs):
    try:
        # 调用给定的可调用对象,传入参数
        callable(*args, **kwargs)
    except FloatingPointError as exc:
        # 检查异常消息中是否包含指定的字符串
        assert_(str(exc).find(strmatch) >= 0,
                "Did not raise floating point %s error" % strmatch)
    else:
        # 如果没有引发预期的异常,抛出断言错误
        assert_(False,
                "Did not raise floating point %s error" % strmatch)

# 定义一个测试类 TestHalf
class TestHalf:
    # 在每个测试方法执行前调用,设置测试环境
    def setup_method(self):
        # 创建一个包含所有可能的 float16 值的数组
        self.all_f16 = np.arange(0x10000, dtype=uint16)
        self.all_f16.dtype = float16

        # 如果硬件支持,NaN 值可能会引发无效的浮点异常,这里忽略无效操作错误
        with np.errstate(invalid='ignore'):
            # 创建包含所有可能的 float16 值的数组,并转换为 float32 和 float64 类型
            self.all_f32 = np.array(self.all_f16, dtype=float32)
            self.all_f64 = np.array(self.all_f16, dtype=float64)

        # 创建一个包含所有非 NaN 值的 float16 数组,并按顺序排列
        self.nonan_f16 = np.concatenate(
                                (np.arange(0xfc00, 0x7fff, -1, dtype=uint16),
                                 np.arange(0x0000, 0x7c01, 1, dtype=uint16)))
        self.nonan_f16.dtype = float16
        # 转换非 NaN 值数组为 float32 和 float64 类型
        self.nonan_f32 = np.array(self.nonan_f16, dtype=float32)
        self.nonan_f64 = np.array(self.nonan_f16, dtype=float64)

        # 创建一个包含所有有限 float16 值的数组,并按顺序排列
        self.finite_f16 = self.nonan_f16[1:-1]
        self.finite_f32 = self.nonan_f32[1:-1]
        self.finite_f64 = self.nonan_f64[1:-1]
    def test_half_conversions(self):
        """Checks that all 16-bit values survive conversion
           to/from 32-bit and 64-bit float"""
        # Because the underlying routines preserve the NaN bits, every
        # value is preserved when converting to/from other floats.

        # Convert from float32 back to float16
        with np.errstate(invalid='ignore'):
            # 创建一个包含所有 float32 值的数组 b,将其转换为 float16 类型
            b = np.array(self.all_f32, dtype=float16)
        # 避免由于 Q/SNaNs 的位差而测试 NaNs
        b_nn = b == b
        # 断言转换后的 float16 数组与原始 float16 数组的 uint16 表示相等
        assert_equal(self.all_f16[b_nn].view(dtype=uint16),
                     b[b_nn].view(dtype=uint16))

        # Convert from float64 back to float16
        with np.errstate(invalid='ignore'):
            # 创建一个包含所有 float64 值的数组 b,将其转换为 float16 类型
            b = np.array(self.all_f64, dtype=float16)
        # 避免由于 Q/SNaNs 的位差而测试 NaNs
        b_nn = b == b
        # 断言转换后的 float16 数组与原始 float16 数组的 uint16 表示相等
        assert_equal(self.all_f16[b_nn].view(dtype=uint16),
                     b[b_nn].view(dtype=uint16))

        # Convert float16 to longdouble and back
        # This doesn't necessarily preserve the extra NaN bits,
        # so exclude NaNs.
        # 创建一个不含 NaN 的 float16 数组,并将其转换为 longdouble 类型的数组 a_ld
        a_ld = np.array(self.nonan_f16, dtype=np.longdouble)
        # 将 longdouble 数组 a_ld 转换回 float16 类型的数组 b
        b = np.array(a_ld, dtype=float16)
        # 断言转换后的 float16 数组与原始 float16 数组的 uint16 表示相等
        assert_equal(self.nonan_f16.view(dtype=uint16),
                     b.view(dtype=uint16))

        # Check the range for which all integers can be represented
        # 创建一个包含所有整数的 int 数组 i_int,将其转换为 float16 类型的数组 i_f16
        i_int = np.arange(-2048, 2049)
        i_f16 = np.array(i_int, dtype=float16)
        # 将 float16 数组 i_f16 转换回 int 类型的数组 j
        j = np.array(i_f16, dtype=int)
        # 断言转换后的 int 数组 j 与原始 int 数组 i_int 相等
        assert_equal(i_int, j)
    # 定义一个测试方法,用于测试半精度浮点数转换的四舍五入行为
    def test_half_conversion_rounding(self, float_t, shift, offset):
        # 假设在转换过程中使用了四舍六入五成双的方式
        max_pattern = np.float16(np.finfo(np.float16).max).view(np.uint16)

        # 测试所有(正数)有限数字,denormalized(非正规化)情况最为有趣
        f16s_patterns = np.arange(0, max_pattern+1, dtype=np.uint16)
        f16s_float = f16s_patterns.view(np.float16).astype(float_t)

        # 将值向上或向下移动半个比特位(或者不移动)
        if shift == "up":
            f16s_float = 0.5 * (f16s_float[:-1] + f16s_float[1:])[1:]
        elif shift == "down":
            f16s_float = 0.5 * (f16s_float[:-1] + f16s_float[1:])[:-1]
        else:
            f16s_float = f16s_float[1:-1]

        # 将浮点数增加一个最小值:
        if offset == "up":
            f16s_float = np.nextafter(f16s_float, float_t(np.inf))
        elif offset == "down":
            f16s_float = np.nextafter(f16s_float, float_t(-np.inf))

        # 转换回 float16 并获取其比特模式:
        res_patterns = f16s_float.astype(np.float16).view(np.uint16)

        # 上述计算尝试使用原始值或 float16 值之间的精确中点。
        # 然后进一步以尽可能小的偏移量对它们进行偏移。
        # 如果没有偏移发生,将需要“四舍六入五成双”的逻辑,一个任意小的偏移应该始终导致正常的上下舍入。

        # 计算预期模式:
        cmp_patterns = f16s_patterns[1:-1].copy()

        if shift == "down" and offset != "up":
            shift_pattern = -1
        elif shift == "up" and offset != "down":
            shift_pattern = 1
        else:
            # 不能进行偏移,要么偏移为 None,因此所有舍入将回到原始状态,
            # 要么偏移过大,也会减少偏移量。
            shift_pattern = 0

        # 如果发生舍入,是正常舍入还是“四舍六入五成双”?
        if offset is None:
            # 发生四舍六入五成双,仅修改非偶数,转换为允许 + (-1)
            cmp_patterns[0::2].view(np.int16)[...] += shift_pattern
        else:
            cmp_patterns.view(np.int16)[...] += shift_pattern

        # 断言结果模式与预期模式相等
        assert_equal(res_patterns, cmp_patterns)

    # 使用 pytest 的参数化装饰器,定义了多个参数组合进行测试
    @pytest.mark.parametrize(["float_t", "uint_t", "bits"],
                             [(np.float32, np.uint32, 23),
                              (np.float64, np.uint64, 52)])
    # 测试半精度浮点数到整数和回合偶数的转换
    def test_half_conversion_denormal_round_even(self, float_t, uint_t, bits):
        # 测试在决定是否进行偶数舍入时是否考虑所有位(即末位不丢失)。
        # 参见 gh-12721。最小的非规格化数可能会丢失最多位:
        smallest_value = np.uint16(1).view(np.float16).astype(float_t)
        assert smallest_value == 2**-24

        # 根据偶数舍入规则将会舍入为零:
        rounded_to_zero = smallest_value / float_t(2)
        assert rounded_to_zero.astype(np.float16) == 0

        # 对于 float_t 来说,尾数将全部为 0,测试不应丢失这些较低位:
        for i in range(bits):
            # 稍微增加值应使其向上舍入:
            larger_pattern = rounded_to_zero.view(uint_t) | uint_t(1 << i)
            larger_value = larger_pattern.view(float_t)
            assert larger_value.astype(np.float16) == smallest_value

    # 测试 NaN 和 Inf
    def test_nans_infs(self):
        with np.errstate(all='ignore'):
            # 检查一些 ufuncs
            assert_equal(np.isnan(self.all_f16), np.isnan(self.all_f32))
            assert_equal(np.isinf(self.all_f16), np.isinf(self.all_f32))
            assert_equal(np.isfinite(self.all_f16), np.isfinite(self.all_f32))
            assert_equal(np.signbit(self.all_f16), np.signbit(self.all_f32))
            assert_equal(np.spacing(float16(65504)), np.inf)

            # 检查所有值与 NaN 的比较
            nan = float16(np.nan)

            assert_(not (self.all_f16 == nan).any())
            assert_(not (nan == self.all_f16).any())

            assert_((self.all_f16 != nan).all())
            assert_((nan != self.all_f16).all())

            assert_(not (self.all_f16 < nan).any())
            assert_(not (nan < self.all_f16).any())

            assert_(not (self.all_f16 <= nan).any())
            assert_(not (nan <= self.all_f16).any())

            assert_(not (self.all_f16 > nan).any())
            assert_(not (nan > self.all_f16).any())

            assert_(not (self.all_f16 >= nan).any())
            assert_(not (nan >= self.all_f16).any())
    def test_half_values(self):
        """Confirms a small number of known half values"""
        # 创建包含一些已知半精度浮点数的 NumPy 数组
        a = np.array([1.0, -1.0,
                      2.0, -2.0,
                      0.0999755859375, 0.333251953125,  # 1/10, 1/3
                      65504, -65504,           # Maximum magnitude
                      2.0**(-14), -2.0**(-14),  # Minimum normal
                      2.0**(-24), -2.0**(-24),  # Minimum subnormal
                      0, -1/1e1000,            # Signed zeros
                      np.inf, -np.inf])
        # 创建用于存储期望半精度浮点数表示的 NumPy 数组,并将其作为 uint16 解释
        b = np.array([0x3c00, 0xbc00,
                      0x4000, 0xc000,
                      0x2e66, 0x3555,
                      0x7bff, 0xfbff,
                      0x0400, 0x8400,
                      0x0001, 0x8001,
                      0x0000, 0x8000,
                      0x7c00, 0xfc00], dtype=np.uint16)
        # 将 b 数组的数据类型更改为 float16
        b.dtype = np.float16
        # 使用 assert_equal 断言两个数组 a 和 b 相等
        assert_equal(a, b)

    def test_half_rounding(self):
        """Checks that rounding when converting to half is correct"""
        # 创建包含各种浮点数的 NumPy 数组,用于测试半精度浮点数转换时的舍入行为
        a = np.array([2.0**-25 + 2.0**-35,  # Rounds to minimum subnormal
                      2.0**-25,       # Underflows to zero (nearest even mode)
                      2.0**-26,       # Underflows to zero
                      1.0+2.0**-11 + 2.0**-16,  # rounds to 1.0+2**(-10)
                      1.0+2.0**-11,   # rounds to 1.0 (nearest even mode)
                      1.0+2.0**-12,   # rounds to 1.0
                      65519,          # rounds to 65504
                      65520],         # rounds to inf
                      dtype=np.float64)
        # 期望的半精度浮点数舍入结果
        rounded = [2.0**-24,
                   0.0,
                   0.0,
                   1.0+2.0**(-10),
                   1.0,
                   1.0,
                   65504,
                   np.inf]

        # 检查从 float64 到 float16 的舍入是否正确
        with np.errstate(over="ignore"):
            # 使用 float16 类型将 a 数组转换为 b 数组
            b = np.array(a, dtype=np.float16)
        # 使用 assert_equal 断言转换后的数组 b 与期望的舍入结果 rounded 相等
        assert_equal(b, rounded)

        # 检查从 float32 到 float16 的舍入是否正确
        a = np.array(a, dtype=np.float32)
        with np.errstate(over="ignore"):
            # 使用 float16 类型将 a 数组转换为 b 数组
            b = np.array(a, dtype=np.float16)
        # 使用 assert_equal 断言转换后的数组 b 与期望的舍入结果 rounded 相等
        assert_equal(b, rounded)
    def test_half_correctness(self):
        """Take every finite float16, and check the casting functions with
           a manual conversion."""

        # Create an array of all finite float16s
        a_bits = self.finite_f16.view(dtype=uint16)

        # Convert to 64-bit float manually
        # 计算符号位
        a_sgn = (-1.0)**((a_bits & 0x8000) >> 15)
        # 计算指数位
        a_exp = np.array((a_bits & 0x7c00) >> 10, dtype=np.int32) - 15
        # 计算尾数位
        a_man = (a_bits & 0x03ff) * 2.0**(-10)
        # 对于标准化浮点数,隐含位为1
        a_man[a_exp != -15] += 1
        # 对于非标准化浮点数,指数为-14
        a_exp[a_exp == -15] = -14

        # 计算手动转换后的64位浮点数
        a_manual = a_sgn * a_man * 2.0**a_exp

        # 找到第一个不相等的浮点数
        a32_fail = np.nonzero(self.finite_f32 != a_manual)[0]
        if len(a32_fail) != 0:
            bad_index = a32_fail[0]
            # 断言第一个不相等的是半精度浮点数,显示具体数值
            assert_equal(self.finite_f32, a_manual,
                 "First non-equal is half value 0x%x -> %g != %g" %
                            (a_bits[bad_index],
                             self.finite_f32[bad_index],
                             a_manual[bad_index]))

        # 找到第一个不相等的双精度浮点数
        a64_fail = np.nonzero(self.finite_f64 != a_manual)[0]
        if len(a64_fail) != 0:
            bad_index = a64_fail[0]
            # 断言第一个不相等的是半精度浮点数,显示具体数值
            assert_equal(self.finite_f64, a_manual,
                 "First non-equal is half value 0x%x -> %g != %g" %
                            (a_bits[bad_index],
                             self.finite_f64[bad_index],
                             a_manual[bad_index]))

    def test_half_ordering(self):
        """Make sure comparisons are working right"""

        # All non-NaN float16 values in reverse order
        a = self.nonan_f16[::-1].copy()

        # 32-bit float copy
        b = np.array(a, dtype=float32)

        # Should sort the same
        # 对a和b进行排序,期望结果相同
        a.sort()
        b.sort()
        assert_equal(a, b)

        # Comparisons should work
        # 比较运算应该正确工作
        assert_((a[:-1] <= a[1:]).all())
        assert_(not (a[:-1] > a[1:]).any())
        assert_((a[1:] >= a[:-1]).all())
        assert_(not (a[1:] < a[:-1]).any())
        # All != except for +/-0
        # 所有元素应该都不相等,除了+/-0
        assert_equal(np.nonzero(a[:-1] < a[1:])[0].size, a.size-2)
        assert_equal(np.nonzero(a[1:] > a[:-1])[0].size, a.size-2)
    def test_half_funcs(self):
        """Test the various ArrFuncs"""

        # 使用 np.arange 创建一个长度为 10 的 float16 类型的数组,并断言与 dtype 为 float32 的相同
        assert_equal(np.arange(10, dtype=float16),
                     np.arange(10, dtype=float32))

        # 使用 np.zeros 创建长度为 5 的 float16 类型的数组,并将所有元素填充为 1
        a = np.zeros((5,), dtype=float16)
        a.fill(1)
        # 断言数组 a 与长度为 5、元素全部为 float16 类型的数组相等
        assert_equal(a, np.ones((5,), dtype=float16))

        # 创建包含特定元素的 float16 类型数组 a
        a = np.array([0, 0, -1, -1/1e20, 0, 2.0**-24, 7.629e-6], dtype=float16)
        # 断言数组 a 中非零元素的索引数组与预期相同
        assert_equal(a.nonzero()[0],
                     [2, 5, 6])
        # 字节交换数组 a,并根据当前平台设置其字节顺序
        a = a.byteswap()
        a = a.view(a.dtype.newbyteorder())
        # 再次断言数组 a 中非零元素的索引数组与预期相同
        assert_equal(a.nonzero()[0],
                     [2, 5, 6])

        # 使用 np.arange 创建一个从 0 到 10(不包括)的步长为 0.5 的 float16 类型数组 a
        a = np.arange(0, 10, 0.5, dtype=float16)
        # 创建一个全为 1 的 float16 类型数组 b,长度为 20
        b = np.ones((20,), dtype=float16)
        # 断言数组 a 与 b 的点积结果为 95
        assert_equal(np.dot(a, b),
                     95)

        # 创建包含特定元素的 float16 类型数组 a
        a = np.array([0, -np.inf, -2, 0.5, 12.55, 7.3, 2.1, 12.4], dtype=float16)
        # 断言数组 a 的最大值索引为 4
        assert_equal(a.argmax(),
                     4)
        # 创建包含特定元素的 float16 类型数组 a
        a = np.array([0, -np.inf, -2, np.inf, 12.55, np.nan, 2.1, 12.4], dtype=float16)
        # 断言数组 a 的最大值索引为 5
        assert_equal(a.argmax(),
                     5)

        # 使用 np.arange 创建一个长度为 10 的 float16 类型数组 a
        a = np.arange(10, dtype=float16)
        # 遍历数组 a 的每个元素,并断言每个元素与其索引相等
        for i in range(10):
            assert_equal(a.item(i), i)
    # 定义一个测试方法,用于测试 np.spacing 和 np.nextafter 的功能
    def test_spacing_nextafter(self):
        """Test np.spacing and np.nextafter"""
        
        # 创建一个包含所有非负有限数的数组,数据类型为 uint16
        a = np.arange(0x7c00, dtype=uint16)
        
        # 创建一个包含正无穷大的 float16 类型数组
        hinf = np.array((np.inf,), dtype=float16)
        
        # 创建一个包含 NaN 的 float16 类型数组
        hnan = np.array((np.nan,), dtype=float16)
        
        # 将 uint16 类型数组 a 视图转换为 float16 类型数组 a_f16
        a_f16 = a.view(dtype=float16)

        # 断言验证 np.spacing 对 a_f16 中除最后一个元素外的元素计算的正确性
        assert_equal(np.spacing(a_f16[:-1]), a_f16[1:] - a_f16[:-1])

        # 断言验证 np.nextafter 对 a_f16 中除最后一个元素外的元素向正无穷大方向计算的正确性
        assert_equal(np.nextafter(a_f16[:-1], hinf), a_f16[1:])
        
        # 断言验证 np.nextafter 对第一个元素向负无穷大方向计算的正确性
        assert_equal(np.nextafter(a_f16[0], -hinf), -a_f16[1])
        
        # 断言验证 np.nextafter 对 a_f16 中除第一个元素外的元素向负无穷大方向计算的正确性
        assert_equal(np.nextafter(a_f16[1:], -hinf), a_f16[:-1])

        # 断言验证 np.nextafter 对正无穷大 hinf 向 a_f16 中各元素计算的正确性
        assert_equal(np.nextafter(hinf, a_f16), a_f16[-1])
        
        # 断言验证 np.nextafter 对负无穷大 -hinf 向 a_f16 中各元素计算的正确性
        assert_equal(np.nextafter(-hinf, a_f16), -a_f16[-1])

        # 断言验证 np.nextafter 对正无穷大 hinf 与自身计算的正确性
        assert_equal(np.nextafter(hinf, hinf), hinf)
        
        # 断言验证 np.nextafter 对正无穷大 hinf 向负无穷大 -hinf 计算的正确性
        assert_equal(np.nextafter(hinf, -hinf), a_f16[-1])
        
        # 断言验证 np.nextafter 对负无穷大 -hinf 向正无穷大 hinf 计算的正确性
        assert_equal(np.nextafter(-hinf, hinf), -a_f16[-1])
        
        # 断言验证 np.nextafter 对负无穷大 -hinf 与自身计算的正确性
        assert_equal(np.nextafter(-hinf, -hinf), -hinf)

        # 断言验证 np.nextafter 对 a_f16 向 hnan 计算的正确性
        assert_equal(np.nextafter(a_f16, hnan), hnan[0])
        
        # 断言验证 np.nextafter 对 hnan 向 a_f16 计算的正确性
        assert_equal(np.nextafter(hnan, a_f16), hnan[0])

        # 断言验证 np.nextafter 对 hnan 与自身计算的正确性
        assert_equal(np.nextafter(hnan, hnan), hnan)
        
        # 断言验证 np.nextafter 对正无穷大 hinf 向 hnan 计算的正确性
        assert_equal(np.nextafter(hinf, hnan), hnan)
        
        # 断言验证 np.nextafter 对 hnan 向正无穷大 hinf 计算的正确性
        assert_equal(np.nextafter(hnan, hinf), hnan)

        # 将数组 a 中的元素切换为负数
        a |= 0x8000

        # 断言验证 np.spacing 对第一个元素计算的正确性
        assert_equal(np.spacing(a_f16[0]), np.spacing(a_f16[1]))
        
        # 断言验证 np.spacing 对 a_f16 中除第一个元素外的元素计算的正确性
        assert_equal(np.spacing(a_f16[1:]), a_f16[:-1] - a_f16[1:])

        # 断言验证 np.nextafter 对第一个元素向正无穷大 hinf 计算的正确性
        assert_equal(np.nextafter(a_f16[0], hinf), -a_f16[1])
        
        # 断言验证 np.nextafter 对 a_f16 中除最后一个元素外的元素向正无穷大 hinf 计算的正确性
        assert_equal(np.nextafter(a_f16[1:], hinf), a_f16[:-1])
        
        # 断言验证 np.nextafter 对 a_f16 中除第一个元素外的元素向负无穷大 -hinf 计算的正确性
        assert_equal(np.nextafter(a_f16[:-1], -hinf), a_f16[1:])

        # 断言验证 np.nextafter 对正无穷大 hinf 向 a_f16 计算的正确性
        assert_equal(np.nextafter(hinf, a_f16), -a_f16[-1])
        
        # 断言验证 np.nextafter 对负无穷大 -hinf 向 a_f16 计算的正确性
        assert_equal(np.nextafter(-hinf, a_f16), a_f16[-1])

        # 断言验证 np.nextafter 对 a_f16 向 hnan 计算的正确性
        assert_equal(np.nextafter(a_f16, hnan), hnan[0])
        
        # 断言验证 np.nextafter 对 hnan 向 a_f16 计算的正确性
        assert_equal(np.nextafter(hnan, a_f16), hnan[0])
    # 定义一个测试方法,用于验证半精度数据在与其他数据类型进行计算时的强制转换
    def test_half_coercion(self, weak_promotion):
        """Test that half gets coerced properly with the other types"""
        # 创建一个包含单个元素的 numpy 数组,数据类型为 float16
        a16 = np.array((1,), dtype=float16)
        # 创建一个包含单个元素的 numpy 数组,数据类型为 float32
        a32 = np.array((1,), dtype=float32)
        # 创建一个 float16 类型的变量,赋值为 1
        b16 = float16(1)
        # 创建一个 float32 类型的变量,赋值为 1
        b32 = float32(1)

        # 断言:a16 的平方的数据类型应为 float16
        assert np.power(a16, 2).dtype == float16
        # 断言:a16 的 2.0 次方的数据类型应为 float16
        assert np.power(a16, 2.0).dtype == float16
        # 断言:a16 的 b16 次方的数据类型应为 float16
        assert np.power(a16, b16).dtype == float16
        # 根据 weak_promotion 变量决定的预期数据类型,断言:a16 的 b32 次方的数据类型
        expected_dt = float32 if weak_promotion else float16
        assert np.power(a16, b32).dtype == expected_dt
        # 断言:a16 的 a16 次方的数据类型应为 float16
        assert np.power(a16, a16).dtype == float16
        # 断言:a16 的 a32 次方的数据类型应为 float32
        assert np.power(a16, a32).dtype == float32

        # 根据 weak_promotion 变量决定的预期数据类型,断言:b16 的 2 次方的数据类型
        expected_dt = float16 if weak_promotion else float64
        assert np.power(b16, 2).dtype == expected_dt
        # 根据 weak_promotion 变量决定的预期数据类型,断言:b16 的 2.0 次方的数据类型
        assert np.power(b16, 2.0).dtype == expected_dt
        # 断言:b16 的 b16 次方的数据类型应为 float16
        assert np.power(b16, b16).dtype, float16
        # 断言:b16 的 b32 次方的数据类型应为 float32
        assert np.power(b16, b32).dtype, float32
        # 断言:b16 的 a16 次方的数据类型应为 float16
        assert np.power(b16, a16).dtype, float16
        # 断言:b16 的 a32 次方的数据类型应为 float32
        assert np.power(b16, a32).dtype, float32

        # 断言:a32 的 a16 次方的数据类型应为 float32
        assert np.power(a32, a16).dtype == float32
        # 断言:a32 的 b16 次方的数据类型应为 float32
        assert np.power(a32, b16).dtype == float32
        # 根据 weak_promotion 变量决定的预期数据类型,断言:b32 的 a16 次方的数据类型
        expected_dt = float32 if weak_promotion else float16
        assert np.power(b32, a16).dtype == expected_dt
        # 断言:b32 的 b16 次方的数据类型应为 float32
        assert np.power(b32, b16).dtype == float32

    # 使用 pytest 的装饰器标记此测试为条件跳过,如果机器架构为 "armv5tel",则跳过并注明原因为 "See gh-413."
    @pytest.mark.skipif(platform.machine() == "armv5tel",
                        reason="See gh-413.")
    # 使用 pytest 的装饰器标记此测试为条件跳过,如果运行环境为 WASM,则跳过并注明原因为 "fp exceptions don't work in wasm."
    @pytest.mark.skipif(IS_WASM,
                        reason="fp exceptions don't work in wasm.")
    # 定义一个测试方法,用于验证 half 类型是否兼容 __array_interface__
    def test_half_array_interface(self):
        """Test that half is compatible with __array_interface__"""
        # 定义一个空类 Dummy
        class Dummy:
            pass

        # 创建一个包含单个元素的 numpy 数组,数据类型为 float16
        a = np.ones((1,), dtype=float16)
        # 创建一个 Dummy 类的实例 b
        b = Dummy()
        # 将 b 的 __array_interface__ 设置为 a 的 __array_interface__
        b.__array_interface__ = a.__array_interface__
        # 创建一个 numpy 数组 c,其值与 b 相同
        c = np.array(b)
        # 断言:c 的数据类型应为 float16
        assert_(c.dtype == float16)
        # 断言:a 与 c 应相等
        assert_equal(a, c)

.\numpy\numpy\_core\tests\test_hashtable.py

# 导入 pytest 模块,用于测试
import pytest

# 导入 random 模块,用于生成随机数和随机选择
import random

# 导入特定的测试函数 identityhash_tester,用于测试哈希表功能
from numpy._core._multiarray_tests import identityhash_tester

# 使用 pytest 的参数化装饰器,定义测试函数的参数组合
@pytest.mark.parametrize("key_length", [1, 3, 6])
@pytest.mark.parametrize("length", [1, 16, 2000])
def test_identity_hashtable(key_length, length):
    # 创建一个包含 20 个对象的对象池列表,用于生成随机的 keys_vals 对
    pool = [object() for i in range(20)]
    
    keys_vals = []
    # 生成 length 次循环,每次生成一个 key_length 长度的 keys 元组和对应的随机值,加入 keys_vals 列表中
    for i in range(length):
        keys = tuple(random.choices(pool, k=key_length))
        keys_vals.append((keys, random.choice(pool)))

    # 根据 keys_vals 列表生成字典 dictionary
    dictionary = dict(keys_vals)

    # 将 keys_vals 列表中的随机项再添加一次,用于后续测试
    keys_vals.append(random.choice(keys_vals))
    # 预期的结果 expected 是 keys_vals 列表中最后一项对应的值
    expected = dictionary[keys_vals[-1][0]]

    # 调用 identityhash_tester 函数进行测试,预期结果应与 expected 相同
    res = identityhash_tester(key_length, keys_vals, replace=True)
    assert res is expected

    # 如果 length 为 1,则直接返回,不再进行后续操作
    if length == 1:
        return

    # 尝试添加一个新的项,其键已经在 keys_vals 中存在,并且值是新的对象,如果 replace 参数为 False,则应引发 RuntimeError 异常,用于验证功能是否正常
    new_key = (keys_vals[1][0], object())
    keys_vals[0] = new_key
    with pytest.raises(RuntimeError):
        identityhash_tester(key_length, keys_vals)

.\numpy\numpy\_core\tests\test_indexerrors.py

# 导入 NumPy 库,并从中导入测试相关的函数
import numpy as np
from numpy.testing import (
        assert_raises, assert_raises_regex,
        )

# 定义一个测试类 TestIndexErrors,用于测试 IndexError 异常情况
class TestIndexErrors:
    '''Tests to exercise indexerrors not covered by other tests.'''

    # 定义测试方法 test_arraytypes_fasttake,测试在空维度上进行 take 操作时的 IndexError
    def test_arraytypes_fasttake(self):
        'take from a 0-length dimension'
        # 创建一个空的多维数组 x
        x = np.empty((2, 3, 0, 4))
        # 测试在空维度 axis=2 上进行 take 操作时的 IndexError
        assert_raises(IndexError, x.take, [0], axis=2)
        assert_raises(IndexError, x.take, [1], axis=2)
        assert_raises(IndexError, x.take, [0], axis=2, mode='wrap')
        assert_raises(IndexError, x.take, [0], axis=2, mode='clip')

    # 定义测试方法 test_take_from_object,测试从对象数组中进行 take 操作时的 IndexError
    def test_take_from_object(self):
        # 检查从对象数组 d 中取索引超出范围时的 IndexError
        d = np.zeros(5, dtype=object)
        assert_raises(IndexError, d.take, [6])

        # 检查从 0 维度对象数组 d 中进行 take 操作时的 IndexError
        d = np.zeros((5, 0), dtype=object)
        assert_raises(IndexError, d.take, [1], axis=1)
        assert_raises(IndexError, d.take, [0], axis=1)
        assert_raises(IndexError, d.take, [0])
        assert_raises(IndexError, d.take, [0], mode='wrap')
        assert_raises(IndexError, d.take, [0], mode='clip')

    # 定义测试方法 test_multiindex_exceptions,测试多维数组索引操作时的 IndexError
    def test_multiindex_exceptions(self):
        # 创建一个空对象数组 a
        a = np.empty(5, dtype=object)
        # 测试从对象数组 a 中超出索引范围的 IndexError
        assert_raises(IndexError, a.item, 20)
        # 创建一个 0 维度的对象数组 a
        a = np.empty((5, 0), dtype=object)
        # 测试从 0 维度对象数组 a 中进行索引操作时的 IndexError
        assert_raises(IndexError, a.item, (0, 0))

    # 定义测试方法 test_put_exceptions,测试在放置元素时的 IndexError
    def test_put_exceptions(self):
        # 创建一个 5x5 的零数组 a
        a = np.zeros((5, 5))
        # 测试向数组 a 中超出索引范围的位置放置元素时的 IndexError
        assert_raises(IndexError, a.put, 100, 0)
        # 创建一个元素为对象的 5x5 零数组 a
        a = np.zeros((5, 5), dtype=object)
        # 测试向元素为对象的数组 a 中超出索引范围的位置放置元素时的 IndexError
        assert_raises(IndexError, a.put, 100, 0)
        # 创建一个 5x5x0 的零数组 a
        a = np.zeros((5, 5, 0))
        # 测试向数组 a 中超出索引范围的位置放置元素时的 IndexError
        assert_raises(IndexError, a.put, 100, 0)
        # 创建一个元素为对象的 5x5x0 零数组 a
        a = np.zeros((5, 5, 0), dtype=object)
        # 测试向元素为对象的数组 a 中超出索引范围的位置放置元素时的 IndexError
        assert_raises(IndexError, a.put, 100, 0)
    # 定义一个测试方法,用于测试迭代器和异常情况
    def test_iterators_exceptions(self):
        # 内部辅助函数,用于给对象赋值
        def assign(obj, ind, val):
            obj[ind] = val
        
        # 创建一个形状为 [1, 2, 3] 的全零数组
        a = np.zeros([1, 2, 3])
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: a[0, 5, None, 2])
        assert_raises(IndexError, lambda: a[0, 5, 0, 2])
        assert_raises(IndexError, lambda: assign(a, (0, 5, None, 2), 1))
        assert_raises(IndexError, lambda: assign(a, (0, 5, 0, 2),  1))

        # 创建一个形状为 [1, 0, 3] 的全零数组
        a = np.zeros([1, 0, 3])
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: a[0, 0, None, 2])
        assert_raises(IndexError, lambda: assign(a, (0, 0, None, 2), 1))

        # 再次创建一个形状为 [1, 2, 3] 的全零数组
        a = np.zeros([1, 2, 3])
        # 断言:索引错误异常应该被触发,尝试通过 flat 属性访问超出数组边界的索引
        assert_raises(IndexError, lambda: a.flat[10])
        assert_raises(IndexError, lambda: assign(a.flat, 10, 5))
        
        # 创建一个形状为 [1, 0, 3] 的全零数组
        a = np.zeros([1, 0, 3])
        # 断言:索引错误异常应该被触发,尝试通过 flat 属性访问超出数组边界的索引
        assert_raises(IndexError, lambda: a.flat[10])
        assert_raises(IndexError, lambda: assign(a.flat, 10, 5))
        
        # 再次创建一个形状为 [1, 2, 3] 的全零数组
        a = np.zeros([1, 2, 3])
        # 断言:索引错误异常应该被触发,尝试通过 flat 属性访问超出数组边界的索引
        assert_raises(IndexError, lambda: a.flat[np.array(10)])
        assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5))
        
        # 创建一个形状为 [1, 0, 3] 的全零数组
        a = np.zeros([1, 0, 3])
        # 断言:索引错误异常应该被触发,尝试通过 flat 属性访问超出数组边界的索引
        assert_raises(IndexError, lambda: a.flat[np.array(10)])
        assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5))
        
        # 再次创建一个形状为 [1, 2, 3] 的全零数组
        a = np.zeros([1, 2, 3])
        # 断言:索引错误异常应该被触发,尝试通过 flat 属性访问超出数组边界的索引
        assert_raises(IndexError, lambda: a.flat[np.array([10])])
        assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5))
        
        # 创建一个形状为 [1, 0, 3] 的全零数组
        a = np.zeros([1, 0, 3])
        # 断言:索引错误异常应该被触发,尝试通过 flat 属性访问超出数组边界的索引
        assert_raises(IndexError, lambda: a.flat[np.array([10])])
        assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5))

    # 定义一个测试方法,用于测试映射操作
    def test_mapping(self):
        # 内部辅助函数,用于给对象赋值
        def assign(obj, ind, val):
            obj[ind] = val
        
        # 创建一个形状为 [0, 10] 的全零数组
        a = np.zeros((0, 10))
        # 断言:索引错误异常应该被触发,尝试访问超出数组边界的索引
        assert_raises(IndexError, lambda: a[12])

        # 创建一个形状为 [3, 5] 的全零数组
        a = np.zeros((3, 5))
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: a[(10, 20)])
        assert_raises(IndexError, lambda: assign(a, (10, 20), 1))
        
        # 创建一个形状为 [3, 0] 的全零数组
        a = np.zeros((3, 0))
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: a[(1, 0)])
        assert_raises(IndexError, lambda: assign(a, (1, 0), 1))

        # 创建一个形状为 [10,] 的全零数组
        a = np.zeros((10,))
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: assign(a, 10, 1))
        
        # 创建一个形状为 [0,] 的全零数组
        a = np.zeros((0,))
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: assign(a, 10, 1))

        # 再次创建一个形状为 [3, 5] 的全零数组
        a = np.zeros((3, 5))
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: a[(1, [1, 20])])
        assert_raises(IndexError, lambda: assign(a, (1, [1, 20]), 1))
        
        # 创建一个形状为 [3, 0] 的全零数组
        a = np.zeros((3, 0))
        # 断言:索引错误异常应该被触发,lambda 函数访问超出数组边界的索引
        assert_raises(IndexError, lambda: a[(1, [0, 1])])
        assert_raises(IndexError, lambda: assign(a, (1, [0, 1]), 1))

    # 定义一个测试方法,用于测试映射操作的错误消息
    def test_mapping_error_message(self):
        # 创建一个形状为 [3, 5] 的全零数组
        a = np.zeros((3, 5))
        # 创建一个超出数组维度的索引元组
        index = (1, 2, 3, 4, 5)
        # 断言:索引错误异常应该被触发,错误消息应指出尝试索引超出数组维度
        assert_raises_regex(
                IndexError,
                "too many indices for array: "
                "array is 2-dimensional, but 5 were indexed",
                lambda: a[index])
    # 定义一个测试方法,用于测试与 methods.c 文件相关的案例
    def test_methods(self):
        # 创建一个 3x3 的全零数组
        a = np.zeros((3, 3))
        # 断言:调用 a.item(100) 应该引发 IndexError 异常
        assert_raises(IndexError, lambda: a.item(100))

.\numpy\numpy\_core\tests\test_indexing.py

# 导入系统模块 sys
import sys
# 导入警告模块 warnings
import warnings
# 导入 functools 模块
import functools
# 导入 operator 模块
import operator

# 导入 pytest 测试框架
import pytest

# 导入 numpy 库,并使用 np 别名
import numpy as np
# 导入 numpy 内部的 array_indexing 测试模块
from numpy._core._multiarray_tests import array_indexing
# 导入 itertools 模块中的 product 函数
from itertools import product
# 导入 numpy 异常模块中的 ComplexWarning 和 VisibleDeprecationWarning 异常
from numpy.exceptions import ComplexWarning, VisibleDeprecationWarning
# 导入 numpy 测试模块中的一系列断言函数
from numpy.testing import (
    assert_, assert_equal, assert_raises, assert_raises_regex,
    assert_array_equal, assert_warns, HAS_REFCOUNT, IS_WASM
    )


class TestIndexing:
    # 定义测试类 TestIndexing
    def test_index_no_floats(self):
        # 创建一个三维 numpy 数组
        a = np.array([[[5]]])

        # 断言索引浮点数会引发 IndexError 异常
        assert_raises(IndexError, lambda: a[0.0])
        assert_raises(IndexError, lambda: a[0, 0.0])
        assert_raises(IndexError, lambda: a[0.0, 0])
        assert_raises(IndexError, lambda: a[0.0,:])
        assert_raises(IndexError, lambda: a[:, 0.0])
        assert_raises(IndexError, lambda: a[:, 0.0,:])
        assert_raises(IndexError, lambda: a[0.0,:,:])
        assert_raises(IndexError, lambda: a[0, 0, 0.0])
        assert_raises(IndexError, lambda: a[0.0, 0, 0])
        assert_raises(IndexError, lambda: a[0, 0.0, 0])
        assert_raises(IndexError, lambda: a[-1.4])
        assert_raises(IndexError, lambda: a[0, -1.4])
        assert_raises(IndexError, lambda: a[-1.4, 0])
        assert_raises(IndexError, lambda: a[-1.4,:])
        assert_raises(IndexError, lambda: a[:, -1.4])
        assert_raises(IndexError, lambda: a[:, -1.4,:])
        assert_raises(IndexError, lambda: a[-1.4,:,:])
        assert_raises(IndexError, lambda: a[0, 0, -1.4])
        assert_raises(IndexError, lambda: a[-1.4, 0, 0])
        assert_raises(IndexError, lambda: a[0, -1.4, 0])
        assert_raises(IndexError, lambda: a[0.0:, 0.0])
        assert_raises(IndexError, lambda: a[0.0:, 0.0,:])
    def test_slicing_no_floats(self):
        # 创建一个包含单个元素的二维 NumPy 数组
        a = np.array([[5]])

        # 测试从浮点数开始的切片操作,期望引发 TypeError 异常
        assert_raises(TypeError, lambda: a[0.0:])
        assert_raises(TypeError, lambda: a[0:, 0.0:2])
        assert_raises(TypeError, lambda: a[0.0::2, :0])
        assert_raises(TypeError, lambda: a[0.0:1:2, :])
        assert_raises(TypeError, lambda: a[:, 0.0:])

        # 测试以浮点数结束的切片操作,期望引发 TypeError 异常
        assert_raises(TypeError, lambda: a[:0.0])
        assert_raises(TypeError, lambda: a[:0, 1:2.0])
        assert_raises(TypeError, lambda: a[:0.0:2, :0])
        assert_raises(TypeError, lambda: a[:0.0, :])
        assert_raises(TypeError, lambda: a[:, 0:4.0:2])

        # 测试以浮点数步长的切片操作,期望引发 TypeError 异常
        assert_raises(TypeError, lambda: a[::1.0])
        assert_raises(TypeError, lambda: a[0:, :2:2.0])
        assert_raises(TypeError, lambda: a[1::4.0, :0])
        assert_raises(TypeError, lambda: a[::5.0, :])
        assert_raises(TypeError, lambda: a[:, 0:4:2.0])

        # 测试混合浮点数的切片操作,期望引发 TypeError 异常
        assert_raises(TypeError, lambda: a[1.0:2:2.0])
        assert_raises(TypeError, lambda: a[1.0::2.0])
        assert_raises(TypeError, lambda: a[0:, :2.0:2.0])
        assert_raises(TypeError, lambda: a[1.0:1:4.0, :0])
        assert_raises(TypeError, lambda: a[1.0:5.0:5.0, :])
        assert_raises(TypeError, lambda: a[:, 0.4:4.0:2.0])

        # 当步长为 0 时,依然应该得到 DeprecationWarning
        assert_raises(TypeError, lambda: a[::0.0])

    def test_index_no_array_to_index(self):
        # 创建一个包含单个元素的三维 NumPy 数组
        a = np.array([[[1]]])

        # 测试在索引中使用非标量数组,期望引发 TypeError 异常
        assert_raises(TypeError, lambda: a[a:a:a])

    def test_none_index(self):
        # 创建一个包含三个元素的一维 NumPy 数组
        a = np.array([1, 2, 3])

        # 测试使用 `None` 作为索引,期望返回一个新的轴
        assert_equal(a[None], a[np.newaxis])
        # 检查添加 `None` 索引后数组的维度增加了 1
        assert_equal(a[None].ndim, a.ndim + 1)

    def test_empty_tuple_index(self):
        # 创建一个包含三个元素的一维 NumPy 数组
        a = np.array([1, 2, 3])

        # 测试使用空元组作为索引,期望返回原数组的视图
        assert_equal(a[()], a)
        # 检查使用空元组索引后的数组与原数组共享数据
        assert_(a[()].base is a)

        # 创建一个标量值为 0 的 NumPy 数组
        a = np.array(0)
        # 检查使用空元组索引后仍然是一个整数类型
        assert_(isinstance(a[()], np.int_))

    def test_void_scalar_empty_tuple(self):
        # 创建一个空的复合类型标量数组,dtype 为 'V4'
        s = np.zeros((), dtype='V4')

        # 测试使用空元组索引,期望返回与原数组相同的标量
        assert_equal(s[()].dtype, s.dtype)
        assert_equal(s[()], s)
        # 检查使用 `...` 索引后返回的对象类型为 ndarray
        assert_equal(type(s[...]), np.ndarray)

    def test_same_kind_index_casting(self):
        # 创建一个包含 0 到 4 的整数的 NumPy 数组
        index = np.arange(5)
        # 将整数数组转换为无符号整数类型数组
        u_index = index.astype(np.uintp)
        # 创建一个包含 0 到 9 的整数的 NumPy 数组
        arr = np.arange(10)

        # 测试在索引操作中,使用不同类型但相同 kind 的索引,应当相等
        assert_array_equal(arr[index], arr[u_index])

        # 将数组 arr 中 u_index 对应的位置赋值为 [0, 1, 2, 3, 4]
        arr[u_index] = np.arange(5)
        assert_array_equal(arr, np.arange(10))

        # 创建一个 5x2 的二维数组
        arr = np.arange(10).reshape(5, 2)
        # 测试使用相同类型但不同类型的索引,应当相等
        assert_array_equal(arr[index], arr[u_index])

        # 将数组 arr 中 u_index 对应的行赋值为 [[0], [1], [2], [3], [4]]
        arr[u_index] = np.arange(5)[:, None]
        assert_array_equal(arr, np.arange(5)[:, None].repeat(2, axis=1))

        # 创建一个 5x5 的二维数组
        arr = np.arange(25).reshape(5, 5)
        # 测试使用相同类型但不同类型的索引,应当相等
        assert_array_equal(arr[u_index, u_index], arr[index, index])
    def test_empty_fancy_index(self):
        # 定义测试函数:测试空的高级索引

        # 创建一个包含元素为 [1, 2, 3] 的 NumPy 数组
        a = np.array([1, 2, 3])
        # 使用空列表索引返回一个空数组
        assert_equal(a[[]], [])
        # 确保返回的空数组与原数组具有相同的数据类型
        assert_equal(a[[]].dtype, a.dtype)

        # 创建一个空数组 b,指定数据类型为 np.intp
        b = np.array([], dtype=np.intp)
        # 使用空列表索引返回一个空数组
        assert_equal(a[[]], [])
        # 确保返回的空数组与原数组具有相同的数据类型
        assert_equal(a[[]].dtype, a.dtype)

        # 创建一个空数组 b
        b = np.array([])
        # 使用空数组 b 进行索引,预期会抛出 IndexError 异常
        assert_raises(IndexError, a.__getitem__, b)

    def test_ellipsis_index(self):
        # 定义测试函数:测试省略号索引

        # 创建一个二维数组 a
        a = np.array([[1, 2, 3],
                      [4, 5, 6],
                      [7, 8, 9]])
        # 确保 a[...] 不是原始数组 a 的引用
        assert_(a[...] is not a)
        # 使用省略号索引返回整个数组 a
        assert_equal(a[...], a)
        # 确保 a[...] 的底层数据是数组 a
        assert_(a[...].base is a)

        # 使用省略号进行切片可以跳过任意数量的维度
        assert_equal(a[0, ...], a[0])
        assert_equal(a[0, ...], a[0, :])
        assert_equal(a[..., 0], a[:, 0])

        # 使用省略号进行切片总是返回一个数组,而不是标量
        assert_equal(a[0, ..., 1], np.array(2))

        # 对于零维数组,可以使用 `(Ellipsis,)` 进行赋值
        b = np.array(1)
        b[(Ellipsis,)] = 2
        assert_equal(b, 2)

    def test_single_int_index(self):
        # 定义测试函数:测试单个整数索引

        # 创建一个二维数组 a
        a = np.array([[1, 2, 3],
                      [4, 5, 6],
                      [7, 8, 9]])

        # 使用单个整数索引返回指定行
        assert_equal(a[0], [1, 2, 3])
        assert_equal(a[-1], [7, 8, 9])

        # 索引超出边界会引发 IndexError 异常
        assert_raises(IndexError, a.__getitem__, 1 << 30)
        assert_raises(IndexError, a.__getitem__, 1 << 64)

    def test_single_bool_index(self):
        # 定义测试函数:测试单个布尔索引

        # 创建一个二维数组 a
        a = np.array([[1, 2, 3],
                      [4, 5, 6],
                      [7, 8, 9]])

        # 使用单个布尔数组索引返回整个数组 a
        assert_equal(a[np.array(True)], a[None])
        # 使用单个假布尔数组索引返回空数组
        assert_equal(a[np.array(False)], a[None][0:0])

    def test_boolean_shape_mismatch(self):
        # 定义测试函数:测试布尔索引形状不匹配的情况

        # 创建一个全为 1 的三维数组
        arr = np.ones((5, 4, 3))

        # 创建一个长度为 1 的布尔数组作为索引,预期抛出 IndexError 异常
        index = np.array([True])
        assert_raises(IndexError, arr.__getitem__, index)

        # 创建一个长度为 6 的布尔数组作为索引,预期抛出 IndexError 异常
        index = np.array([False] * 6)
        assert_raises(IndexError, arr.__getitem__, index)

        # 创建一个形状为 (4, 4) 的布尔数组作为索引,预期抛出 IndexError 异常
        index = np.zeros((4, 4), dtype=bool)
        assert_raises(IndexError, arr.__getitem__, index)

        # 在第一维上使用布尔数组索引,预期抛出 IndexError 异常
        assert_raises(IndexError, arr.__getitem__, (slice(None), index))

    def test_boolean_indexing_onedim(self):
        # 定义测试函数:测试在一维数组上使用布尔索引

        # 创建一个一维数组 a,元素全为 0.0
        a = np.array([[ 0.,  0.,  0.]])
        # 创建一个长度为 1 的布尔数组 b
        b = np.array([ True], dtype=bool)
        # 使用布尔数组 b 索引返回整个数组 a
        assert_equal(a[b], a)
        # 对数组 a 使用布尔数组 b 进行赋值
        a[b] = 1.
        assert_equal(a, [[1., 1., 1.]])
    def test_boolean_assignment_value_mismatch(self):
        # 测试布尔赋值在值的形状无法广播到订阅位置时应该失败。(参见 gh-3458)
        # 创建一个长度为4的数组 a
        a = np.arange(4)

        def f(a, v):
            # 将满足条件 a > -1 的位置赋值为 v
            a[a > -1] = v

        # 断言应该抛出 ValueError 异常,因为空列表不能广播到 a 的形状
        assert_raises(ValueError, f, a, [])
        # 断言应该抛出 ValueError 异常,因为长度为3的列表不能广播到 a 的形状
        assert_raises(ValueError, f, a, [1, 2, 3])
        # 断言应该抛出 ValueError 异常,因为长度为3的列表不能广播到 a[:1] 的形状
        assert_raises(ValueError, f, a[:1], [1, 2, 3])

    def test_boolean_assignment_needs_api(self):
        # 参见 gh-7666
        # 在 Python 2 中由于 GIL 未被持有,当迭代器不需要 GIL 但转移函数需要时,会导致段错误
        arr = np.zeros(1000)
        indx = np.zeros(1000, dtype=bool)
        indx[:100] = True
        # 使用对象数组进行赋值,将前100个位置设置为1
        arr[indx] = np.ones(100, dtype=object)

        expected = np.zeros(1000)
        expected[:100] = 1
        # 断言 arr 与 expected 数组相等
        assert_array_equal(arr, expected)

    def test_boolean_indexing_twodim(self):
        # 使用二维布尔数组对二维数组进行索引
        a = np.array([[1, 2, 3],
                      [4, 5, 6],
                      [7, 8, 9]])
        b = np.array([[ True, False,  True],
                      [False,  True, False],
                      [ True, False,  True]])
        # 断言使用布尔数组索引后的结果正确
        assert_equal(a[b], [1, 3, 5, 7, 9])
        # 断言使用 b[1] 的布尔数组索引后的结果正确
        assert_equal(a[b[1]], [[4, 5, 6]])
        # 断言使用 b[0] 的布尔数组索引后的结果等于使用 b[2] 的布尔数组索引后的结果
        assert_equal(a[b[0]], a[b[2]])

        # 布尔赋值操作
        a[b] = 0
        # 断言布尔赋值操作后的数组 a 符合预期
        assert_equal(a, [[0, 2, 0],
                         [4, 0, 6],
                         [0, 8, 0]])

    def test_boolean_indexing_list(self):
        # 修复 #13715 的回归测试。这是一个使用后释放的 bug,尽管此测试不能直接捕获,但会在 valgrind 中显示出来。
        a = np.array([1, 2, 3])
        b = [True, False, True]
        # 测试两种情况,因为第一种会有快速路径
        assert_equal(a[b], [1, 3])
        assert_equal(a[None, b], [[1, 3]])

    def test_reverse_strides_and_subspace_bufferinit(self):
        # 测试简单和子空间花式索引时是否翻转了步长。
        a = np.ones(5)
        # 创建一个逆序的整数数组
        b = np.zeros(5, dtype=np.intp)[::-1]
        # 创建一个逆序的整数数组
        c = np.arange(5)[::-1]

        # 使用逆序的索引 b 将数组 a 的部分位置赋值为 c 的值
        a[b] = c
        # 如果步长未被翻转,那么 arange 中的 0 会被放在最后。
        assert_equal(a[0], 0)

        # 同时测试子空间缓冲是否被初始化:
        a = np.ones((5, 2))
        c = np.arange(10).reshape(5, 2)[::-1]
        # 使用逆序的索引 b 对数组 a 的子空间赋值为数组 c
        a[b, :] = c
        # 断言数组 a 的第一行是否等于 [0, 1]
        assert_equal(a[0], [0, 1])

    def test_reversed_strides_result_allocation(self):
        # 测试计算结果数组的输出步长时的一个 bug,当子空间大小为1时(同时测试其他情况)。
        a = np.arange(10)[:, None]
        i = np.arange(10)[::-1]
        # 断言 a[i] 与 a[i.copy('C')] 是否相等
        assert_array_equal(a[i], a[i.copy('C')])

        a = np.arange(20).reshape(-1, 2)
    def test_uncontiguous_subspace_assignment(self):
        # 在开发过程中曾出现一个 bug,根据 ndim 而不是 size 激活了跳过逻辑。
        a = np.full((3, 4, 2), -1)
        b = np.full((3, 4, 2), -1)

        # 使用不连续的索引分配数据
        a[[0, 1]] = np.arange(2 * 4 * 2).reshape(2, 4, 2).T
        # 使用复制的方式进行相同操作
        b[[0, 1]] = np.arange(2 * 4 * 2).reshape(2, 4, 2).T.copy()

        assert_equal(a, b)

    def test_too_many_fancy_indices_special_case(self):
        # 文档化行为,这是一个小的限制。
        a = np.ones((1,) * 64)  # 64 是 NPY_MAXDIMS
        # 预期引发 IndexError 异常,因为使用了太多的花式索引
        assert_raises(IndexError, a.__getitem__, (np.array([0]),) * 64)

    def test_scalar_array_bool(self):
        # NumPy 布尔类型可以作为布尔索引使用(Python 原生布尔类型目前不行)
        a = np.array(1)
        assert_equal(a[np.bool(True)], a[np.array(True)])
        assert_equal(a[np.bool(False)], a[np.array(False)])

        # 在废弃布尔类型作为整数之后:
        # a = np.array([0,1,2])
        # assert_equal(a[True, :], a[None, :])
        # assert_equal(a[:, True], a[:, None])
        #
        # assert_(not np.may_share_memory(a, a[True, :]))

    def test_everything_returns_views(self):
        # 在 `...` 之前会返回数组本身。
        a = np.arange(5)

        assert_(a is not a[()])
        assert_(a is not a[...])
        assert_(a is not a[:])

    def test_broaderrors_indexing(self):
        a = np.zeros((5, 5))
        # 预期引发 IndexError 异常,因为索引超出了数组维度
        assert_raises(IndexError, a.__getitem__, ([0, 1], [0, 1, 2]))
        assert_raises(IndexError, a.__setitem__, ([0, 1], [0, 1, 2]), 0)

    def test_trivial_fancy_out_of_bounds(self):
        a = np.zeros(5)
        ind = np.ones(20, dtype=np.intp)
        ind[-1] = 10
        # 预期引发 IndexError 异常,因为索引超出了数组的边界
        assert_raises(IndexError, a.__getitem__, ind)
        assert_raises(IndexError, a.__setitem__, ind, 0)
        ind = np.ones(20, dtype=np.intp)
        ind[0] = 11
        # 预期引发 IndexError 异常,因为索引超出了数组的边界
        assert_raises(IndexError, a.__getitem__, ind)
        assert_raises(IndexError, a.__setitem__, ind, 0)

    def test_trivial_fancy_not_possible(self):
        # 测试在索引非连续或非一维时,不应误用简化的快速路径,参见 gh-11467。
        a = np.arange(6)
        idx = np.arange(6, dtype=np.intp).reshape(2, 1, 3)[:, :, 0]
        assert_array_equal(a[idx], idx)

        # 这种情况不应该进入快速路径,注意 idx 在这里是一个非连续的非一维数组。
        a[idx] = -1
        res = np.arange(6)
        res[0] = -1
        res[3] = -1
        assert_array_equal(a, res)
    def test_nonbaseclass_values(self):
        # 定义一个继承自 np.ndarray 的子类 SubClass
        class SubClass(np.ndarray):
            # 定义特殊方法 __array_finalize__,用于数组初始化后的处理
            def __array_finalize__(self, old):
                # 在初始化过程中执行特定操作,这里将数组填充为 99
                self.fill(99)

        # 创建一个 5x5 的全零数组 a
        a = np.zeros((5, 5))
        # 通过复制和视图创建一个 SubClass 类型的数组 s
        s = a.copy().view(type=SubClass)
        # 将 s 数组填充为 1
        s.fill(1)

        # 将 s 数组的值分别赋给 a 数组的第 0 到第 4 行
        a[[0, 1, 2, 3, 4], :] = s
        # 断言 a 数组中所有元素是否都为 1
        assert_((a == 1).all())

        # 将 s 数组的值分别赋给 a 数组的第 0 到第 4 列
        a[:, [0, 1, 2, 3, 4]] = s
        # 断言 a 数组中所有元素是否都为 1
        assert_((a == 1).all())

        # 将 s 数组的值赋给 a 数组的所有元素
        a.fill(0)
        a[...] = s
        # 断言 a 数组中所有元素是否都为 1
        assert_((a == 1).all())

    def test_array_like_values(self):
        # 类似于上面的测试,但使用 memoryview 替代数组
        a = np.zeros((5, 5))
        s = np.arange(25, dtype=np.float64).reshape(5, 5)

        # 将 memoryview(s) 赋给 a 数组的第 0 到第 4 行
        a[[0, 1, 2, 3, 4], :] = memoryview(s)
        # 断言 a 数组是否与 s 数组相等
        assert_array_equal(a, s)

        # 将 memoryview(s) 赋给 a 数组的第 0 到第 4 列
        a[:, [0, 1, 2, 3, 4]] = memoryview(s)
        # 断言 a 数组是否与 s 数组相等
        assert_array_equal(a, s)

        # 将 memoryview(s) 赋给 a 数组的所有元素
        a[...] = memoryview(s)
        # 断言 a 数组是否与 s 数组相等
        assert_array_equal(a, s)

    def test_subclass_writeable(self):
        # 创建一个结构化数组 d,包含字段 'target' 和 'V_mag'
        d = np.rec.array([('NGC1001', 11), ('NGC1002', 1.), ('NGC1003', 1.)],
                         dtype=[('target', 'S20'), ('V_mag', '>f4')])
        # 创建布尔类型的索引数组 ind
        ind = np.array([False,  True,  True], dtype=bool)
        # 断言通过布尔索引访问的 d 的子数组是否可写
        assert_(d[ind].flags.writeable)
        
        # 创建整数类型的索引数组 ind
        ind = np.array([0, 1])
        # 断言通过整数索引访问的 d 的子数组是否可写
        assert_(d[ind].flags.writeable)
        
        # 断言通过省略号索引访问的 d 的子数组是否可写
        assert_(d[...].flags.writeable)
        
        # 断言通过单个整数索引访问的 d 的子数组是否可写
        assert_(d[0].flags.writeable)

    def test_memory_order(self):
        # 这里不必保留。复杂索引的内存布局不那么简单。
        a = np.arange(10)
        b = np.arange(10).reshape(5,2).T
        # 断言通过复杂索引 b 访问的 a 数组是否是列优先的
        assert_(a[b].flags.f_contiguous)

        # 使用不同的实现分支:
        a = a.reshape(-1, 1)
        # 断言通过复杂索引 b 和第一列访问的 a 数组是否是列优先的
        assert_(a[b, 0].flags.f_contiguous)

    def test_scalar_return_type(self):
        # 完整的标量索引应该返回标量,对象数组不应在其项上调用 PyArray_Return
        class Zero:
            # 最基本的有效索引
            def __index__(self):
                return 0

        z = Zero()

        class ArrayLike:
            # 简单的数组,应该表现得像数组一样
            def __array__(self, dtype=None, copy=None):
                return np.array(0)

        a = np.zeros(())
        # 断言空元组 () 索引访问 a 数组是否返回 np.float64 标量
        assert_(isinstance(a[()], np.float64))
        a = np.zeros(1)
        # 断言使用 Zero 对象 z 索引访问 a 数组是否返回 np.float64 标量
        assert_(isinstance(a[z], np.float64))
        a = np.zeros((1, 1))
        # 断言使用 Zero 对象 z 和 np.array(0) 索引访问 a 数组是否返回 np.float64 标量
        assert_(isinstance(a[z, np.array(0)], np.float64))
        # 断言使用 Zero 对象 z 和 ArrayLike() 索引访问 a 数组是否返回 np.float64 标量
        assert_(isinstance(a[z, ArrayLike()], np.float64))

        # 对象数组也不会频繁调用它:
        b = np.array(0)
        a = np.array(0, dtype=object)
        # 断言空元组 () 索引访问 a 数组是否返回 np.ndarray 对象
        assert_(isinstance(a[()], np.ndarray))
        a = np.array([b, None])
        # 断言使用 Zero 对象 z 索引访问 a 数组是否返回 np.ndarray 对象
        assert_(isinstance(a[z], np.ndarray))
        a = np.array([[b, None]])
        # 断言使用 Zero 对象 z 和 ArrayLike() 索引访问 a 数组是否返回 np.ndarray 对象
        assert_(isinstance(a[z, ArrayLike()], np.ndarray))
    def test_small_regressions(self):
        # Reference count of intp for index checks
        # 创建一个包含单个元素的 NumPy 数组
        a = np.array([0])
        # 如果支持引用计数功能,则获取 intp 类型的引用计数
        if HAS_REFCOUNT:
            refcount = sys.getrefcount(np.dtype(np.intp))
        # 使用整数索引进行元素设置,该过程会在单独的函数中检查索引
        a[np.array([0], dtype=np.intp)] = 1
        # 使用无符号 8 位整数类型进行索引元素设置
        a[np.array([0], dtype=np.uint8)] = 1
        # 断言对超出范围的索引设置会引发 IndexError 异常
        assert_raises(IndexError, a.__setitem__,
                      np.array([1], dtype=np.intp), 1)
        assert_raises(IndexError, a.__setitem__,
                      np.array([1], dtype=np.uint8), 1)

        # 如果支持引用计数功能,则断言 intp 类型的引用计数不变
        if HAS_REFCOUNT:
            assert_equal(sys.getrefcount(np.dtype(np.intp)), refcount)

    def test_unaligned(self):
        # 创建一个由 'a' 字符填充的 int8 类型的零数组,然后进行切片
        v = (np.zeros(64, dtype=np.int8) + ord('a'))[1:-7]
        # 将切片后的数组视图转换为 S8 类型
        d = v.view(np.dtype("S8"))
        # 创建一个未对齐的源数组
        x = (np.zeros(16, dtype=np.int8) + ord('a'))[1:-7]
        # 将切片后的数组视图转换为 S8 类型
        x = x.view(np.dtype("S8"))
        # 使用数组 'x' 中的数据填充数组 'd' 中对应位置的元素
        x[...] = np.array("b" * 8, dtype="S")
        # 创建一个范围数组 'b'
        b = np.arange(d.size)
        # 简单情况下的断言:断言数组 'd' 与数组 'b' 的元素相等
        assert_equal(d[b], d)
        # 使用数组 'x' 中的数据填充数组 'd' 中对应索引 'b' 的元素
        d[b] = x
        # 非简单情况下的断言:使用未对齐的索引数组 'b' 对数组 'd' 进行索引
        # 创建一个未对齐的索引数组
        b = np.zeros(d.size + 1).view(np.int8)[1:-(np.intp(0).itemsize - 1)]
        b = b.view(np.intp)[:d.size]
        # 使用数组 'x' 中的数据填充数组 'd' 中对应索引 'b' 的元素
        d[b.astype(np.int16)] = x
        # 对布尔数组 'b % 2 == 0' 进行索引,并不返回结果
        d[b % 2 == 0]
        # 使用数组 'x' 中的数据填充布尔数组 'b % 2 == 0' 对应的元素
        d[b % 2 == 0] = x[::2]

    def test_tuple_subclass(self):
        # 创建一个全为 1 的 5x5 数组
        arr = np.ones((5, 5))

        # 检查元组子类是否也可以作为索引
        class TupleSubclass(tuple):
            pass
        # 创建一个元组子类实例 'index'
        index = ([1], [1])
        index = TupleSubclass(index)
        # 断言数组 'arr' 使用 'index' 索引后的形状为 (1,)
        assert_(arr[index].shape == (1,))
        # 与非 nd-索引(tuple)不同的是:
        assert_(arr[index,].shape != (1,))

    def test_broken_sequence_not_nd_index(self):
        # 见 gh-5063:
        # 如果我们有一个对象声称自己是一个序列,但在获取项目时失败,
        # 这不应该被转换为 nd-索引(tuple)
        # 如果此对象在其他方面是一个有效的索引,它应该工作
        # 这个对象非常可疑,可能是不好的:
        class SequenceLike:
            def __index__(self):
                return 0

            def __len__(self):
                return 1

            def __getitem__(self, item):
                raise IndexError('Not possible')

        arr = np.arange(10)
        # 断言使用 SequenceLike 实例作为索引与直接使用该实例索引的结果相等
        assert_array_equal(arr[SequenceLike()], arr[SequenceLike(),])

        # 还要测试字段索引不会因此而段错误
        # 通过对结构化数组进行索引,以类似的原因
        arr = np.zeros((1,), dtype=[('f1', 'i8'), ('f2', 'i8')])
        assert_array_equal(arr[SequenceLike()], arr[SequenceLike(),])
    def test_indexing_array_weird_strides(self):
        # 这个测试函数涉及到数组的奇怪步幅情况
        # 以下的形状来自于一个问题,并创建了正确的迭代器缓冲区大小
        x = np.ones(10)  # 创建一个包含10个元素的全为1的数组
        x2 = np.ones((10, 2))  # 创建一个形状为(10, 2)的全为1的数组
        ind = np.arange(10)[:, None, None, None]  # 创建一个形状为(10, 1, 1, 1)的索引数组
        ind = np.broadcast_to(ind, (10, 55, 4, 4))  # 将索引数组广播到形状为(10, 55, 4, 4)

        # 单个高级索引的情况
        assert_array_equal(x[ind], x[ind.copy()])  # 断言数组通过相同的高级索引和其副本得到的结果相等
        # 更高维度的高级索引
        zind = np.zeros(4, dtype=np.intp)  # 创建一个具有4个零元素的整数索引数组
        assert_array_equal(x2[ind, zind], x2[ind.copy(), zind])  # 断言数组通过相同的高级索引和其副本得到的结果相等

    def test_indexing_array_negative_strides(self):
        # 来自于gh-8264
        # 如果在迭代中使用负步长,核心可能会崩溃
        arro = np.zeros((4, 4))  # 创建一个形状为(4, 4)的全零数组
        arr = arro[::-1, ::-1]  # 对数组进行逆向切片操作

        slices = (slice(None), [0, 1, 2, 3])  # 创建一个切片元组
        arr[slices] = 10  # 将切片应用到数组上,并赋值为10
        assert_array_equal(arr, 10.)  # 断言数组的所有元素都等于10.0

    def test_character_assignment(self):
        # 这是一个通过CopyObject进行的函数示例
        # 它曾经有一个未经测试的特殊路径用于标量(字符特殊dtype情况,可能应该被弃用)
        arr = np.zeros((1, 5), dtype="c")  # 创建一个形状为(1, 5)的全零数组,数据类型为字符
        arr[0] = np.str_("asdfg")  # 必须作为一个序列进行赋值
        assert_array_equal(arr[0], np.array("asdfg", dtype="c"))  # 断言数组的第一行等于指定的字符数组
        assert arr[0, 1] == b"s"  # 确保不是所有元素都被设置为"a"

    @pytest.mark.parametrize("index",
            [True, False, np.array([0])])
    @pytest.mark.parametrize("num", [64, 80])
    @pytest.mark.parametrize("original_ndim", [1, 64])
    def test_too_many_advanced_indices(self, index, num, original_ndim):
        # 这些是基于我们能够处理的参数数量的限制
        # 对于`num=32`(以及所有布尔值情况),实际上结果是定义好的
        # 但由于技术原因,使用NpyIter(NPY_MAXARGS)限制了它
        arr = np.ones((1,) * original_ndim)  # 创建一个全为1的数组,形状为(1,)*original_ndim
        with pytest.raises(IndexError):
            arr[(index,) * num]  # 断言使用过多的高级索引会抛出IndexError异常
        with pytest.raises(IndexError):
            arr[(index,) * num] = 1.  # 断言使用过多的高级索引会抛出IndexError异常

    @pytest.mark.skipif(IS_WASM, reason="no threading")
    # 定义一个测试方法,用于验证结构化数据类型中整数数组索引时是否安全,这涉及到 `copyswap(n)` 的使用,详见 gh-15387。
    # 这个测试可能会表现出随机性。
    
    from concurrent.futures import ThreadPoolExecutor
    # 导入线程池执行器,用于并行执行任务
    
    # 创建一个深度嵌套的数据类型,增加出错的可能性:
    dt = np.dtype([("", "f8")])
    dt = np.dtype([("", dt)] * 2)
    dt = np.dtype([("", dt)] * 2)
    # 创建一个足够大的数组,以增加遇到线程问题的概率
    arr = np.random.uniform(size=(6000, 8)).view(dt)[:, 0]
    
    rng = np.random.default_rng()
    # 定义一个函数,接受数组作为参数
    def func(arr):
        indx = rng.integers(0, len(arr), size=6000, dtype=np.intp)
        arr[indx]
    
    tpe = ThreadPoolExecutor(max_workers=8)
    # 创建一个最大工作线程为8的线程池执行器
    
    futures = [tpe.submit(func, arr) for _ in range(10)]
    # 提交10个任务给线程池执行器并获取每个任务的future对象
    
    for f in futures:
        f.result()
        # 等待每个任务完成
    
    # 断言数组的数据类型是否为预期的数据类型 `dt`
    assert arr.dtype is dt
    # 使用断言验证条件,如果条件不成立,则会引发异常
    
    # 下面开始另一个测试方法的定义
    def test_nontuple_ndindex(self):
        a = np.arange(25).reshape((5, 5))
        assert_equal(a[[0, 1]], np.array([a[0], a[1]]))
        assert_equal(a[[0, 1], [0, 1]], np.array([0, 6]))
        assert_raises(IndexError, a.__getitem__, [slice(None)])
class TestFieldIndexing:
    def test_scalar_return_type(self):
        # Field access on an array should return an array, even if it
        # is 0-d.
        a = np.zeros((), [('a','f8')])
        assert_(isinstance(a['a'], np.ndarray))  # 检查字段访问返回的类型是否为 ndarray
        assert_(isinstance(a[['a']], np.ndarray))  # 检查字段访问返回的类型是否为 ndarray


class TestBroadcastedAssignments:
    def assign(self, a, ind, val):
        a[ind] = val  # 对数组 a 执行索引操作并赋值为 val
        return a  # 返回更新后的数组 a

    def test_prepending_ones(self):
        a = np.zeros((3, 2))  # 创建一个形状为 (3, 2) 的零数组

        a[...] = np.ones((1, 3, 2))  # 使用全为 1 的数组填充整个数组 a
        # Fancy with subspace with and without transpose
        a[[0, 1, 2], :] = np.ones((1, 3, 2))  # 在指定的子空间内使用全为 1 的数组进行赋值
        a[:, [0, 1]] = np.ones((1, 3, 2))  # 在指定的子空间内使用全为 1 的数组进行赋值
        # Fancy without subspace (with broadcasting)
        a[[[0], [1], [2]], [0, 1]] = np.ones((1, 3, 2))  # 在指定的子空间内使用全为 1 的数组进行赋值

    def test_prepend_not_one(self):
        assign = self.assign
        s_ = np.s_
        a = np.zeros(5)  # 创建一个长度为 5 的零数组

        # Too large and not only ones.
        assert_raises(ValueError, assign, a, s_[...],  np.ones((2, 1)))  # 检查赋值操作是否会引发 ValueError
        assert_raises(ValueError, assign, a, s_[[1, 2, 3],], np.ones((2, 1)))  # 检查赋值操作是否会引发 ValueError
        assert_raises(ValueError, assign, a, s_[[[1], [2]],], np.ones((2,2,1)))  # 检查赋值操作是否会引发 ValueError

    def test_simple_broadcasting_errors(self):
        assign = self.assign
        s_ = np.s_
        a = np.zeros((5, 1))  # 创建一个形状为 (5, 1) 的零数组

        assert_raises(ValueError, assign, a, s_[...], np.zeros((5, 2)))  # 检查赋值操作是否会引发 ValueError
        assert_raises(ValueError, assign, a, s_[...], np.zeros((5, 0)))  # 检查赋值操作是否会引发 ValueError
        assert_raises(ValueError, assign, a, s_[:, [0]], np.zeros((5, 2)))  # 检查赋值操作是否会引发 ValueError
        assert_raises(ValueError, assign, a, s_[:, [0]], np.zeros((5, 0)))  # 检查赋值操作是否会引发 ValueError
        assert_raises(ValueError, assign, a, s_[[0], :], np.zeros((2, 1)))  # 检查赋值操作是否会引发 ValueError

    @pytest.mark.parametrize("index", [
            (..., [1, 2], slice(None)),
            ([0, 1], ..., 0),
            (..., [1, 2], [1, 2])])
    def test_broadcast_error_reports_correct_shape(self, index):
        values = np.zeros((100, 100))  # 创建一个形状为 (100, 100) 的零数组

        arr = np.zeros((3, 4, 5, 6, 7))  # 创建一个形状为 (3, 4, 5, 6, 7) 的零数组
        # We currently report without any spaces (could be changed)
        shape_str = str(arr[index].shape).replace(" ", "")  # 获取索引 arr[index] 的形状并去除空格
        
        with pytest.raises(ValueError) as e:
            arr[index] = values  # 尝试对 arr 的索引位置赋值为 values

        assert str(e.value).endswith(shape_str)  # 检查错误消息的结尾是否与形状字符串匹配

    def test_index_is_larger(self):
        # Simple case of fancy index broadcasting of the index.
        a = np.zeros((5, 5))  # 创建一个形状为 (5, 5) 的零数组
        a[[[0], [1], [2]], [0, 1, 2]] = [2, 3, 4]  # 在指定的索引位置进行赋值操作

        assert_((a[:3, :3] == [2, 3, 4]).all())  # 检查赋值是否成功

    def test_broadcast_subspace(self):
        a = np.zeros((100, 100))  # 创建一个形状为 (100, 100) 的零数组
        v = np.arange(100)[:,None]  # 创建一个形状为 (100, 1) 的数组
        b = np.arange(100)[::-1]  # 创建一个倒序的长度为 100 的数组
        a[b] = v  # 在指定的索引位置进行赋值操作
        assert_((a[::-1] == v).all())  # 检查赋值是否成功
    def test_basic(self):
        # 定义一个子类 SubClass,继承自 np.ndarray
        class SubClass(np.ndarray):
            pass

        # 创建一个从 0 到 4 的 ndarray
        a = np.arange(5)
        
        # 使用 SubClass 视图对 a 进行切片操作
        s = a.view(SubClass)
        
        # 对视图 s 进行切片操作,得到 s 的一个子切片 s_slice
        s_slice = s[:3]
        
        # 断言 s_slice 的类型是 SubClass
        assert_(type(s_slice) is SubClass)
        
        # 断言 s_slice 的 base 是 s
        assert_(s_slice.base is s)
        
        # 断言 s_slice 的值与 a 的前三个元素相等
        assert_array_equal(s_slice, a[:3])

        # 使用 fancy indexing 从 s 中选择特定索引,得到 s 的一个新子类实例 s_fancy
        s_fancy = s[[0, 1, 2]]
        
        # 断言 s_fancy 的类型是 SubClass
        assert_(type(s_fancy) is SubClass)
        
        # 断言 s_fancy 的 base 不是 s
        assert_(s_fancy.base is not s)
        
        # 断言 s_fancy 的 base 类型是 np.ndarray
        assert_(type(s_fancy.base) is np.ndarray)
        
        # 断言 s_fancy 的值与 a 中索引为 [0, 1, 2] 的元素相等
        assert_array_equal(s_fancy, a[[0, 1, 2]])
        
        # 断言 s_fancy 的 base 值与 a 中索引为 [0, 1, 2] 的元素相等
        assert_array_equal(s_fancy.base, a[[0, 1, 2]])

        # 使用布尔索引从 s 中选择大于 0 的元素,得到 s 的一个新子类实例 s_bool
        s_bool = s[s > 0]
        
        # 断言 s_bool 的类型是 SubClass
        assert_(type(s_bool) is SubClass)
        
        # 断言 s_bool 的 base 不是 s
        assert_(s_bool.base is not s)
        
        # 断言 s_bool 的 base 类型是 np.ndarray
        assert_(type(s_bool.base) is np.ndarray)
        
        # 断言 s_bool 的值与 a 中大于 0 的元素相等
        assert_array_equal(s_bool, a[a > 0])
        
        # 断言 s_bool 的 base 值与 a 中大于 0 的元素相等
        assert_array_equal(s_bool.base, a[a > 0])

    def test_fancy_on_read_only(self):
        # 测试只读 SubClass 的 fancy indexing 不会创建只读副本(gh-14132)
        class SubClass(np.ndarray):
            pass

        # 创建一个从 0 到 4 的 ndarray
        a = np.arange(5)
        
        # 使用 SubClass 视图对 a 进行设置为只读
        s = a.view(SubClass)
        s.flags.writeable = False
        
        # 对只读视图 s 进行 fancy indexing 操作
        s_fancy = s[[0, 1, 2]]
        
        # 断言 s_fancy 的可写标志为 True
        assert_(s_fancy.flags.writeable)


    def test_finalize_gets_full_info(self):
        # Array finalize 应该在填充数组时被调用
        class SubClass(np.ndarray):
            def __array_finalize__(self, old):
                self.finalize_status = np.array(self)
                self.old = old

        # 创建一个从 0 到 9 的 ndarray,视图为 SubClass
        s = np.arange(10).view(SubClass)
        
        # 对 s 进行切片操作,得到一个新子类实例 new_s
        new_s = s[:3]
        
        # 断言 new_s 的 finalize_status 等于 new_s 自身
        assert_array_equal(new_s.finalize_status, new_s)
        
        # 断言 new_s 的 old 属性等于 s
        assert_array_equal(new_s.old, s)

        # 对 s 进行 fancy indexing 操作,得到一个新子类实例 new_s
        new_s = s[[0,1,2,3]]
        
        # 断言 new_s 的 finalize_status 等于 new_s 自身
        assert_array_equal(new_s.finalize_status, new_s)
        
        # 断言 new_s 的 old 属性等于 s
        assert_array_equal(new_s.old, s)

        # 对 s 进行布尔索引操作,得到一个新子类实例 new_s
        new_s = s[s > 0]
        
        # 断言 new_s 的 finalize_status 等于 new_s 自身
        assert_array_equal(new_s.finalize_status, new_s)
        
        # 断言 new_s 的 old 属性等于 s
        assert_array_equal(new_s.old, s)
class TestFancyIndexingCast:
    def test_boolean_index_cast_assign(self):
        # 设置布尔索引和浮点数组。
        shape = (8, 63)
        bool_index = np.zeros(shape).astype(bool)
        bool_index[0, 1] = True
        zero_array = np.zeros(shape)

        # 将值赋给布尔索引是允许的。
        zero_array[bool_index] = np.array([1])
        assert_equal(zero_array[0, 1], 1)

        # 使用复数警告检查,进行高级索引赋值,尽管会得到一个转换警告。
        assert_warns(ComplexWarning,
                     zero_array.__setitem__, ([0], [1]), np.array([2 + 1j]))
        assert_equal(zero_array[0, 1], 2)  # 没有复数部分

        # 将复数转换为浮点数,舍弃虚部。
        assert_warns(ComplexWarning,
                     zero_array.__setitem__, bool_index, np.array([1j]))
        assert_equal(zero_array[0, 1], 0)

class TestFancyIndexingEquivalence:
    def test_object_assign(self):
        # 检查字段和对象特殊情况是否使用了copyto。
        # 右侧的值在此处无法转换为数组。
        a = np.arange(5, dtype=object)
        b = a.copy()
        a[:3] = [1, (1,2), 3]
        b[[0, 1, 2]] = [1, (1,2), 3]
        assert_array_equal(a, b)

        # 对子空间高级索引进行相同的测试
        b = np.arange(5, dtype=object)[None, :]
        b[[0], :3] = [[1, (1,2), 3]]
        assert_array_equal(a, b[0])

        # 检查轴的交换是否起作用。
        # 之前有一个错误,使得后续的赋值引发ValueError,
        # 因为一个不正确转置的临时右侧值 (gh-5714)。
        b = b.T
        b[:3, [0]] = [[1], [(1,2)], [3]]
        assert_array_equal(a, b[:, 0])

        # 子空间的内存顺序的另一个测试
        arr = np.ones((3, 4, 5), dtype=object)
        # 用于比较的等效切片赋值
        cmp_arr = arr.copy()
        cmp_arr[:1, ...] = [[[1], [2], [3], [4]]]
        arr[[0], ...] = [[[1], [2], [3], [4]]]
        assert_array_equal(arr, cmp_arr)
        arr = arr.copy('F')
        arr[[0], ...] = [[[1], [2], [3], [4]]]
        assert_array_equal(arr, cmp_arr)

    def test_cast_equivalence(self):
        # 是的,普通切片使用不安全的转换。
        a = np.arange(5)
        b = a.copy()

        a[:3] = np.array(['2', '-3', '-1'])
        b[[0, 2, 1]] = np.array(['2', '-1', '-3'])
        assert_array_equal(a, b)

        # 对子空间高级索引进行相同的测试
        b = np.arange(5)[None, :]
        b[[0], :3] = np.array([['2', '-3', '-1']])
        assert_array_equal(a, b[0])


class TestMultiIndexingAutomated:
    """
    These tests use code to mimic the C-Code indexing for selection.
    """
    NOTE:

        * This still lacks tests for complex item setting.
        * If you change behavior of indexing, you might want to modify
          these tests to try more combinations.
        * Behavior was written to match numpy version 1.8. (though a
          first version matched 1.7.)
        * Only tuple indices are supported by the mimicking code.
          (and tested as of writing this)
        * Error types should match most of the time as long as there
          is only one error. For multiple errors, what gets raised
          will usually not be the same one. They are *not* tested.

    Update 2016-11-30: It is probably not worth maintaining this test
    indefinitely and it can be dropped if maintenance becomes a burden.

    """

    # 设置测试环境的方法
    def setup_method(self):
        # 创建一个四维的 numpy 数组 a,其形状为 (3, 1, 5, 6),并填充 arange 生成的数据
        self.a = np.arange(np.prod([3, 1, 5, 6])).reshape(3, 1, 5, 6)
        # 创建一个空的 numpy 数组 b,形状为 (3, 0, 5, 6)
        self.b = np.empty((3, 0, 5, 6))
        # 复杂索引的测试集合,包含多种不同类型的索引对象
        self.complex_indices = ['skip', Ellipsis,
            0,
            # 布尔索引,特殊情况下可以吃掉维度,需要测试所有 False 的情况
            np.array([True, False, False]),
            np.array([[True, False], [False, True]]),
            np.array([[[False, False], [False, False]]]),
            # 一些切片:
            slice(-5, 5, 2),
            slice(1, 1, 100),
            slice(4, -1, -2),
            slice(None, None, -3),
            # 一些高级索引:
            np.empty((0, 1, 1), dtype=np.intp),  # 空数组,可以广播
            np.array([0, 1, -2]),
            np.array([[2], [0], [1]]),
            np.array([[0, -1], [0, 1]], dtype=np.dtype('intp').newbyteorder()),
            np.array([2, -1], dtype=np.int8),
            np.zeros([1]*31, dtype=int),  # 触发太大的数组
            np.array([0., 1.])]  # 无效的数据类型
        # 一些简单的索引,涵盖更多情况
        self.simple_indices = [Ellipsis, None, -1, [1], np.array([True]),
                               'skip']
        # 简单的索引以填充其余情况
        self.fill_indices = [slice(None, None), 0]

    def _check_multi_index(self, arr, index):
        """检查多索引项的获取和简单设置。

        Parameters
        ----------
        arr : ndarray
            要索引的数组,必须是重塑后的 arange。
        index : tuple of indexing objects
            正在测试的索引。
        """
        # 测试获取索引项
        try:
            mimic_get, no_copy = self._get_multi_index(arr, index)
        except Exception as e:
            if HAS_REFCOUNT:
                prev_refcount = sys.getrefcount(arr)
            # 断言引发的异常类型与期望一致
            assert_raises(type(e), arr.__getitem__, index)
            assert_raises(type(e), arr.__setitem__, index, 0)
            if HAS_REFCOUNT:
                assert_equal(prev_refcount, sys.getrefcount(arr))
            return

        # 比较索引结果
        self._compare_index_result(arr, index, mimic_get, no_copy)
    def _check_single_index(self, arr, index):
        """Check a single index item getting and simple setting.

        Parameters
        ----------
        arr : ndarray
            要进行索引的数组,必须是一个 arange。
        index : indexing object
            被测试的索引。必须是单个索引对象,不能是索引对象的元组
            (参见 `_check_multi_index`)。
        """
        try:
            # 调用 `_get_multi_index` 方法获取模仿的索引结果和是否复制的标志
            mimic_get, no_copy = self._get_multi_index(arr, (index,))
        except Exception as e:
            if HAS_REFCOUNT:
                # 获取数组的引用计数
                prev_refcount = sys.getrefcount(arr)
            # 断言索引操作抛出的异常类型
            assert_raises(type(e), arr.__getitem__, index)
            assert_raises(type(e), arr.__setitem__, index, 0)
            if HAS_REFCOUNT:
                # 断言操作后数组的引用计数不变
                assert_equal(prev_refcount, sys.getrefcount(arr))
            return

        # 比较索引结果和模仿的索引结果
        self._compare_index_result(arr, index, mimic_get, no_copy)

    def _compare_index_result(self, arr, index, mimic_get, no_copy):
        """Compare mimicked result to indexing result.
        """
        # 复制数组以防止影响原始数据
        arr = arr.copy()
        # 执行索引操作
        indexed_arr = arr[index]
        # 断言索引操作的结果与模仿的索引结果相等
        assert_array_equal(indexed_arr, mimic_get)
        # 检查是否得到视图,除非是大小为0或者0维的数组(这时候不是视图,也不重要)
        if indexed_arr.size != 0 and indexed_arr.ndim != 0:
            # 检查是否共享内存
            assert_(np.may_share_memory(indexed_arr, arr) == no_copy)
            # 检查原始数组的引用计数
            if HAS_REFCOUNT:
                if no_copy:
                    # 如果没有复制,引用计数增加1
                    assert_equal(sys.getrefcount(arr), 3)
                else:
                    assert_equal(sys.getrefcount(arr), 2)

        # 测试非广播的赋值操作
        b = arr.copy()
        b[index] = mimic_get + 1000
        if b.size == 0:
            return  # 没有可比较的内容...
        if no_copy and indexed_arr.ndim != 0:
            # 如果没有复制且索引数组不是0维,则原地修改索引数组以操纵原始数据
            indexed_arr += 1000
            assert_array_equal(arr, b)
            return
        # 利用数组原本是 arange 的特性进行赋值操作
        arr.flat[indexed_arr.ravel()] += 1000
        assert_array_equal(arr, b)

    def test_boolean(self):
        a = np.array(5)
        # 断言布尔索引返回正确的值
        assert_equal(a[np.array(True)], 5)
        # 布尔索引赋值
        a[np.array(True)] = 1
        assert_equal(a, 1)
        # 注意:这与正常的广播操作不同,因为 arr[boolean_array] 的工作方式类似于多索引。
        # 这意味着它被对齐到左边。这对于与 arr[boolean_array,] 保持一致可能是正确的,而且根本不进行广播操作。
        self._check_multi_index(
            self.a, (np.zeros_like(self.a, dtype=bool),))
        self._check_multi_index(
            self.a, (np.zeros_like(self.a, dtype=bool)[..., 0],))
        self._check_multi_index(
            self.a, (np.zeros_like(self.a, dtype=bool)[None, ...],))
    def test_multidim(self):
        # 测试多维索引的功能

        # 捕获警告,防止 np.array(True) 在完整整数索引中被接受,当单独运行文件时
        with warnings.catch_warnings():
            # 忽略 DeprecationWarning 类型的警告
            warnings.filterwarnings('error', '', DeprecationWarning)
            # 忽略 VisibleDeprecationWarning 类型的警告
            warnings.filterwarnings('error', '', VisibleDeprecationWarning)

            # 定义一个函数,用来判断是否需要跳过某个索引
            def isskip(idx):
                return isinstance(idx, str) and idx == "skip"

            # 针对简单的位置(0、2、3)循环进行测试
            for simple_pos in [0, 2, 3]:
                # 准备索引的组合进行检查
                tocheck = [self.fill_indices, self.complex_indices,
                           self.fill_indices, self.fill_indices]
                # 将简单位置替换为简单索引
                tocheck[simple_pos] = self.simple_indices
                # 遍历所有可能的索引组合
                for index in product(*tocheck):
                    # 过滤掉需要跳过的索引,然后执行多维索引检查
                    index = tuple(i for i in index if not isskip(i))
                    self._check_multi_index(self.a, index)
                    self._check_multi_index(self.b, index)

        # 对非常简单的获取单个元素进行检查
        self._check_multi_index(self.a, (0, 0, 0, 0))
        self._check_multi_index(self.b, (0, 0, 0, 0))

        # 同时也检查(简单情况下的)索引过多的情况
        assert_raises(IndexError, self.a.__getitem__, (0, 0, 0, 0, 0))
        assert_raises(IndexError, self.a.__setitem__, (0, 0, 0, 0, 0), 0)
        assert_raises(IndexError, self.a.__getitem__, (0, 0, [1], 0, 0))
        assert_raises(IndexError, self.a.__setitem__, (0, 0, [1], 0, 0), 0)

    def test_1d(self):
        # 测试一维数组的功能
        a = np.arange(10)
        for index in self.complex_indices:
            # 对单个索引进行检查
            self._check_single_index(a, index)
class TestFloatNonIntegerArgument:
    """
    These test that ``TypeError`` is raised when you try to use
    non-integers as arguments to for indexing and slicing e.g. ``a[0.0:5]``
    and ``a[0.5]``, or other functions like ``array.reshape(1., -1)``.

    """

    def test_valid_indexing(self):
        # These should raise no errors.
        a = np.array([[[5]]])

        # 索引操作,使用整数数组
        a[np.array([0])]
        # 索引操作,使用整数列表
        a[[0, 0]]
        # 切片操作,使用整数列表
        a[:, [0, 0]]
        # 切片操作,使用整数
        a[:, 0, :]
        # 完整切片操作
        a[:, :, :]

    def test_valid_slicing(self):
        # These should raise no errors.
        a = np.array([[[5]]])

        # 完整切片操作
        a[::]
        # 从索引0开始切片
        a[0:]
        # 切片到索引1(不包含)
        a[:2]
        # 切片从索引0到2(不包含)
        a[0:2]
        # 步长为2的切片
        a[::2]
        # 从索引1开始,步长为2的切片
        a[1::2]
        # 切片从索引0到2(不包含),步长为2
        a[:2:2]
        # 切片从索引1到2(不包含),步长为2
        a[1:2:2]

    def test_non_integer_argument_errors(self):
        a = np.array([[5]])

        # 测试reshape函数使用非整数参数抛出TypeError异常
        assert_raises(TypeError, np.reshape, a, (1., 1., -1))
        assert_raises(TypeError, np.reshape, a, (np.array(1.), -1))
        # 测试take函数使用非整数参数抛出TypeError异常
        assert_raises(TypeError, np.take, a, [0], 1.)
        assert_raises(TypeError, np.take, a, [0], np.float64(1.))

    def test_non_integer_sequence_multiplication(self):
        # NumPy标量序列乘法不应使用非整数
        def mult(a, b):
            return a * b

        # 测试使用非整数参数抛出TypeError异常
        assert_raises(TypeError, mult, [1], np.float64(3))
        # 以下应该正常运行
        mult([1], np.int_(3))

    def test_reduce_axis_float_index(self):
        d = np.zeros((3, 3, 3))
        # 测试使用浮点数作为reduce操作的轴索引抛出TypeError异常
        assert_raises(TypeError, np.min, d, 0.5)
        assert_raises(TypeError, np.min, d, (0.5, 1))
        assert_raises(TypeError, np.min, d, (1, 2.2))
        assert_raises(TypeError, np.min, d, (.2, 1.2))


class TestBooleanIndexing:
    # Using a boolean as integer argument/indexing is an error.
    def test_bool_as_int_argument_errors(self):
        a = np.array([[[1]]])

        # 测试reshape函数使用布尔值参数抛出TypeError异常
        assert_raises(TypeError, np.reshape, a, (True, -1))
        assert_raises(TypeError, np.reshape, a, (np.bool(True), -1))
        # 注意,operator.index(np.array(True))不能工作,布尔数组因此也被弃用,但错误信息不同:
        assert_raises(TypeError, operator.index, np.array(True))
        assert_warns(DeprecationWarning, operator.index, np.True_)
        # 测试take函数使用布尔值参数抛出TypeError异常
        assert_raises(TypeError, np.take, args=(a, [0], False))

    def test_boolean_indexing_weirdness(self):
        # Weird boolean indexing things
        a = np.ones((2, 3, 4))
        # 使用False作为索引时返回的形状应为空
        assert a[False, True, ...].shape == (0, 2, 3, 4)
        # 使用True和其他混合索引方式返回的形状应为(1, 2)
        assert a[True, [0, 1], True, True, [1], [[2]]].shape == (1, 2)
        # 使用False和其他索引方式应该抛出IndexError异常
        assert_raises(IndexError, lambda: a[False, [0, 1], ...])
    # 定义一个测试函数,测试快速路径下的布尔索引情况
    def test_boolean_indexing_fast_path(self):
        # 创建一个3x3的全1数组
        a = np.ones((3, 3))

        # 使用错误的布尔索引,预期引发IndexError异常,错误信息为:
        # "boolean index did not match indexed array along axis 0; size of axis is 3 but size of corresponding boolean axis is 1"
        idx1 = np.array([[False]*9])
        assert_raises_regex(IndexError,
            "boolean index did not match indexed array along axis 0; "
            "size of axis is 3 but size of corresponding boolean axis is 1",
            lambda: a[idx1])

        # 使用错误的布尔索引,预期引发IndexError异常,错误信息同上
        idx2 = np.array([[False]*8 + [True]])
        assert_raises_regex(IndexError,
            "boolean index did not match indexed array along axis 0; "
            "size of axis is 3 but size of corresponding boolean axis is 1",
            lambda: a[idx2])

        # 使用正确长度的布尔索引,预期引发IndexError异常,错误信息同上
        idx3 = np.array([[False]*10])
        assert_raises_regex(IndexError,
            "boolean index did not match indexed array along axis 0; "
            "size of axis is 3 but size of corresponding boolean axis is 1",
            lambda: a[idx3])

        # 使用错误的布尔索引,预期引发IndexError异常,错误信息为:
        # "boolean index did not match indexed array along axis 1; size of axis is 1 but size of corresponding boolean axis is 2"
        a = np.ones((1, 1, 2))
        idx = np.array([[[True], [False]]])
        assert_raises_regex(IndexError,
            "boolean index did not match indexed array along axis 1; "
            "size of axis is 1 but size of corresponding boolean axis is 2",
            lambda: a[idx])
class TestArrayToIndexDeprecation:
    """Creating an index from array not 0-D is an error.

    This class tests scenarios where creating an index from arrays that are not 0-dimensional raises errors.
    """

    def test_array_to_index_error(self):
        # Define a 3-dimensional numpy array
        a = np.array([[[1]]])

        # Assert that attempting to convert a non-0-D array to index raises a TypeError
        assert_raises(TypeError, operator.index, np.array([1]))

        # Assert that reshaping 'a' with an invalid shape (-1) raises a TypeError
        assert_raises(TypeError, np.reshape, a, (a, -1))

        # Assert that using 'np.take' with invalid arguments raises a TypeError
        assert_raises(TypeError, np.take, a, [0], a)


class TestNonIntegerArrayLike:
    """Tests that array_likes are only valid if they can be safely cast to integers.

    This class tests scenarios where array-like objects should only allow safe casting to integers,
    otherwise IndexError should be raised.
    """

    def test_basic(self):
        # Create a numpy array with range 0 to 9
        a = np.arange(10)

        # Assert that attempting to access non-integer indices raises an IndexError
        assert_raises(IndexError, a.__getitem__, [0.5, 1.5])
        assert_raises(IndexError, a.__getitem__, (['1', '2'],))

        # Assert that accessing with an empty list is valid
        a.__getitem__([])


class TestMultipleEllipsisError:
    """An index can only have a single ellipsis.

    This class tests scenarios where using multiple ellipses (ellipsis objects) in numpy indexing raises an IndexError.
    """

    def test_basic(self):
        # Create a numpy array with range 0 to 9
        a = np.arange(10)

        # Assert that using multiple ellipses raises an IndexError
        assert_raises(IndexError, lambda: a[..., ...])
        assert_raises(IndexError, a.__getitem__, ((Ellipsis,) * 2,))
        assert_raises(IndexError, a.__getitem__, ((Ellipsis,) * 3,))


class TestCApiAccess:
    """Tests for C-API access functionalities.

    This class tests various functionalities related to C-API access in numpy arrays.
    """

    def test_getitem(self):
        # Define a partial function 'subscript' using 'array_indexing' function with fixed first argument as 0
        subscript = functools.partial(array_indexing, 0)

        # Test cases for '__getitem__' method

        # Assert that accessing element of a 0-dimensional array raises IndexError
        assert_raises(IndexError, subscript, np.ones(()), 0)

        # Assert that accessing out-of-bounds values raises IndexError
        assert_raises(IndexError, subscript, np.ones(10), 11)
        assert_raises(IndexError, subscript, np.ones(10), -11)
        assert_raises(IndexError, subscript, np.ones((10, 10)), 11)
        assert_raises(IndexError, subscript, np.ones((10, 10)), -11)

        # Create a numpy array with range 0 to 9
        a = np.arange(10)

        # Assert that array indexing behaves correctly for a 1-dimensional array
        assert_array_equal(a[4], subscript(a, 4))

        # Reshape 'a' to a 2-dimensional array and test indexing
        a = a.reshape(5, 2)
        assert_array_equal(a[-4], subscript(a, -4))

    def test_setitem(self):
        # Define a partial function 'assign' using 'array_indexing' function with fixed first argument as 1
        assign = functools.partial(array_indexing, 1)

        # Test cases for '__setitem__' method

        # Assert that deletion operation raises ValueError
        assert_raises(ValueError, assign, np.ones(10), 0)

        # Assert that assigning values to elements of a 0-dimensional array raises IndexError
        assert_raises(IndexError, assign, np.ones(()), 0, 0)

        # Assert that assigning to out-of-bounds indices raises IndexError
        assert_raises(IndexError, assign, np.ones(10), 11, 0)
        assert_raises(IndexError, assign, np.ones(10), -11, 0)
        assert_raises(IndexError, assign, np.ones((10, 10)), 11, 0)
        assert_raises(IndexError, assign, np.ones((10, 10)), -11, 0)

        # Create a numpy array with range 0 to 9
        a = np.arange(10)

        # Assign a new value to index 4 and assert the change
        assign(a, 4, 10)
        assert_(a[4] == 10)

        # Reshape 'a' to a 2-dimensional array and test assignment
        a = a.reshape(5, 2)
        assign(a, 4, 10)
        assert_array_equal(a[-1], [10, 10])

.\numpy\numpy\_core\tests\test_item_selection.py

import sys  # 导入sys模块,用于获取系统相关信息

import pytest  # 导入pytest模块,用于编写和运行测试用例

import numpy as np  # 导入NumPy库,并使用np作为别名
from numpy.testing import (  # 从NumPy测试模块中导入多个函数和类
    assert_, assert_raises, assert_array_equal, HAS_REFCOUNT
    )


class TestTake:  # 定义测试类TestTake

    def test_simple(self):  # 测试简单取值函数
        a = [[1, 2], [3, 4]]  # 定义一个二维列表a
        a_str = [[b'1', b'2'], [b'3', b'4']]  # 定义一个二维列表a_str,包含字节字符串
        modes = ['raise', 'wrap', 'clip']  # 模式列表,用于测试取值的不同模式
        indices = [-1, 4]  # 索引列表,用于测试取值的不同索引
        index_arrays = [np.empty(0, dtype=np.intp),  # 索引数组列表,包含三个不同形状的空数组
                        np.empty(tuple(), dtype=np.intp),
                        np.empty((1, 1), dtype=np.intp)]
        real_indices = {'raise': {-1: 1, 4: IndexError},  # 实际索引字典,包含不同模式下的预期结果
                        'wrap': {-1: 1, 4: 0},
                        'clip': {-1: 0, 4: 1}}

        # Currently all types but object, use the same function generation.
        # So it should not be necessary to test all. However test also a non
        # refcounted struct on top of object, which has a size that hits the
        # default (non-specialized) path.
        types = int, object, np.dtype([('', 'i2', 3)])  # 类型元组,包含int、object和自定义dtype类型
        for t in types:  # 遍历类型元组中的每个类型
            ta = np.array(a if np.issubdtype(t, np.number) else a_str, dtype=t)  # 根据类型创建NumPy数组ta
            tresult = list(ta.T.copy())  # 复制数组ta的转置并转换为列表,赋值给tresult
            for index_array in index_arrays:  # 遍历索引数组列表中的每个索引数组
                if index_array.size != 0:  # 如果索引数组不为空
                    tresult[0].shape = (2,) + index_array.shape  # 调整tresult[0]的形状
                    tresult[1].shape = (2,) + index_array.shape  # 调整tresult[1]的形状
                for mode in modes:  # 遍历模式列表中的每个模式
                    for index in indices:  # 遍历索引列表中的每个索引
                        real_index = real_indices[mode][index]  # 获取实际索引值
                        if real_index is IndexError and index_array.size != 0:  # 如果预期结果为IndexError且索引数组不为空
                            index_array.put(0, index)  # 将索引放入索引数组的第一个位置
                            assert_raises(IndexError, ta.take, index_array,  # 断言引发IndexError异常
                                          mode=mode, axis=1)
                        elif index_array.size != 0:  # 如果索引数组不为空
                            index_array.put(0, index)  # 将索引放入索引数组的第一个位置
                            res = ta.take(index_array, mode=mode, axis=1)  # 使用指定模式和轴取值
                            assert_array_equal(res, tresult[real_index])  # 断言结果数组与预期相等
                        else:  # 如果索引数组为空
                            res = ta.take(index_array, mode=mode, axis=1)  # 使用指定模式和轴取值
                            assert_(res.shape == (2,) + index_array.shape)  # 断言结果数组的形状符合预期

    def test_refcounting(self):  # 测试引用计数功能
        objects = [object() for i in range(10)]  # 创建包含10个新对象的列表
        for mode in ('raise', 'clip', 'wrap'):  # 遍历模式元组
            a = np.array(objects)  # 创建包含对象的NumPy数组a
            b = np.array([2, 2, 4, 5, 3, 5])  # 创建包含整数的NumPy数组b
            a.take(b, out=a[:6], mode=mode)  # 使用指定模式从a中取值到a的前6个位置
            del a  # 删除数组a的引用
            if HAS_REFCOUNT:  # 如果支持引用计数
                assert_(all(sys.getrefcount(o) == 3 for o in objects))  # 断言所有对象的引用计数为3
            # not contiguous, example:
            a = np.array(objects * 2)[::2]  # 创建包含对象的非连续NumPy数组a
            a.take(b, out=a[:6], mode=mode)  # 使用指定模式从a中取值到a的前6个位置
            del a  # 删除数组a的引用
            if HAS_REFCOUNT:  # 如果支持引用计数
                assert_(all(sys.getrefcount(o) == 3 for o in objects))  # 断言所有对象的引用计数为3
    # 测试Unicode模式下的函数
    def test_unicode_mode(self):
        # 创建一个包含0到9的数组
        d = np.arange(10)
        # 将一个UTF8编码的字节序列解码为Unicode字符串
        k = b'\xc3\xa4'.decode("UTF8")
        # 断言调用d.take(5, mode=k)应该会触发ValueError异常
        assert_raises(ValueError, d.take, 5, mode=k)
    
    # 测试空分区的函数
    def test_empty_partition(self):
        # 创建一个包含[0, 2, 4, 6, 8, 10]的数组,并进行复制
        a_original = np.array([0, 2, 4, 6, 8, 10])
        a = a_original.copy()
    
        # 对空数组进行分区应该是一个成功的空操作
        a.partition(np.array([], dtype=np.int16))
    
        # 断言a分区后的结果应该和a_original保持一致
        assert_array_equal(a, a_original)
    
    # 测试空argpartition的函数
    def test_empty_argpartition(self):
        # 在参考github问题#6530的情况下
        a = np.array([0, 2, 4, 6, 8, 10])
        # 对空数组进行argpartition
        a = a.argpartition(np.array([], dtype=np.int16))
    
        # 创建一个包含[0, 1, 2, 3, 4, 5]的数组
        b = np.array([0, 1, 2, 3, 4, 5])
        # 断言a的argpartition后的结果应该和b保持一致
        assert_array_equal(a, b)
class TestPutMask:
    @pytest.mark.parametrize("dtype", list(np.typecodes["All"]) + ["i,O"])
    def test_simple(self, dtype):
        if dtype.lower() == "m":
            dtype += "8[ns]"

        # 创建一个从0到1000的numpy数组,并根据dtype参数转换其数据类型
        vals = np.arange(1001).astype(dtype=dtype)

        # 创建一个长度为1000的布尔掩码数组
        mask = np.random.randint(2, size=1000).astype(bool)
        
        # 根据vals数组的数据类型创建一个长度为1000的全零数组
        arr = np.zeros(1000, dtype=vals.dtype)
        
        # 创建一个arr的副本
        zeros = arr.copy()

        # 使用np.putmask函数,根据掩码mask将vals数组中的值放入arr数组中
        np.putmask(arr, mask, vals)
        
        # 断言:检查arr中掩码为True的位置,其值与vals中相应位置的值相等
        assert_array_equal(arr[mask], vals[:len(mask)][mask])
        
        # 断言:检查arr中掩码为False的位置,其值与zeros中相应位置的值相等
        assert_array_equal(arr[~mask], zeros[~mask])

    @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"])
    @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"])
    def test_empty(self, dtype, mode):
        # 创建一个长度为1000的dtype类型全零数组
        arr = np.zeros(1000, dtype=dtype)
        
        # 创建arr的一个副本
        arr_copy = arr.copy()
        
        # 创建一个长度为1000的布尔掩码数组
        mask = np.random.randint(2, size=1000).astype(bool)

        # 使用空列表来调用np.put函数,这种用法看起来很奇怪...
        np.put(arr, mask, [])
        
        # 断言:检查arr与其副本arr_copy是否相等
        assert_array_equal(arr, arr_copy)


class TestPut:
    @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"])
    @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"])
    def test_simple(self, dtype, mode):
        if dtype.lower() == "m":
            dtype += "8[ns]"

        # 创建一个从0到1000的numpy数组,并根据dtype参数转换其数据类型
        vals = np.arange(1001).astype(dtype=dtype)

        # 使用vals的数据类型创建一个长度为1000的全零数组
        arr = np.zeros(1000, dtype=vals.dtype)
        
        # 创建一个arr的副本
        zeros = arr.copy()

        if mode == "clip":
            # 特殊情况,因为0和-1值用于clip测试
            indx = np.random.permutation(len(arr) - 2)[:-500] + 1

            indx[-1] = 0
            indx[-2] = len(arr) - 1
            indx_put = indx.copy()
            indx_put[-1] = -1389
            indx_put[-2] = 1321
        else:
            # 避免重复值(简化起见)并只填充一半
            indx = np.random.permutation(len(arr) - 3)[:-500]
            indx_put = indx
            if mode == "wrap":
                indx_put = indx_put + len(arr)

        # 使用np.put函数,根据indx_put数组将vals数组中的值放入arr数组中
        np.put(arr, indx_put, vals, mode=mode)
        
        # 断言:检查arr中indx数组位置的值与vals数组中相应位置的值是否相等
        assert_array_equal(arr[indx], vals[:len(indx)])
        
        # 创建一个全为True的布尔数组
        untouched = np.ones(len(arr), dtype=bool)
        
        # 将indx数组位置的值设置为False
        untouched[indx] = False
        
        # 断言:检查arr中untouched数组位置的值与zeros数组中相应位置的值是否相等
        assert_array_equal(arr[untouched], zeros[untouched])

    @pytest.mark.parametrize("dtype", list(np.typecodes["All"])[1:] + ["i,O"])
    @pytest.mark.parametrize("mode", ["raise", "wrap", "clip"])
    def test_empty(self, dtype, mode):
        # 创建一个长度为1000的dtype类型全零数组
        arr = np.zeros(1000, dtype=dtype)
        
        # 创建arr的一个副本
        arr_copy = arr.copy()

        # 使用列表[1, 2, 3]调用np.put函数,并传入一个空列表作为值,这种用法看起来很奇怪...
        np.put(arr, [1, 2, 3], [])
        
        # 断言:检查arr与其副本arr_copy是否相等
        assert_array_equal(arr, arr_copy)

.\numpy\numpy\_core\tests\test_limited_api.py

# 导入标准库和第三方库
import os                      # 导入操作系统功能模块
import shutil                  # 导入文件和目录操作模块
import subprocess              # 导入子进程管理模块
import sys                     # 导入系统相关功能模块
import sysconfig               # 导入 Python 配置信息模块
import pytest                  # 导入 pytest 测试框架

from numpy.testing import IS_WASM, IS_PYPY, NOGIL_BUILD, IS_EDITABLE  # 导入 numpy 测试相关标志

# 以下代码段是从 random.tests.test_extending 复制过来的
try:
    import cython             # 尝试导入 Cython 模块
    from Cython.Compiler.Version import version as cython_version  # 导入 Cython 版本信息
except ImportError:
    cython = None             # 如果导入失败,将 cython 设为 None
else:
    from numpy._utils import _pep440  # 导入 numpy 内部工具函数

    # 注意:需要与 pyproject.toml 中的版本保持同步
    required_version = "3.0.6"
    if _pep440.parse(cython_version) < _pep440.Version(required_version):
        # 如果 Cython 版本过低或者不符合要求,则跳过该测试
        cython = None

# 使用 pytest.mark.skipif 标记,如果 cython 为 None,则跳过测试,给出原因为需要 Cython
pytestmark = pytest.mark.skipif(cython is None, reason="requires cython")

# 如果是可编辑安装(editable install),则跳过测试并给出原因,这种安装方式不支持需要编译步骤的测试
if IS_EDITABLE:
    pytest.skip(
        "Editable install doesn't support tests with a compile step",
        allow_module_level=True
    )

# 使用 pytest.fixture(scope='module') 标记一个模块级别的 fixture
def install_temp(tmpdir_factory):
    # 基于 random.tests.test_extending 中的 test_cython 的部分内容
    if IS_WASM:
        pytest.skip("No subprocess")  # 如果是在 WASM 环境下,则跳过测试

    # 定义源代码目录和构建目录
    srcdir = os.path.join(os.path.dirname(__file__), 'examples', 'limited_api')
    build_dir = tmpdir_factory.mktemp("limited_api") / "build"
    os.makedirs(build_dir, exist_ok=True)  # 创建构建目录,如果不存在则创建

    try:
        subprocess.check_call(["meson", "--version"])  # 检查 meson 的版本
    except FileNotFoundError:
        pytest.skip("No usable 'meson' found")  # 如果找不到可用的 meson,则跳过测试

    # 根据操作系统不同,执行不同的 meson 构建命令
    if sys.platform == "win32":
        subprocess.check_call(["meson", "setup",
                               "--buildtype=release",
                               "--vsenv", str(srcdir)],
                              cwd=build_dir,
                              )
    else:
        subprocess.check_call(["meson", "setup", str(srcdir)],
                              cwd=build_dir
                              )

    try:
        subprocess.check_call(["meson", "compile", "-vv"], cwd=build_dir)  # 编译项目
    except subprocess.CalledProcessError as p:
        print(f"{p.stdout=}")  # 打印出错时的标准输出
        print(f"{p.stderr=}")  # 打印出错时的标准错误
        raise  # 抛出异常

    sys.path.append(str(build_dir))  # 将构建目录添加到系统路径中,以便导入测试所需的模块

# 使用 pytest.mark.skipif 标记,如果是在 WASM 环境下,则跳过测试
@pytest.mark.skipif(IS_WASM, reason="Can't start subprocess")
# 使用 pytest.mark.xfail 标记,如果 Py_DEBUG 开启,则预期测试失败,给出原因
@pytest.mark.xfail(
    sysconfig.get_config_var("Py_DEBUG"),
    reason=(
        "Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, "
        "and Py_REF_DEBUG"
    ),
)
# 使用 pytest.mark.xfail 标记,如果是 NOGIL_BUILD,则预期测试失败,给出原因
@pytest.mark.xfail(
    NOGIL_BUILD,
    reason="Py_GIL_DISABLED builds do not currently support the limited API",
)
# 使用 pytest.mark.skipif 标记,如果是在 PyPy 环境下,则跳过测试
@pytest.mark.skipif(IS_PYPY, reason="no support for limited API in PyPy")
# 定义测试函数 test_limited_api,并使用 install_temp 作为 fixture
def test_limited_api(install_temp):
    """Test building a third-party C extension with the limited API
    and building a cython extension with the limited API
    """

    import limited_api1  # 导入测试用的 limited_api1 模块
    import limited_api2  # 导入测试用的 limited_api2 模块

.\numpy\numpy\_core\tests\test_longdouble.py

# 引入警告模块,用于管理警告信息
import warnings
# 引入平台模块,用于获取平台相关信息
import platform
# 引入 pytest 测试框架
import pytest

# 引入 numpy 库,并导入一些特定的测试函数和变量
import numpy as np
from numpy.testing import (
    assert_, assert_equal, assert_raises, assert_warns, assert_array_equal,
    temppath, IS_MUSL
    )
# 从 numpy._core.tests._locales 模块导入 CommaDecimalPointLocale 类
from numpy._core.tests._locales import CommaDecimalPointLocale

# 获取长双精度浮点数的信息
LD_INFO = np.finfo(np.longdouble)
# 检查长双精度浮点数是否比双精度浮点数更精确
longdouble_longer_than_double = (LD_INFO.eps < np.finfo(np.double).eps)

# 定义一个临时变量 _o,用于检查字符串到长双精度浮点数的转换是否准确
_o = 1 + LD_INFO.eps
string_to_longdouble_inaccurate = (_o != np.longdouble(str(_o)))
del _o

def test_scalar_extraction():
    """确认提取值时不会转换为 Python 的浮点数"""
    o = 1 + LD_INFO.eps
    a = np.array([o, o, o])
    assert_equal(a[1], o)

# 字符串到长双精度浮点数的转换

# 计算 0.1 在二进制浮点表示中的精度
repr_precision = len(repr(np.longdouble(0.1)))
# 宏块从 scalartypes.c.src 文件大约第 842 行开始,额外增加 2 个精度。

# 根据条件跳过测试,当 IS_MUSL 为真时,测试在 musllinux 上不稳定
@pytest.mark.skipif(IS_MUSL,
                    reason="test flaky on musllinux")
# 根据条件跳过测试,当 repr 的精度不足以显示 eps 时
@pytest.mark.skipif(LD_INFO.precision + 2 >= repr_precision,
                    reason="repr precision not enough to show eps")
def test_str_roundtrip():
    # 只有在 repr 的精度能够显示 eps 时,我们才能在 repr 中看到 eps
    o = 1 + LD_INFO.eps
    assert_equal(np.longdouble(str(o)), o, "str was %s" % str(o))

# 根据条件跳过测试,当字符串到长双精度浮点数的转换不准确时
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
def test_str_roundtrip_bytes():
    o = 1 + LD_INFO.eps
    assert_equal(np.longdouble(str(o).encode("ascii")), o)

# 根据条件跳过测试,当字符串到长双精度浮点数的转换不准确时
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
# 参数化测试,测试不同类型的字符串(np.str_, np.bytes_, str, bytes)
@pytest.mark.parametrize("strtype", (np.str_, np.bytes_, str, bytes))
def test_array_and_stringlike_roundtrip(strtype):
    """
    测试长双精度浮点数的字符串表示在数组转换和标量强制转换中的往返,
    参见 gh-15608。
    """
    o = 1 + LD_INFO.eps

    if strtype in (np.bytes_, bytes):
        o_str = strtype(str(o).encode("ascii"))
    else:
        o_str = strtype(str(o))

    # 测试 `o` 是否能正确从字符串类转换
    assert o == np.longdouble(o_str)

    # 测试数组的往返转换是否正确:
    o_strarr = np.asarray([o] * 3, dtype=strtype)
    assert (o == o_strarr.astype(np.longdouble)).all()

    # 数组强制转换和字符串的强制转换应该与标量的 repr 相同:
    assert (o_strarr == o_str).all()
    assert (np.asarray([o] * 3).astype(strtype) == o_str).all()

def test_bogus_string():
    # 测试不合法的字符串转换是否会引发 ValueError 异常
    assert_raises(ValueError, np.longdouble, "spam")
    assert_raises(ValueError, np.longdouble, "1.0 flub")

# 根据条件跳过测试,当字符串到长双精度浮点数的转换不准确时
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
def test_fromstring():
    o = 1 + LD_INFO.eps
    s = (" " + str(o))*5
    a = np.array([o]*5)
    assert_equal(np.fromstring(s, sep=" ", dtype=np.longdouble), a,
                 err_msg="reading '%s'" % s)

def test_fromstring_complex():
    # 测试复杂字符串到长双精度浮点数的转换
    # 遍历指定的数据类型列表,依次进行以下操作
    for ctype in ["complex", "cdouble"]:
        # 使用 np.fromstring 函数将给定字符串解析为指定数据类型的 NumPy 数组,
        # 使用逗号作为分隔符,进行解析
        assert_equal(np.fromstring("1, 2 ,  3  ,4", sep=",", dtype=ctype),
                     np.array([1., 2., 3., 4.]))
        
        # 当实部未指定时,使用 np.fromstring 解析包含虚数部分的字符串,
        # 使用逗号作为分隔符,生成对应的复数数组
        assert_equal(np.fromstring("1j, -2j,  3j, 4e1j", sep=",", dtype=ctype),
                     np.array([1.j, -2.j, 3.j, 40.j]))
        
        # 当实部和虚部都指定时,使用 np.fromstring 解析包含实部和虚部的字符串,
        # 使用逗号作为分隔符,生成对应的复数数组
        assert_equal(np.fromstring("1+1j,2-2j, -3+3j,  -4e1+4j", sep=",", dtype=ctype),
                     np.array([1. + 1.j, 2. - 2.j, - 3. + 3.j, - 40. + 4j]))
        
        # 测试字符串中空格放置不当的情况,这些情况应该会引发 DeprecationWarning
        with assert_warns(DeprecationWarning):
            assert_equal(np.fromstring("1+2 j,3", dtype=ctype, sep=","),
                         np.array([1.]))
        with assert_warns(DeprecationWarning):
            assert_equal(np.fromstring("1+ 2j,3", dtype=ctype, sep=","),
                         np.array([1.]))
        with assert_warns(DeprecationWarning):
            assert_equal(np.fromstring("1 +2j,3", dtype=ctype, sep=","),
                         np.array([1.]))
        with assert_warns(DeprecationWarning):
            assert_equal(np.fromstring("1+j", dtype=ctype, sep=","),
                         np.array([1.]))
        with assert_warns(DeprecationWarning):
            assert_equal(np.fromstring("1+", dtype=ctype, sep=","),
                         np.array([1.]))
        with assert_warns(DeprecationWarning):
            assert_equal(np.fromstring("1j+1", dtype=ctype, sep=","),
                         np.array([1j]))
# 定义一个测试函数,测试处理不正确字符串的情况
def test_fromstring_bogus():
    # 使用 assert_warns 检查是否会产生 DeprecationWarning 警告
    with assert_warns(DeprecationWarning):
        # 调用 np.fromstring 方法尝试解析字符串,期望返回一个浮点数数组
        assert_equal(np.fromstring("1. 2. 3. flop 4.", dtype=float, sep=" "),
                     np.array([1., 2., 3.]))

# 定义一个测试函数,测试处理空字符串的情况
def test_fromstring_empty():
    # 使用 assert_warns 检查是否会产生 DeprecationWarning 警告
    with assert_warns(DeprecationWarning):
        # 调用 np.fromstring 方法尝试解析字符串,期望返回一个空的数组
        assert_equal(np.fromstring("xxxxx", sep="x"),
                     np.array([]))

# 定义一个测试函数,测试处理字符串中有缺失数据的情况
def test_fromstring_missing():
    # 使用 assert_warns 检查是否会产生 DeprecationWarning 警告
    with assert_warns(DeprecationWarning):
        # 调用 np.fromstring 方法尝试解析字符串,期望返回只有一个元素的数组
        assert_equal(np.fromstring("1xx3x4x5x6", sep="x"),
                     np.array([1]))

# 定义一个文件基础测试类
class TestFileBased:
    # 计算 ldbl 变量的值,LD_INFO.eps 为一个预定义的值
    ldbl = 1 + LD_INFO.eps
    # 创建一个目标数组,包含 5 个 ldbl 元素
    tgt = np.array([ldbl]*5)
    # 将目标数组转换为一个包含每个元素加换行符的字符串
    out = ''.join([str(t) + '\n' for t in tgt])

    # 定义一个测试函数,测试从文件读取不正确字符串的情况
    def test_fromfile_bogus(self):
        # 使用 temppath() 上下文管理器创建临时文件路径
        with temppath() as path:
            # 将字符串写入临时文件
            with open(path, 'w') as f:
                f.write("1. 2. 3. flop 4.\n")

            # 使用 assert_warns 检查是否会产生 DeprecationWarning 警告
            # 调用 np.fromfile 方法尝试从文件中读取数据,期望返回一个浮点数数组
            with assert_warns(DeprecationWarning):
                res = np.fromfile(path, dtype=float, sep=" ")
        # 断言从文件中读取的数组与期望的数组相等
        assert_equal(res, np.array([1., 2., 3.]))
    def test_fromfile_complex(self):
        # 针对复数和复数双精度类型进行测试
        for ctype in ["complex", "cdouble"]:
            # 检查分隔符与仅指定实部之间的空格
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1, 2 ,  3  ,4\n")
                
                # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1., 2., 3., 4.]))

            # 未指定实部的情况
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1j, -2j,  3j, 4e1j\n")

                # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1.j, -2.j, 3.j, 40.j]))

            # 同时指定实部和虚部的情况
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1+1j,2-2j, -3+3j,  -4e1+4j\n")

                # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1. + 1.j, 2. - 2.j, - 3. + 3.j, - 40. + 4j]))

            # 错误位置的空格
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1+2 j,3\n")

                # 验证警告是否抛出 DeprecationWarning
                with assert_warns(DeprecationWarning):
                    # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                    res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1.]))

            # 错误位置的空格
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1+ 2j,3\n")

                # 验证警告是否抛出 DeprecationWarning
                with assert_warns(DeprecationWarning):
                    # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                    res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1.]))

            # 错误位置的空格
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1 +2j,3\n")

                # 验证警告是否抛出 DeprecationWarning
                with assert_warns(DeprecationWarning):
                    # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                    res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1.]))

            # 错误位置的空格
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1+j\n")

                # 验证警告是否抛出 DeprecationWarning
                with assert_warns(DeprecationWarning):
                    # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                    res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1.]))

            # 错误位置的空格
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1+\n")

                # 验证警告是否抛出 DeprecationWarning
                with assert_warns(DeprecationWarning):
                    # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                    res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1.]))

            # 错误位置的空格
            with temppath() as path:
                with open(path, 'w') as f:
                    f.write("1j+1\n")

                # 验证警告是否抛出 DeprecationWarning
                with assert_warns(DeprecationWarning):
                    # 从文件中读取数据并按指定的数据类型和分隔符创建 NumPy 数组
                    res = np.fromfile(path, dtype=ctype, sep=",")
            # 断言结果与期望的 NumPy 数组相等
            assert_equal(res, np.array([1.j]))
    # 在特定条件下跳过测试,条件是 string_to_longdouble_inaccurate 为真
    @pytest.mark.skipif(string_to_longdouble_inaccurate,
                        reason="Need strtold_l")
    # 定义一个测试函数 test_fromfile,测试从文件中读取数据并使用 np.fromfile 转换为长双精度数组
    def test_fromfile(self):
        # 使用 temppath() 创建临时文件路径,并在该路径下写入 self.out 的内容
        with temppath() as path:
            with open(path, 'w') as f:
                f.write(self.out)
            # 使用 np.fromfile 从文件中读取数据,指定数据类型为 np.longdouble,数据分隔符为换行符
            res = np.fromfile(path, dtype=np.longdouble, sep="\n")
        # 断言测试结果与预期结果 self.tgt 相等
        assert_equal(res, self.tgt)
    
    # 在特定条件下跳过测试,条件是 string_to_longdouble_inaccurate 为真
    @pytest.mark.skipif(string_to_longdouble_inaccurate,
                        reason="Need strtold_l")
    # 定义一个测试函数 test_genfromtxt,测试从文件中读取数据并使用 np.genfromtxt 转换为长双精度数组
    def test_genfromtxt(self):
        # 使用 temppath() 创建临时文件路径,并在该路径下写入 self.out 的内容
        with temppath() as path:
            with open(path, 'w') as f:
                f.write(self.out)
            # 使用 np.genfromtxt 从文件中读取数据,指定数据类型为 np.longdouble
            res = np.genfromtxt(path, dtype=np.longdouble)
        # 断言测试结果与预期结果 self.tgt 相等
        assert_equal(res, self.tgt)
    
    # 在特定条件下跳过测试,条件是 string_to_longdouble_inaccurate 为真
    @pytest.mark.skipif(string_to_longdouble_inaccurate,
                        reason="Need strtold_l")
    # 定义一个测试函数 test_loadtxt,测试从文件中读取数据并使用 np.loadtxt 转换为长双精度数组
    def test_loadtxt(self):
        # 使用 temppath() 创建临时文件路径,并在该路径下写入 self.out 的内容
        with temppath() as path:
            with open(path, 'w') as f:
                f.write(self.out)
            # 使用 np.loadtxt 从文件中读取数据,指定数据类型为 np.longdouble
            res = np.loadtxt(path, dtype=np.longdouble)
        # 断言测试结果与预期结果 self.tgt 相等
        assert_equal(res, self.tgt)
    
    # 在特定条件下跳过测试,条件是 string_to_longdouble_inaccurate 为真
    @pytest.mark.skipif(string_to_longdouble_inaccurate,
                        reason="Need strtold_l")
    # 定义一个测试函数 test_tofile_roundtrip,测试数据的写入和读取操作是否能够循环正确处理长双精度数据
    def test_tofile_roundtrip(self):
        # 使用 temppath() 创建临时文件路径,并将 self.tgt 的内容写入该路径下,数据分隔符为空格
        self.tgt.tofile(path, sep=" ")
        # 使用 np.fromfile 从文件中读取数据,指定数据类型为 np.longdouble,数据分隔符为空格
        res = np.fromfile(path, dtype=np.longdouble, sep=" ")
        # 断言测试结果与预期结果 self.tgt 相等
        assert_equal(res, self.tgt)
# Conversions long double -> string

# 定义测试函数,测试 long double 类型到字符串类型的转换
def test_str_exact():
    # 创建一个 long double 对象 o,其值为 LD_INFO.eps + 1
    o = 1 + LD_INFO.eps
    # 断言 o 转换为字符串后不等于 '1'
    assert_(str(o) != '1')


# 跳过条件性测试,如果 long double 类型的精度大于 double 类型
@pytest.mark.skipif(longdouble_longer_than_double, reason="BUG #2376")
# 跳过条件性测试,如果字符串到 long double 转换不精确,需要 strtold_l 函数
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
# 格式化测试函数
def test_format():
    # 创建一个 long double 对象 o,其值为 LD_INFO.eps + 1
    o = 1 + LD_INFO.eps
    # 断言格式化输出 "{0:.40g}" 的结果不等于 '1'
    assert_("{0:.40g}".format(o) != '1')


# 跳过条件性测试,如果 long double 类型的精度大于 double 类型
@pytest.mark.skipif(longdouble_longer_than_double, reason="BUG #2376")
# 跳过条件性测试,如果字符串到 long double 转换不精确,需要 strtold_l 函数
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
# 百分比格式化测试函数
def test_percent():
    # 创建一个 long double 对象 o,其值为 LD_INFO.eps + 1
    o = 1 + LD_INFO.eps
    # 断言百分比格式化输出 "%.40g" 的结果不等于 '1'
    assert_("%.40g" % o != '1')


# 跳过条件性测试,如果 long double 类型的精度大于 double 类型,由于数组表示问题
@pytest.mark.skipif(longdouble_longer_than_double, reason="array repr problem")
# 跳过条件性测试,如果字符串到 long double 转换不精确,需要 strtold_l 函数
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
# 数组表示测试函数
def test_array_repr():
    # 创建一个 long double 对象 o,其值为 LD_INFO.eps + 1
    o = 1 + LD_INFO.eps
    # 创建一个包含 o 的 numpy 数组 a
    a = np.array([o])
    # 创建一个包含 1 的 long double 类型的 numpy 数组 b
    b = np.array([1], dtype=np.longdouble)
    # 如果数组 a 与数组 b 的所有元素均相等,则抛出 ValueError 异常
    if not np.all(a != b):
        raise ValueError("precision loss creating arrays")
    # 断言数组 a 的字符串表示不等于数组 b 的字符串表示
    assert_(repr(a) != repr(b))


# 区域设置测试:标量类型的格式化输出应独立于区域设置
class TestCommaDecimalPointLocale(CommaDecimalPointLocale):

    # 测试用例:测试使用外国语言环境下的字符串转换为 long double 类型的精度
    def test_str_roundtrip_foreign(self):
        # 创建一个浮点数 o,其值为 1.5
        o = 1.5
        # 断言 o 转换为 long double 类型后与原始值相等
        assert_equal(o, np.longdouble(str(o)))

    # 测试用例:从字符串表示中创建 float 类型数组的准确性
    def test_fromstring_foreign_repr(self):
        # 浮点数 f 的值为 1.234
        f = 1.234
        # 从 f 的字符串表示中创建一个 float 类型的 numpy 数组 a
        a = np.fromstring(repr(f), dtype=float, sep=" ")
        # 断言数组 a 的第一个元素等于 f
        assert_equal(a[0], f)

    # 测试用例:从特定字符串中创建 float 类型数组,期望 DeprecationWarning 警告
    def test_fromstring_best_effort_float(self):
        # 期望 DeprecationWarning 警告
        with assert_warns(DeprecationWarning):
            # 从字符串 "1,234" 中创建一个 float 类型的数组,期望结果为 [1.]
            assert_equal(np.fromstring("1,234", dtype=float, sep=" "),
                         np.array([1.]))

    # 测试用例:从特定字符串中创建 long double 类型数组,期望 DeprecationWarning 警告
    def test_fromstring_best_effort(self):
        # 期望 DeprecationWarning 警告
        with assert_warns(DeprecationWarning):
            # 从字符串 "1,234" 中创建一个 long double 类型的数组,期望结果为 [1.]
            assert_equal(np.fromstring("1,234", dtype=np.longdouble, sep=" "),
                         np.array([1.]))

    # 测试用例:从特定字符串中创建 long double 类型数组
    def test_fromstring_foreign(self):
        # 字符串 s 的值为 "1.234"
        s = "1.234"
        # 从字符串 s 中创建一个 long double 类型的 numpy 数组 a
        a = np.fromstring(s, dtype=np.longdouble, sep=" ")
        # 断言数组 a 的第一个元素等于 long double 类型的 s
        assert_equal(a[0], np.longdouble(s))

    # 测试用例:从特定字符串中创建 long double 类型数组,指定分隔符为 ","
    def test_fromstring_foreign_sep(self):
        # 创建一个整数数组 a,值为 [1, 2, 3, 4]
        a = np.array([1, 2, 3, 4])
        # 从字符串 "1,2,3,4," 中创建一个 long double 类型的 numpy 数组 b,指定分隔符为 ","
        b = np.fromstring("1,2,3,4,", dtype=np.longdouble, sep=",")
        # 断言数组 a 与数组 b 相等
        assert_array_equal(a, b)

    # 测试用例:从特定字符串中创建 long double 类型数组,期望 DeprecationWarning 警告
    def test_fromstring_foreign_value(self):
        # 期望 DeprecationWarning 警告
        with assert_warns(DeprecationWarning):
            # 从字符串 "1,234" 中创建一个 long double 类型的数组 b,期望结果为 [1.]
            b = np.fromstring("1,234", dtype=np.longdouble, sep=" ")
            # 断言数组 b 的第一个元素等于 1
            assert_array_equal(b[0], 1)


# 使用参数化测试,测试 long double 类型从整数转换
@pytest.mark.parametrize("int_val", [
    # 讨论 gh-10723 和 gh-9968 中的案例
    2 ** 1024, 0])
def test_longdouble_from_int(int_val):
    # 对于问题 gh-9968
    # 将整数 int_val 转换为字符串 str_val
    str_val = str(int_val)
    # 对于大整数输入,在具有与 np.double 等效的 np.longdouble 平台上,我们期望 RuntimeWarning
    # 我们期望在具有 np.longdouble 等效于 np.double 的平台上看到 RuntimeWarning
    # 创建一个字符串表示时可能会有精度损失的情况
    # 使用 `warnings.catch_warnings` 上下文管理器捕获所有警告
    with warnings.catch_warnings(record=True) as w:
        # 设置警告过滤器,始终捕获 RuntimeWarning 类型的警告
        warnings.filterwarnings('always', '', RuntimeWarning)
        
        # 断言:某些平台上 np.longdouble(int_val) == np.longdouble(str_val) 可能为 True
        assert np.longdouble(int_val) == np.longdouble(str_val)
        
        # 检查是否可以在所有平台上直接比较 int 和最大 longdouble 值
        if np.allclose(np.finfo(np.longdouble).max,
                       np.finfo(np.double).max) and w:
            # 断言:如果条件成立且有警告产生,则确认第一个警告的类别为 RuntimeWarning
            assert w[0].category is RuntimeWarning
# 使用 pytest 的 @pytest.mark.parametrize 装饰器,用于多次运行 test_longdouble_from_bool 函数
@pytest.mark.parametrize("bool_val", [
    True, False])
def test_longdouble_from_bool(bool_val):
    # 断言对于 np.longdouble 类型,将布尔值转换为长双精度数应该等于将布尔值转换为整数后再转换为长双精度数
    assert np.longdouble(bool_val) == np.longdouble(int(bool_val))


# 使用 pytest 的 @pytest.mark.skipif 装饰器,条件不满足时跳过测试
@pytest.mark.skipif(
    not (IS_MUSL and platform.machine() == "x86_64"),
    reason="only need to run on musllinux_x86_64"
)
def test_musllinux_x86_64_signature():
    # 如果在非 musllinux_x86_64 架构上模拟该测试可能会失败,但在本地运行应该通过
    known_sigs = [b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf']
    sig = (np.longdouble(-1.0) / np.longdouble(10.0))
    # 将 sig 转换为小端字节序,并取其前 10 字节
    sig = sig.view(sig.dtype.newbyteorder('<')).tobytes()[:10]
    # 断言 sig 存在于已知签名列表中
    assert sig in known_sigs


# 检查 np.longdouble 类型的机器精度 eps 是否为正值
def test_eps_positive():
    # np.finfo(np.longdouble).eps 应在所有平台上为正值。如果不是,则可能 MachArLike 出了问题,
    # 比如 np._core.getlimits._discovered_machar 没有正常工作
    assert np.finfo(np.longdouble).eps > 0.

.\numpy\numpy\_core\tests\test_machar.py

"""
Test machar. Given recent changes to hardcode type data, we might want to get
rid of both MachAr and this test at some point.

"""
# 从numpy._core._machar模块中导入MachAr类
from numpy._core._machar import MachAr
# 导入numpy._core.numerictypes模块,命名为ntypes
import numpy._core.numerictypes as ntypes
# 从numpy模块中导入errstate和array函数
from numpy import errstate, array

# 定义一个测试类TestMachAr
class TestMachAr:
    # 定义一个私有方法_run_machar_highprec
    def _run_machar_highprec(self):
        # 尝试使用足够高精度的数据类型(ntypes.float96)实例化MachAr对象,
        # 可能会引起下溢(underflow)
        try:
            # 设置hiprec为ntypes.float96
            hiprec = ntypes.float96
            # 实例化MachAr对象,使用lambda函数和array函数处理数据
            MachAr(lambda v: array(v, hiprec))
        except AttributeError:
            # 如果没有找到ntypes.float96属性,则输出相应的跳过测试信息
            "Skipping test: no ntypes.float96 available on this platform."

    # 定义一个测试方法test_underlow
    def test_underlow(self):
        # 回归测试#759:
        # 对于dtype = np.float96,实例化MachAr会引发虚假警告。
        # 使用errstate上下文管理器,设置所有错误都抛出异常
        with errstate(all='raise'):
            try:
                # 调用私有方法_run_machar_highprec
                self._run_machar_highprec()
            except FloatingPointError as e:
                # 捕获FloatingPointError异常,如果被抛出则输出错误信息
                msg = "Caught %s exception, should not have been raised." % e
                # 抛出断言异常,包含错误信息msg
                raise AssertionError(msg)

.\numpy\numpy\_core\tests\test_memmap.py

import sys
import os
import mmap
import pytest
from pathlib import Path
from tempfile import NamedTemporaryFile, TemporaryFile

from numpy import (
    memmap, sum, average, prod, ndarray, isscalar, add, subtract, multiply)

from numpy import arange, allclose, asarray
from numpy.testing import (
    assert_, assert_equal, assert_array_equal, suppress_warnings, IS_PYPY,
    break_cycles
    )

class TestMemmap:
    def setup_method(self):
        # 创建一个临时文件对象,用于测试
        self.tmpfp = NamedTemporaryFile(prefix='mmap')
        # 设置数据形状和类型
        self.shape = (3, 4)
        self.dtype = 'float32'
        # 创建一个数据数组,并调整形状
        self.data = arange(12, dtype=self.dtype)
        self.data.resize(self.shape)

    def teardown_method(self):
        # 关闭临时文件对象
        self.tmpfp.close()
        self.data = None
        # 如果运行环境是 PyPy,调用 break_cycles 两次以确保释放所有资源
        if IS_PYPY:
            break_cycles()
            break_cycles()

    def test_roundtrip(self):
        # 将数据写入文件
        fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+',
                    shape=self.shape)
        fp[:] = self.data[:]
        del fp  # 测试 __del__ 机制,处理清理工作

        # 从文件中读取数据
        newfp = memmap(self.tmpfp, dtype=self.dtype, mode='r',
                       shape=self.shape)
        # 断言数据相似性
        assert_(allclose(self.data, newfp))
        # 断言数组相等性
        assert_array_equal(self.data, newfp)
        # 断言新文件对象不可写
        assert_equal(newfp.flags.writeable, False)

    def test_open_with_filename(self, tmp_path):
        # 在临时目录下创建文件名为 'mmap' 的 memmap 对象
        tmpname = tmp_path / 'mmap'
        fp = memmap(tmpname, dtype=self.dtype, mode='w+',
                       shape=self.shape)
        fp[:] = self.data[:]
        del fp

    def test_unnamed_file(self):
        # 使用 TemporaryFile 创建未命名文件对象
        with TemporaryFile() as f:
            fp = memmap(f, dtype=self.dtype, shape=self.shape)
            del fp

    def test_attributes(self):
        # 设置偏移量和模式
        offset = 1
        mode = "w+"
        # 创建 memmap 对象,指定偏移量和模式
        fp = memmap(self.tmpfp, dtype=self.dtype, mode=mode,
                    shape=self.shape, offset=offset)
        # 断言偏移量和模式正确
        assert_equal(offset, fp.offset)
        assert_equal(mode, fp.mode)
        del fp

    def test_filename(self, tmp_path):
        # 在临时目录下创建文件名为 'mmap' 的 memmap 对象
        tmpname = tmp_path / "mmap"
        fp = memmap(tmpname, dtype=self.dtype, mode='w+',
                       shape=self.shape)
        # 获取绝对路径并进行断言
        abspath = Path(os.path.abspath(tmpname))
        fp[:] = self.data[:]
        assert_equal(abspath, fp.filename)
        b = fp[:1]
        assert_equal(abspath, b.filename)
        del b
        del fp

    def test_path(self, tmp_path):
        # 在临时目录下创建文件名为 'mmap' 的 memmap 对象
        tmpname = tmp_path / "mmap"
        fp = memmap(Path(tmpname), dtype=self.dtype, mode='w+',
                       shape=self.shape)
        # 获取绝对路径并进行断言,使用 Path.resolve 以解决可能存在的符号链接问题
        abspath = str(Path(tmpname).resolve())
        fp[:] = self.data[:]
        assert_equal(abspath, str(fp.filename.resolve()))
        b = fp[:1]
        assert_equal(abspath, str(b.filename.resolve()))
        del b
        del fp


这些注释详细解释了每行代码的作用和意图,确保每个函数和方法的功能清晰可理解。
    # 定义一个测试函数,用于测试 memmap 对象的 filename 属性是否正确返回文件名
    def test_filename_fileobj(self):
        # 创建一个 memmap 对象,以写入模式打开,并使用指定的数据类型和形状
        fp = memmap(self.tmpfp, dtype=self.dtype, mode="w+", shape=self.shape)
        # 断言 memmap 对象的 filename 属性是否与临时文件对象的名称相同
        assert_equal(fp.filename, self.tmpfp.name)

    # 标记为跳过测试,如果系统平台为 'gnu0',原因是它已知在 hurd 上会失败
    @pytest.mark.skipif(sys.platform == 'gnu0', reason="Known to fail on hurd")
    def test_flush(self):
        # 创建一个 memmap 对象,以写入模式打开,并使用指定的数据类型和形状
        fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape)
        # 将数据复制到 memmap 对象中
        fp[:] = self.data[:]
        # 断言 memmap 对象中的第一个元素是否与给定数据的第一个元素相同
        assert_equal(fp[0], self.data[0])
        # 刷新 memmap 对象
        fp.flush()

    # 测试删除操作,确保视图不会删除底层的 mmap
    def test_del(self):
        # 创建一个 memmap 对象作为基础对象,以写入模式打开,并使用指定的数据类型和形状
        fp_base = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape)
        # 修改基础对象的第一个元素的值
        fp_base[0] = 5
        # 创建基础对象的视图
        fp_view = fp_base[0:1]
        # 断言视图对象的第一个元素的值与预期相同
        assert_equal(fp_view[0], 5)
        # 删除视图对象
        del fp_view
        # 在删除视图后仍然可以访问和赋值基础对象的元素
        assert_equal(fp_base[0], 5)
        fp_base[0] = 6
        assert_equal(fp_base[0], 6)

    # 测试算术操作是否会丢弃引用
    def test_arithmetic_drops_references(self):
        # 创建一个 memmap 对象,以写入模式打开,并使用指定的数据类型和形状
        fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape)
        # 对 memmap 对象执行加法操作
        tmp = (fp + 10)
        # 如果结果是 memmap 类型的对象,断言其底层 mmap 对象不是同一个引用
        if isinstance(tmp, memmap):
            assert_(tmp._mmap is not fp._mmap)

    # 测试索引操作是否会丢弃引用
    def test_indexing_drops_references(self):
        # 创建一个 memmap 对象,以写入模式打开,并使用指定的数据类型和形状
        fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape)
        # 对 memmap 对象执行索引操作
        tmp = fp[(1, 2), (2, 3)]
        # 如果结果是 memmap 类型的对象,断言其底层 mmap 对象不是同一个引用
        if isinstance(tmp, memmap):
            assert_(tmp._mmap is not fp._mmap)

    # 测试切片操作是否会保持引用
    def test_slicing_keeps_references(self):
        # 创建一个 memmap 对象,以写入模式打开,并使用指定的数据类型和形状
        fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape)
        # 断言 memmap 对象的切片操作后的 _mmap 属性与原对象的 _mmap 属性是同一个引用
        assert_(fp[:2, :2]._mmap is fp._mmap)

    # 测试视图创建
    def test_view(self):
        # 创建一个 memmap 对象,使用指定的数据类型和形状
        fp = memmap(self.tmpfp, dtype=self.dtype, shape=self.shape)
        # 创建 memmap 对象的视图
        new1 = fp.view()
        new2 = new1.view()
        # 断言新视图对象的 base 属性指向原始 memmap 对象
        assert_(new1.base is fp)
        assert_(new2.base is fp)
        # 使用 asarray 函数创建一个新的数组
        new_array = asarray(fp)
        # 断言新数组对象的 base 属性指向原始 memmap 对象
        assert_(new_array.base is fp)

    # 测试 ufunc 返回 ndarray
    def test_ufunc_return_ndarray(self):
        # 创建一个 memmap 对象,使用指定的数据类型和形状
        fp = memmap(self.tmpfp, dtype=self.dtype, shape=self.shape)
        # 将数据复制到 memmap 对象中
        fp[:] = self.data

        # 忽略特定的警告
        with suppress_warnings() as sup:
            sup.filter(FutureWarning, "np.average currently does not preserve")
            # 对于一元操作,如 sum, average, prod
            for unary_op in [sum, average, prod]:
                # 对 memmap 对象执行一元操作
                result = unary_op(fp)
                # 断言结果是标量
                assert_(isscalar(result))
                # 断言结果的类型与数据的第一个元素的类型相同
                assert_(result.__class__ is self.data[0, 0].__class__)

                # 对 memmap 对象沿着轴执行一元操作
                assert_(unary_op(fp, axis=0).__class__ is ndarray)
                assert_(unary_op(fp, axis=1).__class__ is ndarray)

        # 对于二元操作,如 add, subtract, multiply
        for binary_op in [add, subtract, multiply]:
            assert_(binary_op(fp, self.data).__class__ is ndarray)
            assert_(binary_op(self.data, fp).__class__ is ndarray)
            assert_(binary_op(fp, fp).__class__ is ndarray)

        # 在原 memmap 对象上执行加法操作
        fp += 1
        # 断言对象仍然是 memmap 类型
        assert(fp.__class__ is memmap)
        # 使用 add 函数在原 memmap 对象上执行加法操作
        add(fp, 1, out=fp)
        # 断言对象仍然是 memmap 类型
        assert(fp.__class__ is memmap)
    def test_getitem(self):
        fp = memmap(self.tmpfp, dtype=self.dtype, shape=self.shape)
        fp[:] = self.data

        assert_(fp[1:, :-1].__class__ is memmap)
        # 使用切片索引返回的对象仍然是 memmap 类型的实例
        assert_(fp[[0, 1]].__class__ is ndarray)
        # 使用花式索引返回的对象是 ndarray 类型的实例

    def test_memmap_subclass(self):
        class MemmapSubClass(memmap):
            pass

        fp = MemmapSubClass(self.tmpfp, dtype=self.dtype, shape=self.shape)
        fp[:] = self.data

        # 对于 memmap 的子类,保持之前的行为,即 ufunc 和 __getitem__ 的输出不会转换为 ndarray 类型
        assert_(sum(fp, axis=0).__class__ is MemmapSubClass)
        assert_(sum(fp).__class__ is MemmapSubClass)
        assert_(fp[1:, :-1].__class__ is MemmapSubClass)
        assert(fp[[0, 1]].__class__ is MemmapSubClass)

    def test_mmap_offset_greater_than_allocation_granularity(self):
        size = 5 * mmap.ALLOCATIONGRANULARITY
        offset = mmap.ALLOCATIONGRANULARITY + 1
        fp = memmap(self.tmpfp, shape=size, mode='w+', offset=offset)
        assert_(fp.offset == offset)
        # 确保 memmap 对象的偏移量与预期一致

    def test_no_shape(self):
        self.tmpfp.write(b'a'*16)
        mm = memmap(self.tmpfp, dtype='float64')
        assert_equal(mm.shape, (2,))
        # 在没有明确指定形状的情况下,默认形状为 (2,)

    def test_empty_array(self):
        # gh-12653
        with pytest.raises(ValueError, match='empty file'):
            memmap(self.tmpfp, shape=(0,4), mode='w+')

        self.tmpfp.write(b'\0')

        # 现在文件不再为空
        memmap(self.tmpfp, shape=(0,4), mode='w+')
        # 创建形状为 (0, 4) 的 memmap 对象,不会触发异常

    def test_shape_type(self):
        memmap(self.tmpfp, shape=3, mode='w+')
        memmap(self.tmpfp, shape=self.shape, mode='w+')
        memmap(self.tmpfp, shape=list(self.shape), mode='w+')
        memmap(self.tmpfp, shape=asarray(self.shape), mode='w+')
        # 测试不同形状参数类型下创建 memmap 对象的行为

.\numpy\numpy\_core\tests\test_mem_overlap.py

import itertools  # 导入 itertools 模块,用于生成迭代器的工具函数
import pytest  # 导入 pytest 模块,用于编写和运行测试用例

import numpy as np  # 导入 NumPy 库,并将其命名为 np
from numpy._core._multiarray_tests import solve_diophantine, internal_overlap  # 导入 NumPy 内部的函数和类
from numpy._core import _umath_tests  # 导入 NumPy 内部的数学测试函数
from numpy.lib.stride_tricks import as_strided  # 导入 NumPy 的 as_strided 函数
from numpy.testing import (  # 导入 NumPy 测试模块中的一些断言函数
    assert_, assert_raises, assert_equal, assert_array_equal
    )

ndims = 2  # 定义维度数量为 2
size = 10  # 定义数组的大小为 10
shape = tuple([size] * ndims)  # 创建一个形状为 (10, 10) 的元组

MAY_SHARE_BOUNDS = 0  # 定义常量 MAY_SHARE_BOUNDS 为 0
MAY_SHARE_EXACT = -1  # 定义常量 MAY_SHARE_EXACT 为 -1


def _indices_for_nelems(nelems):
    """Returns slices of length nelems, from start onwards, in direction sign."""
    # 如果 nelems 为 0,则返回一个包含 size // 2 的整数索引的列表
    if nelems == 0:
        return [size // 2]  # int index

    res = []
    # 遍历步长为 1 和 2,符号为 -1 和 1 的组合
    for step in (1, 2):
        for sign in (-1, 1):
            start = size // 2 - nelems * step * sign // 2
            stop = start + nelems * step * sign
            res.append(slice(start, stop, step * sign))

    return res  # 返回生成的切片列表


def _indices_for_axis():
    """Returns (src, dst) pairs of indices."""
    res = []
    # 遍历不同的 nelems 值,生成对应的索引切片组合
    for nelems in (0, 2, 3):
        ind = _indices_for_nelems(nelems)
        res.extend(itertools.product(ind, ind))  # 使用 itertools.product 生成所有 nelems 大小的切片组合

    return res  # 返回生成的 (src, dst) 索引对列表


def _indices(ndims):
    """Returns ((axis0_src, axis0_dst), (axis1_src, axis1_dst), ... ) index pairs."""
    ind = _indices_for_axis()
    return itertools.product(ind, repeat=ndims)  # 使用 itertools.product 生成指定维度的索引对组合


def _check_assignment(srcidx, dstidx):
    """Check assignment arr[dstidx] = arr[srcidx] works."""
    arr = np.arange(np.prod(shape)).reshape(shape)  # 创建一个形状为 shape 的 NumPy 数组,填充为按序排列的元素

    cpy = arr.copy()  # 复制原始数组 arr

    cpy[dstidx] = arr[srcidx]  # 将 arr[srcidx] 的值复制到 cpy[dstidx]
    arr[dstidx] = arr[srcidx]  # 将 arr[srcidx] 的值赋给 arr[dstidx]

    assert_(np.all(arr == cpy),  # 使用 NumPy 的 assert_ 函数检查 arr 是否等于 cpy
            'assigning arr[%s] = arr[%s]' % (dstidx, srcidx))  # 如果不等则输出错误信息


def test_overlapping_assignments():
    # Test automatically generated assignments which overlap in memory.
    inds = _indices(ndims)  # 生成 ndims 维度的所有索引对组合

    for ind in inds:
        srcidx = tuple([a[0] for a in ind])  # 获取源索引 srcidx
        dstidx = tuple([a[1] for a in ind])  # 获取目标索引 dstidx

        _check_assignment(srcidx, dstidx)  # 调用 _check_assignment 函数进行赋值检查


@pytest.mark.slow  # 用 pytest.mark.slow 标记这是一个较慢的测试用例
def test_diophantine_fuzz():
    # Fuzz test the diophantine solver
    rng = np.random.RandomState(1234)  # 使用种子为 1234 的随机状态生成器

    max_int = np.iinfo(np.intp).max  # 获取 NumPy 中 np.intp 类型的最大整数值
    # 对于每个维度从0到9循环
    for ndim in range(10):
        # 可行解计数器和不可行解计数器初始化为0
        feasible_count = 0
        infeasible_count = 0

        # 计算最小计数,确保在小整数问题和大整数问题之间平衡
        min_count = 500 // (ndim + 1)

        # 当可行解计数器和不可行解计数器中的较小值小于最小计数时继续循环
        while min(feasible_count, infeasible_count) < min_count:
            # 确保大整数和小整数问题
            A_max = 1 + rng.randint(0, 11, dtype=np.intp)**6
            U_max = rng.randint(0, 11, dtype=np.intp)**6

            # 将A_max和U_max限制在max_int的范围内
            A_max = min(max_int, A_max)
            U_max = min(max_int - 1, U_max)

            # 生成长度为ndim的A和U元组,元素为随机整数
            A = tuple(int(rng.randint(1, A_max + 1, dtype=np.intp))
                      for j in range(ndim))
            U = tuple(int(rng.randint(0, U_max + 2, dtype=np.intp))
                      for j in range(ndim))

            # 计算b_ub作为A和U的线性组合的和,限制在max_int-2内
            b_ub = min(max_int - 2, sum(a * ub for a, ub in zip(A, U)))
            # 生成b作为介于-1和b_ub+2之间的随机整数
            b = int(rng.randint(-1, b_ub + 2, dtype=np.intp))

            # 如果ndim为0且可行解计数器小于最小计数,则强制b为0
            if ndim == 0 and feasible_count < min_count:
                b = 0

            # 解决给定A、U、b的丢番图方程,返回解X
            X = solve_diophantine(A, U, b)

            # 如果无解X
            if X is None:
                # 检查简化的决策问题是否一致
                X_simplified = solve_diophantine(A, U, b, simplify=1)
                assert_(X_simplified is None, (A, U, b, X_simplified))

                # 检查不存在解(前提是问题足够小,暴力检查不会花费太长时间)
                ranges = tuple(range(0, a * ub + 1, a) for a, ub in zip(A, U))

                size = 1
                for r in ranges:
                    size *= len(r)
                # 如果问题规模小于100000,检查是否存在任何解满足和为b
                if size < 100000:
                    assert_(not any(sum(w) == b for w in itertools.product(*ranges)))
                    infeasible_count += 1
            else:
                # 检查简化的决策问题是否一致
                X_simplified = solve_diophantine(A, U, b, simplify=1)
                assert_(X_simplified is not None, (A, U, b, X_simplified))

                # 检查解的有效性,确保线性组合的结果等于b
                assert_(sum(a * x for a, x in zip(A, X)) == b)
                # 确保解的每个元素在其对应的上界内
                assert_(all(0 <= x <= ub for x, ub in zip(X, U)))
                feasible_count += 1
# 定义一个测试函数,用于检验整数溢出检测功能
def test_diophantine_overflow():
    # 获取平台下整数指针的最大值
    max_intp = np.iinfo(np.intp).max
    # 获取平台下 int64 类型整数的最大值
    max_int64 = np.iinfo(np.int64).max

    # 检查是否 int64 的最大值小于等于整数指针的最大值
    if max_int64 <= max_intp:
        # 确保算法在内部使用 128 位解决问题;
        # 解决这个问题需要处理大量的中间数值
        A = (max_int64//2, max_int64//2 - 10)
        U = (max_int64//2, max_int64//2 - 10)
        b = 2*(max_int64//2) - 10

        # 断言求解二次丢番图方程的结果为 (1, 1)
        assert_equal(solve_diophantine(A, U, b), (1, 1))


# 检查两个数组是否可能共享内存的确切情况
def check_may_share_memory_exact(a, b):
    # 使用 MAY_SHARE_EXACT 参数检查 a 和 b 是否可能共享内存
    got = np.may_share_memory(a, b, max_work=MAY_SHARE_EXACT)

    # 断言默认参数下的共享内存结果与带界限参数的结果相同
    assert_equal(np.may_share_memory(a, b),
                 np.may_share_memory(a, b, max_work=MAY_SHARE_BOUNDS))

    # 修改数组 a 和 b 的内容
    a.fill(0)
    b.fill(0)
    a.fill(1)
    # 确定数组 b 是否有任何非零元素
    exact = b.any()

    # 如果共享内存的结果与实际情况不符,则记录错误消息
    err_msg = ""
    if got != exact:
        err_msg = "    " + "\n    ".join([
            "base_a - base_b = %r" % (a.__array_interface__['data'][0] - b.__array_interface__['data'][0],),
            "shape_a = %r" % (a.shape,),
            "shape_b = %r" % (b.shape,),
            "strides_a = %r" % (a.strides,),
            "strides_b = %r" % (b.strides,),
            "size_a = %r" % (a.size,),
            "size_b = %r" % (b.size,)
        ])

    # 断言得到的共享内存结果与预期结果一致
    assert_equal(got, exact, err_msg=err_msg)


# 手动测试 may_share_memory 函数的测试用例
def test_may_share_memory_manual():
    # 基础数组
    xs0 = [
        np.zeros([13, 21, 23, 22], dtype=np.int8),
        np.zeros([13, 21, 23*2, 22], dtype=np.int8)[:,:,::2,:]
    ]

    # 生成所有负步幅组合
    xs = []
    for x in xs0:
        for ss in itertools.product(*(([slice(None), slice(None, None, -1)],)*4)):
            xp = x[ss]
            xs.append(xp)

    for x in xs:
        # 默认情况下简单检查范围是否重叠
        assert_(np.may_share_memory(x[:,0,:], x[:,1,:]))
        assert_(np.may_share_memory(x[:,0,:], x[:,1,:], max_work=None))

        # 确切检查
        check_may_share_memory_exact(x[:,0,:], x[:,1,:])
        check_may_share_memory_exact(x[:,::7], x[:,3::3])

        try:
            xp = x.ravel()
            if xp.flags.owndata:
                continue
            xp = xp.view(np.int16)
        except ValueError:
            continue

        # 0 大小的数组不可能重叠
        check_may_share_memory_exact(x.ravel()[6:6],
                                     xp.reshape(13, 21, 23, 11)[:,::7])

        # 测试项目大小处理情况
        check_may_share_memory_exact(x[:,::7],
                                     xp.reshape(13, 21, 23, 11))
        check_may_share_memory_exact(x[:,::7],
                                     xp.reshape(13, 21, 23, 11)[:,3::3])
        check_may_share_memory_exact(x.ravel()[6:7],
                                     xp.reshape(13, 21, 23, 11)[:,::7])

    # 检查单位大小
    x = np.zeros([1], dtype=np.int8)
    check_may_share_memory_exact(x, x)
    check_may_share_memory_exact(x, x.copy())
# 定义函数 iter_random_view_pairs,用于生成随机视图对
def iter_random_view_pairs(x, same_steps=True, equal_size=False):
    # 使用种子 1234 初始化随机数生成器
    rng = np.random.RandomState(1234)

    # 如果 equal_size 和 same_steps 同时为 True,则抛出 ValueError 异常
    if equal_size and same_steps:
        raise ValueError()

    # 定义生成随机切片的函数 random_slice
    def random_slice(n, step):
        # 随机生成起始位置 start 和终止位置 stop
        start = rng.randint(0, n+1, dtype=np.intp)
        stop = rng.randint(start, n+1, dtype=np.intp)
        # 随机决定是否反向切片
        if rng.randint(0, 2, dtype=np.intp) == 0:
            stop, start = start, stop
            step *= -1
        return slice(start, stop, step)

    # 定义生成固定大小随机切片的函数 random_slice_fixed_size
    def random_slice_fixed_size(n, step, size):
        # 随机生成起始位置 start 和终止位置 stop
        start = rng.randint(0, n+1 - size*step)
        stop = start + (size-1)*step + 1
        # 随机决定是否反向切片
        if rng.randint(0, 2) == 0:
            stop, start = start-1, stop-1
            if stop < 0:
                stop = None
            step *= -1
        return slice(start, stop, step)

    # 首先生成一些常规视图对
    # 返回原始数组 x 与自身的视图
    yield x, x
    # 循环生成一些特定偏移量 j 的视图对
    for j in range(1, 7, 3):
        yield x[j:], x[:-j]
        yield x[...,j:], x[...,:-j]

    # 生成一个具有零步长内部重叠的数组视图对
    strides = list(x.strides)
    strides[0] = 0
    xp = as_strided(x, shape=x.shape, strides=strides)
    yield x, xp
    yield xp, xp

    # 生成一个具有非零步长内部重叠的数组视图对
    strides = list(x.strides)
    if strides[0] > 1:
        strides[0] = 1
    xp = as_strided(x, shape=x.shape, strides=strides)
    yield x, xp
    yield xp, xp

    # 然后生成不连续的视图对
    while True:
        # 随机生成各维度的步长 steps
        steps = tuple(rng.randint(1, 11, dtype=np.intp)
                      if rng.randint(0, 5, dtype=np.intp) == 0 else 1
                      for j in range(x.ndim))
        # 随机生成一个切片 s1
        s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps))

        # 随机打乱维度顺序 t1
        t1 = np.arange(x.ndim)
        rng.shuffle(t1)

        # 如果 equal_size 为 True,则 t2 与 t1 相同;否则重新随机排序维度
        if equal_size:
            t2 = t1
        else:
            t2 = np.arange(x.ndim)
            rng.shuffle(t2)

        # 取出切片 s1 对应的子数组 a
        a = x[s1]

        # 根据条件生成切片 s2
        if equal_size:
            if a.size == 0:
                continue
            steps2 = tuple(rng.randint(1, max(2, p//(1+pa)))
                           if rng.randint(0, 5) == 0 else 1
                           for p, s, pa in zip(x.shape, s1, a.shape))
            s2 = tuple(random_slice_fixed_size(p, s, pa)
                       for p, s, pa in zip(x.shape, steps2, a.shape))
        elif same_steps:
            steps2 = steps
        else:
            steps2 = tuple(rng.randint(1, 11, dtype=np.intp)
                           if rng.randint(0, 5, dtype=np.intp) == 0 else 1
                           for j in range(x.ndim))

        # 如果 equal_size 为 False,则重新生成切片 s2
        if not equal_size:
            s2 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps2))

        # 对子数组 a 和 b 进行维度重排
        a = a.transpose(t1)
        b = x[s2].transpose(t2)

        # 生成视图对 (a, b)
        yield a, b


# 定义函数 check_may_share_memory_easy_fuzz,用于检查具有通用步长的重叠问题
def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count):
    # 创建一个形状为 [17, 34, 71, 97] 的全零数组 x
    x = np.zeros([17,34,71,97], dtype=np.int16)

    # 初始化可行和不可行的计数器
    feasible = 0
    infeasible = 0

    # 生成 x 的随机视图对的迭代器 pair_iter
    pair_iter = iter_random_view_pairs(x, same_steps)
    # 当 feasible 和 infeasible 中的最小值小于 min_count 时循环执行以下操作
    while min(feasible, infeasible) < min_count:
        # 从 pair_iter 中获取下一对数据 a 和 b
        a, b = next(pair_iter)

        # 检查 a 和 b 是否共享内存,返回布尔值
        bounds_overlap = np.may_share_memory(a, b)
        
        # 检查 a 和 b 是否共享内存,返回布尔值
        may_share_answer = np.may_share_memory(a, b)
        
        # 检查 a 和 b 是否共享内存,返回布尔值,考虑到最大工作量
        easy_answer = np.may_share_memory(a, b, max_work=get_max_work(a, b))
        
        # 检查 a 和 b 是否共享内存,返回布尔值,使用精确的共享内存策略
        exact_answer = np.may_share_memory(a, b, max_work=MAY_SHARE_EXACT)

        # 如果简易答案与精确答案不同,触发断言错误
        if easy_answer != exact_answer:
            # assert_equal 操作较慢,用于验证 easy_answer 和 exact_answer 相等
            assert_equal(easy_answer, exact_answer)

        # 如果 may_share_answer 与 bounds_overlap 不同,触发断言错误
        if may_share_answer != bounds_overlap:
            assert_equal(may_share_answer, bounds_overlap)

        # 如果 bounds_overlap 为 True
        if bounds_overlap:
            # 如果 exact_answer 为 True,增加 feasible 计数
            if exact_answer:
                feasible += 1
            # 否则,增加 infeasible 计数
            else:
                infeasible += 1
@pytest.mark.slow
def test_may_share_memory_easy_fuzz():
    # 检查使用常见步长时,重叠问题是否总是可以用较少的工作解决

    # 调用检查函数,设定最大工作量为1,同步步长,最小计数为2000
    check_may_share_memory_easy_fuzz(get_max_work=lambda a, b: 1,
                                     same_steps=True,
                                     min_count=2000)


@pytest.mark.slow
def test_may_share_memory_harder_fuzz():
    # 对于不一定有共同步长的重叠问题,需要更多的工作量
    #
    # 下面的工作上限无法减少太多。更难的问题也可能存在,但不会在这里检测到,因为问题集来自RNG(随机数生成器)。

    # 调用检查函数,设定最大工作量为数组大小的一半,非同步步长,最小计数为2000
    check_may_share_memory_easy_fuzz(get_max_work=lambda a, b: max(a.size, b.size)//2,
                                     same_steps=False,
                                     min_count=2000)


def test_shares_memory_api():
    x = np.zeros([4, 5, 6], dtype=np.int8)

    # 检查数组是否共享内存
    assert_equal(np.shares_memory(x, x), True)
    assert_equal(np.shares_memory(x, x.copy()), False)

    # 创建切片a和b,检查它们是否共享内存
    a = x[:,::2,::3]
    b = x[:,::3,::2]
    assert_equal(np.shares_memory(a, b), True)
    assert_equal(np.shares_memory(a, b, max_work=None), True)
    
    # 断言引发异常,检查最大工作量设置是否正常
    assert_raises(
        np.exceptions.TooHardError, np.shares_memory, a, b, max_work=1
    )


def test_may_share_memory_bad_max_work():
    x = np.zeros([1])
    
    # 断言引发溢出错误,检查最大工作量设置是否正常
    assert_raises(OverflowError, np.may_share_memory, x, x, max_work=10**100)
    assert_raises(OverflowError, np.shares_memory, x, x, max_work=10**100)


def test_internal_overlap_diophantine():
    def check(A, U, exists=None):
        X = solve_diophantine(A, U, 0, require_ub_nontrivial=1)

        if exists is None:
            exists = (X is not None)

        if X is not None:
            # 断言检查解是否符合特定条件
            assert_(sum(a*x for a, x in zip(A, X)) == sum(a*u//2 for a, u in zip(A, U)))
            assert_(all(0 <= x <= u for x, u in zip(X, U)))
            assert_(any(x != u//2 for x, u in zip(X, U)))

        if exists:
            assert_(X is not None, repr(X))
        else:
            assert_(X is None, repr(X))

    # Smoke tests
    # 调用check函数进行烟雾测试,确保特定输入条件下函数正常工作
    check((3, 2), (2*2, 3*2), exists=True)
    check((3*2, 2), (15*2, (3-1)*2), exists=False)


def test_internal_overlap_slices():
    # 切片数组永远不会生成内部重叠

    x = np.zeros([17,34,71,97], dtype=np.int16)

    rng = np.random.RandomState(1234)

    def random_slice(n, step):
        start = rng.randint(0, n+1, dtype=np.intp)
        stop = rng.randint(start, n+1, dtype=np.intp)
        if rng.randint(0, 2, dtype=np.intp) == 0:
            stop, start = start, stop
            step *= -1
        return slice(start, stop, step)

    cases = 0
    min_count = 5000
    # 在达到最小计数之前循环执行以下操作
    while cases < min_count:
        # 生成一个元组 `steps`,其中每个元素是在指定范围内随机选择的步长值或者固定值 1
        steps = tuple(rng.randint(1, 11, dtype=np.intp)
                      if rng.randint(0, 5, dtype=np.intp) == 0 else 1
                      for j in range(x.ndim))
        
        # 创建一个长度等于 `x` 的维度数的数组 `t1`,其中包含从 0 到 `x.ndim-1` 的整数
        t1 = np.arange(x.ndim)
        
        # 对数组 `t1` 进行随机重排列
        rng.shuffle(t1)
        
        # 根据 `x` 的形状和步长 `steps` 生成一个元组 `s1`,其中每个元素是随机切片对象
        s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps))
        
        # 根据切片 `s1` 从数组 `x` 中获取数据,并根据 `t1` 的顺序进行转置,得到数组 `a`
        a = x[s1].transpose(t1)
        
        # 断言确保数组 `a` 中不存在内部重叠
        assert_(not internal_overlap(a))
        
        # 增加计数器 `cases` 的值
        cases += 1
# 检查输入数组是否存在内部重叠
def check_internal_overlap(a, manual_expected=None):
    # 调用内部函数计算得到数组的内部重叠情况
    got = internal_overlap(a)

    # 使用暴力方法进行检查
    m = set()
    # 生成各维度的范围
    ranges = tuple(range(n) for n in a.shape)
    # 遍历数组所有可能的索引组合
    for v in itertools.product(*ranges):
        # 计算偏移量
        offset = sum(s*w for s, w in zip(a.strides, v))
        # 如果偏移量已经存在于集合中,则表示存在重叠
        if offset in m:
            expected = True
            break
        else:
            m.add(offset)
    else:
        expected = False

    # 比较实际结果和预期结果
    if got != expected:
        # 使用断言检查结果是否相等,如果不相等则会抛出异常
        assert_equal(got, expected, err_msg=repr((a.strides, a.shape)))
    # 如果手动预期结果不为None且与计算得到的结果不一致,则使用断言检查
    if manual_expected is not None and expected != manual_expected:
        assert_equal(expected, manual_expected)
    # 返回计算得到的内部重叠结果
    return got


def test_internal_overlap_manual():
    # Stride tricks可以构建具有内部重叠的数组

    # 我们不关心内存边界,数组不是读/写访问
    x = np.arange(1).astype(np.int8)

    # 检查低维特殊情况

    # 检查一维情况
    check_internal_overlap(x, False)
    # 检查零维情况
    check_internal_overlap(x.reshape([]), False)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(3, 4), shape=(4, 4))
    check_internal_overlap(a, False)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(3, 4), shape=(5, 4))
    check_internal_overlap(a, True)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(0,), shape=(0,))
    check_internal_overlap(a, False)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(0,), shape=(1,))
    check_internal_overlap(a, False)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(0,), shape=(2,))
    check_internal_overlap(a, True)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(0, -9993), shape=(87, 22))
    check_internal_overlap(a, True)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(0, -9993), shape=(1, 22))
    check_internal_overlap(a, False)

    # 使用指定步长和形状创建数组
    a = as_strided(x, strides=(0, -9993), shape=(0, 22))
    check_internal_overlap(a, False)


def test_internal_overlap_fuzz():
    # 模糊测试;暴力检查速度较慢

    x = np.arange(1).astype(np.int8)

    overlap = 0
    no_overlap = 0
    min_count = 100

    rng = np.random.RandomState(1234)

    while min(overlap, no_overlap) < min_count:
        # 随机生成数组的维度和步长
        ndim = rng.randint(1, 4, dtype=np.intp)
        strides = tuple(rng.randint(-1000, 1000, dtype=np.intp)
                        for j in range(ndim))
        shape = tuple(rng.randint(1, 30, dtype=np.intp)
                      for j in range(ndim))

        # 使用指定步长和形状创建数组
        a = as_strided(x, strides=strides, shape=shape)
        # 调用检查函数,获取结果
        result = check_internal_overlap(a)

        # 根据结果增加相应的计数
        if result:
            overlap += 1
        else:
            no_overlap += 1


def test_non_ndarray_inputs():
    # gh-5604的回归检查

    class MyArray:
        def __init__(self, data):
            self.data = data

        @property
        def __array_interface__(self):
            return self.data.__array_interface__

    class MyArray2:
        def __init__(self, data):
            self.data = data

        def __array__(self, dtype=None, copy=None):
            return self.data
    # 遍历包含 MyArray 和 MyArray2 两个类的列表
    for cls in [MyArray, MyArray2]:
        # 创建一个包含五个元素的 NumPy 数组
        x = np.arange(5)
    
        # 断言:检查 cls(x[::2]) 和 x[1::2] 是否可能共享内存
        assert_(np.may_share_memory(cls(x[::2]), x[1::2]))
        # 断言:检查 cls(x[::2]) 和 x[1::2] 是否确实不共享内存
        assert_(not np.shares_memory(cls(x[::2]), x[1::2]))
    
        # 断言:检查 cls(x[1::3]) 和 x[::2] 是否共享内存
        assert_(np.shares_memory(cls(x[1::3]), x[::2]))
        # 断言:检查 cls(x[1::3]) 和 x[::2] 是否可能共享内存
        assert_(np.may_share_memory(cls(x[1::3]), x[::2]))
# 定义一个函数,用于创建一个视图数组,查看输入数组 `x` 中每个元素的第一个字节
def view_element_first_byte(x):
    # 导入需要的模块
    from numpy.lib._stride_tricks_impl import DummyArray
    # 创建一个包含 x 数组接口信息的字典副本
    interface = dict(x.__array_interface__)
    # 设置视图数组的类型字符串为 '|b1',表示每个元素只有一个字节
    interface['typestr'] = '|b1'
    # 设置描述符,每个元素都是一个字节
    interface['descr'] = [('', '|b1')]
    # 使用接口信息创建并返回一个视图数组,该数组查看了 x 的每个元素的第一个字节
    return np.asarray(DummyArray(interface, x))


# 定义一个函数,验证操作 operation(*args, out=out) 和 out[...] = operation(*args, out=out.copy()) 的等价性
def assert_copy_equivalent(operation, args, out, **kwargs):
    # 设置关键字参数 'out' 为给定的 out
    kwargs['out'] = out
    # 复制 kwargs,并设置其 'out' 参数为 out 的副本
    kwargs2 = dict(kwargs)
    kwargs2['out'] = out.copy()

    # 备份原始的 out 数组
    out_orig = out.copy()
    # 将 out[...] 设置为 operation(*args, **kwargs2) 的结果
    out[...] = operation(*args, **kwargs2)
    # 复制得到预期的结果
    expected = out.copy()
    # 恢复 out 到原始状态
    out[...] = out_orig

    # 调用 operation(*args, **kwargs) 得到实际的结果,并复制该结果
    got = operation(*args, **kwargs).copy()

    # 检查实际结果与预期结果是否有不同的地方,如果有则触发断言错误
    if (got != expected).any():
        assert_equal(got, expected)


# 定义一个测试类 TestUFunc,用于测试 ufunc 调用时的内存重叠处理
class TestUFunc:
    """
    Test ufunc call memory overlap handling
    """
    # 定义一个方法,用于检查一元操作的模糊测试情况
    def check_unary_fuzz(self, operation, get_out_axis_size, dtype=np.int16,
                             count=5000):
        # 定义不同形状的数组维度
        shapes = [7, 13, 8, 21, 29, 32]

        # 创建一个随机数生成器,种子为1234
        rng = np.random.RandomState(1234)

        # 遍历不同维度的数组形状
        for ndim in range(1, 6):
            # 生成随机数组,元素为指定数据类型的随机整数
            x = rng.randint(0, 2**16, size=shapes[:ndim]).astype(dtype)

            # 获取随机视图对的迭代器
            it = iter_random_view_pairs(x, same_steps=False, equal_size=True)

            # 根据维度大小确定最小循环次数
            min_count = count // (ndim + 1)**2

            # 初始化重叠计数
            overlapping = 0
            # 当重叠次数小于最小计数时循环
            while overlapping < min_count:
                # 获取下一对随机视图
                a, b = next(it)

                # 复制原始数组a和b
                a_orig = a.copy()
                b_orig = b.copy()

                # 如果输出轴大小为None
                if get_out_axis_size is None:
                    # 断言通过复制等效执行操作后,输出结果b与a等价
                    assert_copy_equivalent(operation, [a], out=b)

                    # 如果a和b共享内存,则增加重叠计数
                    if np.shares_memory(a, b):
                        overlapping += 1
                else:
                    # 对于每个轴,包括None
                    for axis in itertools.chain(range(ndim), [None]):
                        # 恢复a和b的原始值
                        a[...] = a_orig
                        b[...] = b_orig

                        # 确定减少轴的大小(如果是标量则为None)
                        outsize, scalarize = get_out_axis_size(a, b, axis)
                        # 如果输出大小为'skip',则跳过本次循环
                        if outsize == 'skip':
                            continue

                        # 切片b以获取正确大小的输出数组
                        sl = [slice(None)] * ndim
                        if axis is None:
                            if outsize is None:
                                sl = [slice(0, 1)] + [0]*(ndim - 1)
                            else:
                                sl = [slice(0, outsize)] + [0]*(ndim - 1)
                        else:
                            if outsize is None:
                                k = b.shape[axis]//2
                                if ndim == 1:
                                    sl[axis] = slice(k, k + 1)
                                else:
                                    sl[axis] = k
                            else:
                                assert b.shape[axis] >= outsize
                                sl[axis] = slice(0, outsize)
                        b_out = b[tuple(sl)]

                        # 如果需要标量化,则重塑b_out
                        if scalarize:
                            b_out = b_out.reshape([])

                        # 如果a和b_out共享内存,则增加重叠计数
                        if np.shares_memory(a, b_out):
                            overlapping += 1

                        # 断言通过复制等效执行操作后,输出结果b_out与a等价,对于指定轴axis
                        assert_copy_equivalent(operation, [a], out=b_out, axis=axis)

    # 标记为慢速测试,测试一元ufunc调用的模糊测试
    @pytest.mark.slow
    def test_unary_ufunc_call_fuzz(self):
        # 测试np.invert的一元ufunc调用
        self.check_unary_fuzz(np.invert, None, np.int16)

    # 标记为慢速测试,测试复数型一元ufunc调用的模糊测试
    @pytest.mark.slow
    def test_unary_ufunc_call_complex_fuzz(self):
        # 复数型通常具有比itemsize更小的对齐方式
        # 测试np.negative的复数型一元ufunc调用
        self.check_unary_fuzz(np.negative, None, np.complex128, count=500)
    # 定义一个测试函数 test_binary_ufunc_accumulate_fuzz,用于测试二元通用函数 np.add.accumulate 的模糊测试
    def test_binary_ufunc_accumulate_fuzz(self):
        
        # 定义内部函数 get_out_axis_size,用于确定输出轴的大小
        def get_out_axis_size(a, b, axis):
            # 如果 axis 为 None
            if axis is None:
                # 如果 a 的维度为 1
                if a.ndim == 1:
                    # 返回 a 的大小和 False(表示不跳过)
                    return a.size, False
                else:
                    # 返回 'skip' 和 False,表示跳过该情况(accumulate 不支持多维数组)
                    return 'skip', False  # accumulate doesn't support this
            else:
                # 返回 a 在指定 axis 上的形状和 False(表示不跳过)
                return a.shape[axis], False

        # 调用 self.check_unary_fuzz 方法,测试 np.add.accumulate 的模糊测试,指定 dtype=np.int16 和 count=500
        self.check_unary_fuzz(np.add.accumulate, get_out_axis_size,
                              dtype=np.int16, count=500)

    # 定义一个测试函数 test_binary_ufunc_reduce_fuzz,用于测试二元通用函数 np.add.reduce 的模糊测试
    def test_binary_ufunc_reduce_fuzz(self):
        
        # 定义内部函数 get_out_axis_size,用于确定输出轴的大小
        def get_out_axis_size(a, b, axis):
            # 总是返回 None 和 (axis is None or a.ndim == 1)
            return None, (axis is None or a.ndim == 1)

        # 调用 self.check_unary_fuzz 方法,测试 np.add.reduce 的模糊测试,指定 dtype=np.int16 和 count=500
        self.check_unary_fuzz(np.add.reduce, get_out_axis_size,
                              dtype=np.int16, count=500)

    # 定义一个测试函数 test_binary_ufunc_reduceat_fuzz,用于测试二元通用函数 np.add.reduceat 的模糊测试
    def test_binary_ufunc_reduceat_fuzz(self):
        
        # 定义内部函数 get_out_axis_size,用于确定输出轴的大小
        def get_out_axis_size(a, b, axis):
            # 如果 axis 为 None
            if axis is None:
                # 如果 a 的维度为 1
                if a.ndim == 1:
                    # 返回 a 的大小和 False(表示不跳过)
                    return a.size, False
                else:
                    # 返回 'skip' 和 False,表示跳过该情况(reduceat 不支持多维数组)
                    return 'skip', False  # reduceat doesn't support this
            else:
                # 返回 a 在指定 axis 上的形状和 False(表示不跳过)
                return a.shape[axis], False

        # 定义内部函数 do_reduceat,用于执行 np.add.reduceat 的操作
        def do_reduceat(a, out, axis):
            # 如果 axis 为 None
            if axis is None:
                # 计算数组 a 的大小和步长
                size = len(a)
                step = size // len(out)
            else:
                # 计算数组 a 在指定 axis 上的大小和步长
                size = a.shape[axis]
                step = a.shape[axis] // out.shape[axis]
            # 构造索引数组 idx,用于 reduceat 操作
            idx = np.arange(0, size, step)
            # 执行 np.add.reduceat 操作,并将结果存入 out,指定 axis
            return np.add.reduceat(a, idx, out=out, axis=axis)

        # 调用 self.check_unary_fuzz 方法,测试 do_reduceat 函数的模糊测试,指定 dtype=np.int16 和 count=500
        self.check_unary_fuzz(do_reduceat, get_out_axis_size,
                              dtype=np.int16, count=500)

    # 定义一个测试函数 test_binary_ufunc_reduceat_manual,用于手动测试二元通用函数 np.add.reduceat 的功能
    def test_binary_ufunc_reduceat_manual(self):
        
        # 定义内部函数 check,用于检查 reduceat 操作的输出
        def check(ufunc, a, ind, out):
            # 分别使用复制的输入数组执行 reduceat 操作,并比较结果
            c1 = ufunc.reduceat(a.copy(), ind.copy(), out=out.copy())
            c2 = ufunc.reduceat(a, ind, out=out)
            # 使用 assert_array_equal 断言,确保两次操作的结果相等
            assert_array_equal(c1, c2)

        # 测试情况1:完全相同的输入和输出数组
        a = np.arange(10000, dtype=np.int16)
        check(np.add, a, a[::-1].copy(), a)

        # 测试情况2:索引数组与输入数组重叠
        a = np.arange(10000, dtype=np.int16)
        check(np.add, a, a[::-1], a)

    # 使用 pytest.mark.slow 标记该测试函数为慢速测试
    # 定义一个测试函数,用于测试一元通用函数的模糊测试
    def test_unary_gufunc_fuzz(self):
        # 定义不同形状的数组
        shapes = [7, 13, 8, 21, 29, 32]
        # 获取欧几里得距离计算函数的引用
        gufunc = _umath_tests.euclidean_pdist

        # 使用种子为1234的随机数生成器
        rng = np.random.RandomState(1234)

        # 循环测试数组维度从2到5
        for ndim in range(2, 6):
            # 根据当前维度随机生成数组 x
            x = rng.rand(*shapes[:ndim])

            # 生成随机视图对的迭代器
            it = iter_random_view_pairs(x, same_steps=False, equal_size=True)

            # 计算最小重叠次数
            min_count = 500 // (ndim + 1)**2

            # 初始化重叠计数
            overlapping = 0
            # 当重叠次数未达到最小要求时循环
            while overlapping < min_count:
                # 获取下一对视图 a, b
                a, b = next(it)

                # 如果 a 或 b 的最小形状小于2,或者 a 的最后一个维度小于2,则继续下一轮循环
                if min(a.shape[-2:]) < 2 or min(b.shape[-2:]) < 2 or a.shape[-1] < 2:
                    continue

                # 确保形状满足欧几里得距离计算函数的要求
                if b.shape[-1] > b.shape[-2]:
                    b = b[...,0,:]
                else:
                    b = b[...,:,0]

                # 计算 a 的形状
                n = a.shape[-2]
                # 计算可能的对数
                p = n * (n - 1) // 2
                # 如果 p 小于等于 b 的最后一个维度并且大于0,则截取 b 的形状
                if p <= b.shape[-1] and p > 0:
                    b = b[...,:p]
                else:
                    # 否则重新计算 n,使得 n 大于等于2,并计算新的 p
                    n = max(2, int(np.sqrt(b.shape[-1]))//2)
                    p = n * (n - 1) // 2
                    # 截取 a 和 b 的新形状
                    a = a[...,:n,:]
                    b = b[...,:p]

                # 检查 a 和 b 是否共享内存,若是则增加重叠计数
                if np.shares_memory(a, b):
                    overlapping += 1

                # 忽略溢出和无效操作的错误,调用 gufunc 并断言输出与 b 等效
                with np.errstate(over='ignore', invalid='ignore'):
                    assert_copy_equivalent(gufunc, [a], out=b)

    # 定义测试 ufunc 在指定位置进行操作的函数
    def test_ufunc_at_manual(self):
        # 定义一个内部函数 check,用于验证 ufunc 在指定位置进行操作的正确性
        def check(ufunc, a, ind, b=None):
            # 复制数组 a 到 a0
            a0 = a.copy()
            # 如果 b 为空,则调用 ufunc.at(a0, ind) 和 ufunc.at(a, ind),并断言结果相等
            if b is None:
                ufunc.at(a0, ind.copy())
                c1 = a0.copy()
                ufunc.at(a, ind)
                c2 = a.copy()
            else:
                # 否则调用 ufunc.at(a0, ind, b) 和 ufunc.at(a, ind, b),并断言结果相等
                ufunc.at(a0, ind.copy(), b.copy())
                c1 = a0.copy()
                ufunc.at(a, ind, b)
                c2 = a.copy()
            assert_array_equal(c1, c2)

        # 测试反转数组 a 并与其索引重叠的情况
        a = np.arange(10000, dtype=np.int16)
        check(np.invert, a[::-1], a)

        # 测试在第二个数据数组上进行 ufunc 操作
        a = np.arange(100, dtype=np.int16)
        ind = np.arange(0, 100, 2, dtype=np.int16)
        check(np.add, a, ind, a[25:75])
    def test_unary_ufunc_1d_manual(self):
        # 测试一维数组的单目通用函数(ufunc)的快速路径(避免创建 `np.nditer`)

        def check(a, b):
            # 复制输入数组,以便在每次测试前恢复初始状态
            a_orig = a.copy()
            b_orig = b.copy()

            # 使用输出数组 b0 进行 ufunc 操作,并保存结果到 c1
            b0 = b.copy()
            c1 = ufunc(a, out=b0)
            # 使用相同的输出数组 b 进行 ufunc 操作,并保存结果到 c2
            c2 = ufunc(a, out=b)
            # 检查 c1 和 c2 是否相等
            assert_array_equal(c1, c2)

            # 触发“复杂 ufunc 循环”代码路径
            # 使用视图操作获取 b 的第一个字节,并转换为布尔类型的掩码
            mask = view_element_first_byte(b).view(np.bool)

            # 恢复输入数组和输出数组的初始状态
            a[...] = a_orig
            b[...] = b_orig
            # 使用复制的输出数组和复制的掩码进行 ufunc 操作,并保存结果到 c1
            c1 = ufunc(a, out=b.copy(), where=mask.copy()).copy()

            # 恢复输入数组和输出数组的初始状态
            a[...] = a_orig
            b[...] = b_orig
            # 使用原始输出数组和复制的掩码进行 ufunc 操作,并保存结果到 c2
            c2 = ufunc(a, out=b, where=mask.copy()).copy()

            # 恢复输入数组和输出数组的初始状态
            a[...] = a_orig
            b[...] = b_orig
            # 使用原始输出数组和原始掩码进行 ufunc 操作,并保存结果到 c3
            c3 = ufunc(a, out=b, where=mask).copy()

            # 检查 c1、c2 和 c3 是否相等
            assert_array_equal(c1, c2)
            assert_array_equal(c1, c3)

        # 定义被测试的数据类型列表
        dtypes = [np.int8, np.int16, np.int32, np.int64, np.float32,
                  np.float64, np.complex64, np.complex128]
        dtypes = [np.dtype(x) for x in dtypes]

        # 遍历每种数据类型进行测试
        for dtype in dtypes:
            # 根据数据类型选择对应的 ufunc 函数
            if np.issubdtype(dtype, np.integer):
                ufunc = np.invert
            else:
                ufunc = np.reciprocal

            # 设定测试中的数组大小和索引表达式
            n = 1000
            k = 10
            indices = [
                np.index_exp[:n],
                np.index_exp[k:k+n],
                np.index_exp[n-1::-1],
                np.index_exp[k+n-1:k-1:-1],
                np.index_exp[:2*n:2],
                np.index_exp[k:k+2*n:2],
                np.index_exp[2*n-1::-2],
                np.index_exp[k+2*n-1:k-1:-2],
            ]

            # 使用 itertools 生成索引对,并进行测试
            for xi, yi in itertools.product(indices, indices):
                v = np.arange(1, 1 + n*2 + k, dtype=dtype)
                x = v[xi]
                y = v[yi]

                # 忽略所有错误状态,执行 check 函数进行测试
                with np.errstate(all='ignore'):
                    check(x, y)

                    # 测试标量情况
                    check(x[:1], y)
                    check(x[-1:], y)
                    check(x[:1].reshape([]), y)
                    check(x[-1:].reshape([]), y)

    def test_unary_ufunc_where_same(self):
        # 检查 wheremask 重叠时的行为
        ufunc = np.invert

        def check(a, out, mask):
            # 使用复制的掩码和输出数组进行 ufunc 操作,并保存结果到 c1
            c1 = ufunc(a, out=out.copy(), where=mask.copy())
            # 使用原始掩码和输出数组进行 ufunc 操作,并保存结果到 c2
            c2 = ufunc(a, out=out, where=mask)
            # 检查 c1 和 c2 是否相等
            assert_array_equal(c1, c2)

        # 使用布尔类型的数组 x 进行测试
        x = np.arange(100).astype(np.bool)
        # 测试不同的输入和输出组合及其重叠的掩码情况
        check(x, x, x)
        check(x, x.copy(), x)
        check(x, x, x.copy())

    @pytest.mark.slow
    # 定义一个测试函数,用于测试一维数组的逐元素操作(ufunc)
    def test_binary_ufunc_1d_manual(self):
        # 定义要测试的二元通用函数为 np.add
        ufunc = np.add

        # 定义检查函数,用于比较三个数组的逐元素运算结果
        def check(a, b, c):
            # 复制 c 到 c0
            c0 = c.copy()
            # 使用 ufunc 对 a 和 b 执行逐元素运算,结果存入 c0
            c1 = ufunc(a, b, out=c0)
            # 直接使用 ufunc 对 a 和 b 执行逐元素运算,结果存入 c
            c2 = ufunc(a, b, out=c)
            # 断言 c1 和 c2 相等
            assert_array_equal(c1, c2)

        # 遍历不同的数据类型进行测试
        for dtype in [np.int8, np.int16, np.int32, np.int64,
                      np.float32, np.float64, np.complex64, np.complex128]:
            # 检查不同数据依赖顺序的情况

            n = 1000  # 设置数组长度
            k = 10    # 设置步长

            indices = []
            # 使用 itertools.product 生成三重循环的索引组合
            for p in [1, 2]:
                indices.extend([
                    np.index_exp[:p*n:p],           # 切片索引
                    np.index_exp[k:k+p*n:p],        # 起始偏移索引
                    np.index_exp[p*n-1::-p],        # 反向步长索引
                    np.index_exp[k+p*n-1:k-1:-p],   # 起始偏移反向步长索引
                ])

            # 对 indices 中的组合进行排列组合,形成测试样例
            for x, y, z in itertools.product(indices, indices, indices):
                # 创建一个长度为 6*n 的数组,并转换为指定数据类型 dtype
                v = np.arange(6*n).astype(dtype)
                # 根据索引 x,y,z 分别取出对应的子数组
                x = v[x]
                y = v[y]
                z = v[z]

                # 调用 check 函数检查逐元素操作结果
                check(x, y, z)

                # 对标量情况进行检查
                check(x[:1], y, z)
                check(x[-1:], y, z)
                check(x[:1].reshape([]), y, z)
                check(x[-1:].reshape([]), y, z)
                check(x, y[:1], z)
                check(x, y[-1:], z)
                check(x, y[:1].reshape([]), z)
                check(x, y[-1:].reshape([]), z)

    # 定义一个测试函数,用于测试简单的原地操作
    def test_inplace_op_simple_manual(self):
        # 创建一个随机数生成器,并生成一个 200x200 的随机数组 x
        rng = np.random.RandomState(1234)
        x = rng.rand(200, 200)  # 大于缓冲区大小

        # 执行 x 和其转置矩阵的原地相加操作
        x += x.T
        # 断言 x 减去其转置矩阵后的结果全为 0
        assert_array_equal(x - x.T, 0)