decimal API

Luna-Flow/floating/decimal は floating の IEEE 754-2019 十進浮動小数点パッケージです。Decimal は任意精度の十進値で、量子(指数)、ゼロの符号、NaN のペイロードを保持します。DecimalContext は精度、丸め、指数範囲、クランプ、極小性(tininess)を定め、すべてのコンテキスト演算は丸められた値とそれが立てた DecimalFlags を返します。このパッケージは decimal32/64/128 交換形式を DPD と BID の両方でエンコード・デコードし、認証付き丸めで初等関数を評価します。

decimal チュートリアルでは典型的な作業を順に説明し、decimal の設計では演算モデル、エンコーディング、丸め、認証を解説します。IEEE への適合を主張する根拠となる有限の証拠は decimal の適合性に記録されています。General Decimal Arithmetic のスティッキーなステータスとトラップは別パッケージ decimal_gda にあり、decimal_checked は Decimal 演算のパイプラインのフラグを蓄積します。

以下で用いる記法:有限値は符号 ss、非負整数の係数 cc、指数(量子)qq により (−1)s⋅c⋅10q(-1)^s \cdot c \cdot 10^{q} と表されます。pp はコンテキストの精度、emax⁡e_{\max} と emin⁡e_{\min} は調整済み指数 q+digits⁡(c)−1q + \operatorname{digits}(c) - 1 に対するコンテキストの指数の上下限、Etiny=emin⁡−p+1E_{\text{tiny}} = e_{\min} - p + 1 は非正規化数の最小の指数です。

値と表現

Decimal

Decimal は不変の十進浮動小数点値です。

pub struct Decimal {
  // private fields
} derive(@debug.Debug)

Decimal は次のいずれかです:有限値 (−1)sc 10q(-1)^s c\,10^q(±0\pm 0 を含む)、±∞\pm\infty、または符号と非負整数のペイロードを持つ quiet NaN か signaling NaN。すべての値は作業用の precision も持ち、これは素の演算子やコンテキスト引数を持たない変換で使われます。フィールドは非公開なので、以下のオブザーバーを使用してください。数学的な値が同じで指数が異なる 2 つの値(たとえば 1.2 と 1.20)は同じコホートの別のメンバーです。数値としては等しく比較されますが、quantum、same_quantum、compare_total、書式化、交換エンコーディングでは区別されます。

導出された Debug 実装は Decimal::to_repr として公開されています。トレイト実装を参照してください。

Decimal::precision, coefficient, magnitude, exponent10, quantum

これらのオブザーバーは、値の格納された表現を返します。

pub fn Decimal::precision(Self) -> Int
pub fn Decimal::coefficient(Self) -> @bigint.BigInt
pub fn Decimal::magnitude(Self) -> @bigint.BigInt
pub fn Decimal::exponent10(Self) -> Int
pub fn Decimal::quantum(Self) -> Int

precision は値に格納された作業精度(1 以上)です。coefficient と magnitude はどちらも非負の係数 cc を返します。NaN ではペイロードを、無限大では 0 を返します。符号が係数に含まれることはないので、is_negative を使用してください。exponent10 と quantum はどちらも格納された指数 qq を返し、特殊値では 0 です。

///|
test "decimal representation observers" {
  let x = @decimal.Decimal::from_string("-12.300").unwrap()
  inspect(x.coefficient(), content="12300")
  inspect(x.quantum(), content="-3")
  inspect(x.is_negative(), content="true")
  inspect(x.precision(), content="34")
}

Decimal::sign, is_negative, is_signed

これらのオブザーバーは値の符号を報告します。

pub fn Decimal::sign(Self) -> @def.Sign
pub fn Decimal::is_negative(Self) -> Bool
pub fn Decimal::is_signed(Self) -> Bool

sign は両方のゼロとすべての NaN に対して @def.Sign::Zero を返し、それ以外では Negative/Positive を返します。is_negative と is_signed は同じ述語で、格納された符号ビットを返すため、−0-0、−∞-\infty、負の NaN に対して true になります。

Decimal::classify, class_name

classify は値の大まかなクラスを返し、class_name はコンテキストのもとで General Decimal Arithmetic のクラス文字列を返します。

pub fn Decimal::classify(Self) -> @arithmetic.FpClass
pub fn Decimal::class_name(Self, DecimalContext) -> String

classify は Finite、Infinity、NaN のいずれかを返します。class_name は "sNaN"、"NaN"、"-Infinity"、"+Infinity"、"-Zero"、"+Zero"、"-Subnormal"、"+Subnormal"、"-Normal"、"+Normal" のいずれかを返します。正規化数と非正規化数の区別にはコンテキストの emin⁡e_{\min} が使われます。

述語

これらの関数は値のクラスを判定します。

pub fn Decimal::is_finite(Self) -> Bool
pub fn Decimal::is_infinite(Self) -> Bool
pub fn Decimal::is_nan(Self) -> Bool
pub fn Decimal::is_zero(Self) -> Bool
pub fn Decimal::is_negative_zero(Self) -> Bool
pub fn Decimal::is_quiet_nan(Self) -> Bool
pub fn Decimal::is_qnan(Self) -> Bool
pub fn Decimal::is_signaling_nan(Self) -> Bool
pub fn Decimal::is_snan(Self) -> Bool
pub fn Decimal::is_canonical(Self) -> Bool
pub fn Decimal::is_normal(Self, DecimalContext) -> Bool
pub fn Decimal::is_subnormal(Self, DecimalContext) -> Bool

is_qnan と is_snan は、is_quiet_nan と is_signaling_nan の General Decimal Arithmetic における綴りです。is_canonical は常に true を返します。Decimal には非正準形が存在せず、非正準なエンコーディングは DecimalInterchange の性質です。値がコンテキストのもとで正規化数であるのは、有限かつ非ゼロで、調整済み指数が emin⁡e_{\min} 以上のときです。非正規化数であるのは、有限かつ非ゼロで、調整済み指数が emin⁡e_{\min} 未満のときです。ゼロ、無限大、NaN はどちらでもありません。

Decimal::nan_payload, get_payload, set_payload, set_payload_signaling

これらの関数は NaN のペイロードを読み取り、置き換えます。

pub fn Decimal::nan_payload(Self) -> @bigint.BigInt
pub fn Decimal::get_payload(Self) -> @bigint.BigInt
pub fn Decimal::set_payload(Self, @bigint.BigInt) -> Self
pub fn Decimal::set_payload_signaling(Self, @bigint.BigInt) -> Self

nan_payload と get_payload は NaN のペイロードを返し、それ以外のすべての値に対しては 0 を返します。set_payload は与えられたペイロード(の絶対値)と元の符号を持つ quiet NaN を返し、set_payload_signaling は signaling NaN を返します。どちらも NaN でない引数はそのまま返します。

構築と変換

Decimal::make

make は符号付き整数の係数と指数から有限値を構築し、精度に丸めます。

pub fn Decimal::make(@bigint.BigInt, Int, Int, mode? : @arithmetic.RoundingMode) -> Self

Decimal::make(c, q, p, mode~) は c⋅10qc \cdot 10^{q} を表し、符号は c から取られます。まず末尾のゼロが除去され、次に係数が長すぎれば mode(既定は ToNearestEven)で p 桁に丸められ、再び末尾のゼロが除去されます。したがって結果は常にそのコホートの縮約されたメンバーであり、make(0, q, p) は指数 0 の +0+0 です。指数範囲は適用されません。

Decimal::zero, negative_zero, one, inf, nan, quiet_nan, signaling_nan

これらのコンストラクタは特殊値と単位値を構築します。

pub fn Decimal::zero(precision? : Int) -> Self
pub fn Decimal::negative_zero(precision? : Int) -> Self
pub fn Decimal::one(precision? : Int) -> Self
pub fn Decimal::inf(@def.Sign, precision? : Int) -> Self
pub fn Decimal::nan(precision? : Int) -> Self
pub fn Decimal::quiet_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self
pub fn Decimal::signaling_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self

既定の精度は 34 です。zero、negative_zero、one の指数は 0 です。inf(sign) は Negative なら −∞-\infty、それ以外なら +∞+\infty です。nan はペイロード 0 の正の quiet NaN です。quiet_nan と signaling_nan の既定はペイロード 0、正の符号です。

Decimal::from_int, from_bigint

これらのコンストラクタは整数を変換します。

pub fn Decimal::from_int(Int, precision? : Int) -> Self
pub fn Decimal::from_bigint(@bigint.BigInt, precision? : Int) -> Self

どちらも既定の精度 34 での make(n, 0, precision) です。結果は縮約され(from_int(1000) は 1E+3、指数 3)、precision 桁を超える整数は最近接偶数丸め(half-even)で丸められます。

Decimal::from_double, from_float

これらのコンストラクタは二進浮動小数点数を変換します。

pub fn Decimal::from_double(Double, precision? : Int) -> Self
pub fn Decimal::from_float(Float, precision? : Int) -> Self

有限の Double はすべて二進有理数 m⋅2km \cdot 2^{k} であり、したがって k<0k<0 のとき有限の十進展開 m⋅5−k⋅10km \cdot 5^{-k} \cdot 10^{k} を持ちます。変換はこの正確な展開を構成し、precision 桁(既定 34)に half-even で丸めます。符号付きゼロと無限大は保存され、NaN はすべて入力の符号を持つペイロード 0 の quiet NaN になります。from_float はまず Double に拡張しますが、これは正確です。

Decimal::from_bin_float, to_bin_float

これらの関数は Decimal と二進の BinFloat の間で変換を行います。

pub fn Decimal::from_bin_float(@bin_float.BinFloat, precision? : Int) -> Self
pub fn Decimal::to_bin_float(Self, precision? : Int, mode? : @arithmetic.RoundingMode) -> @bin_float.BinFloat

from_bin_float(x, precision~) は、x の十進展開が precision 桁(既定は x の精度)に収まるときは正確で、そうでなければ half-even で丸められます。二進のゼロは +0+0 に、NaN はペイロード 0 の quiet NaN になります。to_bin_float(precision~, mode~) は、正確な十進値を mode(既定 ToNearestEven)で precision ビット(既定は十進値の精度フィールド)の BinFloat に丸めます。ほとんどの十進小数は二進有理数ではないため、この方向の変換は通常不正確です。TowardNegative と TowardPositive で変換すると、十進値を包む二進の包含区間が得られます。ゼロは +0+0 に写され、NaN のペイロードは保持されません。

