chronaxis.core.export_interpolation
源码基线:8904c2f744951857659abd40aaa3535d57faf53c
1"""计算离线导出的线性值;不改变分析中的向后保持、事件或积分语义。23调用方已确定相邻有效端点、范围及最大间隔。参考实现用精确有理数计算后转4float64;NumPy实现以一维longdouble数组计算后转float64,计算内核独立。5整数纳秒先作精确相对差,避免把很大的绝对时间直接转浮点。输出为估计值,6不声称恢复真实观测;无文件、预算或全局状态。7"""89from fractions import Fraction10from math import isfinite11import numpy as np121314def linear_reference(times, left_ns, right_ns, left_value, right_value):15 """独立标量线性参考。参数: times有限ns tuple、相邻端点时间/数值。返回: float tuple。1617 异常: 时间/数值非法或结果不有限;只接受严格位于两个端点之间的目标。18 """19 if (not left_ns < right_ns or any(not left_ns < t < right_ns for t in times)20 or not isfinite(left_value) or not isfinite(right_value)):21 raise ValueError('插值需要有效有序两端与内部目标')22 left,right = Fraction(left_value),Fraction(right_value)23 result = tuple(float(left+(right-left)*Fraction(t-left_ns,right_ns-left_ns)) for t in times)24 if any(not isfinite(value) for value in result):25 raise ValueError('插值结果非有限')26 return result272829def linear_numpy(times, left_ns, right_ns, left_value, right_value):30 """独立数组线性计算。参数: 同reference。返回: shape(N,) float64 ndarray。3132 异常: 时间/值非法或结果不有限;数组副本限当前有限块,不使用object数组。33 """34 if (not left_ns < right_ns or any(not left_ns < t < right_ns for t in times)35 or not isfinite(left_value) or not isfinite(right_value)):36 raise ValueError('插值需要有效有序两端与内部目标')37 # 先精确减绝对坐标再装箱,按相同时间权重对整块执行真实数组运算。38 relative = np.asarray([t-left_ns for t in times],dtype=np.longdouble)39 span=np.longdouble(right_ns-left_ns)40 left,right=np.longdouble(left_value),np.longdouble(right_value)41 # Windows longdouble可能就是float64;用较近端点的增量,减少两项乘法及抵消误差。42 # 两个合法极大有限端点的差可能溢出,只在该明确中间状态采用凸组合。43 with np.errstate(over='ignore'):44 difference=right-left45 if np.isfinite(difference):46 from_right=np.asarray([right_ns-t for t in times],dtype=np.longdouble)47 values=np.where(relative<=from_right,left+difference*(relative/span),48 right-difference*(from_right/span)).astype(np.float64)49 else:50 alpha=relative/span51 values=np.asarray((1-alpha)*left+alpha*right,dtype=np.float64)52 if not np.all(np.isfinite(values)):53 raise ValueError('插值结果非有限')54 return values55