M.Hiroi's Home Page

お気楽 Haskell プログラミング入門

応用編 : 複素関数

Copyright (C) 2021 Makoto Hiroi
All rights reserved.

●複素数の指数関数と対数関数

複素数を引数にとる指数関数はオイラー (Euler) の公式から導くことができます。

\( \begin{array}{l} e^{i\theta} = \cos \theta + i \sin \theta \quad (Euler's formula) \\ \begin{eqnarray} e^{x+iy} &=& e^x e^{iy} \\ &=& e^x (\cos y + i \sin y) \end{eqnarray} \end{array} \)

複素数の対数関数は複素数 z を絶対値 \(|z|\) と偏角 \(\theta\) を使って導くことができます。

\( \begin{array}{l} x + iy = |z| e^{i\theta} \\ \begin{eqnarray} \log_e (x + iy) &=& log_e |z| e^{i\theta} \\ &=& log_e |z| + log_e e^{i\theta} \\ &=& log_e |z| + i\theta, \quad (-\pi \leq \theta \leq \pi) \end{eqnarray} \end{array} \)

複素数 x, y のべき乗 \(x^y\) は次式で求めることができます。

\(x^y = e^{y\log x}\)

関数 exp と log は複素数に対応しています。べき乗も演算子 ** で求めることができます。簡単な例を示しましょう。

ghci> pi
3.141592653589793
ghci> exp (0.0 :+ (pi / 4))
0.7071067811865476 :+ 0.7071067811865475
ghci> exp (0.0 :+ (pi / 2))
6.123233995736766e-17 :+ 1.0
ghci> exp (0.0 :+ pi)
(-1.0) :+ 1.2246467991473532e-16
ghci> exp (1.0 :+ 1.0)
1.4686939399158851 :+ 2.2873552871788423


ghci> log (1.0 :+ 1.0)
0.3465735902799727 :+ 0.7853981633974483
ghci> log (1.0 :+ 0.0)
0.0 :+ 0.0
ghci> log (0.0 :+ 1.0)
0.0 :+ 1.5707963267948966
ghci> log (1.0 :+ (-1.0))
0.3465735902799727 :+ (-0.7853981633974483)
ghci> log (1e300 :+ 1e300)
691.1221014884936 :+ 0.7853981633974483


ghci> (1.0 :+ 1.0) ** 0
1.0 :+ 0.0
ghci> (1.0 :+ 1.0) ** 1
1.0000000000000002 :+ 1.0
ghci> (1.0 :+ 1.0) ** 2
1.2246467991473532e-16 :+ 2.0
ghci> (1.0 :+ 1.0) ** 3
(-2.0) :+ 2.0000000000000004
ghci> (1.0 :+ 1.0) ** (1.0 :+ 1.0)
0.2739572538301211 :+ 0.5837007587586147
ghci> (1.0 :+ 2.0) ** (3.0 :+ 4.0)
0.129009594074467 :+ 3.392409290517014e-2

関数 \(\log z \ (z = x + iy)\) は負の実軸 (\(-\infty \lt x \lt 0\)) において、x + 0.0i と x - 0.0i では値が異なります。

ghci> log ((-1.0) :+ 0.0)
0.0 :+ 3.141592653589793
ghci> log ((-1.0) :+ (-0.0))
0.0 :+ (-3.141592653589793)
ghci> log ((-1e300) :+ 0.0)
690.7755278982137 :+ 3.141592653589793
ghci> log ((-1e300) :+ (-0.0))
690.7755278982137 :+ (-3.141592653589793)

このように、関数 \(\log z\) は負の実軸上で 2 つの値を持ちます。数学では値を一つ返す関数を「一価関数」、複数の値を返す関数を「多価関数」といいます。ここで、定義域を制限することで多価関数を一価関数にみなすことを考えます。関数 log z の場合、負の実軸を定義域から取り除けば、\(\log z\) を一価関数とみなすことができるわけです。

参考 URL 8 によると、この取り除いた領域を branch cut と呼ぶそうです。プログラミングでは branch cut を定義域から取り除くのではなく、その領域では不連続な関数とするそうです。参考文献 1 では「分枝切断線」、Python のドキュメントでは「分枝切断」と記述されています。本稿では branch cut を「分枝切断」と記述することにします。

プログラミング言語の場合、0.0 と -0.0 を区別する処理系であれば、Haskell のように 2 つの値を区別することができます。0.0 と -0.0 を区別しない処理系では、偏角 \(\theta\) の範囲を \(-\pi \lt \theta \leq \pi\) に制限することで、\(\log z\) の返り値を (\(-\pi\) を取り除いて) 一つにすることができます。

●複素数の三角関数

複素数の三角関数の定義は、オイラーの公式から導かれる式の \(\theta\) を複素数 \(z\) に変えたものになります。

\(\sin -\theta = -\sin \theta, \ \cos -\theta = \cos \theta \) より
\( \begin{eqnarray} e^{i(-\theta)} &=& \cos -\theta + i \sin -\theta \\ &=& \cos \theta - i \sin \theta \end{eqnarray} \)

\( \begin{array}{l} e^{i\theta} + e^{-i\theta} = 2 \cos \theta \\ \cos \theta = \dfrac{e^{i\theta} + e^{-i\theta}}{2} \\ e^{i\theta} - e^{-i\theta} = 2i \sin \theta \\ \sin \theta = \dfrac{e^{i\theta} - e^{-i\theta}}{2i} \end{array} \)

\(\theta\) を複素数 z に置き換えた式が三角関数の定義になる

\( \sin z = \dfrac{e^{iz} - e^{-iz}}{2i}, \quad \cos z = \dfrac{e^{iz} + e^{-iz}}{2} \)

\(\sin z, \cos z\) に純虚数 \(ix\) を与えると双曲線関数 (\(\sinh x, \cosh x\)) になります。

双曲線関数の定義
\( \sinh x = \dfrac{e^x - e^{-x}}{2}, \quad \cosh x = \dfrac{e^x + e^{-x}}{2} \)
\(\begin{eqnarray} \sin ix &=& \dfrac{e^{iix} - e^{-iix}}{2i} \\ &=& \dfrac{e^{-x} - e^x}{2i} \times \dfrac{-i}{-i} \\ &=& i \dfrac{e^x - e^{-x}}{2} \\ &=& i \sinh x \\ \end{eqnarray}\)
\(\begin{eqnarray} \cos ix &=& \dfrac{e^{iix} + e^{-iix}}{2} \\ &=& \dfrac{e^{-x} + e^x}{2} \\ &=& \cosh x \end{eqnarray}\)

これに三角関数の加法定理 [*1] を使うと次の式が導かれます。

\(\begin{eqnarray} \sin (x + iy) &=& \sin x \cos iy + \cos x \sin iy \\ &=& \sin x \cosh y + i \cos x \sinh y \\ \cos (x + iy) &=& \cos x \cos iy - \sin x \sin iy \\ &=& \cos x \cosh y - i \sin x \sinh y \\ \tan (x + iy) &=& \dfrac{\sin 2x + \sin 2iy}{\cos 2x + \cos 2iy} \\ &=& \dfrac{\sin 2x + i \sinh 2y}{\cos 2x + \cosh 2y} \end{eqnarray}\)

Haskell の三角関数 (sin, cos, tan) は複素数にも対応しています。簡単な実行例を示します。

ghci> a = [0.0 :+ 1.0, 0.0 :+ (-1.0), 1.0 :+ 1.0, 1.0 :+ (-1.0)]
ghci> a
[0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)]

ghci> map sin a
[0.0 :+ 1.1752011936438014,
 0.0 :+ (-1.1752011936438014),
 1.2984575814159773 :+ 0.6349639147847361,
 1.2984575814159773 :+ (-0.6349639147847361)]
ghci> map (magnitude . sin) a
[1.1752011936438014,1.1752011936438014,1.4453965766582495,1.4453965766582495]

ghci> map cos a
[1.5430806348152437 :+ (-0.0),
 1.5430806348152437 :+ 0.0,
 0.8337300251311491 :+ (-0.9888977057628651),
 0.8337300251311491 :+ 0.9888977057628651]
ghci> map (magnitude . cos) a
[1.5430806348152437,1.5430806348152437,1.2934544550420957,1.2934544550420957]

ghci> map tan a
[0.0 :+ 0.7615941559557649,
 0.0 :+ (-0.7615941559557649),
 0.2717525853195117 :+ 1.0839233273386946,
 0.2717525853195117 :+ (-1.0839233273386946)]
ghci> map (magnitude . tan) a
[0.7615941559557649,0.7615941559557649,1.1174700207060704,1.1174700207060704]
-- note --------
[*1] 三角関数の公式は引数が複素数でも成り立ちます。ただし、\(|\sin x| \leq 1, |\cos x| \leq 1\) という関係式は、x が実数だと成立しますが複素数では成立しません。

●複素数の双曲線関数

複素数の双曲線関数の定義は、実数の定義で引数 x を複素数 z に変えたものになります。

双曲線関数の定義 (z は複素数)
\( \sinh z = \dfrac{e^{z} - e^{-z}}{2}, \quad \cosh z = \dfrac{e^{z} + e^{-z}}{2} \)

sinh z, cosh z に純虚数 ix を与えると三角関数 (sin x, cos x) になります。

\(\begin{eqnarray} \cosh ix &=& \dfrac{e^{ix} + e^{ix}}{2} \\ &=& \cos x \end{eqnarray}\)
\(\begin{eqnarray} \sinh ix &=& \dfrac{e^{ix} - e^{-ix}}{2} \\ &=& \dfrac{e^{ix} - e^{-ix}}{2} \times \dfrac{i}{i} \\ &=& i \dfrac{e^{ix} - e^{-ix}}{2i} \\ &=& i \sin x \\ \end{eqnarray}\)

これに双曲線関数の加法定理を使うと、次の式が導かれます。

双曲線関数の加法定理
\(\begin{eqnarray} \sinh(x + y) &=& \sinh x \cosh y + \cosh x \sinh y \\ \cosh(x + y) &=& \cosh x \cosh y + \sinh x \sinh y \\ \tanh(x + y) &=& \dfrac{\sinh(x + y)}{\cosh(x + y)} \\ &=& \dfrac{\sinh 2x + \sinh 2y}{\cosh 2x + \cosh 2y} \end{eqnarray}\)
\(\begin{eqnarray} \sinh(x + iy) &=& \sinh x \cos y + i \cosh x \sin y \\ \cosh(x + iy) &=& \cosh x \cos y + i \sinh x \sin y \\ \tanh(x + iy) &=& \dfrac{\sinh(x + iy)}{\cosh(x + iy)} \\ &=& \dfrac{\sinh 2x + i \sin 2y}{\cosh 2x + \cos 2y} \end{eqnarray}\)

Haskell の双曲線関数 (sinh, cosh, tanh) は複素数に対応しています。簡単な使用例を示します。

ghci> a
[0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)]