Decimal::from_nat, from_integral

これらの関数は Luna-Flow の任意の整数型を変換します。

pub fn[S : @luna-generic.Nat] Decimal::from_nat(S) -> Self
pub fn[S : @luna-generic.Integral] Decimal::from_integral(S) -> Self

引数を Integral::normalize で BigInt に正規化し、精度 34 の from_bigint(n).normalized() を返します。これらは NatHomomorphism と IntegralHomomorphism の実装です。

解析と書式化

Decimal::parse, from_string

parse は量子を保ったまま十進テキストを Decimal に変換します。

pub fn Decimal::parse(String, precision? : Int) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::from_string(String, precision? : Int) -> Self?

受理される構文は、省略可能な符号、省略可能な小数点を含む数字列、省略可能な符号付きの省略可能な指数 E/e、または Inf、Infinity、NaN、sNaN(大文字小文字は問わない)のいずれかで、NaN の場合はその後に省略可能な十進のペイロード数字が続きます。有効数字が precision(既定 34)に収まれば、テキストの指数はそのまま保たれます。"1.2300" の係数は 12300、指数は −4-4 であり、"0.00" は指数 −2-2 の +0+0 です。より長い係数は precision 桁に half-even で丸められ、縮約されます。指数範囲は適用されません。無効なテキストに対しては、parse は Err(parse_error) を、from_string は None を返します。

Decimal::from_string_ctx

from_string_ctx はコンテキストのもとでテキストを変換し、変換フラグを報告します。

pub fn Decimal::from_string_ctx(String, DecimalContext) -> (Self, DecimalFlags)

構文は parse と同じです。値はコンテキストの精度に丸められ(rounded を立て、非ゼロの桁が捨てられたときは inexact も立てます)、指数範囲に照らして検査され(オーバーフロー、非正規化数、アンダーフロー、クランプ)、clamp が設定されていれば指数が引き下げられます。コンテキストが許すより多くの桁を持つ NaN ペイロード(clamp が設定されていれば精度 −1-1 桁、そうでなければ精度の桁数)は構文エラーです。無効なテキストに対しては、conversion_syntax フラグだけを立てた quiet NaN を返します。拡張でないコンテキストでは、Inf や NaN の綴りは変換構文エラーになります。

///|
test "decimal from_string_ctx rounds and flags" {
  let ctx = @decimal.DecimalContext::decimal32()
  let (x, flags) = @decimal.Decimal::from_string_ctx("3.14159265", ctx)
  inspect(x, content="3.141593")
  inspect(flags.rounded && flags.inexact, content="true")
  let (bad, bad_flags) = @decimal.Decimal::from_string_ctx("1..2", ctx)
  inspect(bad.is_nan(), content="true")
  inspect(bad_flags.conversion_syntax, content="true")
}

Decimal::to_sci_string, to_eng_string

これらの関数は、テキストのオペランドに対する General Decimal Arithmetic の to-scientific-string 変換と to-engineering-string 変換を実装します。

pub fn Decimal::to_sci_string(String, DecimalContext) -> (String, DecimalFlags)
pub fn Decimal::to_eng_string(String, DecimalContext) -> (String, DecimalFlags)

どちらもテキストを受け取り、from_string_ctx で変換して結果を書式化します。科学表記は、指数が正であるか調整済み指数が −6-6 未満のときは係数を指数 E±n 付きで書き、それ以外では通常の数字で書きます。工学表記は 3 の倍数の指数を使います。特殊値は Infinity、-Infinity、NaN、sNaN と書かれ、ペイロードがあれば NaN7 のようになります。フラグは変換のものです。

Decimal::to_string, output

to_string はコンテキストなしで値を科学表記に書式化します。

pub fn Decimal::to_string(Self) -> String
pub fn Decimal::output(Self, &Logger) -> Unit

有限値には to_sci_string の科学表記文字列の規則が使われるため、末尾のゼロと指数が見えます:1.20、1E+3、1.2E-7。特殊値は小文字で書かれます:inf、-inf、nan、snan、-nan12。output は同じテキストをロガーに書き込みます。どちらも Show 実装に由来します。

コンテキスト

DecimalContext

DecimalContext は演算パラメータの不変な集合です。

pub struct DecimalContext {
  // private fields
} derive(Eq)

コンテキストは、精度 pp、Luna-Flow 共通の rounding モード、十進丸めモード(decimal_rounding、演算で実際に使われるもの)、調整済み指数の上下限 emin⁡≤emax⁡e_{\min} \le e_{\max}、clamp スイッチ、extended スイッチ、極小性の規則を保持します。周囲の状態を読み取る演算はありません。すべてのコンテキスト演算はコンテキストを引数として受け取ります。

DecimalContext::new, try_new

これらのコンストラクタは名前付きパラメータからコンテキストを構築します。

pub fn DecimalContext::new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Self
pub fn DecimalContext::try_new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Result[Self, @arithmetic.ArithmeticError]
パラメータ既定値意味
precision34係数の桁数 pp
roundingToNearestEven共通の丸めモード
decimal_roundingrounding から導出演算で使われる丸めモード
e_min, e_max−999 999 999-999\,999\,999, 999 999 999999\,999\,999調整済み指数の範囲
clampfalse大きな指数を emax⁡−p+1e_{\max}-p+1 まで引き下げる
extendedtrueIEEE/拡張演算。false は GDA サブセットを選択
tininessAfterRounding結果を極小とみなす条件

decimal_rounding を省略すると DecimalRoundingMode::from_arithmetic(rounding) になります。HalfUp、HalfDown、ZeroFiveUp を使うには明示的に渡してください。new は precision <= 0 または e_min > e_max のとき中断し、try_new は代わりに Err(domain_error) を返します。

サブセットモード(extended=false)は古典的な decNumber のサブセットを再現します。pp 桁より長いオペランドは先に丸められ(lost_digits を立てる)、ゼロの結果は符号と指数を失い、特殊値のテキストは拒否されます。これは General Decimal Arithmetic のテストとの互換性のために存在します。

DecimalContext::decimal32, decimal64, decimal128, exact

これらのコンストラクタは、交換形式のコンテキストと正確な作業用コンテキストを返します。

pub fn DecimalContext::decimal32() -> Self
pub fn DecimalContext::decimal64() -> Self
pub fn DecimalContext::decimal128() -> Self
pub fn DecimalContext::exact() -> Self
コンテキストppemin⁡e_{\min}emax⁡e_{\max}clamp
decimal327−95-9596あり
decimal6416−383-383384あり
decimal12834−6143-61436144あり

3 つとも ToNearestEven(HalfEven)、拡張演算、丸め後の極小性判定を使います。exact() の精度は 0 で、これは「無制限」を意味します。結果はすべての桁を保持し、精度による丸めは行われません。指数範囲は既定のものです。精度 0 を得る方法はこれだけです。

DecimalContext::from_arithmetic_context

from_arithmetic_context は Luna-Flow 共通のコンテキストを変換します。

pub fn DecimalContext::from_arithmetic_context(@arithmetic.ArithmeticContext) -> Self

精度、丸め、クランプはコピーされ、欠けている e_min や e_max は ∓999 999 999\mp 999\,999\,999 になります。結果は拡張コンテキストで、丸め後の極小性判定を使います。contextual および checked のトレイト実装はこの変換を使用します。

DecimalContext::precision, rounding, decimal_rounding, e_min, e_max, clamp, extended, tininess

これらのアクセサはコンテキストのフィールドを返します。

pub fn DecimalContext::precision(Self) -> Int
pub fn DecimalContext::rounding(Self) -> @arithmetic.RoundingMode
pub fn DecimalContext::decimal_rounding(Self) -> DecimalRoundingMode
pub fn DecimalContext::e_min(Self) -> Int
pub fn DecimalContext::e_max(Self) -> Int
pub fn DecimalContext::clamp(Self) -> Bool
pub fn DecimalContext::extended(Self) -> Bool
pub fn DecimalContext::tininess(Self) -> DecimalTininessDetection

precision が 0 になるのは exact() の場合だけです。

DecimalContext::with_rounding, with_tininess, ieee754, is754version2019

これらの関数はコンテキストを派生させるか、その準拠規格を記述します。

pub fn DecimalContext::with_rounding(Self, @arithmetic.RoundingMode) -> Self
pub fn DecimalContext::with_tininess(Self, DecimalTininessDetection) -> Self
pub fn DecimalContext::ieee754(Self) -> Self
pub fn DecimalContext::is754version2019(Self) -> Bool

with_rounding は両方の丸めフィールドを置き換えます(十進モードは from_arithmetic(rounding) になります)。with_tininess は極小性の規則を置き換えます。ieee754 はコンテキストをそのまま返します。すべてのコンテキストはすでにこのパッケージの IEEE 754-2019 のセマンティクスに従っているからです。is754version2019 は常に true を返します。

DecimalContext::equal, not_equal

これらの関数はコンテキストをフィールドごとに比較します。

pub fn DecimalContext::equal(Self, Self) -> Bool
pub fn DecimalContext::not_equal(Self, Self) -> Bool

丸めモードと極小性

DecimalRoundingMode

DecimalRoundingMode は 8 つの十進丸め方向を列挙します。

pub(all) enum DecimalRoundingMode {
  HalfEven
  HalfUp
  HalfDown
  Down
  Ceiling
  Floor
  Up
  ZeroFiveUp
}
pub fn DecimalRoundingMode::equal(Self, Self) -> Bool
pub fn DecimalRoundingMode::not_equal(Self, Self) -> Bool

x>0x>0 が隣接する 2 つの表現可能な係数 cc と c+1c+1(最終桁の単位で)の間に厳密にあるとします。Down は cc を、Up は c+1c+1 を返します。Ceiling と Floor は +∞+\infty 方向と −∞-\infty 方向に丸めます(したがって符号に依存します)。HalfEven、HalfUp、HalfDown は 2 つのうち近いほうを返し、ちょうど中間のときはそれぞれ偶数の係数へ、ゼロから遠いほうへ、ゼロに近いほうへ丸めます。ZeroFiveUp は cc の最終桁が 0 または 5 なら c+1c+1 を、それ以外なら cc を返します。IEEE 754 では HalfEven を roundTiesToEven、HalfUp を roundTiesToAway、Down を roundTowardZero、Ceiling を roundTowardPositive、Floor を roundTowardNegative と呼びます。

