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。

名前種類由来意味
Zerotraitluna-generic加法単位元 zero()
Onetraitluna-generic乗法単位元 one()
Inversetraitluna-generic乗法逆元 inv(x)
Conjugatetraitluna-generic対合 conjugate(x)。組み込みの実数型にはインスタンスがない
Sqrttraitarithmetic検査なしの sqrt(x)
Cbrttraitarithmetic検査なしの cbrt(x)
Powertraitarithmetic検査なしの pow(x, y)
Exponentialtraitarithmeticexp(x), exp2(x)
Logarithmictraitarithmeticln(x), log2(x), log10(x)
Constantstraitarithmeticpi(), tau(), e()
SqrtCheckedtraitarithmeticResult を返す sqrt_checked(x, ctx)
DivCheckedtraitarithmeticResult を返す div_checked(x, y, ctx)
CompareCheckedtraitarithmeticResult[Int, _] を返す compare_checked(x, y)
ArithmeticContext型arithmetic検査付き演算に渡す精度と丸めの設定
ArithmeticError型arithmetickind と message を持つ構造化されたスカラーエラー
ArithmeticErrorKind型arithmeticDivisionByZero, DomainError, UnorderedComparison, …
FpClass型arithmeticFinite, Infinity, NaN
RoundingMode型arithmeticToNearestEven, 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 は ∣x∣|x| を返します。

fn Abs::abs(Self) -> Self

実装は luna-generic の Num::abs に委譲します。Int では、2 の補数演算と同様に ∣−231∣|-2^{31}| は −231-2^{31} に折り返されます。

///|
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
型規則
Inta=ba = b
Float∣a−b∣≤10−6\lvert a - b\rvert \le 10^{-6}
Double∣a−b∣≤10−12\lvert a - b\rvert \le 10^{-12}

許容誤差は絶対的なので、大きな値には厳しすぎ、小さな値には緩すぎます。また、この関係は推移的ではありません。オペランドのいずれかが 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]
オペランド結果
0/00 / 0Err、種類 DomainError
±∞/±∞\pm\infty / \pm\inftyErr、種類 DomainError
x/0x / 0, x≠0x \ne 0Err、種類 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) は x≥0x \ge 0 なら Ok(√x) を、x<0x < 0 なら種類 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) は x<yx < y、x=yx = y、x>yx > 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 は下流のアルゴリズムのための部品であり、このリポジトリの行列メソッドでこれらを要求するものはありません。