ghci> map sinh a
[0.0 :+ 0.8414709848078965,
 0.0 :+ (-0.8414709848078965),
 0.6349639147847361 :+ 1.2984575814159773,
 0.6349639147847361 :+ (-1.2984575814159773)]

ghci> map cosh a
[0.5403023058681398 :+ 0.0,
 0.5403023058681398 :+ (-0.0),
 0.8337300251311491 :+ 0.9888977057628651,
 0.8337300251311491 :+ (-0.9888977057628651)]

ghci> map tanh a
[0.0 :+ 1.557407724654902,
 0.0 :+ (-1.557407724654902),
 1.0839233273386946 :+ 0.2717525853195117,
 1.0839233273386946 :+ (-0.2717525853195117)]

●複素数の平方根

複素数 z の平方根は次の式で求めることができます。

\(z = x + iy, \ |z| = \sqrt{x^2 + y^2}, \ \theta = \arg z \ (-\pi \leq \theta \leq \pi)\) とすると

\( \sqrt{x + iy} = \begin{cases} \sqrt{|z| e^{i\theta}} = \sqrt{|z|} e^{i\theta/2} & (1) \\ \sqrt{|z| e^{i\theta + 2\pi}} = \sqrt{|z|} e^{i\theta/2 + \pi} & (2) \end{cases} \)