DecimalRoundingMode::from_arithmetic, to_arithmetic

これらの関数は十進モードと共通の @arithmetic.RoundingMode の間で対応付けを行います。

pub fn DecimalRoundingMode::from_arithmetic(@arithmetic.RoundingMode) -> Self
pub fn DecimalRoundingMode::to_arithmetic(Self) -> @arithmetic.RoundingMode?
@arithmetic.RoundingModeDecimalRoundingMode
ToNearestEvenHalfEven
TowardZeroDown
TowardPositiveCeiling
TowardNegativeFloor
AwayFromZeroUp

to_arithmetic は、共通の列挙型に存在しない HalfUp、HalfDown、ZeroFiveUp に対して None を返します。

DecimalTininessDetection

DecimalTininessDetection は、非ゼロの結果を極小とみなす時点を選びます。

pub(all) enum DecimalTininessDetection {
  BeforeRounding
  AfterRounding
}
pub fn DecimalTininessDetection::equal(Self, Self) -> Bool
pub fn DecimalTininessDetection::not_equal(Self, Self) -> Bool

BeforeRounding は、正確な結果の調整済み指数が emin⁡e_{\min} 未満のとき結果を極小とみなします。AfterRounding は、指数を無制限として pp 桁に丸めた結果を使います。極小な結果は subnormal を立て、不正確であれば underflow も立てます。

ステータスフラグ

DecimalFlags

DecimalFlags は 1 回の演算で発生した条件を記録します。

pub struct DecimalFlags {
  inexact : Bool
  rounded : Bool
  lost_digits : Bool
  invalid_operation : Bool
  division_by_zero : Bool
  overflow : Bool
  underflow : Bool
  subnormal : Bool
  clamped : Bool
  conversion_syntax : Bool
  division_impossible : Bool
  division_undefined : Bool
  invalid_context : Bool
} derive(Eq)
フィールド立つ条件
inexact結果が正確な結果と異なる
rounded桁が捨てられた(すべてゼロであっても)
lost_digitsサブセットモードで pp より長いオペランドが非ゼロの桁を失った
invalid_operation演算が無効である(signaling NaN、∞−∞\infty-\infty、0×∞0\times\infty、不正な quantize、定義域エラー)
division_by_zero有限のオペランドから正確な無限大の結果が生じた(x/0x/0、log⁡0\log 0)
overflow丸めた結果の調整済み指数が emax⁡e_{\max} を超える
underflow結果が極小かつ不正確である
subnormal結果が極小である
clamped収めるために指数が変更された(引き下げ、またはゼロの指数のクランプ)
conversion_syntaxテキストを解析できなかった
division_impossible整数商に pp 桁より多くの桁が必要である
division_undefined0/00/0(invalid_operation と同時に立つ)
invalid_contextコンテキストが初等関数のサポートする範囲外である

フィールドは公開かつ読み取り専用です。フラグが暗黙に蓄積されることはありません。

DecimalFlags::new, combine, contains, has_error

これらの関数はフラグ集合を作成、統合、照会します。

pub fn DecimalFlags::new() -> Self
pub fn DecimalFlags::combine(Self, Self) -> Self
pub fn DecimalFlags::contains(Self, DecimalSignal) -> Bool
pub fn DecimalFlags::has_error(Self) -> Bool
pub fn DecimalFlags::equal(Self, Self) -> Bool
pub fn DecimalFlags::not_equal(Self, Self) -> Bool

new はすべてのフラグがクリアされた状態です。combine はフィールドごとの OR なので、結合的、可換、冪等で、new() を単位元とします。contains は DecimalSignal で指定されたフラグを読み取ります。has_error は invalid_operation∨division_by_zero∨division_undefined∨division_impossible∨invalid_context\text{invalid\_operation} \lor \text{division\_by\_zero} \lor \text{division\_undefined} \lor \text{division\_impossible} \lor \text{invalid\_context} であり、conversion_syntax、overflow、underflow は含みません。

///|
test "decimal flags accumulate by combine" {
  let ctx = @decimal.DecimalContext::decimal64()
  let one = @decimal.Decimal::one()
  let three = @decimal.Decimal::from_int(3)
  let (third, f1) = one.div_ctx(three, ctx)
  let (_, f2) = one.div_ctx(@decimal.Decimal::zero(), ctx)
  let all = f1.combine(f2)
  inspect(third, content="0.3333333333333333")
  inspect(all.contains(@decimal.DecimalSignal::Inexact), content="true")
  inspect(all.division_by_zero, content="true")
  inspect(all.has_error(), content="true")
}

DecimalSignal

DecimalSignal は DecimalFlags の 1 つのフラグを指します。

pub(all) enum DecimalSignal {
  ConversionSyntax
  DivisionByZero
  DivisionImpossible
  DivisionUndefined
  InvalidContext
  InvalidOperation
  Overflow
  Underflow
  Subnormal
  Inexact
  Rounded
  Clamped
  LostDigits
}
pub fn DecimalSignal::equal(Self, Self) -> Bool
pub fn DecimalSignal::not_equal(Self, Self) -> Bool

各コンストラクタは同名のフィールドに対応します。

コンテキストを使わない素の演算

このグループの演算子と関数はコンテキストを受け取らず、フラグも返しません。正確な計算や、Luna-Flow の代数トレイト上のジェネリックなコードには便利です。丸め、指数範囲、フラグが重要な場合は、常にコンテキスト演算を使用してください。

Decimal::add, sub, mul, div, neg

これらの関数は算術演算子 +、-、*、/ と単項の - です。

pub fn Decimal::add(Self, Self) -> Self
pub fn Decimal::sub(Self, Self) -> Self
pub fn Decimal::mul(Self, Self) -> Self
pub fn Decimal::div(Self, Self) -> Self
pub fn Decimal::neg(Self) -> Self

結果の精度は、オペランドの精度フィールドの max⁡(pa,pb)\max(p_a, p_b) です。

  • add/sub は正確な和を計算し、その精度に half-even で丸めて、コホートの縮約されたメンバーを返します。1.20 + 3.40 は 4.6 です。
  • mul は指数 qa+qbq_a+q_b の正確な積を返し、丸めません。1.25 * 2.50 は 3.1250 であり、係数が精度フィールドより長くなることがあります。
  • div は商をその精度に half-even で丸め、縮約します。商は数桁のガード桁を付けて計算されてから再び丸められるため、まれに正しく丸められた結果と最終桁の 1 単位だけ異なることがあります。div_ctx は丸めを 1 回だけ行います。
  • neg は、ゼロと NaN を含むすべての値の符号ビットを反転します。

特殊値:NaN のオペランドからは、最初の NaN の符号とペイロードを持つ quiet NaN が得られます。∞−∞\infty-\infty、0×∞0\times\infty、0/00/0、∞/∞\infty/\infty は正の NaN を、x/0x/0 は符号付き無限大を、有限値/∞/\infty は +0+0 を与えます。指数範囲は適用されません。正確な相殺は +0+0 を与え、2 つの負のゼロの和は −0-0 です。

///|
test "decimal plain operators" {
  let a = @decimal.Decimal::from_string("1.20").unwrap()
  let b = @decimal.Decimal::from_string("3.40").unwrap()
  inspect(a + b, content="4.6")
  inspect(a * b, content="4.0800")
  inspect(a - b, content="-2.2")
  inspect(-a, content="-1.20")
  inspect(@decimal.Decimal::one() / @decimal.Decimal::from_int(8), content="0.125")
}

Decimal::abs, copy, copy_abs, copy_negate, copy_sign

これらの関数は符号ビットだけを変更します。

pub fn Decimal::abs(Self) -> Self
pub fn Decimal::copy(Self) -> Self
pub fn Decimal::copy_abs(Self) -> Self
pub fn Decimal::copy_negate(Self) -> Self
pub fn Decimal::copy_sign(Self, Self) -> Self

丸めもフラグの発生も一切行わず、指数、ペイロード、NaN の種類を保持します。abs と copy_abs は符号をクリアし、copy_negate は反転し、copy_sign は第 2 オペランドの符号ビットをコピーし、copy は引数をそのまま返します。

Decimal::normalized, trim, with_precision

これらの関数はコホートのメンバーまたは精度フィールドを変更します。

pub fn Decimal::normalized(Self) -> Self
pub fn Decimal::trim(Self) -> Self
pub fn Decimal::with_precision(Self, Int, @arithmetic.RoundingMode) -> Self

normalized はコホートの縮約されたメンバー(末尾のゼロをすべて除去し、ゼロは指数 0)を返し、係数が長すぎれば値自身の精度に half-even で丸めます。trim は小数部の末尾のゼロを除去します。指数が負のときは指数 0 で止まり(12.300 は 12.3 になり、1200 は 1200 のまま)、指数が正のときはすべて除去します(1.20E+3 は 1.2E+3 になる)。ゼロは指数 0 になります。with_precision(p, mode) は有限値を mode で p 桁に丸めて縮約し、p を精度フィールドに格納します。特殊値は新しい精度フィールドを得るだけです。3 つともフラグを生じません。

Decimal::div_checked, sqrt

これらの関数は除算と平方根を行い、定義域エラーを Result として報告します。

pub fn Decimal::div_checked(Self, Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt(Self) -> Result[Self, @arithmetic.ArithmeticError]

div_checked(a, b) は DecimalContext::new(precision=max(p_a, p_b)) のもとでの div_ctx です。x/0x/0 に対しては Err(division_by_zero) を、無効な除算に対しては Err(domain_error) を返します。sqrt は DecimalContext::new(precision=p) のもとでの sqrt_ctx で、負の非ゼロのオペランドに対して Err(domain_error) を返します。どちらも half-even で正しく丸められます。

コンテキスト演算

このグループのすべての関数は DecimalContext を受け取り、(result, flags) を返します。結果は、正確な結果をコンテキストの十進丸めモードでコンテキストの精度に一度だけ丸めたもので、その後に指数範囲に照らして検査されます。オーバーフローでは設計ページにある丸めモード依存の結果が得られ、極小な結果は非正規化数の格子 10Etiny10^{E_{\text{tiny}}} に丸められ、clamp があれば大きな指数は emax⁡−p+1e_{\max}-p+1 まで引き下げられます。正確な結果が収まる場合、指数はその演算の優先指数になるため、コホートが情報を運びます。NaN のオペランドは、最初の NaN の符号とペイロードを持つ quiet NaN として伝播します(ペイロードは下位 pp 桁に切り詰められます)。signaling NaN のオペランドがあれば invalid_operation が立ちます。

Decimal::add_ctx, sub_ctx, mul_ctx, div_ctx

これらの関数は正しく丸められた算術演算です。

pub fn Decimal::add_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sub_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::mul_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::div_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)

