ball_float_checked API

ball_float_checked は、区間計算のための Result[BallFloat, ArithmeticError] を包む閉じたラッパー BallFloatResult を提供します。構築時に入力を検証し、すべての演算は最初のエラーをそのまま伝播し、すべてのオペランドが成功値のときに ball_float の区間演算が適用されます。有効だが情報の乏しい包含区間(空集合や実数直線全体)は成功であり、エラーではありません。ラッパーは装飾も BallFlags も保持しません。チュートリアルではパイプラインを構築し、設計ページではどの結果がエラーとなるのか、その理由を説明しています。

例では次の補助関数で結果を出力します(有界なボールの to_string は厳密な二進記法による centre +/- radius であり、mpe は m⋅2em \cdot 2^{e} を意味します):

///|
fn show(r : @ball_float_checked.BallFloatResult) -> String {
  match r.result() {
    Ok(v) => v.to_string()
    Err(e) => "error: " + e.message
  }
}

ラッパー型

BallFloatResult

BallFloatResult は、成功した BallFloat または ArithmeticError のいずれかです。

pub struct BallFloatResult {
  // private fields
}

唯一の非公開フィールドは Result[@ball_float.BallFloat, @arithmetic.ArithmeticError] を保持します。この型には Eq も Show もないので、result() を使ってください。

構築

BallFloatResult::ok, BallFloatResult::err, BallFloatResult::from_result

これらの関数は、既存の区間、エラー、または Result をそのまま包みます。

pub fn BallFloatResult::ok(@ball_float.BallFloat) -> Self
pub fn BallFloatResult::err(@arithmetic.ArithmeticError) -> Self
pub fn BallFloatResult::from_result(Result[@ball_float.BallFloat, @arithmetic.ArithmeticError]) -> Self

BallFloatResult::from_int, BallFloatResult::from_coefficient

これらのコンストラクタは BallFloat::from_int / BallFloat::from_coefficient を通じて整数から点区間を構築します。失敗することはありません。

pub fn BallFloatResult::from_int(Int, precision? : Int) -> Self
pub fn BallFloatResult::from_coefficient(@bin_float.BinCoeff, precision? : Int, negative? : Bool) -> Self

既定の精度は 16 ビットです。整数はまず最近接丸めで max⁡(precision,8)\max(\textit{precision}, 8) ビットの BinFloat に変換され、その後包含されます。

BallFloatResult::from_double, BallFloatResult::from_float

これらのコンストラクタは有限な Double または Float を包含します。

pub fn BallFloatResult::from_double(Double, precision? : Int) -> Self
pub fn BallFloatResult::from_float(Float, precision? : Int) -> Self

元の値は厳密に(少なくとも 53 または 24 ビットで)変換され、その後 precision(既定値 53 と 24)へ外向きに丸められるため、結果は常に元の値を含みます。NaN または無限大の元の値からは DomainError(ball double source must be finite、ball float source must be finite)が得られます。

BallFloatResult::exact

exact(x, precision~) は有限な BinFloat を包含します。

pub fn BallFloatResult::exact(@bin_float.BinFloat, precision? : Int) -> Self

precision の既定値は x.precision() です。上下界は x をその精度へ切り下げ・切り上げたものなので、結果は x を含みます。有限でない x からは DomainError(ball exact source must be finite)が得られます。

BallFloatResult::from_bounds

from_bounds(lo, hi, precision~) は区間 [lo,hi][\textit{lo}, \textit{hi}] を構築します。

pub fn BallFloatResult::from_bounds(@bin_float.BinFloat, @bin_float.BinFloat, precision? : Int) -> Self

precision の既定値は上下界の精度のうち大きい方です。lo は切り下げられ、hi は切り上げられます。上下界のいずれかが NaN のとき、lo が +∞+\infty のとき、hi が −∞-\infty のとき(IEEE 1788 の区間は R\mathbb{R} の部分集合なので、[+∞,+∞][+\infty, +\infty] は区間ではありません)、または lo > hi のとき、DomainError を返します。開いた側の無限大の上下界は許されます。[−∞,0][-\infty, 0] は有効です。

BallFloatResult::whole

whole(precision~) は実数直線全体 [−∞,+∞][-\infty, +\infty](既定の精度 53)であり、失敗することはありません。

