checked API

checked 包是带检查定义域求导的门面包。它重新导出 Dual、Dual[T] 实现的两个带检查 trait 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}

带检查的 trait

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")
      }
  }
}