優先指数:加算と減算では min⁡(qa,qb)\min(q_a,q_b)、乗算では qa+qbq_a+q_b、除算では qa−qbq_a-q_b です。正確な商は優先指数に最も近いメンバーで返され、不正確な商は pp 桁を持ちます。ゼロの和は +0+0 です。ただし Floor のもと(どちらかのオペランドが負なら −0-0)や、両方のオペランドが −0-0 の場合は除きます。

特殊ケース:∞−∞\infty-\infty、0×∞0\times\infty、∞/∞\infty/\infty は invalid_operation 付きの NaN を与えます。0/00/0 は invalid_operation と division_undefined 付きの NaN を、有限の非ゼロ xx に対する x/0x/0 は division_by_zero 付きの符号付き無限大を、有限値/∞/\infty は指数 EtinyE_{\text{tiny}} の符号付きゼロと clamped を与えます。

///|
test "decimal context arithmetic keeps preferred exponents" {
  let ctx = @decimal.DecimalContext::decimal64()
  let d = fn(s : String) { @decimal.Decimal::from_string(s).unwrap() }
  inspect(d("1.20").add_ctx(d("3.40"), ctx).0, content="4.60")
  inspect(d("1.25").mul_ctx(d("2.50"), ctx).0, content="3.1250")
  inspect(d("2.400").div_ctx(d("1.2"), ctx).0, content="2.00")
  let (q, flags) = d("2").div_ctx(d("3"), ctx)
  inspect(q, content="0.6666666666666667")
  inspect(flags.inexact, content="true")
}

Decimal::fma_ctx

fma_ctx は x⋅y+zx \cdot y + z を 1 回の丸めで計算します。

pub fn Decimal::fma_ctx(Self, Self, Self, DecimalContext) -> (Self, DecimalFlags)

積は正確に作られ、z に正確に加えられます。丸められるのは和だけです。0×∞0\times\infty は、z が quiet NaN であっても無効です。符号が逆の ∞⋅y+(−∞)\infty \cdot y + (-\infty) は無効です。拡張でないコンテキストでは、この演算は invalid_operation 付きの NaN を返します。

Decimal::sqrt_ctx

sqrt_ctx は正しく丸められた平方根を返します。

pub fn Decimal::sqrt_ctx(Self, DecimalContext) -> (Self, DecimalFlags)

優先指数は ⌊q/2⌋\lfloor q/2 \rfloor です。正確な根はそれに最も近いメンバーで返され(sqrt(0.0400) は 0.20)、不正確な根は pp 桁を持ち、inexact と rounded を立てます。−0=−0\sqrt{-0} = -0 です。負の非ゼロのオペランドや −∞-\infty は invalid_operation 付きの NaN を与えます。+∞=+∞\sqrt{+\infty}=+\infty です。

Decimal::plus_ctx, minus_ctx, abs_ctx, apply_ctx

これらの関数は 1 つのオペランドをコンテキストに合わせて丸めます。

pub fn Decimal::plus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::abs_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::apply_ctx(Self, DecimalContext) -> (Self, DecimalFlags)

apply_ctx は値をコンテキスト(精度、指数範囲、クランプ)に合わせて丸め、NaN を quiet にし、ゼロの符号を保ちます。plus_ctx は 0+x0 + x で、apply_ctx と同様ですがゼロは +0+0 になります。minus_ctx は 0−x0 - x、abs_ctx は ∣x∣|x| をコンテキストに合わせて丸めたものです。signaling NaN は invalid_operation を立てます。

Decimal::divide_integer, remainder, remainder_near, remainder_ctx

これらの関数は整数商と剰余を計算します。

pub fn Decimal::divide_integer(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_near(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)

divide_integer(x, y) は指数 0 の trunc⁡(x/y)\operatorname{trunc}(x/y) です。整数商に pp 桁より多くの桁が必要なときは、結果は division_impossible と invalid_operation 付きの NaN です。remainder(x, y) は xx の符号を持つ x−y⋅trunc⁡(x/y)x - y\cdot\operatorname{trunc}(x/y) です(General Decimal Arithmetic の remainder)。remainder_near(x, y) は x−y⋅nx - y\cdot n で、nn は x/yx/y を最も近い整数に丸めたもの(中間は偶数へ)です(IEEE 754 の remainder)。remainder_ctx は同じ演算です。剰余は収まる場合は正確で、優先指数は min⁡(qx,qy)\min(q_x, q_y) です。剰余がゼロのときの符号は xx の符号です。xrem⁡0x \operatorname{rem} 0 と ∞rem⁡y\infty \operatorname{rem} y は無効であり(0rem⁡00 \operatorname{rem} 0 は division_undefined も立てる)、xrem⁡∞=xx \operatorname{rem} \infty = x です。

///|
test "decimal remainders" {
  let ctx = @decimal.DecimalContext::decimal64()
  let d = fn(s : String) { @decimal.Decimal::from_string(s).unwrap() }
  inspect(d("10").divide_integer(d("3"), ctx).0, content="3")
  inspect(d("10").remainder(d("3"), ctx).0, content="1")
  inspect(d("10").remainder_near(d("6"), ctx).0, content="-2")
  inspect(d("-7.5").remainder(d("2"), ctx).0, content="-1.5")
}

量子と指数の演算

Decimal::quantize

quantize は値を別の値の指数に合わせて丸めます。

pub fn Decimal::quantize(Self, Self, DecimalContext) -> (Self, DecimalFlags)

x.quantize(y, ctx) は指数 qyq_y を持つ x の値を返し、桁が捨てられるときはコンテキストのモードで丸めます(rounded を立て、捨てた桁が非ゼロなら inexact も立てます)。目標の指数が [Etiny,emax⁡][E_{\text{tiny}}, e_{\max}] の外にあるとき、結果の係数に pp 桁より多くの桁が必要なとき、その調整済み指数が emax⁡e_{\max} を超えるとき、またはちょうど一方のオペランドだけが無限大のとき、結果は invalid_operation 付きの NaN です。2 つの無限大からは x の無限大が得られます。量子が黙って変わることはありません。結果が指数 qyq_y を持てなければ、演算は失敗します。

///|
test "decimal quantize to cents" {
  let ctx = @decimal.DecimalContext::decimal64()
  let d = fn(s : String) { @decimal.Decimal::from_string(s).unwrap() }
  let (cents, flags) = d("12.3456").quantize(d("0.01"), ctx)
  inspect(cents, content="12.35")
  inspect(flags.inexact, content="true")
  let small = @decimal.DecimalContext::new(precision=3, e_min=-99, e_max=99)
  let (bad, bad_flags) = d("999.9").quantize(d("0.1"), small)
  inspect(bad.is_nan(), content="true")
  inspect(bad_flags.invalid_operation, content="true")
}

Decimal::rescale

rescale は指数を整数オペランドに設定します。

pub fn Decimal::rescale(Self, Self, DecimalContext) -> (Self, DecimalFlags)

x.rescale(n, ctx) は目標指数を nn とする quantize で、nn は有限の整数でなければなりません。それ以外の第 2 オペランドは invalid_operation 付きの NaN を与えます。

Decimal::same_quantum

same_quantum は 2 つの値が同じ指数を持つかを判定します。

pub fn Decimal::same_quantum(Self, Self) -> Bool

2 つの有限値は指数が等しいとき同じ量子を持ちます。2 つの無限大どうし、2 つの NaN どうしは常に同じ量子を持ち、それ以外の組は同じ量子を持ちません。フラグを立てることはありません。

Decimal::reduce_ctx, normalize_ctx

これらの関数は値をコンテキストに合わせて丸め、末尾のゼロを除去します。

pub fn Decimal::reduce_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::normalize_ctx(Self, DecimalContext) -> (Self, DecimalFlags)

reduce_ctx はコンテキストを適用した後、指数が emax⁡e_{\max} 以下(clamp があれば emax⁡−p+1e_{\max}-p+1 以下)にとどまる範囲で末尾のゼロを除去します。ゼロは指数 0 のゼロになります(拡張コンテキストでは符号を保ちます)。normalize_ctx は同じ演算の、General Decimal Arithmetic における旧名です。

Decimal::to_integral_exact, to_integral_value

これらの関数は整数に丸めます。

pub fn Decimal::to_integral_exact(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_integral_value(Self, DecimalContext) -> (Self, DecimalFlags)

指数が負の有限値はコンテキストの丸めモードで指数 0 に quantize され、指数が ≥0\ge 0 の値はコンテキストに合わせて丸められるだけです。to_integral_exact は rounded/inexact を報告し、to_integral_value は同じ値をその 2 つのフラグをクリアして返します。無限大はそのまま返され、NaN は quiet にされます。

Decimal::scaleb_ctx, logb_ctx

これらの関数は 10 の冪で拡大縮小し、調整済み指数を取り出します。

pub fn Decimal::scaleb_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logb_ctx(Self, DecimalContext) -> (Self, DecimalFlags)

x.scaleb_ctx(n, ctx) は指数に nn を加えて x⋅10nx \cdot 10^{n} を返します。nn は指数 0 の有限の整数で ∣n∣≤2(emax⁡+p)|n| \le 2(e_{\max}+p) でなければならず、そうでなければ結果は invalid_operation 付きの NaN です。結果は x の係数を保持し(pp 桁には丸められません)、非正規化数とクランプの規則を適用し、オーバーフローするとすべての丸めモードで overflow、inexact、rounded 付きの符号付き無限大になります。logb_ctx(x) は調整済み指数 ⌊log⁡10∣x∣⌋\lfloor\log_{10}|x|\rfloor を整数の Decimal として返します。logb⁡(±0)=−∞\operatorname{logb}(\pm 0) = -\infty で division_by_zero が立ち、logb⁡(±∞)=+∞\operatorname{logb}(\pm\infty) = +\infty です。

Adjacent value

Decimal::next_plus, next_minus, next_toward

これらの関数は隣接する表現可能な値を返します。

pub fn Decimal::next_plus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_minus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_toward(Self, Self, DecimalContext) -> (Self, DecimalFlags)

next_plus はコンテキストにおいて x より大きい最小の表現可能な値、next_minus はそれより小さい最大の値で、10Etiny10^{E_{\text{tiny}}} までの非正規化数と最大の有限値 (10p−1) 10emax⁡−p+1(10^{p}-1)\,10^{e_{\max}-p+1} を含みます。next_plus(-∞) は最も負の有限値です。有限の結果に対してはフラグを立てません。next_toward(x, y) は x を y に向けて 1 ステップ動かします。x=yx = y のときは x を返し、ゼロの場合は y の符号を付けます。next_toward のステップが無限大で終わると overflow、inexact、rounded が立ち、非正規化数またはゼロで終わると underflow、subnormal、inexact、rounded が立ちます。

///|
test "decimal neighbours of one" {
  let ctx = @decimal.DecimalContext::decimal64()
  let one = @decimal.Decimal::one()
  inspect(one.next_plus(ctx).0, content="1.000000000000001")
  inspect(one.next_minus(ctx).0, content="0.9999999999999999")
}

比較と順序

Decimal::compare, equal, not_equal, op_lt, op_le, op_gt, op_ge

compare は、Compare と比較演算子が使う数値の三方比較です。

pub fn Decimal::compare(Self, Self) -> Int
pub fn Decimal::equal(Self, Self) -> Bool
pub fn Decimal::not_equal(Self, Self) -> Bool
pub fn Decimal::op_lt(Self, Self) -> Bool
pub fn Decimal::op_le(Self, Self) -> Bool
pub fn Decimal::op_gt(Self, Self) -> Bool
pub fn Decimal::op_ge(Self, Self) -> Bool

compare は数値に従って −1-1、0、1 を返し、−0=+0-0 = +0 であり、コホートのすべてのメンバーは等しくなります。NaN には数値の順序がないため、Compare が全前順序であり続ける(ソートが中断しない)ように、すべての NaN は他のすべての NaN と等しく、すべての非 NaN より大きいと比較されます。equal(==)は compare と一致し、NaN == NaN は true です。これは IEEE の等価性ではありません。NaN を順序付けできないものとして扱う必要がある場合は、compare_checked、compare_ctx、または NaN の述語を使用してください。op_lt などは Compare の公開された演算子メソッドです。

///|
test "decimal numeric order is a total preorder" {
  let d = fn(s : String) { @decimal.Decimal::from_string(s).unwrap() }
  inspect(d("1.0") == d("1.00"), content="true")
  inspect(d("-0").compare(d("0")), content="0")
  inspect(@decimal.Decimal::nan().compare(d("1E+999")), content="1")
  let sorted = [d("2"), @decimal.Decimal::nan(), d("-1")]
  sorted.sort()
  inspect(sorted.map(fn(x) { x.to_string() }).join(" "), content="-1 2 nan")
}

Decimal::compare_checked

compare_checked は NaN をエラーとする IEEE の数値比較です。

pub fn Decimal::compare_checked(Self, Self) -> Result[Int, @arithmetic.ArithmeticError]

どちらのオペランドも NaN でなければ Ok(compare(x, y)) を、そうでなければ Err(unordered_comparison) を返します。これは CompareChecked の実装です。

Decimal::compare_ctx, compare_signal_ctx

これらの関数は、十進の結果を返す General Decimal Arithmetic の比較です。

pub fn Decimal::compare_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_signal_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)

Decimal の −1-1、0、1 を返し、オペランドが NaN のときは quiet NaN を返します。compare_ctx は signaling NaN に対してのみ invalid_operation を立て、compare_signal_ctx はすべての NaN に対して立てます(IEEE の signaling 比較)。

Decimal::compare_total, compare_total_magnitude, compare_total_ctx, compare_total_magnitude_ctx

これらの関数は IEEE 754 の totalOrder 述語を三方比較として実装します。

pub fn Decimal::compare_total(Self, Self) -> Int
pub fn Decimal::compare_total_magnitude(Self, Self) -> Int
pub fn Decimal::compare_total_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::compare_total_magnitude_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)