式 (1) を平方根の主値といいます。角度は \(2\pi\) を足すと同じ角度になるので、式 (2) がもう一つの解になります。三角関数の半角の公式を使うと、式 (1) から次の式が導かれます。

三角関数の半角の公式
\(\begin{eqnarray} \sin^2{\left(\frac{\theta}{2}\right)} = \dfrac{1 - \cos \theta}{2} \\ \cos^2{\left(\frac{\theta}{2}\right)} = \dfrac{1 + \cos \theta}{2} \end{eqnarray}\)

式 (1) を平方根の主値といいます。角度は \(2\pi\) を足すと同じ角度になるので、式 (2) がもう一つの解になります。三角関数の半角の公式を使うと、式 (1) から次の式が導かれます。

三角関数の半角の公式
\(\begin{eqnarray} \sin^2{\left(\frac{\theta}{2}\right)} = \dfrac{1 - \cos \theta}{2} \\ \cos^2{\left(\frac{\theta}{2}\right)} = \dfrac{1 + \cos \theta}{2} \end{eqnarray}\)
\(y \geq 0\) の場合
\(\begin{eqnarray} \sqrt{|z|} e^{i\theta/2} &=& \sqrt{|z|} \left(\cos{\frac{\theta}{2}} + i \sin{\frac{\theta}{2}}\right) \\ &=& \sqrt{|z|} \left(\sqrt{\frac{1 + \cos \theta}{2}}) + i \sqrt{\frac{1 - \cos \theta}{2}}\right) \\ &=& \dfrac{\sqrt{|z| + |z|\cos \theta}}{2} + i \sqrt{\frac{|z| - |z| \cos \theta}{2}} \\ &=& \sqrt{\frac{|z| + x}{2}} + i \sqrt{\frac{|z| - x}{2}}, \quad (|z|\cos \theta = x) \end{eqnarray}\)

