decimal_gda API

decimal_gda 实现了 M. F. Cowlishaw 的 General Decimal Arithmetic 规范(GDA,1.70 版)。其 Decimal 由符号、任意长度的十进制系数和十进制指数组成;其 GdaContext 携带精度、舍入模式、指数限制、钳制、扩展/子集开关、粘滞状态以及已启用的陷阱;每个 GDA 运算都是纯函数,返回一个 GdaOutcome,其中包含所定义的结果、下一个上下文以及它所引发的条件。教程展示了该包的用法;设计页面推导了此处陈述的规则。

该包不依赖 IEEE 754 包 decimal。除 GDA 接口外,它还公开一个更底层、无状态的层——DecimalContext、DecimalFlags 以及 Decimal::*_ctx 方法,GDA 函数即构建于其上——以及面向 Luna-Flow/arithmetic 和 Luna-Flow/luna-generic trait 的适配器。

全文中,有限值记作 (−1)s⋅c⋅10e(-1)^s \cdot c \cdot 10^{e},其中系数 c≥0c \ge 0,指数为 ee;其调整后指数为 e^=e+digits⁡(c)−1\hat e = e + \operatorname{digits}(c) - 1,即其首位数字的指数。对于精度为 pp 的上下文,Etiny=emin⁡−p+1E_{\mathrm{tiny}} = e_{\min} - p + 1 是结果可以具有的最小指数。

Decimal 值

Decimal

Decimal 是不可变的 GDA 数:有限值、无穷、静默 NaN 或信号 NaN。

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

有限值保留其指数,因此 2.50 与 2.5 是同一同值类的不同成员:它们在数值上比较相等,但在 compare_total、same_quantum 和打印上有所不同。零带有符号。NaN 携带符号和非负整数载荷。每个值还存储一个精度属性(precision()),即产生它的上下文或构造函数的精度;GDA 运算忽略它,而改用上下文精度。系数以持久化的十进制分段(limb)数组存储,因此值可以自由共享。

Decimal::zero, Decimal::negative_zero, Decimal::one

它们分别返回 +0+0、−0-0 和 11,指数均为 0。

pub fn Decimal::zero(precision? : Int) -> Self
pub fn Decimal::negative_zero(precision? : Int) -> Self
pub fn Decimal::one(precision? : Int) -> Self

precision(默认 34,至少钳制为 1)仅是所存储的精度属性。

Decimal::inf, Decimal::nan, Decimal::quiet_nan, Decimal::signaling_nan

这些函数构建特殊值。

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

inf(Negative) 为 −∞-\infty;其他任何 Sign 都得到 +∞+\infty。nan() 是载荷为 0 的正静默 NaN。载荷以其绝对值存储。信号 NaN 在被算术运算使用时引发 InvalidOperation,并被替换为符号和载荷相同的静默 NaN。

Decimal::make

make(c, e, p) 返回舍入到 p 位有效数字并去除尾随零的 c⋅10ec \cdot 10^{e}。

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

符号取自 c 的符号。舍入使用 mode(默认 ToNearestEven)。由于尾随零会被去除,make(1200, 0, 34) 为 1.2E+3;当量子重要时,请从字符串构建。不报告任何标志。

Decimal::from_int, Decimal::from_bigint, Decimal::from_double, Decimal::from_float, Decimal::from_bin_float

这些函数将二进制值转换为十进制,按半值取偶舍入到 precision 位,并去除尾随零。

pub fn Decimal::from_int(Int, precision? : Int) -> Self
pub fn Decimal::from_bigint(@bigint.BigInt, 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_bin_float(@bin_float.BinFloat, precision? : Int) -> Self

precision 默认为 34(对 from_bin_float 而言默认为参数的精度)。k<0k < 0 的二进制浮点数 m⋅2km \cdot 2^{k} 首先被精确写成 m5−k⋅10km 5^{-k} \cdot 10^{k},因此只要结果能容纳于 precision 位,转换就是精确的;例如 from_double(0.1) 是最接近 0.10.1 的 binary64 值舍入到 34 位的结果。NaN 变为静默 NaN(from_double 保留符号),无穷保留符号,零保留符号(from_bin_float 返回 +0+0)。from_int(100) 为 1E+2。

Decimal::to_bin_float

to_bin_float 将值舍入为具有 precision 位有效二进制位的 BinFloat。

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

precision 默认为所存储的精度属性,mode 默认为 ToNearestEven。用 TowardNegative 和 TowardPositive 得到的两个结果包住该十进制值;初等函数正是借此构建其经过认证的输入区间。零映射为 +0+0,NaN 映射为二进制 NaN。

Decimal::parse, Decimal::from_string

这些函数在没有 GDA 上下文的情况下读取 GDA 数值字符串。

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

可接受的语法为 GDA 数值字符串文法:可选符号、带可选小数点的数字、可选指数 E±n,或者 Infinity/Inf/NaN/sNaN(不区分大小写)并可带十进制 NaN 载荷。指数被精确保留,因此 from_string("2.50") 的指数为 −2-2。有效数字多于 precision(默认 34)位的字面量按半值取偶舍入,并去除尾随零。格式错误的字面量得到 Err(parse_error) 或 None。当必须应用上下文的指数限制、标志、状态或陷阱时,请使用包函数 parse。

Decimal::to_string, Decimal::output

这些函数以 GDA 科学记数法打印值,特殊值使用小写。

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

满足 e≤0e \le 0 且 e^≥−6\hat e \ge -6 的有限值不带指数打印(0.000123、7.50);否则打印一位数字、小数点后的其余数字以及 E±e^\hat e(1.23E+7、1E-7、0E+2)。无穷打印为 inf/-inf,NaN 打印为 nan、snan、-nan,载荷非零时后跟载荷。若要使用 GDA 写法 Infinity/NaN/sNaN,请使用 Decimal::to_sci_string。

Decimal::to_sci_string, Decimal::to_eng_string

这些函数在 DecimalContext 下转换数值字符串,并以 GDA 的 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)

字符串的转换方式与 Decimal::from_string_ctx 完全相同(舍入到上下文,并返回转换标志),然后再格式化。工程记数法使用 3 的倍数作为指数(123E+5 打印为 12.3E+6)。特殊值打印为 Infinity、-Infinity、NaN、sNaN,并带载荷。

Decimal::from_string_ctx

from_string_ctx 是无状态上下文下的 GDA to-number 转换。

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

字面量被舍入到上下文精度,按指数范围检查(上溢、次正规、下溢、钳制),并连同其标志一起返回。格式错误的输入返回带 conversion_syntax 的静默 NaN。在非扩展上下文中,无穷与 NaN 本身就是转换语法错误,且零会丢失其符号和指数。

