decimal_gda_checked API
decimal_gda_checked 提供 GdaDecimalChecked,即基于 decimal_gda 中通用十进制算术(GDA)运算的流水线。它恰好持有一个 GdaOutcome[Decimal]:当前的定义值、下一个上下文(其粘滞的 status 累积迄今为止引发的所有信号)、最近一次运算引发的信号,以及(若有陷阱触发)被捕获的信号。对已完成状态执行运算时,会在所存储的上下文下执行相应的 GDA 运算;对已陷入陷阱的状态执行运算则不做任何事。resume_defined() 是陷阱触发后继续执行的唯一途径。本包从不产生 ArithmeticError。教程 逐步讲解陷阱与恢复;设计页面 将该流水线建模为带吸收性陷阱的状态单子,并证明了粘滞状态的定律。
示例使用以下辅助函数列出 GDA 标志:
///|
fn gda_flags(f : @decimal_gda.GdaFlags) -> String {
let named = [
("inexact", f.inexact),
("rounded", f.rounded),
("invalid_operation", f.invalid_operation),
("division_by_zero", f.division_by_zero),
("overflow", f.overflow),
("underflow", f.underflow),
("conversion_syntax", f.conversion_syntax),
("invalid_context", f.invalid_context),
]
[ for p in named if p.1 => p.0 ].join(",")
}
状态类型
GdaDecimalChecked
GdaDecimalChecked 包装一个 GdaOutcome[@decimal_gda.Decimal]。
pub struct GdaDecimalChecked {
// private fields
}
结果为 Completed(value, next_context, raised) 或 Trapped(signal, value, next_context, raised) 之一;参见 decimal_gda API 中的 GdaOutcome。
构造
GdaDecimalChecked::from_outcome
from_outcome(outcome) 包装任意 decimal_gda 运算的结果。
pub fn GdaDecimalChecked::from_outcome(@decimal_gda.GdaOutcome[@decimal_gda.Decimal]) -> Self
Trapped 结果会得到一个已陷入陷阱的流水线。
GdaDecimalChecked::from_decimal
from_decimal(value, context) 通过 GDA apply 运算将值舍入到上下文中(即类似 plus 的、转换到该上下文的操作)。
pub fn GdaDecimalChecked::from_decimal(@decimal_gda.Decimal, @decimal_gda.GdaContext) -> Self
舍入所引发的信号会被引发、合并到状态中并与陷阱比对,因此构造本身也可能触发陷阱。
GdaDecimalChecked::parse
parse(source, context) 是 GDA 中字符串的 to-number 转换。
pub fn GdaDecimalChecked::parse(String, @decimal_gda.GdaContext) -> Self
无效字符串会得到 NaN 并伴随 conversion_syntax;由于 GDA 将转换语法错误视为一种无效运算条件,捕获 InvalidOperation 的上下文(例如 GdaContext::default())会对其触发陷阱。
观察
outcome, value, context, raised, status
这些方法返回所包装的结果及其各组成部分。
pub fn GdaDecimalChecked::outcome(Self) -> @decimal_gda.GdaOutcome[@decimal_gda.Decimal]
pub fn GdaDecimalChecked::value(Self) -> @decimal_gda.Decimal
pub fn GdaDecimalChecked::context(Self) -> @decimal_gda.GdaContext
pub fn GdaDecimalChecked::raised(Self) -> @decimal_gda.GdaFlags
pub fn GdaDecimalChecked::status(Self) -> @decimal_gda.GdaFlags
value() 是定义结果,在陷入陷阱时亦然。context() 是下一个上下文,包括其更新后的状态及陷阱设置。raised() 仅保存最近一次运算的信号。status() 为 context().status(),即自上下文状态上次清除以来所引发的全部信号的粘滞并集;每当引发任何无效运算条件(conversion_syntax、division_impossible、division_undefined、invalid_context)时,状态中也会加入 invalid_operation。
is_trapped, trapped_signal
这些方法报告是否有陷阱触发以及触发的是哪个信号。
pub fn GdaDecimalChecked::is_trapped(Self) -> Bool
pub fn GdaDecimalChecked::trapped_signal(Self) -> @decimal_gda.GdaSignal?
当多个被引发的信号同时被捕获时,报告的是按以下优先级顺序排在最前的那个:InvalidOperation、DivisionByZero、DivisionUndefined、DivisionImpossible、InvalidContext、ConversionSyntax、Overflow、Underflow、Subnormal、Inexact、Rounded、Clamped、LostDigits。
恢复
GdaDecimalChecked::resume_defined
resume_defined() 以已陷入陷阱的流水线的定义结果继续执行。
pub fn GdaDecimalChecked::resume_defined(Self) -> Self
对于 Trapped(signal, value, context, raised),它返回 Completed(value, context, GdaFlags::none()):值和上下文(其状态中已包含被捕获的信号)被保留,陷阱标记和最近一步的标志被丢弃。对于已完成的流水线,它不做任何事。陷阱在上下文中保持启用,因此同一条件若再次出现会再次触发陷阱。
///|
test "a trap stops the pipeline until it is resumed" {
let ctx = @decimal_gda.GdaContext::new(precision=5).trap(
@decimal_gda.GdaSignal::DivisionByZero,
)
let one = @decimal_gda.Decimal::one()
let trapped = @decimal_gda_checked.GdaDecimalChecked::parse("1.234567", ctx).divide(
@decimal_gda.Decimal::zero(),
)
inspect(trapped.is_trapped(), content="true")
inspect(
trapped.trapped_signal() == Some(@decimal_gda.GdaSignal::DivisionByZero),
content="true",
)
inspect(trapped.value().to_string(), content="inf")
inspect(gda_flags(trapped.raised()), content="division_by_zero")
inspect(gda_flags(trapped.status()), content="inexact,rounded,division_by_zero")
inspect(trapped.add(one).is_trapped(), content="true")
let resumed = trapped.resume_defined()
inspect(gda_flags(resumed.raised()), content="")
let next = resumed.minus()
inspect(next.value().to_string(), content="-inf")
inspect(gda_flags(next.status()), content="inexact,rounded,division_by_zero")
}
运算
apply, plus, minus, abs, add, subtract, multiply, divide, fma, sqrt, exp, ln, log10, power, quantize, remainder, reduce, next_minus, next_plus, next_toward
这些方法在所存储的上下文下,对当前值执行 decimal_gda 中同名的运算。
pub fn GdaDecimalChecked::apply(Self) -> Self
pub fn GdaDecimalChecked::plus(Self) -> Self
pub fn GdaDecimalChecked::minus(Self) -> Self
pub fn GdaDecimalChecked::abs(Self) -> Self
pub fn GdaDecimalChecked::add(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::subtract(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::multiply(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::divide(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::fma(Self, @decimal_gda.Decimal, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::sqrt(Self) -> Self
pub fn GdaDecimalChecked::exp(Self) -> Self
pub fn GdaDecimalChecked::ln(Self) -> Self
pub fn GdaDecimalChecked::log10(Self) -> Self
pub fn GdaDecimalChecked::power(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::quantize(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::remainder(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::reduce(Self) -> Self
pub fn GdaDecimalChecked::next_minus(Self) -> Self
pub fn GdaDecimalChecked::next_plus(Self) -> Self
pub fn GdaDecimalChecked::next_toward(Self, @decimal_gda.Decimal) -> Self
对于 Completed(v, c, _),该方法返回 @decimal_gda.op(v, …, c) 的结果;对于 Trapped,它原样返回状态。第二个操作数(other、multiplier、addend、exponent、quantum、divisor、target)是普通的 Decimal。GDA 运算在 c 的精度、舍入、指数界限、钳制和扩展模式下计算结果;若未引发任何信号,则上下文原样传递且 raised 为空;否则,引发的信号会合并到下一个上下文的状态中,若其中有信号在 c.traps() 中启用,结果即为 Trapped。数学函数 exp、ln、log10 和 power 要求精度和指数界限位于 之内;否则返回 NaN 并伴随 invalid_context。
///|
test "sticky status across operations" {
let ctx = @decimal_gda.GdaContext::new(precision=5)
let parsed = @decimal_gda_checked.GdaDecimalChecked::parse("1.234567", ctx)
inspect(parsed.value().to_string(), content="1.2346")
inspect(gda_flags(parsed.raised()), content="inexact,rounded")
let added = parsed.add(@decimal_gda.Decimal::zero())
inspect(gda_flags(added.raised()), content="")
inspect(gda_flags(added.status()), content="inexact,rounded")
let e = @decimal_gda_checked.GdaDecimalChecked::parse(
"2",
@decimal_gda.GdaContext::decimal64(),
).exp()
inspect(e.value().to_string(), content="7.389056098930650")
let q = parsed.quantize(@decimal_gda.Decimal::from_string("0.01").unwrap())
inspect(q.value().to_string(), content="1.23")
}
完整公共接口
以下快照是该包完整的生成接口。
// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/decimal_gda_checked"
import {
"Luna-Flow/floating/decimal_gda",
}
// Values
// Errors
// Types and methods
pub struct GdaDecimalChecked {
// private fields
}
pub fn GdaDecimalChecked::abs(Self) -> Self
pub fn GdaDecimalChecked::add(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::apply(Self) -> Self
pub fn GdaDecimalChecked::context(Self) -> @decimal_gda.GdaContext
pub fn GdaDecimalChecked::divide(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::exp(Self) -> Self
pub fn GdaDecimalChecked::fma(Self, @decimal_gda.Decimal, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::from_decimal(@decimal_gda.Decimal, @decimal_gda.GdaContext) -> Self
pub fn GdaDecimalChecked::from_outcome(@decimal_gda.GdaOutcome[@decimal_gda.Decimal]) -> Self
pub fn GdaDecimalChecked::is_trapped(Self) -> Bool
pub fn GdaDecimalChecked::ln(Self) -> Self
pub fn GdaDecimalChecked::log10(Self) -> Self
pub fn GdaDecimalChecked::minus(Self) -> Self
pub fn GdaDecimalChecked::multiply(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::next_minus(Self) -> Self
pub fn GdaDecimalChecked::next_plus(Self) -> Self
pub fn GdaDecimalChecked::next_toward(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::outcome(Self) -> @decimal_gda.GdaOutcome[@decimal_gda.Decimal]
pub fn GdaDecimalChecked::parse(String, @decimal_gda.GdaContext) -> Self
pub fn GdaDecimalChecked::plus(Self) -> Self
pub fn GdaDecimalChecked::power(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::quantize(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::raised(Self) -> @decimal_gda.GdaFlags
pub fn GdaDecimalChecked::reduce(Self) -> Self
pub fn GdaDecimalChecked::remainder(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::resume_defined(Self) -> Self
pub fn GdaDecimalChecked::sqrt(Self) -> Self
pub fn GdaDecimalChecked::status(Self) -> @decimal_gda.GdaFlags
pub fn GdaDecimalChecked::subtract(Self, @decimal_gda.Decimal) -> Self
pub fn GdaDecimalChecked::trapped_signal(Self) -> @decimal_gda.GdaSignal?
pub fn GdaDecimalChecked::value(Self) -> @decimal_gda.Decimal
// Type aliases
// Traits