arithmetic API
Luna-Flow/linear-algebra/arithmetic 是本仓库的标量运算层。它重新导出线性代数代码从 Luna-Flow/luna-generic 和 Luna-Flow/arithmetic 中使用的标量类型和 trait,并新增五个小型运算 trait:Abs、ApproxEq、CheckedDiv、CheckedSqrt 和 CheckedCompare。运算 trait 只表明某个运算可用,并不声明代数定律。
源码:src/arithmetic/operation_traits.mbt、src/arithmetic/alias.mbt。设计考量见 arithmetic 设计。
导入
本页示例使用以下别名:
///|
import {
"Luna-Flow/linear-algebra/arithmetic" @la_arithmetic,
"Luna-Flow/arithmetic" @lf_arith,
}
重导出的名称
该包通过 pub using 重新导出这些上游名称,因此 @la_arithmetic.Sqrt 和 @lf_arith.Sqrt 指代同一个 trait。它们的行为由上游文档说明:luna-generic 和 arithmetic。
| 名称 | 种类 | 来源 | 含义 |
|---|---|---|---|
Zero | trait | luna-generic | 加法单位元 zero() |
One | trait | luna-generic | 乘法单位元 one() |
Inverse | trait | luna-generic | 乘法逆元 inv(x) |
Conjugate | trait | luna-generic | 对合 conjugate(x);内置实数类型没有实例 |
Sqrt | trait | arithmetic | 非受检 sqrt(x) |
Cbrt | trait | arithmetic | 非受检 cbrt(x) |
Power | trait | arithmetic | 非受检 pow(x, y) |
Exponential | trait | arithmetic | exp(x), exp2(x) |
Logarithmic | trait | arithmetic | ln(x), log2(x), log10(x) |
Constants | trait | arithmetic | pi(), tau(), e() |
SqrtChecked | trait | arithmetic | 返回 Result 的 sqrt_checked(x, ctx) |
DivChecked | trait | arithmetic | 返回 Result 的 div_checked(x, y, ctx) |
CompareChecked | trait | arithmetic | 返回 Result[Int, _] 的 compare_checked(x, y) |
ArithmeticContext | 类型 | arithmetic | 传递给受检运算的精度与舍入设置 |
ArithmeticError | 类型 | arithmetic | 带有 kind 和 message 的结构化标量错误 |
ArithmeticErrorKind | 类型 | arithmetic | DivisionByZero, DomainError, UnorderedComparison, … |
FpClass | 类型 | arithmetic | Finite, Infinity, NaN |
RoundingMode | 类型 | arithmetic | ToNearestEven, TowardZero, … |
绝对值
Abs
Abs 标记具有绝对值的标量类型。
pub(open) trait Abs {
fn abs(Self) -> Self
}
pub impl Abs for Int
pub impl Abs for Float
pub impl Abs for Double
Abs::abs
Abs::abs 返回 。
fn Abs::abs(Self) -> Self
这些实现委托给 luna-generic 的 Num::abs。对于 Int, 会按补码算术回绕为 。
///|
fn[T : @la_arithmetic.Abs] arith_api_magnitude(x : T) -> T {
@la_arithmetic.Abs::abs(x)
}
///|
test "Abs on integers and doubles" {
inspect(arith_api_magnitude(-3), content="3")
inspect(arith_api_magnitude(-2.5), content="2.5")
}
近似相等
ApproxEq
ApproxEq 标记支持近似比较的标量类型。
pub(open) trait ApproxEq {
fn approx_eq(Self, Self) -> Bool
}
pub impl ApproxEq for Int
pub impl ApproxEq for Float
pub impl ApproxEq for Double
ApproxEq::approx_eq
ApproxEq::approx_eq 判断两个值之差是否在固定的绝对容差之内。
fn ApproxEq::approx_eq(Self, Self) -> Bool
| 类型 | 规则 |
|---|---|
Int | |
Float | |
Double |
该容差是绝对的,因此对大数值过严、对极小数值过松,而且该关系不具有传递性。只要有操作数是 NaN,它就返回 false。其后果见设计页面。
///|
test "ApproxEq uses an absolute tolerance" {
inspect(
@la_arithmetic.ApproxEq::approx_eq(1.0, 1.0 + 1.0e-13),
content="true",
)
inspect(
@la_arithmetic.ApproxEq::approx_eq(1.0e20, 1.0e20 + 1.0e5),
content="false",
)
inspect(@la_arithmetic.ApproxEq::approx_eq(3, 3), content="true")
}
受检运算
受检 trait 返回 Result[_, ArithmeticError],而不是 NaN 或无穷大。Float 和 Double 的实现委托给上游的 DivChecked、SqrtChecked 和 CompareChecked trait;为了接口统一,它们接受一个 ArithmeticContext,但会忽略它,因为硬件二进制浮点数的精度是固定的。
CheckedDiv
CheckedDiv 标记具有能报告非法操作数的除法的标量类型。
pub(open) trait CheckedDiv {
fn checked_div(Self, Self, @Luna-Flow/arithmetic.ArithmeticContext) -> Result[Self, @Luna-Flow/arithmetic.ArithmeticError]
}
pub impl CheckedDiv for Float
pub impl CheckedDiv for Double
CheckedDiv::checked_div
CheckedDiv::checked_div(x, y, ctx) 返回 Ok(x / y) 或一个错误。
fn CheckedDiv::checked_div(Self, Self, ArithmeticContext) -> Result[Self, ArithmeticError]
| 操作数 | 结果 |
|---|---|
Err,kind 为 DomainError | |
Err,kind 为 DomainError | |
| , | Err,kind 为 DivisionByZero |
| 其他情况 | Ok(x / y),舍入到最近值 |
CheckedSqrt
CheckedSqrt 标记具有能报告定义域错误的平方根的标量类型。
pub(open) trait CheckedSqrt {
fn checked_sqrt(Self, @Luna-Flow/arithmetic.ArithmeticContext) -> Result[Self, @Luna-Flow/arithmetic.ArithmeticError]
}
pub impl CheckedSqrt for Float
pub impl CheckedSqrt for Double
CheckedSqrt::checked_sqrt
CheckedSqrt::checked_sqrt(x, ctx) 在 时返回 Ok(√x),在 时返回 kind 为 DomainError 的错误。
fn CheckedSqrt::checked_sqrt(Self, ArithmeticContext) -> Result[Self, ArithmeticError]
NaN 参数会原样传递为 Ok(NaN)。
CheckedCompare
CheckedCompare 标记具有能报告无序操作数的三路比较的标量类型。
pub(open) trait CheckedCompare {
fn checked_compare(Self, Self) -> Result[Int, @Luna-Flow/arithmetic.ArithmeticError]
}
pub impl CheckedCompare for Float
pub impl CheckedCompare for Double
CheckedCompare::checked_compare
CheckedCompare::checked_compare(x, y) 在 、 和 时分别返回 Ok(-1)、Ok(0) 或 Ok(1),当任一操作数为 NaN 时返回 kind 为 UnorderedComparison 的错误。
fn CheckedCompare::checked_compare(Self, Self) -> Result[Int, ArithmeticError]
三个受检 trait 的综合示例:
///|
test "checked scalar operations" {
let ctx = @lf_arith.ArithmeticContext::new(53)
inspect(
@la_arithmetic.CheckedDiv::checked_div(6.0, 2.0, ctx).unwrap(),
content="3",
)
match @la_arithmetic.CheckedDiv::checked_div(1.0, 0.0, ctx) {
Err(e) => inspect(e.is_division_by_zero(), content="true")
Ok(_) => fail("1 / 0 must fail")
}
match @la_arithmetic.CheckedSqrt::checked_sqrt(-4.0, ctx) {
Err(e) => inspect(e.is_domain_error(), content="true")
Ok(_) => fail("sqrt(-4) must fail")
}
inspect(
@la_arithmetic.CheckedCompare::checked_compare(2.0, 3.0).unwrap(),
content="-1",
)
let nan = 0.0 / 0.0
inspect(
@la_arithmetic.CheckedCompare::checked_compare(nan, 1.0) is Err(_),
content="true",
)
}
这些 trait 的使用位置
具体的矩阵包从 luna-generic(Zero、AddMonoid、Semiring、Field、Num)以及 Sqrt 获取标量约束。@mutable 的数值例程通过此处的重导出使用 Sqrt,并使用它们自己的 Tolerance trait(见 mutable API)。本地 trait Abs、ApproxEq 以及各受检 trait 是供下游算法使用的构件;本仓库中没有任何矩阵方法依赖它们。