float_backend API

float_backend パッケージは Complex[Double] の解析関数を提供します。絶対値と偏角、除算、根、指数関数と対数、べき乗、そして三角関数・双曲線関数とその逆関数です。また、浮動小数点スカラー向けに 3 つの能力トレイトを定義し、Float と Double に対して実装しています。式の導出と分岐切断については float_backend の設計 で説明しています。

ソース: src/float_backend/(float_backend_traits.mbt、complex_elementary.mbt、complex_trigonometric.mbt、complex_hyperbolic.mbt)。

インポート

import {
  "Luna-Flow/luna-complex/float_backend" @fb,
}

例では、このパッケージに @fb、ルートパッケージに @complex を使います。すべての関数は Complex[Double] 上の自由関数です(MoonBit では、パッケージが他のパッケージの型にメソッドを追加できないため)。

規約

  • 主値。 多価関数は、関数ごとに説明する固定された分枝の値を 1 つ返します。arg は負の実軸上を除き (−π,π](-\pi, \pi] の値を返します(下の警告を参照)。
  • 特殊値。 NaN と無限大は明記された箇所(div、atan、atanh、acosh、abs_log、pow)で処理されます。それ以外では通常の Double 算術を通じて伝播し、NaN の部分を生じることがあります。
  • 逆数系の関数は極で中断します。 sec、csc、cot、sech、csch、coth、asec、acsc、asech、acsch、acoth、および pow の指数 −1-1 は Complex::inv を使うため、絶対値がゼロのときに Double::inv: division by zero で中断します。

能力トレイト

FloatingAnalyticScalar

解析バックエンドが実スカラーに求める代数的・解析的な能力です。

pub(open) trait FloatingAnalyticScalar : @luna-generic.Field + @luna-generic.Num + Compare + @arithmetic.Constants + @arithmetic.Sqrt + @arithmetic.Exponential + @arithmetic.Logarithmic + @arithmetic.Trigonometric + @arithmetic.InverseTrigonometric + @arithmetic.Hyperbolic + @arithmetic.InverseHyperbolic {
}
pub impl FloatingAnalyticScalar for Float
pub impl FloatingAnalyticScalar for Double

独自のメソッドは持たず、luna-generic と arithmetic のトレイトの合成に名前を付けたものです。

FloatingSpecialValues

IEEE 754 の特殊値とその判定です。

pub(open) trait FloatingSpecialValues {
  fn nan() -> Self
  fn infinity() -> Self
  fn neg_infinity() -> Self
  fn is_nan(Self) -> Bool
  fn is_inf(Self) -> Bool
  fn is_pos_inf(Self) -> Bool
  fn is_neg_inf(Self) -> Bool
  fn is_negative_zero(Self) -> Bool
}
pub impl FloatingSpecialValues for Float
pub impl FloatingSpecialValues for Double

is_negative_zero(x) は is_neg_inf(1.0 / x) なので、ちょうど −0-0 のときに真になります。

FloatingBackendScalar

上記 2 つのトレイトに加えて、数値的に安定なアルゴリズムが使うプリミティブです。

pub(open) trait FloatingBackendScalar : FloatingAnalyticScalar + FloatingSpecialValues {
  fn from_double(Double) -> Self
  fn trunc(Self) -> Self
  fn to_int(Self) -> Int
  fn hypot(Self, Self) -> Self
  fn log1p(Self) -> Self
}
pub impl FloatingBackendScalar for Float
pub impl FloatingBackendScalar for Double
メソッド意味DoubleFloat
from_doubleDouble 定数を変換恒等関数Float::from_double
truncゼロ方向への丸めDouble::truncFloat::trunc
to_intInt へ変換Double::to_intFloat::to_int
hypotオーバーフローしない x2+y2\sqrt{x^2 + y^2}@math.hypot@math.hypotf
log1pln⁡(1+x)\ln(1 + x)@math.log1pln(1.0 + x)

