decimal_gda_checked API
decimal_gda_checked は GdaDecimalChecked を提供します。これは decimal_gda の General Decimal Arithmetic(GDA)演算を連結するパイプラインです。このパイプラインはちょうど 1 つの 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 は 1 つの 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
不正な文字列は conversion_syntax を伴う NaN になります。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 に対しては状態をそのまま返します。第 2 オペランド(other、multiplier、addend、exponent、quantum、divisor、target)は通常の Decimal です。GDA 演算は c の精度、丸め、指数の上下限、クランプ、拡張モードのもとで結果を計算します。シグナルが発生しなければコンテキストは変更されずに引き継がれ、raised は空になります。そうでなければ発生したシグナルが次のコンテキストのステータスにマージされ、そのいずれかが c.traps() で有効になっていれば結果は Trapped になります。数学関数 exp、ln、log10、power は精度と指数の上下限が 以内であることを必要とし、そうでない場合は invalid_context を伴う NaN を返します。
///|
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