\(y \lt 0\) の場合、虚部の符号が \(-\) になる
\( \sqrt{|z|} e^{i\theta/2} = \sqrt{\dfrac{|z| + x}{2}} - i \sqrt{\dfrac{|z| - x}{2}} \)

Haskell の sqrt は複素数にも対応しています。簡単な実行例を示します。

ghci> sqrt (1.0 :+ 0.0)
1.0 :+ 0.0
ghci> sqrt (2.0 :+ 0.0)
1.4142135623730951 :+ 0.0
ghci> sqrt (3.0 :+ 0.0)
1.7320508075688772 :+ 0.0
ghci> sqrt ((-1.0) :+ 0.0)
0.0 :+ 1.0
ghci> sqrt ((-2.0) :+ 0.0)
0.0 :+ 1.4142135623730951
ghci> sqrt ((-3.0) :+ 0.0)
0.0 :+ 1.7320508075688772

ghci> a
[0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)]
ghci> map sqrt a
[0.7071067811865476 :+ 0.7071067811865475,
 0.7071067811865476 :+ (-0.7071067811865475),
 1.09868411346781 :+ 0.45508986056222733,
 1.09868411346781 :+ (-0.45508986056222733)]

ghci> map (**2) (map sqrt a)
[6.123233995736766e-17 :+ 1.0,
 6.123233995736766e-17 :+ (-1.0),
 1.0 :+ 0.9999999999999998,
 1.0 :+ (-0.9999999999999998)]

\(\sqrt x\) は \(\log x\) と同じ分枝切断を持っています。x を負の整数とすると sqrt(x) の解は \(i \sqrt x\) になりますが、もうひとつ \(-i \sqrt x\) という解があります。

ghci> sqrt ((-2.0) :+ 0.0)
0.0 :+ 1.4142135623730951
ghci> sqrt ((-2.0) :+ (-0.0))
0.0 :+ 1.4142135623730951
ghci> sqrt ((-1e300) :+ 0.0)
0.0 :+ 1.0e150
ghci> sqrt ((-1e300) :+ (-0.0))
0.0 :+ 1.0e150

M.Hiroi が使っているバージョン (GHC version 8.8.4) では、sqrt の分枝切断に不具合がある、もしくは負のゼロには対応していないのかもしれません。新しいバージョンでは修正されているかもしれません。

●逆三角関数

三角関数の逆関数を「逆三角関数 (inverse trigonometric function)」といいます。以下に Haskell に用意されている逆三角関数を示します。

ここでは引数 x を実数とします。asin x は引数 x が与えられたとき sin w = x となる角度 w を求めます。同様に acos x は cos w = x となる角度 w を、atan x は tan x = w となる角度 w を求めます。三角関数には周期性があるので、上式を満たす角度 w は無数に存在します。つまり、逆三角関数の返り値は無数にあることになりますが、通常は一つの値を返すように範囲を制限します。これを「主値」といいます。

逆三角関数の主値を以下に示します。

\(\begin{array}{lcc} \arcsin x = w & -1 \leq x \lt 1 & -\pi/2 \leq w \leq \pi/2 \\ \arccos x = w & -1 \leq x \lt 1 & 0 \leq w \leq \pi \\ \arctan x = w & x \in \mathbb{R} & -\pi/2 \leq w \leq \pi/2 \end{array}\)