Float の log1p は直接の式であり、∣x∣≪1|x| \ll 1 で相対精度が失われます。このパッケージの公開関数で、これらのトレイトについてジェネリックなものはまだありません。以下の Complex[Double] 関数は Double のプリミティブを直接呼び出します。

fn[T : @fb.FloatingSpecialValues] classify(x : T) -> String {
  if @fb.FloatingSpecialValues::is_nan(x) {
    "nan"
  } else if @fb.FloatingSpecialValues::is_inf(x) {
    "inf"
  } else if @fb.FloatingSpecialValues::is_negative_zero(x) {
    "-0"
  } else {
    "finite"
  }
}

test "special values" {
  assert_eq(classify(-0.0), "-0")
  assert_eq(classify(@double.infinity), "inf")
  let nan : Float = @fb.FloatingSpecialValues::nan()
  assert_eq(classify(nan), "nan")
  assert_eq(@fb.FloatingBackendScalar::hypot(3.0, 4.0), 5.0)
}

再エクスポートされる型

Complex

@fb.Complex は @complex.Complex です。core API を参照してください。

pub using @luna-complex {type Complex}

構築と格納

polar

reiθ=rcos⁡θ+i rsin⁡θr e^{i\theta} = r\cos\theta + i\,r\sin\theta を構築します。

pub fn polar(Double, Double) -> Complex[Double]

正規化は行いません。負の rr や任意の実数 θ\theta も受け付けます。

pack

インターリーブされたバッファ [re0, im0, re1, im1, …] の複素インデックス offset の位置に zz を書き込みます。

pub fn pack(Complex[Double], Array[Double], Int) -> Unit

native_pack

実部と虚部をインターリーブされたバッファに書き込みます。

pub fn native_pack(Double, Double, Array[Double], Int) -> Unit

バッファの長さは偶数でなければなりません。offset が複素要素の個数(arr.length() / 2)に等しい場合はペアを追加し、そうでなければ要素 offset を上書きします。長さが奇数の場合は native_pack: buffer length must be even で、オフセットが 0..=arr.length() / 2 の範囲外の場合は native_pack: offset out of bounds で中断します。

test "polar and packing" {
  let z = @fb.polar(2.0, 0.0)
  assert_eq(z, @complex.Complex::new(2.0, 0.0))
  let buf : Array[Double] = []
  @fb.pack(z, buf, 0)
  @fb.native_pack(3.0, 4.0, buf, 1)
  @fb.native_pack(5.0, 6.0, buf, 0)
  assert_eq(buf, [5.0, 6.0, 3.0, 4.0])
}

絶対値と偏角

abs

hypot を使い、途中でオーバーフローやアンダーフローを起こさずに ∣z∣=x2+y2|z| = \sqrt{x^2 + y^2} を返します。

pub fn abs(Complex[Double]) -> Double

abs_sqr

m=max⁡(∣x∣,∣y∣)m = \max(|x|, |y|) として m2((x/m)2+(y/m)2)m^2\big((x/m)^2 + (y/m)^2\big) で計算した ∣z∣2|z|^2 を返します。

pub fn abs_sqr(Complex[Double]) -> Double

スケーリングにより 2 乗の見かけ上のアンダーフローを避けますが、∣z∣2|z|^2 が Double の範囲を超える場合は結果自体が無限大にオーバーフローします。00 は 00 に写ります。

abs_log

m=max⁡(∣x∣,∣y∣)m = \max(|x|,|y|)、t=min⁡/max⁡t = \min/\max として、ln⁡m+12ln⁡(1+t2)\ln m + \tfrac12\ln(1 + t^2) により ln⁡∣z∣\ln|z| を返します。

pub fn abs_log(Complex[Double]) -> Double

∣z∣|z| 自体がオーバーフローする場合でも、ゼロでない有限の zz すべてに対して有限です。abs_log(0) は −∞-\infty です。

arg

z=∣z∣eiθz = |z| e^{i\theta} となる偏角 θ\theta を返します。