pub fn BallFloatResult::whole(precision? : Int) -> Self
///|
test "construction validates its inputs" {
  let one = @bin_float.BinFloat::from_int(1)
  let three = @bin_float.BinFloat::from_int(3)
  inspect(show(@ball_float_checked.BallFloatResult::from_bounds(one, three)), content="1p1 +/- 1p0")
  inspect(
    show(@ball_float_checked.BallFloatResult::from_bounds(three, one)),
    content="error: ball lower bound must not exceed upper bound",
  )
  inspect(
    show(@ball_float_checked.BallFloatResult::from_double(0.1, precision=8)),
    content="409p-12 +/- 1p-12",
  )
  inspect(
    show(@ball_float_checked.BallFloatResult::from_double(0.0 / 0.0)),
    content="error: ball double source must be finite",
  )
  let infinity = @bin_float.BinFloat::inf(@def.Sign::Positive)
  inspect(
    show(@ball_float_checked.BallFloatResult::from_bounds(infinity, infinity)),
    content="error: ball lower bound must not be positive infinity",
  )
  inspect(show(@ball_float_checked.BallFloatResult::whole()), content="[-inf, inf]")
}

観測

BallFloatResult::result, is_ok, is_err, error

これらのメソッドは、包まれた Result を公開し、その分岐を判定し、またはエラーをオプションとして返します。

pub fn BallFloatResult::result(Self) -> Result[@ball_float.BallFloat, @arithmetic.ArithmeticError]
pub fn BallFloatResult::is_ok(Self) -> Bool
pub fn BallFloatResult::is_err(Self) -> Bool
pub fn BallFloatResult::error(Self) -> @arithmetic.ArithmeticError?

error() は、result() が Err(e) であるときに限り Some(e) です。

合成

BallFloatResult::map, BallFloatResult::bind

map(f) は失敗しない区間関数を成功値に適用し、bind(f) は失敗し得る関数を適用します。エラーはそのまま伝播します。

pub fn BallFloatResult::map(Self, (@ball_float.BallFloat) -> @ball_float.BallFloat) -> Self
pub fn BallFloatResult::bind(Self, (@ball_float.BallFloat) -> Self) -> Self

これらは bin_float_checked の設計で証明されたモナド則と関手則を満たします。証明は値の型に依存しません。

単項の値写像

neg, abs, normalized, with_precision

これらのメソッドは、同名の BallFloat メソッドの map です。

pub fn BallFloatResult::neg(Self) -> Self
pub fn BallFloatResult::abs(Self) -> Self
pub fn BallFloatResult::normalized(Self) -> Self
pub fn BallFloatResult::with_precision(Self, Int, @arithmetic.RoundingMode) -> Self

neg と abs は厳密な区間の像 {−t}\{-t\} と {∣t∣}\{|t|\} です。with_precision は、どの丸めモードでも新しい精度で入力の包含区間を返します(モードは中心の向きを決めるだけです)。

算術演算

add, sub, mul, div

これらのメソッドは、BallFloat の演算子で 2 つのラッパーを組み合わせます。

pub fn BallFloatResult::add(Self, Self) -> Self
pub fn BallFloatResult::sub(Self, Self) -> Self
pub fn BallFloatResult::mul(Self, Self) -> Self
pub fn BallFloatResult::div(Self, Self) -> Self

左オペランドのエラーが先に、次に右オペランドのエラーが採用されます。区間演算自体が失敗することはなく、結果は { s∘t:s∈X,t∈Y }\{\, s \circ t : s \in X, t \in Y \,\} を包含します。ちょうど {0}\{0\} である区間による除算は空集合を与え、内部にゼロを含む区間による除算は実数直線全体を与えます。

pow_nat, pow_int

これらのメソッドは、Luna-Flow/arithmetic のトレイト PowNatChecked と PowIntChecked を通じて区間を整数乗します。

pub fn BallFloatResult::pow_nat(Self, UInt) -> Self
pub fn BallFloatResult::pow_int(Self, Int) -> Self

コンテキストは ArithmeticContext::new(x.precision()) で、ball_float はその精度だけを使います。結果は {tn}\{t^{n}\} の包含区間であり、べきとして計算されます(そのため [1,3][1, 3] の pow_int(2) は [1,9][1, 9] となり、ゼロを含む区間に対しては x * x よりも狭くなります)。ゼロの底と負の指数からは空集合が得られます。

rootn

rootn(n) は BallFloat::try_rootn によって実数の nn 乗根を包含します。

pub fn BallFloatResult::rootn(Self, Int) -> Self

次数 00 からは DomainError が得られます。偶数乗根は区間の負の部分を無視します(集合意味論)。[−1,1][-1, 1] の根は [0,1][0, 1] です。

pow, hypot, atan2

これらの二項関数は、xyx^{y}、x2+y2\sqrt{x^2+y^2}、および (abscissa,self)(\text{abscissa}, \text{self}) の角度を包含します。

pub fn BallFloatResult::pow(Self, Self) -> Self
pub fn BallFloatResult::hypot(Self, Self) -> Self
pub fn BallFloatResult::atan2(Self, Self) -> Self

これらは try_pow_interval、try_hypot、try_atan2_interval を呼び出します。オペランドのエラーは左から順に採用され、演算自体は CertificationFailure で失敗することがあります。実数の定義域外の点は結果の集合から除かれるため、(−2)0.5(-2)^{0.5} は空の区間です。