///|
test "Decimal construction and printing" {
  inspect(@decimal_gda.Decimal::from_string("2.50").unwrap(), content="2.50")
  inspect(@decimal_gda.Decimal::from_int(100), content="1E+2")
  inspect(@decimal_gda.Decimal::make(12345N, -2, 3), content="123")
  inspect(@decimal_gda.Decimal::from_double(0.5), content="0.5")
  inspect(@decimal_gda.Decimal::signaling_nan(payload=7N), content="snan7")
  inspect(@decimal_gda.Decimal::from_string("1.2.3") is None, content="true")
  let ctx = @decimal_gda.DecimalContext::new(precision=3)
  let (v, flags) = @decimal_gda.Decimal::from_string_ctx("1.2345", ctx)
  inspect(v, content="1.23")
  inspect(flags.inexact, content="true")
  let (sci, _) = @decimal_gda.Decimal::to_sci_string("-sNaN12", ctx)
  inspect(sci, content="-sNaN12")
}

观察值

Decimal::classify, Decimal::sign, Decimal::precision

这些函数报告类别、数值符号以及所存储的精度属性。

pub fn Decimal::classify(Self) -> @arithmetic.FpClass
pub fn Decimal::sign(Self) -> @def.Sign
pub fn Decimal::precision(Self) -> Int

classify 返回 Finite、Infinity 或 NaN。sign 对任一符号的零以及 NaN 返回 Zero,否则返回 Positive/Negative;若要读取符号位,请使用 is_negative。

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

这些函数暴露所存储的表示 (c,e)(c, e)。

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

coefficient 和 magnitude 都返回 c≥0c \ge 0(对 NaN 为载荷,对无穷为 0)。exponent10 和 quantum 都返回 ee(对特殊值为 0)。

Decimal::is_finite, Decimal::is_infinite, Decimal::is_nan, Decimal::is_zero, Decimal::is_negative, Decimal::is_signed, Decimal::is_negative_zero

这些是类别与符号谓词。

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(Self) -> Bool
pub fn Decimal::is_signed(Self) -> Bool
pub fn Decimal::is_negative_zero(Self) -> Bool

is_negative 与 is_signed 相同:它们读取符号位,因此对 −0-0、−∞-\infty 和负 NaN 为真。is_zero 对任意指数的有限零为真。

Decimal::is_quiet_nan, Decimal::is_qnan, Decimal::is_signaling_nan, Decimal::is_snan

这些函数区分静默 NaN 与信号 NaN;每一对互为别名。

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

Decimal::is_canonical

is_canonical 总是返回 true:每个 Decimal 值都是规范的(只有交换编码可能是非规范的,参见 GdaInterchange::is_canonical)。

pub fn Decimal::is_canonical(Self) -> Bool

Decimal::nan_payload, Decimal::get_payload, Decimal::set_payload, Decimal::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 将 NaN 变为带给定载荷且符号不变的静默 NaN;set_payload_signaling 则使其成为信号 NaN。二者对非 NaN 值都原样返回。

Decimal::is_normal, Decimal::is_subnormal, Decimal::class_name

这些函数依据 DecimalContext 的指数范围对值进行分类。

pub fn Decimal::is_normal(Self, DecimalContext) -> Bool
pub fn Decimal::is_subnormal(Self, DecimalContext) -> Bool
pub fn Decimal::class_name(Self, DecimalContext) -> String

非零有限值在 e^≥emin⁡\hat e \ge e_{\min} 时为正规数,在 e^<emin⁡\hat e < e_{\min} 时为次正规数;零、无穷与 NaN 两者都不是。class_name 返回 GDA 类别字符串:sNaN、NaN、-Infinity、+Infinity、-Zero、+Zero、-Subnormal、+Subnormal、-Normal 或 +Normal。接受 GdaContext 的 GDA 形式是包函数 class_name、is_normal、is_subnormal。

符号、同值类与精度变换

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

这些函数只改变符号位;它们从不舍入,也从不发出信号,即使对信号 NaN 也是如此。

pub fn Decimal::neg(Self) -> Self
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

neg 和 copy_negate 翻转符号,abs 和 copy_abs 清除符号,copy 返回该值,copy_sign(x, y) 赋予 x 以 y 的符号位。这些是 GDA 的 copy 运算;会舍入的版本是包函数 minus、plus、abs。

Decimal::normalized, Decimal::trim, Decimal::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 按半值取偶舍入到所存储的精度,并去除所有尾随零(7.50 变为 7.5,1200 变为 1.2E+3)。trim 只去除小数部分的尾随零,且从不使指数变为正(7.50 变为 7.5,1200 保持 1200);零变为指数为 0 的 0。with_precision(p, mode) 以 mode 舍入到 p 位,去除尾随零并设置精度属性;特殊值只获得新的属性。它们都不报告标志。

Decimal::same_quantum

same_quantum 检测两个值是否具有相同的指数。

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

对于指数相等的两个有限值、两个无穷以及两个 NaN,它为真,否则为假。

GDA 上下文

GdaContext

GdaContext 是不可变的 GDA 上下文:算术策略加上粘滞状态,再加上已启用的陷阱。

pub struct GdaContext {
  // private fields
}

策略包括精度 p≥1p \ge 1、一个 GdaRoundingMode、emin⁡≤emax⁡e_{\min} \le e_{\max}、clamp 以及 extended。状态是一个 GdaFlags 值,运算只会使它增大;陷阱是一个 GdaTrapSet。状态和陷阱都不影响运算的数值结果:它们只决定下一个上下文,以及结果是 Completed 还是 Trapped。

GdaContext::new, GdaContext::try_new

这些函数构建状态为空的上下文。

pub fn GdaContext::new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Self
pub fn GdaContext::try_new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Result[Self, @arithmetic.ArithmeticError]

默认值:precision=34、rounding=HalfEven、e_min=-999_999_999、e_max=999_999_999、clamp=false、extended=true,无陷阱。new 在 precision <= 0 或 e_min > e_max 时中止;try_new 则返回 Err(domain_error)。clamp=true 像交换格式那样将指数限制为 emax⁡−p+1e_{\max} - p + 1。extended=false 选择 GDA 子集算术:长于 pp 位的操作数先被舍入(若不精确则引发 LostDigits),特殊值无法解析,零以及某些结果会被规范化,且 fma 无效。

GdaContext::basic, GdaContext::default, GdaContext::decimal32, GdaContext::decimal64, GdaContext::decimal128

这些函数返回标准上下文。

pub fn GdaContext::basic() -> Self
pub fn GdaContext::default() -> Self
pub fn GdaContext::decimal32() -> Self
pub fn GdaContext::decimal64() -> Self
pub fn GdaContext::decimal128() -> Self
上下文pp舍入emin⁡e_{\min}emax⁡e_{\max}clamp扩展陷阱
basic, default9HalfUp−999 999 999-999\,999\,999999 999 999999\,999\,999否否DivisionByZero、InvalidOperation、Overflow、Underflow、Clamped
decimal327HalfEven−95-959696是是无
decimal6416HalfEven−383-383384384是是无
decimal12834HalfEven−6143-614361446144是是无

basic 是 GDA 的基本默认上下文;default 是同一个值。这些值只创建一次并共享。

context, decimal32_context, decimal64_context, decimal128_context

这些包函数是 GdaContext::new(不带陷阱参数)以及三个交换格式预设的简写。

pub fn context(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool) -> GdaContext
pub fn decimal32_context() -> GdaContext
pub fn decimal64_context() -> GdaContext
pub fn decimal128_context() -> GdaContext