pub fn arg(Complex[Double]) -> Double
入力結果
z=0z = 0(ゼロの符号はどちらでも)00
y=±0y = \pm 0, x<0x < 02π2\pi(上の警告を参照)
それ以外atan2(y, x) ∈(−π,π)\in (-\pi, \pi)
test "modulus and argument" {
  let z = @complex.Complex::new(3.0, 4.0)
  assert_eq(@fb.abs(z), 5.0)
  assert_eq(@fb.abs_sqr(z), 25.0)
  assert_eq(@fb.arg(@complex.Complex::new(0.0, 1.0)), @math.PI / 2.0)
  let huge = @complex.Complex::new(1.0e300, 1.0e300)
  assert_true(@fb.abs_sqr(huge).is_inf())
  assert_true(@fb.abs_log(huge) < 692.0) // ln(sqrt 2 * 1e300) is about 691.1
}

除算

div

Smith のスケーリングと IEEE の特殊値処理を用いて z/wz / w を計算します。

pub fn div(Complex[Double], Complex[Double]) -> Complex[Double]

有限の ww に対しては、まず ∣c∣,∣d∣|c|, |d| の大きい方で割ります(∣c∣≥∣d∣|c| \ge |d| のときは r=d/cr = d/c):

a+bic+di=(a+br)+(b−ar) ic (1+r2),\frac{a + bi}{c + di} = \frac{(a + b r) + (b - a r)\,i}{c\,(1 + r^2)} ,

そのため cc や dd の 2 乗は計算されません。zz に NaN の部分がなく、ww に無限大の部分がある場合、結果は無限大の符号から計算されます。有限の zz は ±0\pm 0 の部分を与え、無限大の zz は符号パターンの商を与えます。0+0i0 + 0i による除算は無限大または NaN を生じます(中断はしません)。

test "robust division" {
  let one = @complex.Complex::new(1.0, 0.0)
  let tiny = @complex.Complex::new(1.0e-300, 1.0e-300)
  let q = @fb.div(one, tiny)
  assert_true(q.re > 4.9e299 && q.im < -4.9e299)
  let z = @fb.div(@complex.Complex::new(1.0, 2.0), @complex.Complex::new(@double.infinity, 0.0))
  assert_eq(z.re, 0.0)
}

根

sqrt

主値の平方根を返します。Re⁡z≥0\operatorname{Re}\sqrt z \ge 0 で、分岐切断は負の実軸に沿っています。

pub fn sqrt(Complex[Double]) -> Complex[Double]

スケーリングした形で w=(∣x∣+∣z∣)/2w = \sqrt{(|x| + |z|)/2} を計算し、x≥0x \ge 0 のときは w+y2wiw + \frac{y}{2w} i を、x<0x < 0 のときは yy の符号に応じて ∣y∣2w±w i\frac{|y|}{2w} \pm w\,i を返します。分岐切断上(y=±0y = \pm 0、x<0x < 0)では、ゼロの符号によらず結果は +∣x∣ i+\sqrt{|x|}\,i です。sqrt(0) は 00 です。

sqrt_real

実数の平方根を複素数として返します。x≥0x \ge 0 では x\sqrt x、x<0x < 0 では i−xi\sqrt{-x} です。

pub fn sqrt_real(Double) -> Complex[Double]
test "square roots" {
  assert_eq(@fb.sqrt(@complex.Complex::new(-3.0, 4.0)), @complex.Complex::new(1.0, 2.0))
  assert_eq(@fb.sqrt(@complex.Complex::new(-4.0, 0.0)), @complex.Complex::new(0.0, 2.0))
  assert_eq(@fb.sqrt_real(-9.0), @complex.Complex::new(0.0, 3.0))
}

指数関数と対数

exp

ez=ex(cos⁡y+isin⁡y)e^z = e^x(\cos y + i\sin y) を返します。

pub fn exp(Complex[Double]) -> Complex[Double]

exe^x を先に計算するため、結果の一部が有限になる場合でも x>709.78x > 709.78 でオーバーフローし、exp(710 + 0i) の虚部は NaN になります(∞⋅0\infty \cdot 0)。

log

