checked API

checked パッケージは、定義域をチェックする微分のためのファサードです。Dual、Dual[T] が実装する 2 つのチェック付きトレイト DivChecked と SqrtChecked、およびそれらが使うコンテキスト型とエラー型を、すべて arithmetic から再エクスポートします。チェック付きの規則そのものは dual API に記載されています。

ソース:src/checked/alias.mbt。

インポート

import {
  "Luna-Flow/autodiff/checked",
}

再エクスポートされる型

Dual

双対数型です。チェック付きメソッドは Dual::div_checked と Dual::sqrt_checked です。

pub using @dual {type Dual}

チェック付きトレイト

DivChecked

Result[Self, ArithmeticError] を返す除算です。

pub using @arithmetic {trait DivChecked}

Dual[T] 上(T : DivChecked + Sub + Mul の場合)では、T の div_checked で a/ca/c と (bc−ad)/c2(bc - ad)/c^2 を計算し、最初のエラーを返します。Double では、c=0≠ac = 0 \ne a のとき is_division_by_zero() で、0/00/0 と ∞/∞\infty/\infty のとき is_domain_error() で失敗します。

SqrtChecked

Result[Self, ArithmeticError] を返す平方根です。

pub using @arithmetic {trait SqrtChecked}

Dual[T] 上では、T の sqrt_checked で a\sqrt a を、div_checked で接成分 b/(2a)b/(2\sqrt a) を計算します。Double では、a<0a < 0 のとき(定義域エラー)と a=0a = 0 のとき(ゼロ除算、または b=0b = 0 なら 0/00/0)に失敗します。

test "checked traits on dual numbers" {
  let ctx = @checked.ArithmeticContext::new(53)
  let x : @checked.Dual[Double] = @checked.Dual::variable(4.0)
  match @checked.SqrtChecked::sqrt_checked(x, ctx) {
    Ok(r) => assert_eq(r.tangent(), 0.25)
    Err(_) => fail("unexpected error")
  }
  let z : @checked.Dual[Double] = @checked.Dual::constant(0.0)
  assert_true(@checked.DivChecked::div_checked(x, z, ctx) is Err(_))
}

コンテキストとエラー

ArithmeticContext

すべてのチェック付き呼び出しに渡される明示的な数値コンテキストです。

pub using @arithmetic {type ArithmeticContext}

ArithmeticContext::new(precision, rounding?, e_min?, e_max?, clamp?) で構築します。Dual[T] はこれをそのまま T に渡します。Double と Float のインスタンスはこれを無視します。

RoundingMode

コンテキストに格納される丸め方向です。

pub using @arithmetic {type RoundingMode}

ArithmeticError

チェック付き演算が返す構造化エラーです。kind と人間が読める message を持ちます。

pub using @arithmetic {type ArithmeticError}

述語 is_division_by_zero() と is_domain_error() で、チェック付き Dual 演算が Double に対して生成するすべてのエラーを判定できます。

ArithmeticErrorKind

ArithmeticError の種類です。

pub using @arithmetic {type ArithmeticErrorKind}
test "matching on the error kind" {
  let ctx = @checked.ArithmeticContext::new(53)
  let x : @checked.Dual[Double] = @checked.Dual::new(-1.0, 1.0)
  match x.sqrt_checked(ctx) {
    Ok(_) => fail("expected an error")
    Err(e) =>
      match e.kind {
        @checked.ArithmeticErrorKind::DomainError => ()
        _ => fail("expected a domain error")
      }
  }
}