GdaContext::precision, GdaContext::rounding, GdaContext::e_min, GdaContext::e_max, GdaContext::clamp, GdaContext::extended, GdaContext::radix

这些函数读取算术策略。

pub fn GdaContext::precision(Self) -> Int
pub fn GdaContext::rounding(Self) -> GdaRoundingMode
pub fn GdaContext::e_min(Self) -> Int
pub fn GdaContext::e_max(Self) -> Int
pub fn GdaContext::clamp(Self) -> Bool
pub fn GdaContext::extended(Self) -> Bool
pub fn GdaContext::radix(Self) -> Int

radix 总是返回 10。

GdaContext::status, GdaContext::traps

这些函数读取粘滞状态和已启用的陷阱。

pub fn GdaContext::status(Self) -> GdaFlags
pub fn GdaContext::traps(Self) -> GdaTrapSet

GdaContext::trap, GdaContext::with_traps, GdaContext::clear_status, GdaContext::reset

这些函数返回陷阱或状态被修改后的新上下文;接收者本身不被修改。

pub fn GdaContext::trap(Self, GdaSignal, enabled? : Bool) -> Self
pub fn GdaContext::with_traps(Self, GdaTrapSet) -> Self
pub fn GdaContext::clear_status(Self) -> Self
pub fn GdaContext::reset(Self) -> Self

trap(s) 启用(或在 enabled=false 时禁用)一个陷阱;with_traps 替换整个集合。clear_status 清空状态并保留陷阱;reset 将两者都清空。

GdaRoundingMode

GdaRoundingMode 列出八种 GDA 舍入模式。

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

当精确结果严格位于两个可表示的相邻值之间时,Down 取更接近零的一个,Up 取离零更远的一个,Ceiling 取较大者,Floor 取较小者;HalfEven、HalfUp 和 HalfDown 取较近的一个,恰好处于中点时分别取末位为偶数者、远离零、趋向零;ZeroFiveUp 向零舍入,除非这样得到的末位数字为 0 或 5,此时改为远离零舍入。设计页面以公式给出了每种模式。

信号、标志与陷阱

GdaSignal

GdaSignal 指定十三种 GDA 条件。

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

GDA 信号为 Clamped、DivisionByZero、Inexact、InvalidOperation、Overflow、Rounded、Subnormal 和 Underflow。ConversionSyntax、DivisionImpossible、DivisionUndefined 和 InvalidContext 是规范通过 InvalidOperation 信号报告的条件;本包将它们保留为独立的标志和陷阱,以便加以区分。LostDigits 仅在子集算术中引发。

GdaFlags

GdaFlags 是条件的集合,既用于表示单个运算引发的条件,也用于表示上下文的粘滞状态。

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

字段是只读的;请用 none 和 combine(逐字段并集)构建集合。contains(s) 读取 s 对应的字段,但 contains(InvalidOperation) 例外:只要 invalid_operation、conversion_syntax、division_impossible、division_undefined 或 invalid_context 中任一被设置,它即为真。

GdaTrapSet

GdaTrapSet 是已启用陷阱的集合。

pub struct GdaTrapSet {
  conversion_syntax : Bool
  division_by_zero : Bool
  division_impossible : Bool
  division_undefined : Bool
  invalid_context : Bool
  invalid_operation : Bool
  overflow : Bool
  underflow : Bool
  subnormal : Bool
  inexact : Bool
  rounded : Bool
  clamped : Bool
  lost_digits : Bool
} derive(Eq)
pub fn GdaTrapSet::none() -> Self
pub fn GdaTrapSet::with_signal(Self, GdaSignal, enabled? : Bool) -> Self
pub fn GdaTrapSet::contains(Self, GdaSignal) -> Bool
pub fn GdaTrapSet::equal(Self, Self) -> Bool
pub fn GdaTrapSet::not_equal(Self, Self) -> Bool

with_signal(s) 启用一个陷阱(或在 enabled=false 时禁用);contains(s) 恰好读取 s 对应的字段。

GdaOutcome

GdaOutcome[T] 是每个 GDA 运算的结果。

pub(all) enum GdaOutcome[T] {
  Completed(T, GdaContext, GdaFlags)
  Trapped(GdaSignal, T, GdaContext, GdaFlags)
}
pub fn[T] GdaOutcome::value(Self[T]) -> T
pub fn[T] GdaOutcome::next_context(Self[T]) -> GdaContext
pub fn[T] GdaOutcome::raised(Self[T]) -> GdaFlags

两个变体都携带 GDA 定义的结果、下一个上下文以及本次运算引发的条件;Trapped 还指明所触发的陷阱。value、next_context 和 raised 无需模式匹配即可读取公共字段。

陷阱选择

每个 GDA 函数都以相同的方式结束。设 RR 为运算引发的条件,CC 为输入上下文。

  1. 若 RR 为空,结果为 Completed(v, C, none):返回的正是同一个上下文。
  2. 否则,下一个上下文是状态为 C.status∪RC.\mathrm{status} \cup R 的 CC;只要 RR 包含四种细分无效条件之一,invalid_operation 标志也会被设置。
  3. 被捕获的信号是按以下顺序中第一个同时满足 raised.contains(s) 与 traps.contains(s) 的 ss:InvalidOperation、DivisionByZero、DivisionUndefined、DivisionImpossible、InvalidContext、ConversionSyntax、Overflow、Underflow、Subnormal、Inexact、Rounded、Clamped、LostDigits。若存在这样的信号,结果为 Trapped(s, v, C', R),否则为 Completed(v, C', R)。

由于 contains(InvalidOperation) 涵盖了各细分无效条件,InvalidOperation 陷阱会捕获所有这些条件,并且优先于针对细分条件本身的陷阱。

///|
test "GDA context, status and traps" {
  let ctx = @decimal_gda.GdaContext::decimal64()
    .trap(DivisionUndefined)
    .trap(InvalidOperation)
  let zero = @decimal_gda.Decimal::zero()
  let out = @decimal_gda.divide(zero, zero, ctx) // 0/0
  inspect(out.value(), content="nan")
  inspect(out.raised().division_undefined, content="true")
  inspect(out.raised().contains(InvalidOperation), content="true")
  match out {
    @decimal_gda.GdaOutcome::Trapped(signal, _, _, _) =>
      inspect(signal == InvalidOperation, content="true")
    @decimal_gda.GdaOutcome::Completed(_, _, _) => fail("expected a trap")
  }
  inspect(out.next_context().status().invalid_operation, content="true")
  inspect(ctx.status() == @decimal_gda.GdaFlags::none(), content="true")
  inspect(ctx.reset().traps() == @decimal_gda.GdaTrapSet::none(), content="true")
}

GDA 运算

本节中的每个函数都接受其操作数和一个 GdaContext,舍入到该上下文,并返回按陷阱选择规则构建的 GdaOutcome。信号 NaN 操作数引发 InvalidOperation 并产生对应的静默 NaN;静默 NaN 操作数直接传播,不引发任何条件(第一个 NaN 操作数优先)。在子集上下文(extended=false)中,长于精度的有限操作数会先被舍入。除非另有说明,结果是精确数学结果只舍入一次所得;当结果精确时,其指数为该运算所列的理想指数。

