internal API
internal 包含各数值核心共享的精确整数与有理数辅助函数:2、5 和 10 的幂,数字位数计数,去除尾部因子,带显式舍入模式的整数除法,十进制字符串拆分器,最简有理数,二进有理数包络,以及经认证初等函数的细化预算。bin_float、decimal、decimal_gda、ball_float、semantic 以及 consistency 测试都使用它。它是一个内部包:无法从 Luna-Flow/floating 之外导入,其接口可能会变化。因此示例不会被编译。设计页面证明舍入与包络不变式;教程展示各核心如何使用这些辅助函数。
导入(仅限模块内部):
import {
"Luna-Flow/floating/internal",
}
@bigint.BigInt 即 moonbitlang/core/bigint;接口将 Luna-Flow/arithmetic 显示为 @arithmetic(RoundingMode、ArithmeticError、CertificationStage、CertificationFailureReason),并使用 @def.Sign。
整数基础
bigint_zero, bigint_one
这些函数返回 BigInt 常量 和 。
pub fn bigint_zero() -> @bigint.BigInt
pub fn bigint_one() -> @bigint.BigInt
abs_bigint, sign_of_bigint, compare_abs
abs_bigint(x) 为 ,sign_of_bigint(x) 为 Negative、Zero 或 Positive,compare_abs(a, b) 比较 与 (返回负数、零或正数的 Int)。
pub fn abs_bigint(@bigint.BigInt) -> @bigint.BigInt
pub fn sign_of_bigint(@bigint.BigInt) -> @def.Sign
pub fn compare_abs(@bigint.BigInt, @bigint.BigInt) -> Int
幂
pow2, pow5, pow10
这些函数返回 、 和 。
pub fn pow2(Int) -> @bigint.BigInt
pub fn pow5(Int) -> @bigint.BigInt
pub fn pow10(Int) -> @bigint.BigInt
当 时它们会中止。pow2 是一次移位。pow5 和 pow10 读取一个进程级缓存,该缓存初始包含 的幂,并按需扩展到至多 ;更大的幂每次都重新计算,不做缓存。
digits10
digits10(x) 是 的十进制位数,且 digits10(0) == 1。
pub fn digits10(@bigint.BigInt) -> Int
对于 ,它返回满足 的唯一 :先根据位长给出估计,再通过与 10 的幂比较加以修正(不构造十进制字符串)。
尾部因子
remove_factor2
remove_factor2(sig, exp) 从 sig 中去除所有因子 2,并相应调整二进制指数。
pub fn remove_factor2(@bigint.BigInt, Int) -> (@bigint.BigInt, Int)
对于 ,它返回 ,其中 是 尾部零比特的个数,因此 保持不变,且新的有效数为奇数。对于 ,它返回 。
remove_factor10
remove_factor10(coeff, exp) 从 coeff 中去除所有因子 10,并相应调整十进制指数。
pub fn remove_factor10(@bigint.BigInt, Int) -> (@bigint.BigInt, Int)
值 保持不变,且新的系数不能被 10 整除。零得到 。
trim_trailing_decimal_zeros
trim_trailing_decimal_zeros(coeff, exp, max_drop?) 去除至多 max_drop 个十进制尾随零。
pub fn trim_trailing_decimal_zeros(@bigint.BigInt, Int, max_drop? : Int) -> (@bigint.BigInt, Int, Int)
它返回 ,满足 、,且 在 max_drop 的约束下取最大。负的 max_drop(默认 )表示没有限制。零得到 。设置限制可让调用方在某个目标指数处停下,正如 decNumber 风格的、截尾到理想指数的做法那样。
exact_divide_by_power_of_ten
当除法精确时,exact_divide_by_power_of_ten(coeff, shift) 为 Some(coeff / 10^shift),否则为 None。
pub fn exact_divide_by_power_of_ten(@bigint.BigInt, Int) -> @bigint.BigInt?
符号保持不变。对于任意 shift,零都得到 Some(0);对于非零系数,负的 shift 会导致中止。
整数商的舍入
round_positive_div
round_positive_div(n, d, negative, mode) 将商 舍入为一个整数量值。
pub fn round_positive_div(@bigint.BigInt, @bigint.BigInt, Bool, @arithmetic.RoundingMode) -> @bigint.BigInt
要求 且 (否则中止)。negative 是量值为 的实数商的符号;结果为 ,其中 表示舍入到整数:
mode | 对 、 的结果 |
|---|---|
TowardZero | |
TowardPositive | |
TowardNegative | |
AwayFromZero | |
ToNearestEven |
结果是精确的(等于 )当且仅当 。
round_shift
round_shift(m, s, negative, mode) 即用移位计算的 round_positive_div(m, 2^s, negative, mode)。
pub fn round_shift(@bigint.BigInt, Int, Bool, @arithmetic.RoundingMode) -> @bigint.BigInt
应为非负(不做检查)。当 时,它原样返回 。
十进制字符串
split_decimal_string
split_decimal_string(text) 将一个有限十进制字面量拆分为符号、数字串和指数。
pub fn split_decimal_string(String) -> (Bool, String, Int)?
所接受的语法为
[+|-] digit* [. digit*] [(e|E) [+|-] digit+] with at least one mantissa digit
结果 满足 ,其中 是全部尾数数字组成的字符串(保留前导零), 是书写的指数减去小数部分的位数。书写的指数在相减之前饱和于 ,因此巨大的指数不会使 Int 溢出。其他任何输入,包括 inf 和 nan,都得到 None。
///|
test "split decimal string" {
debug_inspect(@internal.split_decimal_string("-12.50e3"), content="Some((true, \"1250\", 1))")
debug_inspect(@internal.split_decimal_string(".5"), content="Some((false, \"5\", -1))")
debug_inspect(@internal.split_decimal_string("1e"), content="None")
}
Result 组合子
result_lift2, result_lift2_checked
这些函数组合两个 Result,返回第一个错误。
pub fn[A, B, E, C] result_lift2(Result[A, E], Result[B, E], (A, B) -> C) -> Result[C, E]
pub fn[A, B, E, C] result_lift2_checked(Result[A, E], Result[B, E], (A, B) -> Result[C, E]) -> Result[C, E]
result_lift2(Ok(a), Ok(b), f) 为 Ok(f(a, b));result_lift2_checked 则直接返回 f(a, b)。若 left 为 Err,则返回该错误;否则返回 right 中的 Err。
精确有理数
ExactRat
ExactRat 是一个最简形式的有理数。
pub struct ExactRat {
// private fields
} derive(Eq)
ExactRat::new, ExactRat::numerator, ExactRat::denominator
ExactRat::new(n, d) 将 约简为分母为正的最简形式;访问器返回约简后的各部分。
pub fn ExactRat::new(@bigint.BigInt, @bigint.BigInt) -> Self
pub fn ExactRat::numerator(Self) -> @bigint.BigInt
pub fn ExactRat::denominator(Self) -> @bigint.BigInt
当 时中止。零存储为 。由于该形式是规范的,ExactRat 上的 == 就是有理数的相等。
ExactRat::equal, ExactRat::not_equal
这些方法比较规范形式;请使用 == 和 !=。
pub fn ExactRat::equal(Self, Self) -> Bool
pub fn ExactRat::not_equal(Self, Self) -> Bool
///|
test "exact rational" {
let r = @internal.ExactRat::new(-6N, -8N)
inspect(r.numerator(), content="3")
inspect(r.denominator(), content="4")
inspect(r == @internal.ExactRat::new(9N, 12N), content="true")
}
二进有理数包络
CertifiedDyadic
CertifiedDyadic 是二进有理数 ,其中 为 numerator_,标度 = scale_ 非负。
pub struct CertifiedDyadic {
numerator_ : @bigint.BigInt
scale_ : Int
}
这些字段可读;请用 new 或 from_int 构建值。
CertifiedDyadic::new, from_int, numerator, scale
new(n, s) 为 (若 则中止);from_int(k) 为 ;访问器返回各字段。
pub fn CertifiedDyadic::new(@bigint.BigInt, Int) -> Self
pub fn CertifiedDyadic::from_int(Int) -> Self
pub fn CertifiedDyadic::numerator(Self) -> @bigint.BigInt
pub fn CertifiedDyadic::scale(Self) -> Int
该表示未经规范化: 和 是该结构体的两个不同的值,但表示同一个数。
CertifiedDyadic::add, sub, mul, neg, compare
这些方法是二进有理数的精确算术与比较。
pub fn CertifiedDyadic::add(Self, Self) -> Self
pub fn CertifiedDyadic::sub(Self, Self) -> Self
pub fn CertifiedDyadic::mul(Self, Self) -> Self
pub fn CertifiedDyadic::neg(Self) -> Self
pub fn CertifiedDyadic::compare(Self, Self) -> Int
add 和 sub 对齐到较大的标度;mul 将标度相加;compare 比较的是数值(而非表示)。
CertifiedDyadic::round_down, CertifiedDyadic::round_up
x.round_down(s) 和 x.round_up(s) 分别是标度为 的二进有理数中 的最大者和 的最小者: 与 。
pub fn CertifiedDyadic::round_down(Self, Int) -> Self
pub fn CertifiedDyadic::round_up(Self, Int) -> Self
若 则中止。当 不小于当前标度时,该值被精确地重新表示。
CertifiedInterval
CertifiedInterval[T] 是一个满足 lower <= upper 的有序对,用作包络。
pub struct CertifiedInterval[T] {
lower_ : T
upper_ : T
}
pub fn[T] CertifiedInterval::new(T, T, (T, T) -> Int) -> Result[Self[T], @arithmetic.ArithmeticError]
pub fn[T] CertifiedInterval::lower(Self[T]) -> T
pub fn[T] CertifiedInterval::upper(Self[T]) -> T
当 compare(lower, upper) > 0 时,new(lower, upper, compare) 返回一个认证失败错误,其阶段为 EnclosurePropagation,原因为 InvalidEnclosure。
certified_dyadic_fraction
certified_dyadic_fraction(n, d, s) 用两个标度为 的二进有理数包络 。
pub fn certified_dyadic_fraction(@bigint.BigInt, @bigint.BigInt, Int) -> Result[CertifiedInterval[CertifiedDyadic], @arithmetic.ArithmeticError]
结果为 :它包含 ,宽度为 或 ,且当且仅当 时为单点。非正的 产生定义域错误。
certified_dyadic_div
certified_dyadic_div(a, b, s) 以标度 包络两个二进有理数的商 。
pub fn certified_dyadic_div(CertifiedDyadic, CertifiedDyadic, Int) -> Result[CertifiedInterval[CertifiedDyadic], @arithmetic.ArithmeticError]
产生除以零错误。否则,结果是将 certified_dyadic_fraction 作用于写成正分母形式的 。
///|
test "one third at scale 8" {
let third = @internal.certified_dyadic_div(
@internal.CertifiedDyadic::from_int(1),
@internal.CertifiedDyadic::from_int(3),
8,
).unwrap()
inspect(third.lower().numerator(), content="85") // 85/256 <= 1/3
inspect(third.upper().numerator(), content="86") // 86/256 >= 1/3
}
细化预算
CertifiedRefinementBudget
CertifiedRefinementBudget 跟踪 Ziv 式求值循环的工作精度和细化次数。
pub struct CertifiedRefinementBudget {
work_precision : Int
refinements_ : Int
limit_ : Int
}
CertifiedRefinementBudget::new, next, available, precision, refinements
new(p, limit?) 以工作精度 、零次细化开始,细化次数上限为 (默认 12)。next() 将精度增加 ,并计入一次细化。只要已进行的细化次数少于 limit,available() 就为真。
pub fn CertifiedRefinementBudget::new(Int, limit? : Int) -> Self
pub fn CertifiedRefinementBudget::next(Self) -> Self
pub fn CertifiedRefinementBudget::available(Self) -> Bool
pub fn CertifiedRefinementBudget::precision(Self) -> Int
pub fn CertifiedRefinementBudget::refinements(Self) -> Int
例如 。
certified_failure
certified_failure(operation, stage, reason, target_precision, budget) 构建经认证运算放弃时返回的 ArithmeticError。
pub fn certified_failure(String, @arithmetic.CertificationStage, @arithmetic.CertificationFailureReason, Int, CertifiedRefinementBudget) -> @arithmetic.ArithmeticError
该错误的详情记录运算名、阶段、原因、目标精度,以及预算当前的工作精度和细化次数。
完整公共接口
此快照是该包生成的 pkg.generated.mbti。当正文与接口不一致时,以接口为准。
// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/internal"
import {
"Luna-Flow/arithmetic",
"Luna-Flow/floating/def",
"moonbitlang/core/bigint",
}
// Values
pub fn abs_bigint(@bigint.BigInt) -> @bigint.BigInt
pub fn bigint_one() -> @bigint.BigInt
pub fn bigint_zero() -> @bigint.BigInt
pub fn certified_dyadic_div(CertifiedDyadic, CertifiedDyadic, Int) -> Result[CertifiedInterval[CertifiedDyadic], @arithmetic.ArithmeticError]
pub fn certified_dyadic_fraction(@bigint.BigInt, @bigint.BigInt, Int) -> Result[CertifiedInterval[CertifiedDyadic], @arithmetic.ArithmeticError]
pub fn certified_failure(String, @arithmetic.CertificationStage, @arithmetic.CertificationFailureReason, Int, CertifiedRefinementBudget) -> @arithmetic.ArithmeticError
pub fn compare_abs(@bigint.BigInt, @bigint.BigInt) -> Int
pub fn digits10(@bigint.BigInt) -> Int
pub fn exact_divide_by_power_of_ten(@bigint.BigInt, Int) -> @bigint.BigInt?
pub fn pow10(Int) -> @bigint.BigInt
pub fn pow2(Int) -> @bigint.BigInt
pub fn pow5(Int) -> @bigint.BigInt
pub fn remove_factor10(@bigint.BigInt, Int) -> (@bigint.BigInt, Int)
pub fn remove_factor2(@bigint.BigInt, Int) -> (@bigint.BigInt, Int)
pub fn[A, B, E, C] result_lift2(Result[A, E], Result[B, E], (A, B) -> C) -> Result[C, E]
pub fn[A, B, E, C] result_lift2_checked(Result[A, E], Result[B, E], (A, B) -> Result[C, E]) -> Result[C, E]
pub fn round_positive_div(@bigint.BigInt, @bigint.BigInt, Bool, @arithmetic.RoundingMode) -> @bigint.BigInt
pub fn round_shift(@bigint.BigInt, Int, Bool, @arithmetic.RoundingMode) -> @bigint.BigInt
pub fn sign_of_bigint(@bigint.BigInt) -> @def.Sign
pub fn split_decimal_string(String) -> (Bool, String, Int)?
pub fn trim_trailing_decimal_zeros(@bigint.BigInt, Int, max_drop? : Int) -> (@bigint.BigInt, Int, Int)
// Errors
// Types and methods
pub struct CertifiedDyadic {
numerator_ : @bigint.BigInt
scale_ : Int
}
pub fn CertifiedDyadic::add(Self, Self) -> Self
pub fn CertifiedDyadic::compare(Self, Self) -> Int
pub fn CertifiedDyadic::from_int(Int) -> Self
pub fn CertifiedDyadic::mul(Self, Self) -> Self
pub fn CertifiedDyadic::neg(Self) -> Self
pub fn CertifiedDyadic::new(@bigint.BigInt, Int) -> Self
pub fn CertifiedDyadic::numerator(Self) -> @bigint.BigInt
pub fn CertifiedDyadic::round_down(Self, Int) -> Self
pub fn CertifiedDyadic::round_up(Self, Int) -> Self
pub fn CertifiedDyadic::scale(Self) -> Int
pub fn CertifiedDyadic::sub(Self, Self) -> Self
pub struct CertifiedInterval[T] {
lower_ : T
upper_ : T
}
pub fn[T] CertifiedInterval::lower(Self[T]) -> T
pub fn[T] CertifiedInterval::new(T, T, (T, T) -> Int) -> Result[Self[T], @arithmetic.ArithmeticError]
pub fn[T] CertifiedInterval::upper(Self[T]) -> T
pub struct CertifiedRefinementBudget {
work_precision : Int
refinements_ : Int
limit_ : Int
}
pub fn CertifiedRefinementBudget::available(Self) -> Bool
pub fn CertifiedRefinementBudget::new(Int, limit? : Int) -> Self
pub fn CertifiedRefinementBudget::next(Self) -> Self
pub fn CertifiedRefinementBudget::precision(Self) -> Int
pub fn CertifiedRefinementBudget::refinements(Self) -> Int
pub struct ExactRat {
// private fields
} derive(Eq)
pub fn ExactRat::denominator(Self) -> @bigint.BigInt
pub fn ExactRat::equal(Self, Self) -> Bool
pub fn ExactRat::new(@bigint.BigInt, @bigint.BigInt) -> Self
pub fn ExactRat::not_equal(Self, Self) -> Bool
pub fn ExactRat::numerator(Self) -> @bigint.BigInt
// Type aliases
// Traits