abs_log と arg を使って ln⁡∣z∣+iarg⁡z\ln|z| + i\arg z を返します。

pub fn log(Complex[Double]) -> Complex[Double]

虚部は arg に従うため、負の実軸上では 2π2\pi になります。log(0) は −∞+0i-\infty + 0i です。

log_10

log⁡10z=log⁡z/ln⁡10\log_{10} z = \log z / \ln 10 を返します。

pub fn log_10(Complex[Double]) -> Complex[Double]

log_b

div で除算して log⁡bz=log⁡z/log⁡b\log_b z = \log z / \log b を返します。

pub fn log_b(Complex[Double], Complex[Double]) -> Complex[Double]
test "exponential and logarithm" {
  let z = @complex.Complex::new(1.0, 2.0)
  let back = @fb.exp(@fb.log(z))
  assert_true((back.re - 1.0).abs() < 1.0e-12 && (back.im - 2.0).abs() < 1.0e-12)
  let l = @fb.log_10(@complex.Complex::new(100.0, 0.0))
  assert_true((l.re - 2.0).abs() < 1.0e-15)
}

べき乗

pow

zwz^w を返します。

pub fn pow(Complex[Double], Complex[Double]) -> Complex[Double]

次のケースが順に試されます:

ケース結果
z=0z = 0, w=0w = 011
z=0z = 0、ww が正の実数00
z=0z = 0、それ以外NaN + NaNii
w=1w = 1zz
w=−1w = -1z.inv()(z=0z = 0 のとき中断するが、最初の行で除外済み)
ww が実整数で ∣w∣≤231−1\lvert w\rvert \le 2^{31} - 1二進累乗法。負の指数ではまず zz の逆数をとる
それ以外極形式での ewlog⁡ze^{w\log z}

極形式では ρ=eRe⁡wln⁡∣z∣−Im⁡warg⁡z\rho = e^{\operatorname{Re} w \ln|z| - \operatorname{Im} w \arg z} と β=Re⁡warg⁡z+Im⁡wln⁡∣z∣\beta = \operatorname{Re} w \arg z + \operatorname{Im} w \ln|z| を計算し、ρ(cos⁡β+isin⁡β)\rho(\cos\beta + i\sin\beta) を返します。

pow_real

実数の指数 pp に対して zpz^p を返します。ゼロ、整数、極形式のケースは pow と同じです。

pub fn pow_real(Complex[Double], Double) -> Complex[Double]
test "powers" {
  let z = @complex.Complex::new(1.0, 2.0)
  assert_eq(@fb.pow_real(z, 2.0), @complex.Complex::new(-3.0, 4.0))
  let r = @fb.pow(@complex.Complex::new(0.0, 1.0), @complex.Complex::new(0.5, 0.0))
  assert_true((r.re - 0.7071067811865476).abs() < 1.0e-15)
  assert_true(@fb.pow_real(@complex.Complex::new(0.0, 0.0), -1.0).re.is_nan())
}

スカラーオペランド

op_bin_re

2 番目のオペランドを実数 x+0ix + 0i として 2 項複素関数を適用します。

pub fn op_bin_re(Complex[Double], Double, (Complex[Double], Complex[Double]) -> Complex[Double]) -> Complex[Double]

op_bin_im

2 番目のオペランドを純虚数 0+yi0 + yi として 2 項複素関数を適用します。

pub fn op_bin_im(Complex[Double], Double, (Complex[Double], Complex[Double]) -> Complex[Double]) -> Complex[Double]
test "scalar operands" {
  let z = @complex.Complex::new(1.0, 2.0)
  assert_eq(@fb.op_bin_re(z, 2.0, @fb.div), @complex.Complex::new(0.5, 1.0))
  assert_eq(@fb.op_bin_im(z, 1.0, (a, b) => a * b), @complex.Complex::new(-2.0, 1.0))
}

三角関数

sin

sin⁡z=sin⁡xcosh⁡y+icos⁡xsinh⁡y\sin z = \sin x\cosh y + i\cos x\sinh y を返します。y=0y = 0 ちょうどのときは実数の sin⁡x\sin x を返します。