compare_total はすべての表現を順序付けます。

−NaN<−sNaN<−∞<negative finite<−0<+0<positive finite<+∞<+sNaN<+NaN.-\text{NaN} < -\text{sNaN} < -\infty < \text{negative finite} < -0 < +0 < \text{positive finite} < +\infty < +\text{sNaN} < +\text{NaN}.

等しい有限値は指数で順序付けられます。正の値では指数の小さいほうが先(1.00<1.01.00 < 1.0)、負の値では大きいほうが先です。同じ符号と種類の NaN はペイロードで順序付けられます(負の NaN では逆順)。0 を返すのは表現が同一の場合だけです。compare_total_magnitude は絶対値を比較します。_ctx 版は、まずオペランドをコンテキストに合わせて準備し(これはサブセットモードでのみ意味があります)、その段階のフラグを返します。

Decimal::min, max, clamp, clamp_checked

これらの関数はコンテキストなしで数値の順序に従って選択します。

pub fn Decimal::min(Self, Self) -> Self
pub fn Decimal::max(Self, Self) -> Self
pub fn Decimal::clamp(Self, min~ : Self, max~ : Self) -> Self
pub fn Decimal::clamp_checked(Self, min~ : Self, max~ : Self) -> Result[Self, @arithmetic.ArithmeticError]

min と max は、ちょうど一方が quiet NaN のときはもう一方のオペランドを、両方が NaN かどちらかが signaling のときは quiet NaN を、等しいときはレシーバを返します。clamp は範囲より下なら min、上なら max、それ以外では値(NaN を含む)を返します。境界が NaN であるか min > max のときは中断します。clamp_checked はそれらの場合に Err(domain_error) を返します。

Decimal::min_ctx, max_ctx, min_mag_ctx, max_mag_ctx

これらの関数は General Decimal Arithmetic の min、max、min-magnitude、max-magnitude 演算です。

pub fn Decimal::min_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::max_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::max_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)

quiet NaN は数値に負けます。2 つの NaN からは最初のものを quiet にしたものが得られ、signaling NaN からは invalid_operation 付きの quiet NaN が得られます。数値的に等しいオペランドは compare_total で区別されます(したがって min_ctx(1.0, 1.00) は 1.00、min_ctx(-0, 0) は -0)。選ばれた値はコンテキストに合わせて丸められます。

IEEE の最小値と最大値

これら 12 個の関数は IEEE 754-2019 §9.6 の最小値・最大値演算です。

pub fn Decimal::minimum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)

minimum_ctx と maximum_ctx は NaN を伝播させ、NaN のオペランドがあれば quiet NaN を与えます。_number_ 版は、ちょうど一方のオペランドが NaN のとき数値のほうを返します。どちらでも signaling NaN は invalid_operation を立てます。絶対値版は ∣x∣|x| と ∣y∣|y| を比較し、絶対値が等しければ符号付きの順序に戻ります。同順位は compare_total で決まるので、−0<+0-0 < +0 です。_mag_ という綴りは _magnitude_ 版の別名です。選ばれた値はコンテキストに合わせて丸められます。

桁ごとの演算

Decimal::logical_and, logical_or, logical_xor, logical_invert

これらの関数は論理オペランドに対して桁ごとにブール演算を適用します。

