chronaxis.core.expression_math_reference
源码基线:8904c2f744951857659abd40aaa3535d57faf53c
1"""逐点解释已统一dtype和单位的极值、限幅与平方根节点。23输入是白名单操作及本时刻的ScalarValue,输出保留必要输入及数值错误原因。4使用标准库标量计算;定宽平方在编译时展开为现有的精确乘法。5"""67from math import sqrt8from .numeric import ScalarValue, to_float_reference9from .types import QualityFlag as Q, SignalDType as D101112def math_reference(name, args):13 """按标量数值协议执行一个极值、限幅或开方节点。1415 参数: name为编译好的函数名,args为依次排列的ScalarValue。16 返回: ScalarValue;有效极值/限幅保持dtype,开方输出FLOAT64。17 异常: ValueError为内部未注册名称。缺失、倒置或开方不可计算表示为质量。18 """19 value = args[0]20 if name == 'sqrt':21 # 先在原数域判负,不把很大的负整数舍入或当作一般转换失败。22 if value.valid and value.value < 0:23 return ScalarValue(None, D.FLOAT64, False, Q.DOMAIN_ERROR)24 converted = to_float_reference(value)25 if not converted.valid:26 return converted27 return ScalarValue(sqrt(converted.value), D.FLOAT64)28 # 任何必要输入的既有异常都进入输出,不能静默少比较一个通道。29 quality = Q.NONE30 for arg in args:31 quality |= arg.quality32 if name == 'clip':33 lower, upper = args[1:]34 if lower.valid and upper.valid and lower.value > upper.value:35 quality |= Q.DOMAIN_ERROR36 if quality != Q.NONE:37 return ScalarValue(None, value.dtype, False, quality)38 # 相等时保留首操作数的表示(包括带符号零),两后端共用同一择值契约。39 if name == 'minimum':40 return min(args, key=lambda arg: arg.value)41 if name == 'maximum':42 return max(args, key=lambda arg: arg.value)43 if name == 'clip':44 if value.value < lower.value:45 return lower46 if value.value > upper.value:47 return upper48 return value49 raise ValueError('未注册的逐点数值函数')50