parse

parse 是对字符串进行的 GDA to-number 转换。

pub fn parse(String, GdaContext) -> GdaOutcome[Decimal]

字面量保留其指数,除非必须舍入到精度或钳制到指数范围。格式错误的文本得到带 ConversionSyntax 的静默 NaN。在子集上下文中,无穷与 NaN 也属于转换语法错误。

apply, plus, minus, abs

这些函数将单个操作数舍入到上下文:plus 即 0+x0 + x,minus 即 0−x0 - x,abs 即 ∣x∣|x|,apply 则是将值直接转换到上下文。

pub fn apply(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn plus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn minus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn abs(Decimal, GdaContext) -> GdaOutcome[Decimal]

理想指数:操作数的指数。plus、minus 和 abs 将零结果返回为 +0+0;apply 保留零的符号,且不会先舍入子集操作数。

add, subtract, multiply, divide, fma

这些是基本算术运算;fma(a, b, c) 是只舍入一次的 a×b+ca \times b + c。

pub fn add(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn subtract(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn multiply(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn divide(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn fma(Decimal, Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

理想指数:add 和 subtract 为 min⁡(e1,e2)\min(e_1, e_2);multiply 为 e1+e2e_1 + e_2;divide 为 e1−e2e_1 - e_2(不精确的商具有完整的 pp 位系数);fma 则将 add 的规则应用于精确乘积与加数。精确的零和为 +0+0;当两个操作数均为负或模式为 Floor 时为 −0-0。特殊情形:∞−∞\infty - \infty、0×∞0 \times \infty 与 ∞/∞\infty / \infty 是无效的;x/0x / 0 为 ±∞\pm\infty 并带 DivisionByZero;0/00 / 0 为带 DivisionUndefined 的 NaN;x/∞x / \infty 是指数为 EtinyE_{\mathrm{tiny}} 的零并带 Clamped。在子集上下文中 fma 是无效的。

divide_integer, remainder, remainder_near

这些函数做除法得到整数商。

pub fn divide_integer(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn remainder(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn remainder_near(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

divide_integer 返回指数为 0 的 q=trunc⁡(x/y)q = \operatorname{trunc}(x / y);remainder 返回 x−qyx - q y(符号与 xx 相同);remainder_near 返回 x−nyx - n y,其中 nn 是将 x/yx / y 就近舍入(偶数优先)得到的整数。余数的理想指数为 min⁡(ex,ey)\min(e_x, e_y)。当 qq(或 nn)需要多于 pp 位数字时,结果为带 DivisionImpossible 的 NaN。除数为零时得到 DivisionByZero(非零数的 divide_integer)或 DivisionUndefined(0/00 / 0);除数为零或被除数为无穷都会使两种余数无效;有限被除数除以无穷除数时,余数就是被除数本身。

quantize, rescale

这些函数将值舍入到指定的指数。

pub fn quantize(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn rescale(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

quantize(x, q) 返回指数为 eqe_q 的 xx 的值,并以上下文模式舍入(引发 Rounded,丢失数字时还引发 Inexact)。rescale(x, n) 以指数 nn 做同样的事,其中 nn 必须是整数值。当目标指数位于 [Etiny,emax⁡][E_{\mathrm{tiny}}, e_{\max}](子集上下文中为 [emin⁡,emax⁡][e_{\min}, e_{\max}])之外、结果系数需要多于 pp 位数字,或恰有一个操作数为无穷时,结果无效。两个无穷得到该无穷。量化结果从不引发 Underflow。

to_integral_exact, to_integral_value

这些函数以上下文舍入模式舍入到整数。

pub fn to_integral_exact(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn to_integral_value(Decimal, GdaContext) -> GdaOutcome[Decimal]

指数为负的值被量化到指数 0;丢弃数字时 to_integral_exact 引发 Inexact 和 Rounded,而 to_integral_value 从不引发。指数 ≥0\ge 0 的值经由 apply 处理,因此若它长于 pp 位,就会被舍入到上下文精度。11 GDA 参考实现会原样返回此类操作数;例如在精度 3 下,它将 12345 映射为 12345,而本包返回带 Inexact 的 1.23E+4。所固定的测试套件中没有这样的用例。

sqrt, exp, ln, log10

这些是正确舍入的平方根、指数函数、自然对数和以 10 为底的对数。

pub fn sqrt(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn exp(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn ln(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn log10(Decimal, GdaContext) -> GdaOutcome[Decimal]

无论上下文舍入模式为何,它们总是按半值取偶舍入。精确结果:完全平方数的 sqrt 具有理想指数 ⌊e/2⌋\lfloor e/2 \rfloor;exp(0) = 1;ln(1) = 0;10 的幂 10k10^k 的 log10 为整数 kk。其他所有有限结果都是不精确的,具有 pp 位数字。定义域:负数的平方根和对数是无效的,ln⁡0=log⁡100=−∞\ln 0 = \log_{10} 0 = -\infty,exp⁡(−∞)=0\exp(-\infty) = 0,且四者都将 +∞+\infty 映射为 +∞+\infty。除非 pp、emax⁡e_{\max} 和 −emin⁡-e_{\min} 都不超过 999,999,否则 exp、ln 和 log10 会引发 InvalidContext。若认证求值无法在其细化预算内确定舍入,结果为带 InvalidOperation 的 NaN。在子集上下文中,ln 重现经典参考算法的结果,该结果可能比正确舍入的结果大一个末位单位。

power

power(x, y) 即 xyx^y。

pub fn power(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

对整数 yy,结果通过二进制幂算法以 p+digits⁡(∣y∣)+2p + \operatorname{digits}(|y|) + 2 位工作精度(子集上下文中少一位)计算,然后以上下文模式舍入;能容纳于 pp 位的精确幂以指数 y⋅exy \cdot e_x 精确返回。对非整数 yy,xx 必须为正(负底数无效),并且结果经认证是按上下文舍入模式正确舍入的;y=0.5y = 0.5 按上下文舍入模式作为平方根计算。对非整数指数施加与 exp 相同的上下文限制。特殊情形遵循 GDA:x0=1x^0 = 1(而 000^0 无效),±∞\pm\infty 和 ±0\pm 0 的幂的符号取决于整数指数的奇偶性,且 1y=11^y = 1。

reduce

reduce 舍入到上下文并去除尾随零。

pub fn reduce(Decimal, GdaContext) -> GdaOutcome[Decimal]

零变为指数为 0 的 00(在扩展上下文中保留其符号)。在钳制上下文中,指数不会被提高到 emax⁡−p+1e_{\max} - p + 1 以上。

scaleb, logb

这些函数按 10 的幂进行缩放,并提取调整后指数。

pub fn scaleb(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logb(Decimal, GdaContext) -> GdaOutcome[Decimal]

scaleb(x, n) 通过将 nn 加到指数上返回 x⋅10nx \cdot 10^n;nn 必须是指数为 0 且满足 ∣n∣≤2(emax⁡+p)|n| \le 2(e_{\max} + p) 的整数,否则结果无效。之后对结果进行上溢、次正规和钳制检查。logb(x) 以整数形式返回 e^\hat e;logb(0) 为带 DivisionByZero 的 −∞-\infty,logb(±∞) 为 +∞+\infty。

next_plus, next_minus, next_toward

这些函数步进到相邻的可表示值。

pub fn next_plus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn next_minus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn next_toward(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

next_plus 返回上下文中大于 xx 的最小可表示数,next_minus 返回比它小的最大可表示数;从零出发时它们步进到 ±10Etiny\pm 10^{E_{\mathrm{tiny}}},越过最大有限数时到达 ±∞\pm\infty。对有限结果,二者都不引发标志。next_toward(x, y) 从 xx 朝 yy 步进(当二者比较相等时返回 xx,对零则取 yy 的符号);当这一步离开正规范围时,引发 Overflow,或 Underflow 和 Subnormal,并同时引发 Inexact 和 Rounded。

logical_and, logical_or, logical_xor, logical_invert

这些是对逻辑操作数(指数为 0、各位均为 0 或 1 的非负整数)的逐位逻辑运算。

pub fn logical_and(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_or(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_xor(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_invert(Decimal, GdaContext) -> GdaOutcome[Decimal]

每个操作数都恰好按 pp 位读取:较短的操作数以前导零填充,较长的只使用其低 pp 位。logical_invert 对全部 pp 位取反。任何其他操作数都会使结果无效。

shift, rotate

这些函数在 pp 位的窗口内将 xx 的系数数字移动 nn 位。

pub fn shift(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn rotate(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

nn 必须是指数为 0 且满足 ∣n∣≤p|n| \le p 的整数,否则结果无效。正的 nn 将数字向左移动。shift 丢弃移出窗口的数字并以零填充;rotate 将它们循环移到另一端。指数与符号不变;无穷的 xx 原样返回。

compare, compare_signal, compare_total, compare_total_magnitude

这些函数比较两个值。

pub fn compare(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn compare_signal(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn compare_total(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]
pub fn compare_total_magnitude(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]

compare 按数值返回十进制值 −1-1、00 或 11(−0=+0-0 = +0,2.50=2.52.50 = 2.5),当某个操作数为 NaN 时返回静默 NaN(仅对信号 NaN 引发 InvalidOperation)。compare_signal 与之相同,但对任何 NaN 都引发 InvalidOperation。compare_total 按 GDA 全序返回 −1-1、00 或 11:先比较符号位,然后对正值有 finite<∞<sNaN<NaN\text{finite} < \infty < \text{sNaN} < \text{NaN},有限值先按数值、再按指数排序(2.50 < 2.5),NaN 按载荷排序;对负值则顺序相反。compare_total_magnitude 对绝对值应用该全序。全序比较从不引发标志。

max, min, max_mag, min_mag

这些是 GDA 的 max 与 min 运算,作用于值或其大小。

pub fn max(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn min(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn max_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn min_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

单个静默 NaN 会被忽略而取数值;两个静默 NaN 时取第一个;信号 NaN 产生带 InvalidOperation 的静默 NaN。比较相等的值由全序加以区分(因此 max(2.5, 2.50) 为 2.5)。所选操作数随后像 plus 那样被舍入到上下文。

class_name, is_normal, is_subnormal, same_quantum

这些函数在上下文下对值进行分类;它们从不引发条件,因此总是返回带输入上下文的 Completed。

pub fn class_name(Decimal, GdaContext) -> GdaOutcome[String]
pub fn is_normal(Decimal, GdaContext) -> GdaOutcome[Bool]
pub fn is_subnormal(Decimal, GdaContext) -> GdaOutcome[Bool]
pub fn same_quantum(Decimal, Decimal, GdaContext) -> GdaOutcome[Bool]

它们包装 Decimal::class_name、Decimal::is_normal、Decimal::is_subnormal 和 Decimal::same_quantum。

///|
test "GDA operation sampler" {
  let ctx = @decimal_gda.GdaContext::decimal64()
  let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
  inspect(@decimal_gda.divide_integer(d("17"), d("5"), ctx).value(), content="3")
  inspect(@decimal_gda.remainder(d("-17"), d("5"), ctx).value(), content="-2")
  inspect(@decimal_gda.remainder_near(d("17"), d("5"), ctx).value(), content="2")
  inspect(@decimal_gda.fma(d("1.5"), d("2"), d("0.25"), ctx).value(), content="3.25")
  inspect(@decimal_gda.to_integral_exact(d("2.5"), ctx).value(), content="2")
  inspect(@decimal_gda.rescale(d("1.2345"), d("-2"), ctx).value(), content="1.23")
  inspect(@decimal_gda.reduce(d("120.00"), ctx).value(), content="1.2E+2")
  inspect(@decimal_gda.scaleb(d("1.5"), d("3"), ctx).value(), content="1.5E+3")
  inspect(@decimal_gda.logb(d("0.00123"), ctx).value(), content="-3")
  inspect(@decimal_gda.next_plus(d("1"), ctx).value(), content="1.000000000000001")
  inspect(@decimal_gda.logical_xor(d("1100"), d("1010"), ctx).value(), content="110")
  inspect(@decimal_gda.shift(d("12345"), d("2"), ctx).value(), content="1234500")
  inspect(@decimal_gda.rotate(d("12345"), d("-1"), @decimal_gda.context(precision=5)).value(), content="51234")
  inspect(@decimal_gda.power(d("2"), d("-3"), ctx).value(), content="0.125")
  inspect(@decimal_gda.max(d("2.5"), d("2.50"), ctx).value(), content="2.5")
  inspect(@decimal_gda.class_name(d("-0"), ctx).value(), content="-Zero")
  let wide = @decimal_gda.context() // exponent range ±999,999,999
  inspect(@decimal_gda.exp(d("1"), wide).raised().invalid_context, content="true")
}

值上的排序与普通算术

这些方法和运算符不接受上下文。它们从不发出信号,也从不触发陷阱;当标志重要时,请使用 GDA 函数。

Decimal::compare, Decimal::compare_checked

compare 是对所有值都完全的三路数值比较;compare_checked 拒绝 NaN。

pub fn Decimal::compare(Self, Self) -> Int
pub fn Decimal::compare_checked(Self, Self) -> Result[Int, @arithmetic.ArithmeticError]
pub impl Compare for Decimal
pub impl @arithmetic.CompareChecked for Decimal

compare 按数值对有限值和无穷排序,其中 −0=+0-0 = +0,并使每个 NaN 与其他所有 NaN 相等且大于所有数,因此它是全预序,排序永不中止。当任一操作数为 NaN 时,compare_checked 返回 Err(unordered_comparison)。

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

这些是 Eq 与 Compare 的运算符方法。

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
pub impl Eq for Decimal

== 对有限值是数值相等(2.50=2.52.50 = 2.5,−0=+0-0 = +0),对无穷是符号相等,对任意两个 NaN 为真。<、<=、>、>= 遵循 compare。

Decimal::compare_total, Decimal::compare_total_magnitude

这些是以普通方法形式提供的 GDA 全序,返回 −1-1、00 或 11。

pub fn Decimal::compare_total(Self, Self) -> Int
pub fn Decimal::compare_total_magnitude(Self, Self) -> Int

它们与包函数 compare_total、compare_total_magnitude 一致(但不进行子集操作数舍入)。

Decimal::min, Decimal::max, Decimal::clamp, Decimal::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]

当一个操作数为静默 NaN 时,min 和 max 返回另一个操作数;涉及信号 NaN 或两者均为 NaN 时,返回(静默化的)第一个 NaN;两者比较相等时返回接收者。当值位于 [min⁡,max⁡][\min, \max] 之外时,clamp 返回 min 或 max,否则返回该值(NaN 值原样返回);当某个边界为 NaN 或 min > max 时它会中止,而 clamp_checked 在这些情形下返回 Err(domain_error)。

Decimal::add, Decimal::sub, Decimal::mul, Decimal::div, Decimal::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 impl Add for Decimal
pub impl Sub for Decimal
pub impl Mul for Decimal
pub impl Div for Decimal
pub impl Neg for Decimal

设 PP 为操作数中较大的精度属性。+、- 和 / 按半值取偶舍入到 PP 位,然后去除尾随零;* 返回精确乘积(从不舍入),其属性为 PP。特殊值遵循 IEEE 规则但不发出信号:NaN 操作数产生静默 NaN,∞−∞\infty - \infty、0×∞0 \times \infty、0/00/0 和 ∞/∞\infty/\infty 产生 NaN,x/0x/0 产生带符号的无穷,x/∞x/\infty 产生 +0+0。neg 即 Decimal::neg。

Decimal::div_checked, Decimal::sqrt

这些是便利的 checked 函数,使用以较大操作数精度为精度的默认上下文。

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

div_checked 用 DecimalContext::new(precision=P) 做除法,对零除数返回 Err(division_by_zero),对无效除法返回 Err(domain_error)。sqrt 以值自身的精度属性求平方根,对负操作数返回 Err(domain_error)。

///|
test "context-free ordering and operators" {
  let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
  inspect(d("2.50") == d("2.5"), content="true")
  inspect(d("2.50").compare_total(d("2.5")), content="-1")
  inspect(@decimal_gda.Decimal::nan() == @decimal_gda.Decimal::nan(), content="true")
  inspect(d("1").compare(@decimal_gda.Decimal::nan()), content="-1")
  inspect(d("1").compare_checked(@decimal_gda.Decimal::nan()) is Err(_), content="true")
  inspect(d("1.10") + d("2.20"), content="3.3")
  inspect(d("1.10") * d("2.20"), content="2.4200")
  inspect(d("1") / d("3"), content="0.3333333333333333333333333333333333")
  inspect(d("5").clamp(min=d("0"), max=d("3")), content="3")
}

无状态上下文层

GDA 函数是对以下方法的薄包装:每个 GDA 函数都将 GdaContext 策略转换为 DecimalContext,调用一个方法,并将返回的 DecimalFlags 交给陷阱选择。当你需要不带粘滞状态的逐运算标志,或需要该层额外提供的 IEEE 风格功能(IEEE 754-2019 minimum/maximum、可选择的微小性检测方式)时,可以直接调用该层。受支持的 IEEE 754 实现是 decimal 包,而不是这一层。

DecimalContext

DecimalContext 是无状态的上下文:精度、舍入模式的两种视图、指数范围、clamp、extended 以及微小性检测。

pub struct DecimalContext {
  // private fields
} derive(Eq)
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]
pub fn DecimalContext::exact() -> Self
pub fn DecimalContext::decimal32() -> Self
pub fn DecimalContext::decimal64() -> Self
pub fn DecimalContext::decimal128() -> Self
pub fn DecimalContext::from_arithmetic_context(@arithmetic.ArithmeticContext) -> Self
pub fn DecimalContext::precision(Self) -> Int
pub fn DecimalContext::rounding(Self) -> @arithmetic.RoundingMode
pub fn DecimalContext::decimal_rounding(Self) -> DecimalRoundingMode
pub fn DecimalContext::with_rounding(Self, @arithmetic.RoundingMode) -> Self
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
pub fn DecimalContext::with_tininess(Self, DecimalTininessDetection) -> Self
pub fn DecimalContext::equal(Self, Self) -> Bool
pub fn DecimalContext::not_equal(Self, Self) -> Bool

默认值与 GdaContext::new 相同,并取 rounding=ToNearestEven 和 tininess=BeforeRounding。实际使用的舍入是 decimal_rounding,其默认值为 rounding 的转换结果(DecimalRoundingMode::from_arithmetic);传入 decimal_rounding 可选择 HalfUp、HalfDown 或 ZeroFiveUp。with_rounding 同时设置两种视图。对 precision <= 0 或 e_min > e_max,new 中止,try_new 返回 Err(domain_error)。exact() 是精度无界的上下文(精度 0):结果从不舍入。decimal32/64/128 与 GdaContext 的预设一致。from_arithmetic_context 复制精度、舍入、可选的指数边界(默认 ±999 999 999\pm 999\,999\,999)以及 clamp。GDA 函数总是使用 BeforeRounding 微小性判定。

DecimalRoundingMode

DecimalRoundingMode 是与 GdaRoundingMode 相同的八种模式集合,供无状态层使用。

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

from_arithmetic 将 ToNearestEven、TowardZero、TowardPositive、TowardNegative、AwayFromZero 映射为 HalfEven、Down、Ceiling、Floor、Up;to_arithmetic 是其逆映射,对 HalfUp、HalfDown 和 ZeroFiveUp 返回 None。

DecimalTininessDetection

DecimalTininessDetection 决定就 Underflow 和 Subnormal 而言结果何时算作微小。

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

BeforeRounding 将精确结果的调整后指数与 emin⁡e_{\min} 比较;AfterRounding 则检测舍入到 EtinyE_{\mathrm{tiny}} 后的结果。

DecimalSignal, DecimalFlags

这些是无状态层中逐运算的条件名称与标志集合。

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 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::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 是并集。与 GdaFlags 不同,DecimalFlags::contains(InvalidOperation) 只读取 invalid_operation 字段(该层会将它与 division_undefined 和 division_impossible 一起设置,但不会与 conversion_syntax 或 invalid_context 一起设置)。只要 invalid_operation、division_by_zero、division_undefined、division_impossible 或 invalid_context 中任一被设置,has_error 即为真。

Decimal 的上下文方法

下面每个方法都是同名 GDA 函数的无状态形式;它以给定的 DecimalContext 舍入,并返回 (result, DecimalFlags)。

pub fn Decimal::apply_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
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::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)
pub fn Decimal::fma_ctx(Self, Self, Self, DecimalContext) -> (Self, DecimalFlags)
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::quantize(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rescale(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_integral_exact(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_integral_value(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::reduce_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::scaleb_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logb_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
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)
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)
pub fn Decimal::shift_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rotate_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
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_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::compare_total_magnitude_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
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)

其结果和标志与 GDA 函数在其结果中报告的完全相同。(GDA 函数 parse、add、subtract、multiply 和 fma 会先对较小的精确整数操作数尝试一条快速路径;只有当它产生相同的值且不带标志时才会采用。)

Decimal::sqrt_ctx, Decimal::exp_ctx, Decimal::ln_ctx, Decimal::log10_ctx, Decimal::power_ctx

这些是无状态的初等函数。

pub fn Decimal::sqrt_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
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::power_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)

与 GDA 函数 sqrt、exp、ln 和 log10 不同,这些方法以上下文自身的舍入模式进行舍入(GDA 函数传给它们的是上下文的半值取偶副本)。认证失败时得到带 invalid_operation 的 NaN。

Decimal::try_exp_ctx, Decimal::try_ln_ctx, Decimal::try_log10_ctx, Decimal::try_power_ctx

这些是同样的函数,但将认证失败作为错误报告。

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]
pub fn Decimal::try_power_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]

当细化预算(十二次精度提升)耗尽仍无法认证舍入时,它们返回 Err(certification_failure(...)),其中包含运算名称、目标精度、最终工作精度和细化次数。定义域错误仍在 Ok 中以 NaN 加标志的形式报告。

Decimal::normalize_ctx, Decimal::remainder_ctx

这些是为沿用 IEEE 术语而保留的别名。

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

normalize_ctx 即 reduce_ctx;remainder_ctx 是 IEEE 余数,即 remainder_near。

Decimal::minimum_ctx、Decimal::maximum_ctx 及其 number 与 magnitude 变体

这些是 IEEE 754-2019 的 minimum、maximum、minimumNumber、maximumNumber、minimumMagnitude、maximumMagnitude、minimumMagnitudeNumber 和 maximumMagnitudeNumber 运算。

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)

普通变体在任一操作数为 NaN 时返回静默 NaN;number 变体在恰有一个操作数为 NaN 时返回数值。两者中信号 NaN 都会引发 invalid_operation。相等的值由全序加以区分。*_mag_ctx 名称是 *_magnitude_ctx 名称的别名。这些不是 GDA 运算,没有 GdaContext 形式。

///|
test "status-free layer" {
  let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
  let ctx = @decimal_gda.DecimalContext::new(precision=5, decimal_rounding=HalfUp)
  let (q, flags) = d("2").div_ctx(d("3"), ctx)
  inspect(q, content="0.66667")
  inspect(flags.inexact, content="true")
  inspect(flags.contains(Rounded), content="true")
  let floor = @decimal_gda.DecimalContext::new(
    precision=3,
    rounding=TowardNegative,
    e_min=-999_999,
    e_max=999_999,
  )
  inspect(d("1").exp_ctx(floor).0, content="2.71") // context rounding
  let nan = @decimal_gda.Decimal::nan()
  inspect(d("1").maximum_ctx(nan, ctx).0, content="nan")
  inspect(d("1").maximum_number_ctx(nan, ctx).0, content="1")
  let (_, zero_div) = d("0").div_ctx(d("0"), ctx)
  inspect(zero_div.has_error(), content="true")
}

交换编码

GdaInterchangeFormat

GdaInterchangeFormat 指定三种 IEEE 754 十进制交换格式。

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

context 返回对应的 DecimalContext 预设(精度 7、16 或 34,启用钳制)。

GdaInterchange

GdaInterchange 是采用密集压缩十进制(DPD)编码的 decimal32、decimal64 或 decimal128 比特模式。

pub struct GdaInterchange {
  // private fields
}
pub fn GdaInterchange::format(Self) -> GdaInterchangeFormat

format 返回该比特模式的格式。

GdaInterchange::from_decimal, GdaInterchange::to_decimal, GdaInterchange::to_decimal_ctx

这些函数对值进行编码和解码。

pub fn GdaInterchange::from_decimal(Decimal, GdaInterchangeFormat) -> (Self, DecimalFlags)
pub fn GdaInterchange::to_decimal(Self) -> Decimal
pub fn GdaInterchange::to_decimal_ctx(Self) -> (Decimal, DecimalFlags)

from_decimal 将值舍入到该格式(报告舍入、上溢、下溢和钳制标志)并对其编码。to_decimal 精确解码并保留指数;to_decimal_ctx 对次正规值还会报告 subnormal。

GdaInterchange::from_hex, GdaInterchange::to_hex

这些函数在比特模式与其十六进制文本之间转换。

pub fn GdaInterchange::from_hex(String, GdaInterchangeFormat) -> Self?
pub fn GdaInterchange::to_hex(Self) -> String

文本为 #(输入时可选)后跟恰好 8、16 或 32 个十六进制数字;两侧空格被忽略,其他任何输入都得到 None。to_hex 打印 # 和大写数字。

GdaInterchange::canonical, GdaInterchange::is_canonical

这些函数将编码规范化。

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

canonical 对比特模式解码后重新编码,从而将非规范的 declet 和载荷替换为其规范形式;is_canonical 检测这样做是否会改变比特模式。

GdaInterchange::copy, GdaInterchange::copy_abs, GdaInterchange::copy_negate, GdaInterchange::copy_sign

这些函数直接操作编码的符号位,而无需解码。

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

当两个比特模式的格式不同时,copy_sign 会中止。

Decimal::from_interchange_hex, Decimal::to_interchange_hex

这些是直接在 Decimal 与十六进制文本之间进行的同样转换。

pub fn Decimal::from_interchange_hex(String, GdaInterchangeFormat) -> Self?
pub fn Decimal::to_interchange_hex(Self, GdaInterchangeFormat) -> (String, DecimalFlags)
///|
test "DPD interchange" {
  let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
  let (bits, flags) = @decimal_gda.GdaInterchange::from_decimal(d("1.234567890"), Decimal32)
  inspect(bits.to_hex(), content="#25F4D2E8")
  inspect(bits.to_decimal(), content="1.234568")
  inspect(flags.inexact, content="true")
  let back = @decimal_gda.Decimal::from_interchange_hex("#A2300000000003D0", Decimal64).unwrap()
  inspect(back, content="-7.50")
  inspect(bits.copy_negate().to_decimal(), content="-1.234568")
}

trait 实现

Luna-Flow/arithmetic 的 contextual trait

这些函数将无状态层适配到 ArithmeticContext。

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 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

每个函数都用 DecimalContext::from_arithmetic_context 转换上下文,调用 _ctx 方法:若引发了 division_by_zero 则返回 Err(division_by_zero),若引发了其他错误标志则返回 Err(domain_error),否则返回带值及诊断信息 inexact、rounded、overflow、underflow、subnormal 和 clamped 的 Ok。

NumericFormatContextual

这些函数描述 ArithmeticContext 的数值格式。

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.NumericFormatContextual for Decimal

epsilon_contextual 为 next_plus⁡(1)−1=101−p\operatorname{next\_plus}(1) - 1 = 10^{1-p},min_normal_contextual 为 10emin⁡10^{e_{\min}},max_finite_contextual 为 (10p−1)⋅10emax⁡−p+1(10^p - 1) \cdot 10^{e_{\max} - p + 1}。

checked trait

这些函数返回 Result 而非标志。

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_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 impl @arithmetic.ParseChecked for Decimal
pub impl @arithmetic.SqrtChecked for Decimal
pub impl @arithmetic.PowIntChecked for Decimal
pub impl @arithmetic.PowNatChecked for Decimal
pub impl @arithmetic.DivChecked for Decimal

parse_checked 即以上下文精度进行的 Decimal::parse。sqrt_checked 对负操作数返回 Err(domain_error)。pow_int_checked 和 pow_nat_checked 以整数指数调用 power_ctx;对零底数配负指数返回 Err(division_by_zero),对无效结果返回 Err(domain_error),且 pow_nat_checked 对大于 999,999,999 的指数返回 Err(unsupported)。DivChecked::div_checked 在给定上下文下做除法,其错误与 Decimal::div_checked 相同。

luna-generic 代数 trait

这些实现使泛型代数代码能够使用 Decimal。

pub fn[S : @luna-generic.Nat] Decimal::from_nat(S) -> Self
pub fn[S : @luna-generic.Integral] Decimal::from_integral(S) -> Self
pub impl @luna-generic.NatHomomorphism for Decimal
pub impl @luna-generic.IntegralHomomorphism for Decimal
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

from_nat 和 from_integral 经由 BigInt 用 Decimal::from_bigint 转换(34 位,去除尾随零),因此它们只对至多 34 位有效数字的整数是精确的。Zero::zero 和 One::one 即 Decimal::zero() 和 Decimal::one()。环结构使用无上下文的运算符;由于 + 会舍入到操作数精度,只有当和保持在该精度之内时,环公理才精确成立。

@def.Floating, Show, Debug

Decimal 实现了 def 包的浮点词汇、Show(参见 Decimal::to_string)以及 Debug。

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

Floating 方法为 classify、sign、precision、with_precision 和 normalized,均已在上文说明。to_repr 是结构化的 Debug 表示。

///|
test "trait adapters" {
  let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
  let actx = @lf_arith.ArithmeticContext::new(4)
  let out = d("2").div_contextual(d("3"), actx).unwrap()
  inspect(out.value, content="0.6667")
  inspect(out.diagnostics.inexact, content="true")
  inspect(d("1").div_contextual(d("0"), actx) is Err(_), content="true")
  inspect(@decimal_gda.Decimal::epsilon_contextual(actx), content="0.001")
  inspect(d("1.5").pow_int_checked(3, actx).unwrap(), content="3.375")
  inspect(@decimal_gda.Decimal::from_integral(1200), content="1.2E+3")
}

完整公共接口

此快照是该包生成的 pkg.generated.mbti。当正文与接口不一致时,以接口为准。

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

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

// Values
pub fn abs(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn add(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn apply(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn class_name(Decimal, GdaContext) -> GdaOutcome[String]

pub fn compare(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn compare_signal(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn compare_total(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]

pub fn compare_total_magnitude(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]

pub fn context(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool) -> GdaContext

pub fn decimal128_context() -> GdaContext

pub fn decimal32_context() -> GdaContext

pub fn decimal64_context() -> GdaContext

pub fn divide(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn divide_integer(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn exp(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn fma(Decimal, Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn is_normal(Decimal, GdaContext) -> GdaOutcome[Bool]

pub fn is_subnormal(Decimal, GdaContext) -> GdaOutcome[Bool]

pub fn ln(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn log10(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn logb(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn logical_and(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn logical_invert(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn logical_or(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn logical_xor(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn max(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn max_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn min(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn min_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn minus(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn multiply(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn next_minus(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn next_plus(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn next_toward(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn parse(String, GdaContext) -> GdaOutcome[Decimal]

pub fn plus(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn power(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn quantize(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn reduce(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn remainder(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn remainder_near(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn rescale(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn rotate(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn same_quantum(Decimal, Decimal, GdaContext) -> GdaOutcome[Bool]

pub fn scaleb(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn shift(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn sqrt(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn subtract(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn to_integral_exact(Decimal, GdaContext) -> GdaOutcome[Decimal]

pub fn to_integral_value(Decimal, GdaContext) -> GdaOutcome[Decimal]

// 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::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::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::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::exp_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::exp_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, GdaInterchangeFormat) -> 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::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::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::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::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::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::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, GdaInterchangeFormat) -> (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_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]
pub fn Decimal::try_power_ctx(Self, 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::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(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

pub struct GdaContext {
  // private fields
}
pub fn GdaContext::basic() -> Self
pub fn GdaContext::clamp(Self) -> Bool
pub fn GdaContext::clear_status(Self) -> Self
pub fn GdaContext::decimal128() -> Self
pub fn GdaContext::decimal32() -> Self
pub fn GdaContext::decimal64() -> Self
pub fn GdaContext::default() -> Self
pub fn GdaContext::e_max(Self) -> Int
pub fn GdaContext::e_min(Self) -> Int
pub fn GdaContext::extended(Self) -> Bool
pub fn GdaContext::new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Self
pub fn GdaContext::precision(Self) -> Int
pub fn GdaContext::radix(Self) -> Int
pub fn GdaContext::reset(Self) -> Self
pub fn GdaContext::rounding(Self) -> GdaRoundingMode
pub fn GdaContext::status(Self) -> GdaFlags
pub fn GdaContext::trap(Self, GdaSignal, enabled? : Bool) -> Self
pub fn GdaContext::traps(Self) -> GdaTrapSet
pub fn GdaContext::try_new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Result[Self, @arithmetic.ArithmeticError]
pub fn GdaContext::with_traps(Self, GdaTrapSet) -> Self

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

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

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

pub(all) enum GdaOutcome[T] {
  Completed(T, GdaContext, GdaFlags)
  Trapped(GdaSignal, T, GdaContext, GdaFlags)
}
pub fn[T] GdaOutcome::next_context(Self[T]) -> GdaContext
pub fn[T] GdaOutcome::raised(Self[T]) -> GdaFlags
pub fn[T] GdaOutcome::value(Self[T]) -> T

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

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

pub struct GdaTrapSet {
  conversion_syntax : Bool
  division_by_zero : Bool
  division_impossible : Bool
  division_undefined : Bool
  invalid_context : Bool
  invalid_operation : Bool
  overflow : Bool
  underflow : Bool
  subnormal : Bool
  inexact : Bool
  rounded : Bool
  clamped : Bool
  lost_digits : Bool
} derive(Eq)
pub fn GdaTrapSet::contains(Self, GdaSignal) -> Bool
pub fn GdaTrapSet::equal(Self, Self) -> Bool
pub fn GdaTrapSet::none() -> Self
pub fn GdaTrapSet::not_equal(Self, Self) -> Bool
pub fn GdaTrapSet::with_signal(Self, GdaSignal, enabled? : Bool) -> Self

// Type aliases

// Traits

Footnotes

  1. GDA 参考实现会原样返回此类操作数;例如在精度 3 下,它将 12345 映射为 12345,而本包返回带 Inexact 的 1.23E+4。所固定的测试套件中没有这样的用例。 ↩