pub fn sin(Complex[Double]) -> Complex[Double]

cos

cos⁡z=cos⁡xcosh⁡y−isin⁡xsinh⁡y\cos z = \cos x\cosh y - i\sin x\sinh y を返します。y=0y = 0 ちょうどのときは実数の cos⁡x\cos x を返します。

pub fn cos(Complex[Double]) -> Complex[Double]

tan

tan⁡z\tan z を返します。

pub fn tan(Complex[Double]) -> Complex[Double]

∣y∣<1|y| < 1 では sin⁡2x+isinh⁡2y2(cos⁡2x+sinh⁡2y)\dfrac{\sin 2x + i\sinh 2y}{2(\cos^2 x + \sinh^2 y)} を使い、∣y∣≥1|y| \ge 1 では e−2∣y∣e^{-2|y|} でスケーリングした、オーバーフローせずに ±i\pm i へ収束する形を使います(設計を参照)。

sec

1/cos⁡z1/\cos z を返します。cos⁡z=0\cos z = 0 となる点で中断します。

pub fn sec(Complex[Double]) -> Complex[Double]

csc

1/sin⁡z1/\sin z を返します。z=kπz = k\pi で中断します。

pub fn csc(Complex[Double]) -> Complex[Double]

cot

1/tan⁡z1/\tan z を返します。z=kπz = k\pi で中断します。

pub fn cot(Complex[Double]) -> Complex[Double]
test "trigonometric functions" {
  let z = @complex.Complex::new(1.0, 1.0)
  let s = @fb.sin(z)
  let c = @fb.cos(z)
  let one = s * s + c * c
  assert_true((one.re - 1.0).abs() < 1.0e-15 && one.im.abs() < 1.0e-15)
  let t = @fb.tan(@complex.Complex::new(1.0, 100.0))
  assert_eq(t.im, 1.0)
}

逆三角関数

asin

主値の逆正弦を返します。分岐切断は実軸上の [−1,1][-1, 1] の外側にあり、Re⁡\operatorname{Re} は [−π/2,π/2][-\pi/2, \pi/2] に入ります。

pub fn asin(Complex[Double]) -> Complex[Double]

実数の入力は asin_real へ、純虚数の入力は iasinh⁡yi\operatorname{asinh} y へ、いずれかの部分が 1015010^{150} を超える入力は漸近形 atan2⁡(∣x∣,∣y∣)+i(ln⁡2+ln⁡∣z∣)\operatorname{atan2}(|x|, |y|) + i(\ln 2 + \ln|z|) へ、それ以外はすべて Hull–Fairgrieve–Tang アルゴリズムへ送られます(設計を参照)。結果は各部分について奇関数であり、xx と yy の符号がそれぞれ実部と虚部にコピーされます。

asin_real

実数の逆正弦です。∣x∣≤1|x| \le 1 では arcsin⁡x\arcsin x、∣x∣>1|x| > 1 では ±π/2+iacosh⁡∣x∣\pm\pi/2 + i\operatorname{acosh}|x|(xx の符号)、NaN に対しては NaN です。

pub fn asin_real(Double) -> Complex[Double]

acos

逆余弦を返します。分岐切断は実軸上の [−1,1][-1, 1] の外側にあります。

pub fn acos(Complex[Double]) -> Complex[Double]

x≥0x \ge 0 では、実部は [0,π/2][0, \pi/2] の主値で、虚部は yy と逆の符号を持ちます。x<0x < 0 では虚部は主値ですが、実部は主値の π−ρ\pi - \rho ではなく 2π−ρ2\pi - \rho になります。ここで ρ∈[0,π/2]\rho \in [0, \pi/2] は arccos⁡(−z)\arccos(-z) の実部です(上の警告を参照)。純虚数の入力は π/2−iasinh⁡y\pi/2 - i\operatorname{asinh} y を与え、実数の入力は acos_real へ送られます。

acos_real