本ページでは、数式の表示に JavaScript のライブラリ MathJax を使っています。MathJax では、逆三角関数を arcsin, arccos, arctan と表示します。

簡単な実行例を示します。

ghci> map asin [-1.0, -0.5, 0.0, 0.5, 1.0]
[-1.5707963267948966,
 -0.5235987755982989,
 0.0,
 0.5235987755982989,
 1.5707963267948966]

ghci> map acos [-1.0, -0.5, 0.0, 0.5, 1.0]
[3.141592653589793,
 2.0943951023931957,
 1.5707963267948966,
 1.0471975511965979,
 0.0]

ghci> map atan [-1e100, -1.0, 0.0, 1.0, 1e100]
[-1.5707963267948966,
 -0.7853981633974483,
 0.0,
 0.7853981633974483,
 1.5707963267948966]

Haskell には 2 引数の関数 atan2 y x も用意されています。これは他のプログラミング言語、たとえばC言語の数学関数 atan2 と同じです。

atan2 y x => 角度 (ラジアン)

引数 x, y は実数です。atan2 は直交座標系においてベクトル (x, y) と x 軸との角度を求める関数です。複素平面で考えると、複素数 \(x + iy\) の偏角 \(\theta\) を求めることと同じです。返り値 (角度 \(\theta\)) の範囲は \(-\pi \leq \theta \leq \pi\) になります。

簡単な実行例を示します。

ghci> map (\(x, y) -> atan2 y x) [(-1.0, 0.0),(-1.0, 1.0),(0.0, 1.0),(1.0, 1.0),
(1.0, 0.0),(1.0, -1.0),(0.0, -1.0),(-1.0, -1.0),(-1.0, -0.0)]
[3.141592653589793,
 2.356194490192345,
 1.5707963267948966,
 0.7853981633974483,
 0.0,
 -0.7853981633974483,
 -1.5707963267948966,
 -2.356194490192345,
 -3.141592653589793]

●複素数の逆三角関数

複素数の逆三角関数の定義は、複素数の三角関数の定義から導くことができます。\(\arcsin z\) の定義は次のようになります。

\(z, w\) は複素数とする

\(\begin{array}{l} \arcsin z = w \\ z = \sin w = \dfrac{e^{iw} - e^{-iw}}{2i} \\ z \times 2ie^{iw} = \dfrac{e^{iw} - e^{-iw}}{2i} \times 2ie^{iw} \\ 2iz(e^{iw}) = (e^{iw})^2 - 1 \\ (e^{iw})^2 - 2iz(e^{iw}) - 1 = 0 \end{array}\)

\(e^{iw}\) の二次方程式と考えて解くと

\(e^{iw} = iz \pm \sqrt{1 - z^2}\)

両辺の対数をとって \(-i\) を掛け算し、平方根の主値 \(+\) を選ぶ

\(w = \arcsin z = -i \log{\left(iz + \sqrt{1 - z^2}\right)} \)

\(\arccos z, \arctan z\) は定義だけを示します。

\(\begin{array}{l} \arccos z = \dfrac{\pi}{2} - \arcsin z \\ \arctan z = i \dfrac{\log{\left(1 - iz\right)} - \log{\left(1 + iz\right)}}{2} \end{array}\)

asin, acos, atan は次に示す分枝切断を持っています。

Haskell の逆三角関数 (asin, acos, atan) は複素数に対応しています。簡単な実行例を示します。

ghci> a
[0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)]

ghci> map asin a
[0.0 :+ 0.8813735870195428,
 0.0 :+ (-0.8813735870195429),
 0.6662394324925153 :+ 1.0612750619050355,
 0.6662394324925153 :+ (-1.0612750619050357)]
ghci> map (sin . asin) a
[0.0 :+ 0.9999999999999997,
 0.0 :+ (-1.0),
 1.0 :+ 0.9999999999999998,
 1.0000000000000002 :+ (-1.0)]

ghci> asin(2.0 :+ 0.0)
1.5707963267948966 :+ (-1.3169578969248166)
ghci> asin(2.0 :+ (-0.0))
1.5707963267948966 :+ (-1.3169578969248166)
ghci> asin((-4.0) :+ 0.0)
(-1.5707963267948966) :+ 2.0634370688955617
ghci> asin((-4.0) :+ (-0.0))
(-1.5707963267948966) :+ 2.0634370688955617