///|
test "interval arithmetic in the wrapper" {
  let x = @ball_float_checked.BallFloatResult::from_bounds(
    @bin_float.BinFloat::from_int(1),
    @bin_float.BinFloat::from_int(3),
  )
  inspect(show(x * x - x), content="3p0 +/- 5p0")
  inspect(show(x.pow_int(2)), content="5p0 +/- 1p2")
  let one = @ball_float_checked.BallFloatResult::from_int(1)
  let zero = @ball_float_checked.BallFloatResult::from_int(0)
  inspect(show(one / zero), content="[empty]")
  let around_zero = @ball_float_checked.BallFloatResult::from_bounds(
    @bin_float.BinFloat::from_int(-1),
    @bin_float.BinFloat::from_int(1),
  )
  inspect(show(one / around_zero), content="[-inf, inf]")
  inspect(show(around_zero.rootn(2)), content="1p-1 +/- 1p-1")
  inspect(show(x.rootn(0)), content="error: rootn degree must not be zero")
}

初等関数

指数関数、対数関数、三角関数、双曲線関数

exp、exp2、exp10、expm1、ln、log2、log10、log1p、sin、cos、tan、sinpi、cospi、tanpi、asin、acos、atan、sinh、cosh、tanh、asinh、acosh、atanh は、関数による区間の像を包含します。

pub fn BallFloatResult::exp(Self) -> Self
pub fn BallFloatResult::exp2(Self) -> Self
pub fn BallFloatResult::exp10(Self) -> Self
pub fn BallFloatResult::expm1(Self) -> Self
pub fn BallFloatResult::ln(Self) -> Self
pub fn BallFloatResult::log2(Self) -> Self
pub fn BallFloatResult::log10(Self) -> Self
pub fn BallFloatResult::log1p(Self) -> Self
pub fn BallFloatResult::sin(Self) -> Self
pub fn BallFloatResult::cos(Self) -> Self
pub fn BallFloatResult::tan(Self) -> Self
pub fn BallFloatResult::sinpi(Self) -> Self
pub fn BallFloatResult::cospi(Self) -> Self
pub fn BallFloatResult::tanpi(Self) -> Self
pub fn BallFloatResult::asin(Self) -> Self
pub fn BallFloatResult::acos(Self) -> Self
pub fn BallFloatResult::atan(Self) -> Self
pub fn BallFloatResult::sinh(Self) -> Self
pub fn BallFloatResult::cosh(Self) -> Self
pub fn BallFloatResult::tanh(Self) -> Self
pub fn BallFloatResult::asinh(Self) -> Self
pub fn BallFloatResult::acosh(Self) -> Self
pub fn BallFloatResult::atanh(Self) -> Self

各メソッドは、区間の精度での BallFloat::try_<name>_interval の bind です。結果 YY は f(X∩dom⁡f)⊆Yf(X \cap \operatorname{dom} f) \subseteq Y を満たします。XX のうち定義域外の部分は無視されるため、ln⁡([−1,1])=[−∞,0]\ln([-1, 1]) = [-\infty, 0] であり、ln⁡([−2,−2])\ln([-2, -2]) は空です。唯一のエラーは、包含区間を認証できない場合の CertificationFailure であり、たとえば 2700002^{70000} の余弦がそうです(理由は ResourceLimit)。コンテキスト付きの変種はなく、精度は with_precision で設定します。

///|
test "elementary enclosures" {
  let two = @ball_float_checked.BallFloatResult::from_int(2, precision=53)
  inspect(show(two.ln()), content="12486629536330719p-54 +/- 1p-54")
  inspect(show(two.ln().exp()), content="18014398509481985p-53 +/- 3p-53")
  let around_zero = @ball_float_checked.BallFloatResult::from_bounds(
    @bin_float.BinFloat::from_int(-1),
    @bin_float.BinFloat::from_int(1),
  )
  inspect(show(around_zero.ln()), content="[-inf, 0]")
  let huge = @ball_float_checked.BallFloatResult::exact(
    @bin_float.BinFloat::make(@bin_float.BinCoeff::one(), 70000, 53),
  )
  match huge.cos().error() {
    Some(e) => {
      let detail = e.certification_failure_detail().unwrap()
      inspect(detail.operation(), content="cos")
      inspect(
        detail.reason() == @lf_arith.CertificationFailureReason::ResourceLimit,
        content="true",
      )
    }
    None => fail("expected a certification failure")
  }
}

トレイト実装

Add, Sub, Mul, Div, Neg

演算子 +、-、*、/ と単項 - は、add、sub、mul、div、neg を呼び出します。

pub impl Add for BallFloatResult
pub impl Sub for BallFloatResult
pub impl Mul for BallFloatResult
pub impl Neg for BallFloatResult
pub impl Div for BallFloatResult

非推奨