実数の逆余弦です。∣x∣≤1|x| \le 1 では arccos⁡x\arccos x、x>1x > 1 では −iacosh⁡x-i\operatorname{acosh} x、x<−1x < -1 では 2π−iacosh⁡(−x)2\pi - i\operatorname{acosh}(-x) です。

pub fn acos_real(Double) -> Complex[Double]

atan

主値の逆正接を返します。分岐切断は虚軸上の [−i,i][-i, i] の外側にあります。

pub fn atan(Complex[Double]) -> Complex[Double]

虚部は 14ln⁡x2+(1+y)2x2+(1−y)2\tfrac14\ln\frac{x^2 + (1+y)^2}{x^2 + (1-y)^2} で、比が 11 に近いときは log1p で計算します。実部は 12atan2⁡(2x,1−x2−y2)\tfrac12\operatorname{atan2}(2x, 1 - x^2 - y^2) で、大きな入力に対してはスケーリングし直します。分岐切断上(x=0x = 0、∣y∣>1|y| > 1)では、実部は yy の符号を持つ ±π/2\pm\pi/2 です。無限大の入力は ±π/2+0i\pm\pi/2 + 0i を返します。

asec

acos⁡(1/z)\operatorname{acos}(1/z) を返します。z=0z = 0 で中断します。

pub fn asec(Complex[Double]) -> Complex[Double]

asec_real

実数の逆正割です。∣x∣≥1|x| \ge 1 では arccos⁡(1/x)\arccos(1/x)、0≤x<10 \le x < 1 では −iacosh⁡(1/x)-i\operatorname{acosh}(1/x)、−1<x<0-1 < x < 0 では 2π−iacosh⁡(−1/x)2\pi - i\operatorname{acosh}(-1/x) です。

pub fn asec_real(Double) -> Complex[Double]

acsc

asin⁡(1/z)\operatorname{asin}(1/z) を返します。z=0z = 0 で中断します。

pub fn acsc(Complex[Double]) -> Complex[Double]

acsc_real

実数の逆余割です。∣x∣≥1|x| \ge 1 では arcsin⁡(1/x)\arcsin(1/x)、∣x∣<1|x| < 1 では ±π/2+iacosh⁡∣1/x∣\pm\pi/2 + i\operatorname{acosh}|1/x| です。

pub fn acsc_real(Double) -> Complex[Double]

acot

atan⁡(1/z)\operatorname{atan}(1/z) を返し、z=0z = 0 では π/2\pi/2 を返します。

pub fn acot(Complex[Double]) -> Complex[Double]
test "inverse trigonometric functions" {
  let z = @complex.Complex::new(1.0, 1.0)
  let back = @fb.sin(@fb.asin(z))
  assert_true((back.re - 1.0).abs() < 1.0e-10 && (back.im - 1.0).abs() < 1.0e-10)
  assert_eq(@fb.asin_real(2.0).re, @math.PI / 2.0)
  assert_eq(@fb.acot(@complex.Complex::new(0.0, 0.0)).re, @math.PI / 2.0)
}

双曲線関数

sinh

sinh⁡z=sinh⁡xcos⁡y+icosh⁡xsin⁡y\sinh z = \sinh x\cos y + i\cosh x\sin y を返します。

pub fn sinh(Complex[Double]) -> Complex[Double]

cosh

cosh⁡z=cosh⁡xcos⁡y+isinh⁡xsin⁡y\cosh z = \cosh x\cos y + i\sinh x\sin y を返します。

pub fn cosh(Complex[Double]) -> Complex[Double]

tanh

tanh⁡z\tanh z を返します。∣x∣≥1|x| \ge 1 では e−2∣x∣e^{-2|x|} でスケーリングした、オーバーフローせずに ±1\pm 1 へ収束する形を使います。

pub fn tanh(Complex[Double]) -> Complex[Double]

sech

1/cosh⁡z1/\cosh z を返します。cosh⁡z=0\cosh z = 0 となる点で中断します。

pub fn sech(Complex[Double]) -> Complex[Double]