ghci> map acos a
[1.5707963267948966 :+ (-0.8813735870195429),
 1.5707963267948966 :+ 0.8813735870195428,
 0.9045568943023814 :+ (-1.0612750619050357),
 0.9045568943023814 :+ 1.0612750619050355]
ghci> map (cos . acos) a
[8.659560562354932e-17 :+ 1.0,
 8.659560562354932e-17 :+ (-0.9999999999999997),
 0.9999999999999999 :+ 1.0,
 0.9999999999999998 :+ (-0.9999999999999998)]

ghci> acos(2.0 :+ 0.0)
0.0 :+ 1.3169578969248164
ghci> acos(2.0 :+ (-0.0))
0.0 :+ 1.3169578969248164
ghci> acos((-4.0) :+ 0.0)
3.141592653589793 :+ (-2.0634370688955608)
ghci> acos((-4.0) :+ (-0.0))
3.141592653589793 :+ (-2.0634370688955608)

ghci> map atan a
[NaN :+ NaN,
 NaN :+ NaN,
 1.0172219678978514 :+ 0.4023594781085251,
 1.0172219678978514 :+ (-0.4023594781085249)]
ghci> map (tan . atan) a
[NaN :+ NaN,
 NaN :+ NaN,
 1.0 :+ 1.0000000000000002,
 1.0000000000000004 :+ (-0.9999999999999999)]

ghci> atan (0.0 :+ 2.0)
1.5707963267948966 :+ 0.5493061443340547
ghci> atan ((-0.0) :+ 2.0)
1.5707963267948966 :+ 0.5493061443340547
ghci> atan (0.0 :+ (-4.0))
(-1.5707963267948966) :+ (-0.25541281188299514)
ghci> atan ((-0.0) :+ (-4.0))
(-1.5707963267948966) :+ (-0.25541281188299514)

M.Hiroi が使っているバージョン (GHC version 8.8.4) では、逆三角関数の分枝切断に不具合がある、もしくは負のゼロには対応していないのかもしれません。新しいバージョンでは修正されているかもしれません。

●逆双曲線関数

双曲線関数の逆関数を「逆双曲線関数 (inverse hyperbolic function)」といいます。Haskell に用意されている逆双曲線関数には asinh, acosh, atanh があります。MathJax では逆双曲線関数を \(\sinh^{-1} x, \cosh^{-1} x, \tanh^{-1} x \) で表します。双曲線関数と逆双曲線関数の定義域と値域を示します。

\(\begin{array}{lcc} y = \sinh x & -\infty \lt x \lt \infty & -\infty \lt y \lt \infty \\ y = \cosh x & -\infty \lt x \lt \infty & 1 \leq y \lt \infty \\ y = \tanh x & -\infty \lt x \lt \infty & -1 \lt y \lt 1 \\ y = \sinh^{-1} x & -\infty \lt x \lt \infty & -\infty \lt y \lt \infty \\ y = \cosh^{-1} x & 1 \leq x \lt \infty & 0 \leq y \lt \infty \\ y = \tanh^{-1} x & -1 \lt x \lt 1 & -\infty \lt y \lt \infty \end{array}\)

x と y は実数です。x = cosh y の逆関数 y = acosh x を満たす y の値は 2 つありますが、ここでは \(y \geq 0\) を主値として選ぶことにします。

逆双曲線関数の定義は双曲線関数の定義から導くことができます。

\(\begin{array}{l} \sinh^{-1} x = y \\ y = \sinh x = \dfrac{e^{x} - e^{-x}}{2} \\ y \times 2e^{x} = \dfrac{e^{x} - e^{-x}}{2} \times 2e^{x} \\ 2ye^{x} = e^{2x} - 1 \\ e^{2x} - 2ye^{x} - 1 = 0 \end{array}\)

\(e^{x}\) の 2 次方程式として解く

\(e^{x} = \dfrac{2y \pm \sqrt{4y^2 + 4}}{2} = y \pm \sqrt{y^2 + 1} \)

\(e^{x} \gt 0\) だから平方根の符号に \(+\) を選んで対数をとる

