arithmetic API
Luna-Flow/linear-algebra/arithmetic はリポジトリのスカラー演算層です。線形代数コードが使うスカラー型と trait を Luna-Flow/luna-generic と Luna-Flow/arithmetic から再公開し、五つの小さな演算 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 では、2 の補数演算と同様に は に折り返されます。
///|
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 は NaN や無限大の代わりに Result[_, ArithmeticError] を返します。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、種類 DomainError | |
Err、種類 DomainError | |
| , | Err、種類 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) を、 なら種類 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 なら種類 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 は下流のアルゴリズムのための部品であり、このリポジトリの行列メソッドでこれらを要求するものはありません。