csch

1/sinh⁡z1/\sinh z を返します。z=kπiz = k\pi i で中断します。

pub fn csch(Complex[Double]) -> Complex[Double]

coth

1/tanh⁡z1/\tanh z を返します。z=kπiz = k\pi i で中断します。

pub fn coth(Complex[Double]) -> Complex[Double]

逆双曲線関数

asinh

asinh⁡z=−iasin⁡(iz)\operatorname{asinh} z = -i\operatorname{asin}(iz) を返します。分岐切断は虚軸上の [−i,i][-i, i] の外側にあります。

pub fn asinh(Complex[Double]) -> Complex[Double]

実数の入力には実数の asinh を使います。純虚数の入力 iyiy は、∣y∣≤1|y| \le 1 では iarcsin⁡yi\arcsin y を、それ以外では ±(acosh⁡∣y∣+iπ/2)\pm(\operatorname{acosh}|y| + i\pi/2) を与えます。

acosh

acosh⁡z=2ln⁡(z+12+z−12)\operatorname{acosh} z = 2\ln\Big(\sqrt{\tfrac{z+1}{2}} + \sqrt{\tfrac{z-1}{2}}\Big) を返します。分岐切断は実軸上の 11 より下の部分にあります。

pub fn acosh(Complex[Double]) -> Complex[Double]

実数の入力は acosh_real へ送られます。無限大の部分があると ∞+iarg⁡z\infty + i\arg z を与えます。

acosh_real

実数の逆双曲線余弦です。x≥1x \ge 1 では acosh⁡x\operatorname{acosh} x、−1≤x<1-1 \le x < 1 では iarccos⁡xi\arccos x、x<−1x < -1 では acosh⁡(−x)+2πi\operatorname{acosh}(-x) + 2\pi i です。

pub fn acosh_real(Double) -> Complex[Double]

atanh

atanh⁡z\operatorname{atanh} z を返します。分岐切断は実軸上の [−1,1][-1, 1] の外側にあります。

pub fn atanh(Complex[Double]) -> Complex[Double]

実部は 14ln⁡(1+x)2+y2(1−x)2+y2\tfrac14\ln\frac{(1+x)^2 + y^2}{(1-x)^2 + y^2}(ゼロ付近では log1p を使用)、虚部は 12atan2⁡(2y,1−x2−y2)\tfrac12\operatorname{atan2}(2y, 1 - x^2 - y^2) で、大きな入力では再スケーリングされます。無限大の入力は 0±iπ/20 \pm i\pi/2 を返します。

atanh_real

実数の逆双曲線正接です。∣x∣<1|x| < 1 では atanh⁡x\operatorname{atanh} x、±1\pm 1 では ±∞\pm\infty、∣x∣>1|x| > 1 では atanh⁡(1/x)+iπ/2\operatorname{atanh}(1/x) + i\pi/2 です。

pub fn atanh_real(Double) -> Complex[Double]

asech

acosh⁡(1/z)\operatorname{acosh}(1/z) を返します。z=0z = 0 で中断します。

pub fn asech(Complex[Double]) -> Complex[Double]

acsch

asinh⁡(1/z)\operatorname{asinh}(1/z) を返します。z=0z = 0 で中断します。

pub fn acsch(Complex[Double]) -> Complex[Double]

acoth

atanh⁡(1/z)\operatorname{atanh}(1/z) を返します。z=0z = 0 で中断します。

pub fn acoth(Complex[Double]) -> Complex[Double]
test "hyperbolic functions" {
  let z = @complex.Complex::new(0.5, 0.25)
  let back = @fb.tanh(@fb.atanh(z))
  assert_true((back.re - 0.5).abs() < 1.0e-12 && (back.im - 0.25).abs() < 1.0e-12)
  let w = @fb.sinh(@fb.asinh(@complex.Complex::new(0.0, 2.0)))
  assert_true((w.im - 2.0).abs() < 1.0e-12)
  assert_eq(@fb.atanh_real(2.0).im, @math.PI / 2.0)
}