\(x = \log \left(y + \sqrt{y^2 + 1}\right)\)
\(\begin{array}{l} \cosh^{-1} x = y \\ y = \cosh x = \dfrac{e^{x} + e^{-x}}{2} \\ y \times 2e^{x} = \dfrac{e^{x} + e^{-x}}{2} \times 2e^{x} \\ 2ye^{x} = e^{2x} + 1 \\ e^{2x} - 2ye^{x} + 1 = 0 \end{array}\)

\(e^{x}\) の 2 次方程式として解く

\(e^{x} = \dfrac{2y \pm \sqrt{\left(4y^2 - 4\right)}}{2} = y \pm \sqrt{y^2 - 1} \)

\(e^{x} \gt 0\) だから平方根の符号に \(+\) を選んで対数をとる

\(x = \log \left(y + \sqrt{y^2 - 1}\right), \quad (y \geq 1) \)
\(\begin{array}{l} \tanh^{-1} x = y \\ \begin{eqnarray} y &=& \tanh x \\ &=& \dfrac{\sinh x}{\cosh x} \\ &=& \dfrac{e^{x} - e^{-x}}{e^{x} + e^{-x}} \\ &=& \dfrac{e^{2x} - 1}{e^{2x} + 1} \end{eqnarray} \\ y(e^{2x} + 1) = (e^{2x} - 1) \\ (1 - y)e^{2x} = 1 + y \\ e^{2x} = \dfrac{1 + y}{1 - y} \\ x = \dfrac{1}{2} \log{\dfrac{1 + y}{1 - y}} \end{array}\)

関数 \(\tanh^{-1} x\) を使うと、次の関係式から \(\sinh^{-1} x, \ \cosh^{-1} x\) を求めることができます。

\(\sinh^{-1} x = \tanh^{-1}{\dfrac{x}{\sqrt{x^2 + 1}}} \)

\(\cosh^{-1} x = \tanh^{-1}{\dfrac{\sqrt{1 - x^2}}{x}} \)

簡単な実行例を示します。

ghci> map asinh [1.5, 1.0, 0.5, 0.0, -0.5, -1.0, -1.5]
[1.1947632172871094,
 0.881373587019543,
 0.48121182505960347,
 0.0,
 -0.48121182505960347,
 -0.881373587019543,
 -1.1947632172871094]
ghci> map (sinh . asinh) [1.5, 1.0, 0.5, 0.0, -0.5, -1.0, -1.5]
[1.5000000000000004,
 1.0,
 0.5,
 0.0,
 -0.5,
 -1.0,
 -1.5000000000000004]


julia> for x = [1.5, 1.0, 0.5, 0.0, -0.5, -1.0, -1.5] b = asinh(x); println(b); println(sinh(b)) end
1.1947632172871094
1.5000000000000002
0.881373587019543
1.0
0.48121182505960347
0.5
0.0
0.0
-0.48121182505960347
-0.5
-0.881373587019543
-1.0
-1.1947632172871094
-1.5000000000000002