BallFloatResult::flat_map

flat_map は bind の旧名です。r.flat_map(f) を r.bind(f) に置き換えてください。

#deprecated
pub fn BallFloatResult::flat_map(Self, (@ball_float.BallFloat) -> Self) -> Self

公開インターフェース全体

以下のスナップショットは、パッケージの生成された完全なインターフェースです。

// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/ball_float_checked"

import {
  "Luna-Flow/arithmetic",
  "Luna-Flow/floating/ball_float",
  "Luna-Flow/floating/bin_float",
}

// Values

// Errors

// Types and methods
pub struct BallFloatResult {
  // private fields
}
pub fn BallFloatResult::abs(Self) -> Self
pub fn BallFloatResult::acos(Self) -> Self
pub fn BallFloatResult::acosh(Self) -> Self
pub fn BallFloatResult::add(Self, Self) -> Self
pub fn BallFloatResult::asin(Self) -> Self
pub fn BallFloatResult::asinh(Self) -> Self
pub fn BallFloatResult::atan(Self) -> Self
pub fn BallFloatResult::atan2(Self, Self) -> Self
pub fn BallFloatResult::atanh(Self) -> Self
pub fn BallFloatResult::bind(Self, (@ball_float.BallFloat) -> Self) -> Self
pub fn BallFloatResult::cos(Self) -> Self
pub fn BallFloatResult::cosh(Self) -> Self
pub fn BallFloatResult::cospi(Self) -> Self
pub fn BallFloatResult::div(Self, Self) -> Self
pub fn BallFloatResult::err(@arithmetic.ArithmeticError) -> Self
pub fn BallFloatResult::error(Self) -> @arithmetic.ArithmeticError?
pub fn BallFloatResult::exact(@bin_float.BinFloat, precision? : Int) -> Self
pub fn BallFloatResult::exp(Self) -> Self
pub fn BallFloatResult::exp10(Self) -> Self
pub fn BallFloatResult::exp2(Self) -> Self
pub fn BallFloatResult::expm1(Self) -> Self
#deprecated
pub fn BallFloatResult::flat_map(Self, (@ball_float.BallFloat) -> Self) -> Self
pub fn BallFloatResult::from_bounds(@bin_float.BinFloat, @bin_float.BinFloat, precision? : Int) -> Self
pub fn BallFloatResult::from_coefficient(@bin_float.BinCoeff, precision? : Int, negative? : Bool) -> Self
pub fn BallFloatResult::from_double(Double, precision? : Int) -> Self
pub fn BallFloatResult::from_float(Float, precision? : Int) -> Self
pub fn BallFloatResult::from_int(Int, precision? : Int) -> Self
pub fn BallFloatResult::from_result(Result[@ball_float.BallFloat, @arithmetic.ArithmeticError]) -> Self
pub fn BallFloatResult::hypot(Self, Self) -> Self
pub fn BallFloatResult::is_err(Self) -> Bool
pub fn BallFloatResult::is_ok(Self) -> Bool
pub fn BallFloatResult::ln(Self) -> Self
pub fn BallFloatResult::log10(Self) -> Self
pub fn BallFloatResult::log1p(Self) -> Self
pub fn BallFloatResult::log2(Self) -> Self
pub fn BallFloatResult::map(Self, (@ball_float.BallFloat) -> @ball_float.BallFloat) -> Self
pub fn BallFloatResult::mul(Self, Self) -> Self
pub fn BallFloatResult::neg(Self) -> Self
pub fn BallFloatResult::normalized(Self) -> Self
pub fn BallFloatResult::ok(@ball_float.BallFloat) -> Self
pub fn BallFloatResult::pow(Self, Self) -> Self
pub fn BallFloatResult::pow_int(Self, Int) -> Self
pub fn BallFloatResult::pow_nat(Self, UInt) -> Self
pub fn BallFloatResult::result(Self) -> Result[@ball_float.BallFloat, @arithmetic.ArithmeticError]
pub fn BallFloatResult::rootn(Self, Int) -> Self
pub fn BallFloatResult::sin(Self) -> Self
pub fn BallFloatResult::sinh(Self) -> Self
pub fn BallFloatResult::sinpi(Self) -> Self
pub fn BallFloatResult::sub(Self, Self) -> Self
pub fn BallFloatResult::tan(Self) -> Self
pub fn BallFloatResult::tanh(Self) -> Self
pub fn BallFloatResult::tanpi(Self) -> Self
pub fn BallFloatResult::whole(precision? : Int) -> Self
pub fn BallFloatResult::with_precision(Self, Int, @arithmetic.RoundingMode) -> Self
pub impl Add for BallFloatResult
pub impl Div for BallFloatResult
pub impl Mul for BallFloatResult
pub impl Neg for BallFloatResult
pub impl Sub for BallFloatResult

// Type aliases

// Traits