Chronaxis用户手册English
本页目录

chronaxis.core.integral_sum_reference

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""独立按原序累计积分面积,用有界浮点误差项保留大数抵消后的低位。23输入为 ReferenceIntegralTerms,输出为最终单位下的 IntegralSumResult 快照。4每项使用标量精确拆分,保存非重叠误差项;结束时用标准库 fsum 归约误差项。5任何原序中间溢出永久失败;不会靠后续抵消恢复,也不会按块先求和。6状态最多 partial_limit 项,不保存整窗面积;容量不足明确抛错而不截断。7纯核无文件副作用,状态及候选内存由外层 owner 在调用前申请预算。8"""910# 参考实现独立依赖标准库,不调用数组归约、数组面积或数组对齐实现。11from math import fsum, isfinite12from .integral_sum import (IntegralSumResult, IntegralStateLimitError,13                           require_partial_limit, require_sum_finish)14from .integral_terms import ReferenceIntegralTerms15from .types import QualityFlag as Q161718class ReferenceIntegralSum:19    """持有有界非重叠误差项、有效面积计数及持久累计故障。2021    push 为原序状态驱动;finish 不清空状态,最终转换故障仅影响返回快照。22    调用方在任意推进异常后须放弃当前累计并清理,不能接着使用半段输入。23    """2425    def __init__(self, partial_limit: int = 4096):26        """建立空累计状态。参数: partial_limit 为硬容量。返回: None。异常: 非法容量。27        """28        # 初始零项没有面积证据;不能提前返回正常零值。29        self._limit = require_partial_limit(partial_limit)30        self._partials = []31        self._valid_terms = 032        self._failed = False3334    @property35    def valid_term_count(self) -> int:36        """读取有效面积项数。参数: 无。返回: int。异常: 无。"""37        return self._valid_terms  # 与真实更新样本计数分开。3839    @property40    def calculation_failed(self) -> bool:41        """读取持久累计故障。参数: 无。返回: bool。异常: 无。"""42        return self._failed  # 后续抵消不会清除此状态。4344    @property45    def partial_count(self) -> int:46        """读取当前误差项数量。参数: 无。返回: int。异常: 无。"""47        return len(self._partials)  # 仅报告有界数值状态,不含输入面积。4849    def push(self, terms: ReferenceIntegralTerms) -> None:50        """按原顺序推进有效面积,保留块间误差状态。5152        参数: terms 为有限冻结面积块。返回: None。53        异常: TypeError 为后端不符;IntegralStateLimitError/MemoryError 为状态容量或分配失败。54        """55        try:56            # 后端模型必须明确,不隐式把 NumPy 数据搬入标量参考核。57            if not isinstance(terms, ReferenceIntegralTerms):58                raise TypeError('参考归约需要ReferenceIntegralTerms')59            # 原积分入口仍检查真实模型;同后端数值推进可用于其他已定义的原序浮点项。60            self.push_values(terms.areas, terms.valid)61        finally:62            # 原异常及TB仍交调用方;只断本层借入参数、视图和临时,不清外部帧。63            self = terms = None6465    def push_values(self, values: tuple[float, ...], valid: tuple[bool, ...]) -> None:66        """累计有限原序浮点项,不要求调用方伪造积分事实。6768        参数: values/valid 为同长冻结tuple;数值为有限原生float,未知位置必须存0。69        返回: None;使用与原积分入口相同的误差状态、容量及中间失败规则。70        异常: TypeError/ValueError 为列结构;容量、分配或取消原样传播。71        边界: 仅复用本参考后端数值算法;调用方负责量纲、覆盖与候选内存预算。72        """73        try:74            # 完整门槛在推进前检查,错误输入不能留下半段新增状态。75            if type(values) is not tuple or type(valid) is not tuple or len(values) != len(valid):76                raise TypeError('原序参考归约需要同长tuple数值与掩码')77            # 显式循环保持原any的逐项/短路顺序;取消时没有genexpr的隐藏zip保留整列。78            for value, keep in zip(values, valid):79                if (type(value) is not float or not isfinite(value) or type(keep) is not bool80                        or not keep and value != 0):81                    raise ValueError('参考归约需有限float及bool,未知位置存0')82            # 保留原积分算法、原序、中间溢出和有界误差状态,不先归约块和。83            for area, keep in zip(values, valid):84                # 无效存储零不是数值证据;累计失败后仍统计后续有效项。85                if not keep:86                    continue87                if self._failed or area == 0:88                    self._valid_terms += 189                    continue90                # state_driver: 每项在原序状态上拆分,不把块和作为新的输入。91                candidate, current = [], area92                for partial in self._partials:93                    large, small = (current, partial) if abs(current) >= abs(partial) else (partial, current)94                    high = large + small95                    if not isfinite(high):96                        # 原序中途溢出保持失败,后续负项不能把已失败计算恢复正常。97                        self._failed = True98                        candidate = []99                        break100                    low = small - (high - large)101                    if low != 0:102                        candidate.append(low)103                    current = high104                if self._failed:105                    self._partials = []106                    self._valid_terms += 1107                    continue108                # 零和不占用误差项;容量检查后才安装该项及其计数。109                if current != 0:110                    candidate.append(current)111                if len(candidate) > self._limit:112                    raise IntegralStateLimitError('积分误差项超过容量,不能截断继续')113                self._partials = candidate114                self._valid_terms += 1115        finally:116            # 原异常及TB仍交调用方;只断本层借入参数、视图和临时,不清外部帧。117            self = values = valid = candidate = None118            current = area = partial = large = small = high = low = None119            value = keep = None120121    def finish(self, unit: str, factor: float = 1.0) -> IntegralSumResult:122        """归约有界误差项并只转换一次,保留原累计状态。123124        参数: unit/factor 为外层核实的最终单位及倍率。返回: 冻结数值快照。125        异常: 非法配置或分配错误传播;数值溢出/转换下溢写入失败结果。126        """127        try:128            # 配置先校验,空证据和持久溢出保持 None,不能回退为零。129            unit, factor = require_sum_finish(unit, factor)130            if self._failed:131                return IntegralSumResult(None, unit, True, Q.NONFINITE, self._valid_terms)132            if self._valid_terms == 0:133                return IntegralSumResult(None, unit, False, Q.NONE, 0)134            try:135                # 仅归约有界误差项;独立标准库求和不调用 NumPy 内核。136                total = fsum(self._partials)137            except OverflowError:138                return IntegralSumResult(None, unit, True, Q.NONFINITE, self._valid_terms)139            value = total * factor140            if not isfinite(value):141                return IntegralSumResult(None, unit, True, Q.NONFINITE, self._valid_terms)142            if total != 0 and value == 0:143                return IntegralSumResult(None, unit, True, Q.PRECISION_LOSS, self._valid_terms)144            # 零值规范为 +0.0;成功的结果不混入输入未知质量。145            return IntegralSumResult(0.0 if value == 0 else value, unit, False, Q.NONE, self._valid_terms)146        finally:147            # 原异常及TB仍交调用方;只断本层借入参数、视图和临时,不清外部帧。148            self = unit = factor = total = value = None149
Chronaxis 用户手册 · 离线阅读