pub fn Decimal::logical_and(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_or(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_xor(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_invert(Self, DecimalContext) -> (Self, DecimalFlags)

論理オペランドとは、指数 0 の有限な非負値で、係数の桁がすべて 0 か 1 のもの(1101 など)です。演算は下位 pp 桁に対して働き、論理オペランドを返します。それ以外のオペランドは invalid_operation 付きの NaN を与えます。

Decimal::shift_ctx, rotate_ctx

これらの関数は係数の桁をシフトまたはローテートします。

pub fn Decimal::shift_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rotate_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)

係数は pp 桁として扱われます。正の数 nn は桁を最上位側へ、負の数は最下位側へ動かします。shift_ctx はゼロで埋めて窓からはみ出た桁を捨て、rotate_ctx はそれを反対側へ回り込ませます。指数と符号は保持されます。シフト量は指数 0 で ∣n∣≤p|n| \le p の整数でなければならず、そうでなければ結果は invalid_operation 付きの NaN です。無限大はそのまま返されます。

初等関数

すべての初等関数には 2 つの形があります。f_ctx(x, ctx) は (result, flags) を返します。try_f_ctx(x, ctx) は同じ組を Ok で返すか、結果を認証できなかったときは Err を返します。その ArithmeticError の certification_failure_detail() は、演算、目標精度、使い切った精緻化の予算を示します。認証に失敗すると、f_ctx は invalid_operation 付きの NaN を返します。

有限の結果は、すべての DecimalRoundingMode で正しく丸められます。実装は ball_float で f(x)f(x) の保証付き包含区間を評価し、両端点が同じフラグで同じ Decimal に丸められるときにだけそれを受け入れます(設計を参照)。正確なケース(log⁡101000=3\log_{10} 1000 = 3、e0=1e^0 = 1、sin⁡0=0\sin 0 = 0、cospi⁡(1)=−1\operatorname{cospi}(1) = -1、整数乗など)は検出され、inexact なしで正確に返されます。

いずれの関数も、p>999 999p > 999\,999、emax⁡>999 999e_{\max} > 999\,999、emin⁡<−999 999e_{\min} < -999\,999 のとき、または有限のオペランドが 999,999 桁を超えるか調整済み指数がおよそ ±106\pm 10^6 を超えるとき、invalid_context 付きの NaN を返します。

Decimal::exp_ctx、ln_ctx、log10_ctx とその try_ 版

これらの関数は General Decimal Arithmetic の指数関数と対数関数です。

pub fn Decimal::exp_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::ln_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log10_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::try_exp_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_ln_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log10_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]

e±0=1e^{\pm 0} = 1、e+∞=+∞e^{+\infty}=+\infty、e−∞=+0e^{-\infty} = +0 です。ln⁡\ln と log⁡10\log_{10} は、±0\pm 0 に対しては −∞-\infty(拡張コンテキストではフラグなし)、+∞+\infty に対しては +∞+\infty、負の値や −∞-\infty に対しては invalid_operation 付きの NaN です。ln⁡1=0\ln 1 = 0 であり、10 の冪の log⁡10\log_{10} は正確な整数の指数です。exe^x が確実にオーバーフローまたはアンダーフローするほど大きい・小さい引数は、評価せずに判定されます。

Decimal::power_ctx、pown_ctx、rootn_ctx、hypot_ctx とその try_ 版

これらの関数は冪、冪根、ユークリッドノルムを計算します。

pub fn Decimal::power_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::pown_ctx(Self, Int, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rootn_ctx(Self, Int, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::hypot_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::try_power_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_pown_ctx(Self, Int, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_rootn_ctx(Self, Int, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_hypot_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]

power_ctx(x, y) は General Decimal Arithmetic の特殊ケースを伴う xyx^y です。整数の指数は作業桁を追加した正確な繰り返し乗算で計算されて一度だけ丸められます。x0.5x^{0.5} は sqrt_ctx です。正の底と非整数の指数は認証付きで計算されます。負の底と非整数の指数は無効です。拡張コンテキストでは 000^0 は無効です。0−n0^{-n} は ±∞\pm\infty です。pown_ctx(x, n) は、整数 n をコンテキスト精度の Decimal に変換した power_ctx です。rootn_ctx(x, n) は整数 n≠0n \ne 0 に対する x1/nx^{1/n} です。負の値の偶数乗根と n=0n=0 は無効であり、rootn⁡(±0,n<0)\operatorname{rootn}(\pm 0, n<0) は division_by_zero 付きの無限大です。hypot_ctx(x, y) は x2+y2\sqrt{x^2+y^2} で、どちらかのオペランドが無限大なら、もう一方が quiet NaN であっても +∞+\infty です。

拡張初等関数

これらの IEEE 754-2019 §9.2 の関数も、同じ f_ctx/try_f_ctx の形を持ちます。

pub fn Decimal::exp2_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::exp10_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::expm1_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log2_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log1p_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sin_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::cos_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::tan_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sinpi_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::cospi_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::tanpi_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::asin_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::acos_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::atan_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::atan2_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sinh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::cosh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::tanh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::asinh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::acosh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::atanh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::try_exp2_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_exp10_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_expm1_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log2_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log1p_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_sin_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_cos_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_tan_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_sinpi_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_cospi_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_tanpi_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_asin_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_acos_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_atan_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_atan2_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_sinh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_cosh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_tanh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_asinh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_acosh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_atanh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]

定義域と特殊値:

関数無効(invalid_operation)極(division_by_zero)正確なケース
exp2, exp10なしなし整数の引数(power_ctx 経由)、±0↦1\pm 0 \mapsto 1
expm1なしなし±0↦±0\pm0 \mapsto \pm0, −∞↦−1-\infty\mapsto -1
log2x<0x<0, −∞-\infty±0↦−∞\pm 0 \mapsto -\infty1↦01 \mapsto 0
log1px<−1x<-1, ±∞\pm\infty−1↦−∞-1 \mapsto -\infty±0↦±0\pm0 \mapsto \pm0
sin, cos, tan±∞\pm\inftyなしsin⁡(±0)=±0\sin(\pm 0)=\pm 0, cos⁡0=1\cos 0 = 1
sinpi, cospi, tanpi±∞\pm\infty奇数の半整数における tanpi整数と半整数
asin, acos∣x∣>1\lvert x\rvert > 1, ±∞\pm\inftyなしasin⁡(±0)=±0\operatorname{asin}(\pm0)=\pm0
atanなしなし±0\pm 0;±∞↦±π/2\pm\infty \mapsto \pm\pi/2(認証付き)
atan2(y, x)なしなしatan2⁡(±0,+0)=±0\operatorname{atan2}(\pm 0, +0) = \pm 0
sinh, tanh, asinhなしなし±0↦±0\pm0\mapsto\pm0; tanh⁡(±∞)=±1\tanh(\pm\infty)=\pm 1
coshなしなしcosh⁡0=1\cosh 0 = 1, cosh⁡(±∞)=+∞\cosh(\pm\infty)=+\infty
acoshx<1x < 1, −∞-\inftyなし1↦01 \mapsto 0
atanh∣x∣>1\lvert x\rvert>1, ±∞\pm\infty±1↦±∞\pm1 \mapsto \pm\infty±0↦±0\pm0 \mapsto \pm0
///|
test "decimal certified elementary functions" {
  let ctx = @decimal.DecimalContext::decimal64()
  let d = fn(s : String) { @decimal.Decimal::from_string(s).unwrap() }
  inspect(d("1").exp_ctx(ctx).0, content="2.718281828459045")
  inspect(d("1000").log10_ctx(ctx).0, content="3")
  inspect(d("0.5").sinpi_ctx(ctx).0, content="1")
  let down = ctx.with_rounding(@def.RoundingMode::TowardZero)
  inspect(d("2").ln_ctx(down).0, content="0.6931471805599453")
  match d("2").try_ln_ctx(@decimal.DecimalContext::new()) {
    Ok((value, flags)) => {
      inspect(value.is_nan(), content="true")
      inspect(flags.invalid_context, content="true")
    }
    Err(_) => fail("not a certification failure")
  }
}

交換形式

DecimalInterchangeFormat

DecimalInterchangeFormat は IEEE 754 の十進交換形式を指します。

pub(all) enum DecimalInterchangeFormat {
  Decimal32
  Decimal64
  Decimal128
}
pub fn DecimalInterchangeFormat::context(Self) -> DecimalContext
pub fn DecimalInterchangeFormat::equal(Self, Self) -> Bool
pub fn DecimalInterchangeFormat::not_equal(Self, Self) -> Bool

context は DecimalContext::decimal32()、decimal64()、decimal128() のいずれかを返します。

DecimalInterchangeEncoding

DecimalInterchangeEncoding は係数をビットにどう格納するかを選択します。

pub(all) enum DecimalInterchangeEncoding {
  DPD
  BID
}
pub fn DecimalInterchangeEncoding::equal(Self, Self) -> Bool
pub fn DecimalInterchangeEncoding::not_equal(Self, Self) -> Bool

DPD は 10 ビットの declet ごとに 3 桁の十進数字を格納し(densely packed decimal)、BID は係数を二進整数として格納します。エンコーディング引数を持たない関数は DPD を使用します。

Decimal::to_interchange_hex, to_interchange_hex_with_encoding

これらの関数は値を交換形式のビットにエンコードし、16 進数で書き出します。

pub fn Decimal::to_interchange_hex(Self, DecimalInterchangeFormat) -> (String, DecimalFlags)
pub fn Decimal::to_interchange_hex_with_encoding(Self, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> (String, DecimalFlags)

有限値はまず形式のコンテキストのもとで apply_ctx により丸められ(そのフラグが返されます)、その指数でエンコードされるため、収まる場合はコホートが保たれます。テキストは # に続く 8、16、または 32 桁の大文字の 16 進数字です。無限大は末尾フィールドをゼロとしてエンコードされます。NaN は符号と種類を保ちます。DPD はペイロードの下位 p−1p-1 桁を保持し、BID は pvalue−1p_{\text{value}}-1 桁で書いたペイロードの上位 p−1p-1 桁を保持するため、ペイロードを BID に移植できるのは値の精度が形式の精度と等しい場合だけです。

Decimal::from_interchange_hex, from_interchange_hex_with_encoding

これらの関数は交換形式の 16 進テキストをデコードします。

pub fn Decimal::from_interchange_hex(String, DecimalInterchangeFormat) -> Self?
pub fn Decimal::from_interchange_hex_with_encoding(String, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> Self?

テキストの前後に ASCII の空白があってもよく、先頭に # があってもかまいません。16 進数字の桁数は形式のものとちょうど一致しなければならず(大文字・小文字は問いません)、そうでなければ結果は None です。デコードは正確で、指数、ゼロの符号、NaN の種類とペイロードを保持します。非正準なエンコーディングは、IEEE 754 が割り当てる値にデコードされます。非正準な DPD の declet はその数字に、≥10p\ge 10^{p} の BID 係数はゼロに、範囲外の BID の NaN ペイロードは 0 になります。無限大と NaN の未使用の指数ビットは無視されます。結果は形式の精度を持ちます。

///|
test "decimal64 interchange in both encodings" {
  let x = @decimal.Decimal::from_string("1.25").unwrap()
  let fmt = @decimal.DecimalInterchangeFormat::Decimal64
  let (dpd, _) = x.to_interchange_hex(fmt)
  let (bid, _) = x.to_interchange_hex_with_encoding(
    fmt,
    @decimal.DecimalInterchangeEncoding::BID,
  )
  inspect(dpd, content="#22300000000000A5")
  inspect(bid, content="#318000000000007D")
  let back = @decimal.Decimal::from_interchange_hex(dpd, fmt).unwrap()
  inspect(back, content="1.25")
}

DecimalInterchange

DecimalInterchange は、1 つの交換形式の値の生のビットを、その形式とエンコーディングとともに保持します。

pub struct DecimalInterchange {
  // private fields
}
pub fn DecimalInterchange::format(Self) -> DecimalInterchangeFormat
pub fn DecimalInterchange::encoding(Self) -> DecimalInterchangeEncoding
pub fn DecimalInterchange::to_hex(Self) -> String

ビットを調べたり正確に保持したりする必要があるときに使用します。これには Decimal では表現できない非正準なエンコーディングも含まれます。to_hex は # と全幅の大文字の 16 進数字を書き出します。

DecimalInterchange::from_hex, from_hex_with_encoding, from_decimal, from_decimal_with_encoding

これらの関数はテキストまたは Decimal から交換形式の値を構築します。

pub fn DecimalInterchange::from_hex(String, DecimalInterchangeFormat) -> Self?
pub fn DecimalInterchange::from_hex_with_encoding(String, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> Self?
pub fn DecimalInterchange::from_decimal(Decimal, DecimalInterchangeFormat) -> (Self, DecimalFlags)
pub fn DecimalInterchange::from_decimal_with_encoding(Decimal, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> (Self, DecimalFlags)

from_hex はビットを変更せずに格納します(テキストの規則は from_interchange_hex と同じ)。from_decimal は to_interchange_hex と同様にエンコードし、同じフラグを返します。エンコーディングを指定しない版は DPD を使用します。

DecimalInterchange::to_decimal, to_decimal_ctx

これらの関数は格納されたビットをデコードします。

pub fn DecimalInterchange::to_decimal(Self) -> Decimal
pub fn DecimalInterchange::to_decimal_ctx(Self) -> (Decimal, DecimalFlags)

デコードは正確です。to_decimal_ctx はさらに、デコードした値がその形式で非正規化数であるとき subnormal を立てます。それ以外のフラグが立つことはありません。

DecimalInterchange::canonical, is_canonical

これらの関数は格納されたビットを正準化します。

pub fn DecimalInterchange::canonical(Self) -> Self
pub fn DecimalInterchange::is_canonical(Self) -> Bool

canonical は同じ形式とエンコーディングでデコードして再エンコードします。非正準な declet、範囲外の BID 係数、無限大や NaN の未使用ビットはすべて正準形に置き換えられます。これは冪等です。is_canonical はビットがすでに正準かどうかを判定します。

DecimalInterchange::copy, copy_abs, copy_negate, copy_sign

これらの関数は格納されたビットの符号ビットだけを変更します。

pub fn DecimalInterchange::copy(Self) -> Self
pub fn DecimalInterchange::copy_abs(Self) -> Self
pub fn DecimalInterchange::copy_negate(Self) -> Self
pub fn DecimalInterchange::copy_sign(Self, Self) -> Self

それ以外のビットは、正準かどうかにかかわらずすべて保持されます。copy_sign は両方のオペランドが同じ形式とエンコーディングでなければ中断します。

トレイト実装

代数トレイト

Decimal は素の演算子を通じて Luna-Flow の代数トレイトを実装します。

pub impl @luna-generic.Zero for Decimal
pub impl @luna-generic.One for Decimal
pub impl @luna-generic.AddMonoid for Decimal
pub impl @luna-generic.MulMonoid for Decimal
pub impl @luna-generic.AddGroup for Decimal
pub impl @luna-generic.Semiring for Decimal
pub impl @luna-generic.Ring for Decimal
pub impl @luna-generic.NatHomomorphism for Decimal
pub impl @luna-generic.IntegralHomomorphism for Decimal
pub impl Add for Decimal
pub impl Sub for Decimal
pub impl Mul for Decimal
pub impl Div for Decimal
pub impl Neg for Decimal
pub impl Eq for Decimal
pub impl Compare for Decimal

Zero::zero() と One::one() は Decimal::zero() と Decimal::one() です。和が丸められない限り(正確な係数がオペランドの精度に収まる和、および * は正確なのですべての積)、+、-、* について環の法則は正確に成り立ちます。丸められた和は近似的にしか結合的ではありません。from_nat と from_integral は構築の項で説明しています。

@def.Floating

Decimal は floating のスカラートレイトを実装します。

pub impl @def.Floating for Decimal

トレイトメソッドは classify、sign、precision、with_precision、normalized で、いずれも上で説明しています。@def.is_finite(x) などのジェネリックな述語はこれを通じて動作します。

contextual トレイト

Decimal は Luna-Flow/arithmetic の contextual トレイトを実装します。

pub fn Decimal::add_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sub_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::mul_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::div_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::abs_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::exp_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::zero_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::one_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::epsilon_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::min_normal_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::max_finite_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::classify_contextual(Self) -> @arithmetic.FpClass
pub impl @arithmetic.AddContextual for Decimal
pub impl @arithmetic.SubContextual for Decimal
pub impl @arithmetic.MulContextual for Decimal
pub impl @arithmetic.DivContextual for Decimal
pub impl @arithmetic.AbsContextual for Decimal
pub impl @arithmetic.SqrtContextual for Decimal
pub impl @arithmetic.ExpContextual for Decimal
pub impl @arithmetic.NumericFormatContextual for Decimal

各 *_contextual 演算は DecimalContext::from_arithmetic_context でコンテキストを変換し、対応する *_ctx 演算を実行して、division_by_zero が立てば Err(division_by_zero) を、それ以外の has_error のフラグが立てば Err(domain_error) を返し、そうでなければフラグからコピーした診断情報 inexact、rounded、overflow、underflow、subnormal、clamped とともに Ok を返します。変換後のコンテキストは既定の指数範囲を持つため、明示的な e_min/e_max なしの exp_contextual は domain_error(invalid_context)で失敗します。

zero_contextual と one_contextual はコンテキストの精度を持ちます。epsilon_contextual は 101−p10^{1-p}(next_plus(1) - 1)です。min_normal_contextual は 10emin⁡10^{e_{\min}}(既定は emin⁡=−999 999 999e_{\min} = -999\,999\,999)です。max_finite_contextual は (10p−1) 10emax⁡−p+1(10^{p}-1)\,10^{e_{\max}-p+1} です。classify_contextual は classify です。

checked トレイト

Decimal は Luna-Flow/arithmetic の checked トレイトを実装します。

pub fn Decimal::parse_checked(String, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_checked(Self, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::pow_nat_checked(Self, UInt, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::pow_int_checked(Self, Int, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub impl @arithmetic.ParseChecked for Decimal
pub impl @arithmetic.DivChecked for Decimal
pub impl @arithmetic.CompareChecked for Decimal
pub impl @arithmetic.SqrtChecked for Decimal
pub impl @arithmetic.PowNatChecked for Decimal
pub impl @arithmetic.PowIntChecked for Decimal

parse_checked(s, ctx) は Decimal::parse(s, precision=ctx.precision) です。DivChecked::div_checked(x, y, ctx) は変換後のコンテキストのもとでの div_ctx で、div_checked と同様に Err(division_by_zero) と Err(domain_error) を返します。sqrt_checked は変換後のコンテキストのもとでの sqrt_ctx で、負のオペランドに対して失敗します。pow_nat_checked と pow_int_checked は、整数の指数をコンテキスト精度の Decimal に変換した power_ctx です。底がゼロで指数が負なら Err(division_by_zero) を、無効な冪なら Err(domain_error) を返し、pow_nat_checked は 999,999,999 を超える指数に対して Err(unsupported) を返します。CompareChecked は compare_checked です。

Show と Debug

Decimal は Show と Debug を実装します。

pub impl Show for Decimal
pub fn Decimal::to_repr(Self) -> @debug.Repr

Show は to_string と output を提供します。to_repr は、debug_inspect や assert_eq が使う導出された構造的表現です。

公開インターフェース全体

このスナップショットは、パッケージの生成された pkg.generated.mbti です。説明文とインターフェースが食い違う場合は、こちらが正となります。

// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/decimal"

import {
  "Luna-Flow/arithmetic",
  "Luna-Flow/floating/bin_float",
  "Luna-Flow/floating/def",
  "Luna-Flow/luna-generic",
  "moonbitlang/core/bigint",
  "moonbitlang/core/debug",
}

// Values

// Errors

// Types and methods
pub struct Decimal {
  // private fields
} derive(@debug.Debug)
pub fn Decimal::abs(Self) -> Self
pub fn Decimal::abs_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::abs_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::acos_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::acosh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::add(Self, Self) -> Self
pub fn Decimal::add_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::add_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::apply_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::asin_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::asinh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::atan2_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::atan_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::atanh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::clamp(Self, min~ : Self, max~ : Self) -> Self
pub fn Decimal::clamp_checked(Self, min~ : Self, max~ : Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::class_name(Self, DecimalContext) -> String
pub fn Decimal::classify(Self) -> @arithmetic.FpClass
pub fn Decimal::classify_contextual(Self) -> @arithmetic.FpClass
pub fn Decimal::coefficient(Self) -> @bigint.BigInt
pub fn Decimal::compare(Self, Self) -> Int
pub fn Decimal::compare_checked(Self, Self) -> Result[Int, @arithmetic.ArithmeticError]
pub fn Decimal::compare_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_signal_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_total(Self, Self) -> Int
pub fn Decimal::compare_total_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::compare_total_magnitude(Self, Self) -> Int
pub fn Decimal::compare_total_magnitude_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::copy(Self) -> Self
pub fn Decimal::copy_abs(Self) -> Self
pub fn Decimal::copy_negate(Self) -> Self
pub fn Decimal::copy_sign(Self, Self) -> Self
pub fn Decimal::cos_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::cosh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::cospi_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::div(Self, Self) -> Self
pub fn Decimal::div_checked(Self, Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::div_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::div_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::divide_integer(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::epsilon_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::equal(Self, Self) -> Bool
pub fn Decimal::exp10_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::exp2_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::exp_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::exp_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::expm1_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::exponent10(Self) -> Int
pub fn Decimal::fma_ctx(Self, Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::from_bigint(@bigint.BigInt, precision? : Int) -> Self
pub fn Decimal::from_bin_float(@bin_float.BinFloat, precision? : Int) -> Self
pub fn Decimal::from_double(Double, precision? : Int) -> Self
pub fn Decimal::from_float(Float, precision? : Int) -> Self
pub fn Decimal::from_int(Int, precision? : Int) -> Self
pub fn[S : @luna-generic.Integral] Decimal::from_integral(S) -> Self
pub fn Decimal::from_interchange_hex(String, DecimalInterchangeFormat) -> Self?
pub fn Decimal::from_interchange_hex_with_encoding(String, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> Self?
pub fn[S : @luna-generic.Nat] Decimal::from_nat(S) -> Self
pub fn Decimal::from_string(String, precision? : Int) -> Self?
pub fn Decimal::from_string_ctx(String, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::get_payload(Self) -> @bigint.BigInt
pub fn Decimal::hypot_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::inf(@def.Sign, precision? : Int) -> Self
pub fn Decimal::is_canonical(Self) -> Bool
pub fn Decimal::is_finite(Self) -> Bool
pub fn Decimal::is_infinite(Self) -> Bool
pub fn Decimal::is_nan(Self) -> Bool
pub fn Decimal::is_negative(Self) -> Bool
pub fn Decimal::is_negative_zero(Self) -> Bool
pub fn Decimal::is_normal(Self, DecimalContext) -> Bool
pub fn Decimal::is_qnan(Self) -> Bool
pub fn Decimal::is_quiet_nan(Self) -> Bool
pub fn Decimal::is_signaling_nan(Self) -> Bool
pub fn Decimal::is_signed(Self) -> Bool
pub fn Decimal::is_snan(Self) -> Bool
pub fn Decimal::is_subnormal(Self, DecimalContext) -> Bool
pub fn Decimal::is_zero(Self) -> Bool
pub fn Decimal::ln_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log10_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log1p_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log2_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logb_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_and(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_invert(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_or(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_xor(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::magnitude(Self) -> @bigint.BigInt
pub fn Decimal::make(@bigint.BigInt, Int, Int, mode? : @arithmetic.RoundingMode) -> Self
pub fn Decimal::max(Self, Self) -> Self
pub fn Decimal::max_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::max_finite_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::max_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min(Self, Self) -> Self
pub fn Decimal::min_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min_normal_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::minimum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::mul(Self, Self) -> Self
pub fn Decimal::mul_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::mul_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::nan(precision? : Int) -> Self
pub fn Decimal::nan_payload(Self) -> @bigint.BigInt
pub fn Decimal::neg(Self) -> Self
pub fn Decimal::negative_zero(precision? : Int) -> Self
pub fn Decimal::next_minus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_plus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_toward(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::normalize_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::normalized(Self) -> Self
pub fn Decimal::not_equal(Self, Self) -> Bool
pub fn Decimal::one(precision? : Int) -> Self
pub fn Decimal::one_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::op_ge(Self, Self) -> Bool
pub fn Decimal::op_gt(Self, Self) -> Bool
pub fn Decimal::op_le(Self, Self) -> Bool
pub fn Decimal::op_lt(Self, Self) -> Bool
pub fn Decimal::output(Self, &Logger) -> Unit
pub fn Decimal::parse(String, precision? : Int) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::parse_checked(String, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::plus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::pow_int_checked(Self, Int, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::pow_nat_checked(Self, UInt, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::power_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::pown_ctx(Self, Int, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::precision(Self) -> Int
pub fn Decimal::quantize(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::quantum(Self) -> Int
pub fn Decimal::quiet_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self
pub fn Decimal::reduce_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_near(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rescale(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rootn_ctx(Self, Int, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rotate_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::same_quantum(Self, Self) -> Bool
pub fn Decimal::scaleb_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::set_payload(Self, @bigint.BigInt) -> Self
pub fn Decimal::set_payload_signaling(Self, @bigint.BigInt) -> Self
pub fn Decimal::shift_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sign(Self) -> @def.Sign
pub fn Decimal::signaling_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self
pub fn Decimal::sin_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sinh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sinpi_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sqrt(Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_checked(Self, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sub(Self, Self) -> Self
pub fn Decimal::sub_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sub_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::tan_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::tanh_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::tanpi_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_bin_float(Self, precision? : Int, mode? : @arithmetic.RoundingMode) -> @bin_float.BinFloat
pub fn Decimal::to_eng_string(String, DecimalContext) -> (String, DecimalFlags)
pub fn Decimal::to_integral_exact(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_integral_value(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_interchange_hex(Self, DecimalInterchangeFormat) -> (String, DecimalFlags)
pub fn Decimal::to_interchange_hex_with_encoding(Self, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> (String, DecimalFlags)
pub fn Decimal::to_repr(Self) -> @debug.Repr
pub fn Decimal::to_sci_string(String, DecimalContext) -> (String, DecimalFlags)
pub fn Decimal::to_string(Self) -> String
pub fn Decimal::trim(Self) -> Self
pub fn Decimal::try_acos_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_acosh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_asin_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_asinh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_atan2_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_atan_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_atanh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_cos_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_cosh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_cospi_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_exp10_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_exp2_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_exp_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_expm1_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_hypot_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_ln_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log10_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log1p_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log2_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_power_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_pown_ctx(Self, Int, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_rootn_ctx(Self, Int, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_sin_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_sinh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_sinpi_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_tan_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_tanh_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_tanpi_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::with_precision(Self, Int, @arithmetic.RoundingMode) -> Self
pub fn Decimal::zero(precision? : Int) -> Self
pub fn Decimal::zero_contextual(@arithmetic.ArithmeticContext) -> Self
pub impl @arithmetic.AbsContextual for Decimal
pub impl @arithmetic.AddContextual for Decimal
pub impl @arithmetic.CompareChecked for Decimal
pub impl @arithmetic.DivChecked for Decimal
pub impl @arithmetic.DivContextual for Decimal
pub impl @arithmetic.ExpContextual for Decimal
pub impl @arithmetic.MulContextual for Decimal
pub impl @arithmetic.NumericFormatContextual for Decimal
pub impl @arithmetic.ParseChecked for Decimal
pub impl @arithmetic.PowIntChecked for Decimal
pub impl @arithmetic.PowNatChecked for Decimal
pub impl @arithmetic.SqrtChecked for Decimal
pub impl @arithmetic.SqrtContextual for Decimal
pub impl @arithmetic.SubContextual for Decimal
pub impl @def.Floating for Decimal
pub impl @luna-generic.AddGroup for Decimal
pub impl @luna-generic.AddMonoid for Decimal
pub impl @luna-generic.IntegralHomomorphism for Decimal
pub impl @luna-generic.MulMonoid for Decimal
pub impl @luna-generic.NatHomomorphism for Decimal
pub impl @luna-generic.One for Decimal
pub impl @luna-generic.Ring for Decimal
pub impl @luna-generic.Semiring for Decimal
pub impl @luna-generic.Zero for Decimal
pub impl Add for Decimal
pub impl Compare for Decimal
pub impl Div for Decimal
pub impl Eq for Decimal
pub impl Mul for Decimal
pub impl Neg for Decimal
pub impl Show for Decimal
pub impl Sub for Decimal

pub struct DecimalContext {
  // private fields
} derive(Eq)
pub fn DecimalContext::clamp(Self) -> Bool
pub fn DecimalContext::decimal128() -> Self
pub fn DecimalContext::decimal32() -> Self
pub fn DecimalContext::decimal64() -> Self
pub fn DecimalContext::decimal_rounding(Self) -> DecimalRoundingMode
pub fn DecimalContext::e_max(Self) -> Int
pub fn DecimalContext::e_min(Self) -> Int
pub fn DecimalContext::equal(Self, Self) -> Bool
pub fn DecimalContext::exact() -> Self
pub fn DecimalContext::extended(Self) -> Bool
pub fn DecimalContext::from_arithmetic_context(@arithmetic.ArithmeticContext) -> Self
pub fn DecimalContext::ieee754(Self) -> Self
pub fn DecimalContext::is754version2019(Self) -> Bool
pub fn DecimalContext::new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Self
pub fn DecimalContext::not_equal(Self, Self) -> Bool
pub fn DecimalContext::precision(Self) -> Int
pub fn DecimalContext::rounding(Self) -> @arithmetic.RoundingMode
pub fn DecimalContext::tininess(Self) -> DecimalTininessDetection
pub fn DecimalContext::try_new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Result[Self, @arithmetic.ArithmeticError]
pub fn DecimalContext::with_rounding(Self, @arithmetic.RoundingMode) -> Self
pub fn DecimalContext::with_tininess(Self, DecimalTininessDetection) -> Self

pub struct DecimalFlags {
  inexact : Bool
  rounded : Bool
  lost_digits : Bool
  invalid_operation : Bool
  division_by_zero : Bool
  overflow : Bool
  underflow : Bool
  subnormal : Bool
  clamped : Bool
  conversion_syntax : Bool
  division_impossible : Bool
  division_undefined : Bool
  invalid_context : Bool
} derive(Eq)
pub fn DecimalFlags::combine(Self, Self) -> Self
pub fn DecimalFlags::contains(Self, DecimalSignal) -> Bool
pub fn DecimalFlags::equal(Self, Self) -> Bool
pub fn DecimalFlags::has_error(Self) -> Bool
pub fn DecimalFlags::new() -> Self
pub fn DecimalFlags::not_equal(Self, Self) -> Bool

pub struct DecimalInterchange {
  // private fields
}
pub fn DecimalInterchange::canonical(Self) -> Self
pub fn DecimalInterchange::copy(Self) -> Self
pub fn DecimalInterchange::copy_abs(Self) -> Self
pub fn DecimalInterchange::copy_negate(Self) -> Self
pub fn DecimalInterchange::copy_sign(Self, Self) -> Self
pub fn DecimalInterchange::encoding(Self) -> DecimalInterchangeEncoding
pub fn DecimalInterchange::format(Self) -> DecimalInterchangeFormat
pub fn DecimalInterchange::from_decimal(Decimal, DecimalInterchangeFormat) -> (Self, DecimalFlags)
pub fn DecimalInterchange::from_decimal_with_encoding(Decimal, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> (Self, DecimalFlags)
pub fn DecimalInterchange::from_hex(String, DecimalInterchangeFormat) -> Self?
pub fn DecimalInterchange::from_hex_with_encoding(String, DecimalInterchangeFormat, DecimalInterchangeEncoding) -> Self?
pub fn DecimalInterchange::is_canonical(Self) -> Bool
pub fn DecimalInterchange::to_decimal(Self) -> Decimal
pub fn DecimalInterchange::to_decimal_ctx(Self) -> (Decimal, DecimalFlags)
pub fn DecimalInterchange::to_hex(Self) -> String

pub(all) enum DecimalInterchangeEncoding {
  DPD
  BID
} derive(Eq)
pub fn DecimalInterchangeEncoding::equal(Self, Self) -> Bool
pub fn DecimalInterchangeEncoding::not_equal(Self, Self) -> Bool

pub(all) enum DecimalInterchangeFormat {
  Decimal32
  Decimal64
  Decimal128
} derive(Eq)
pub fn DecimalInterchangeFormat::context(Self) -> DecimalContext
pub fn DecimalInterchangeFormat::equal(Self, Self) -> Bool
pub fn DecimalInterchangeFormat::not_equal(Self, Self) -> Bool

pub(all) enum DecimalRoundingMode {
  HalfEven
  HalfUp
  HalfDown
  Down
  Ceiling
  Floor
  Up
  ZeroFiveUp
} derive(Eq)
pub fn DecimalRoundingMode::equal(Self, Self) -> Bool
pub fn DecimalRoundingMode::from_arithmetic(@arithmetic.RoundingMode) -> Self
pub fn DecimalRoundingMode::not_equal(Self, Self) -> Bool
pub fn DecimalRoundingMode::to_arithmetic(Self) -> @arithmetic.RoundingMode?

pub(all) enum DecimalSignal {
  ConversionSyntax
  DivisionByZero
  DivisionImpossible
  DivisionUndefined
  InvalidContext
  InvalidOperation
  Overflow
  Underflow
  Subnormal
  Inexact
  Rounded
  Clamped
  LostDigits
} derive(Eq)
pub fn DecimalSignal::equal(Self, Self) -> Bool
pub fn DecimalSignal::not_equal(Self, Self) -> Bool

pub(all) enum DecimalTininessDetection {
  BeforeRounding
  AfterRounding
} derive(Eq)
pub fn DecimalTininessDetection::equal(Self, Self) -> Bool
pub fn DecimalTininessDetection::not_equal(Self, Self) -> Bool

// Type aliases

// Traits