ghci> map acosh [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
[0.0,
 0.9624236501192069,
 1.3169578969248166,
 1.566799236972411,
 1.762747174039086,
 1.9248473002384139,
 2.0634370688955608]
ghci> map (cosh . acosh) [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
[1.0,
 1.5,
 1.9999999999999998,
 2.5,
 3.0000000000000004,
 3.5000000000000004,
 4.000000000000001]

ghci> map atanh [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75]
[-0.9729550745276566,
 -0.5493061443340548,
 -0.25541281188299536,
 0.0,
 0.25541281188299536,
 0.5493061443340548,
 0.9729550745276566]
ghci> map (tanh . atanh) [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75]
[-0.75,
 -0.49999999999999994,
 -0.25,
 0.0,
 0.25,
 0.49999999999999994,
 0.75]

●複素数の逆双曲線関数

複素数の逆双曲線関数の定義は、実数の定義で引数 x を複素数 z に変えたものになります。

\(\begin{array}{l} \sinh^{-1} z = \log \left(z + \sqrt{z^2 + 1}\right) \\ \begin{eqnarray} \cosh^{-1} z &=& \log \left(z + \sqrt{z^2 - 1}\right) &(1)& \\ &=& \log \left(z + \sqrt{z + 1} \sqrt{z - 1}\right) \quad &(2)& \end{eqnarray} \\ \tanh^{-1} z = \dfrac{1}{2} \log\left(\dfrac{1 + z}{1 - z}\right) = \dfrac{1}{2} \left( \log {\left( 1 + z \right)} - \log {\left(1 - z\right)} \right) \end{array}\)

参考文献, URL 7 によると、\(\cosh^{-1} z\) を式 (1) でプログラムすると「分枝切断線」が複雑になるため、他の式 (たとえば (2) など) でプログラムする処理系が多いようです。ちなみに、ANSI Common Lisp では \(\cosh^{-1} z\) を次の式で定義しています。

\( \cosh^{-1} z = 2 \log \left( \sqrt{\dfrac{z + 1}{2}} + \sqrt{\dfrac{z - 1}{2}} \right) \)

asinh, acosh, atanh は次に示す分枝切断を持っています。

Haskell の逆双曲線関数 (asinh, acosh, atanh) は複素数に対応しています。簡単な実行例を示します。

ghci> a
[0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)]

ghci> map asinh a
[0.0 :+ 1.5707963267948966,
 0.0 :+ (-1.5707963267948966),
 1.0612750619050357 :+ 0.6662394324925153,
 1.0612750619050357 :+ (-0.6662394324925153)]
ghci> map (sinh . asinh) a
[0.0 :+ 1.0,
 0.0 :+ (-1.0),
 1.0 :+ 1.0000000000000002,
 1.0 :+ (-1.0000000000000002)]

ghci> asinh(0.0 :+ 2.0)
1.3169578969248166 :+ 1.5707963267948966
ghci> asinh((-0.0) :+ 2.0)
1.3169578969248166 :+ 1.5707963267948966
ghci> asinh(0.0 :+ (-4.0))
(-2.0634370688955617) :+ (-1.5707963267948966)
ghci> asinh((-0.0) :+ (-4.0))
(-2.0634370688955617) :+ (-1.5707963267948966)

ghci> map acosh a
[0.8813735870195429 :+ 1.5707963267948966,
 0.8813735870195429 :+ (-1.5707963267948966),
 1.0612750619050357 :+ 0.9045568943023814,
 1.0612750619050357 :+ (-0.9045568943023814)]
ghci> map (cosh . acosh) a
[8.659560562354932e-17 :+ 1.0,
 8.659560562354932e-17 :+ (-1.0),
 0.9999999999999999 :+ 1.0,
 0.9999999999999999 :+ (-1.0)]

ghci> acosh(0.0 :+ 0.0)
0.0 :+ 1.5707963267948966
ghci> acosh(0.0 :+ (-0.0))
0.0 :+ 1.5707963267948966
ghci> acosh((-4.0) :+ 0.0)
2.0634370688955608 :+ 3.141592653589793
ghci> acosh((-4.0) :+ (-0.0))
2.0634370688955608 :+ 3.141592653589793

ghci> map atanh a
[0.0 :+ 0.7853981633974483,
 0.0 :+ (-0.7853981633974483),
 0.4023594781085251 :+ 1.0172219678978514,
 0.4023594781085251 :+ (-1.0172219678978514)]
ghci> map (tanh . atanh) a
[0.0 :+ 0.9999999999999998,
 0.0 :+ (-0.9999999999999998),
 1.0000000000000002 :+ 1.0,
 1.0000000000000002 :+ (-1.0)]

ghci> atanh(2.0 :+ 0.0)
0.5493061443340549 :+ (-1.5707963267948966)
ghci> atanh(2.0 :+ (-0.0))
0.5493061443340549 :+ (-1.5707963267948966)
ghci> atanh((-4.0) :+ 0.0)
(-0.25541281188299536) :+ 1.5707963267948966
ghci> atanh((-4.0) :+ (-0.0))
(-0.25541281188299536) :+ 1.5707963267948966

M.Hiroi が使っているバージョン (GHC version 8.8.4) では、逆双曲線関数の分枝切断に不具合がある、もしくは負のゼロには対応していないのかもしれません。新しいバージョンでは修正されているかもしれません。

●参考文献, URL

  1. Guy L. Steele Jr., 『COMMON LISP 第 2 版』, 共立出版, 1991
  2. 奥村晴彦,『C言語による最新アルゴリズム事典』, 技術評論社, 1991
  3. IEEE 754 -- Wikipedia
  4. IEEE 754における負のゼロ - Wikipedia
  5. NaN - Wikipedia
  6. 逆三角関数 - Wikipedia
  7. 逆双曲線関数 - Wikipedia
  8. 逆双曲線関数と逆三角関数の branch cut | 雑記帳

初版 2021 年 11 月 20 日