@@ -47,7 +47,7 @@ namespace std {
4747
4848
4949## 戻り値
50- 引数 `l`, `m`, `theta` について $Y_l^m(\theta, 0)$ を返す。
50+ 引数 `l`, `m`, `theta` について $Y_l^m(\theta, 0)$ (ただし $0 \le m \le l$) を返す。
5151$Y_l^m(\theta, \phi)$ は球面調和関数
5252$$
5353Y_l^m(\theta, \phi) = (-1)^m \sqrt{\frac{2l + 1}{4\pi} \frac{(l - m)!}{(l + m)!}} P_l^m(\cos \theta) \exp(i m \phi)
5656である。
5757$P_l^m$ はルジャンドル陪関数 ([`assoc_legendre`](assoc_legendre.md)) である。
5858
59-
6059## 備考
6160- `l >= 128` の場合、この関数の呼び出しの効果は実装定義である
6261- (1) : C++23では、拡張浮動小数点数型を含む浮動小数点数型へのオーバーロードとして定義された
6362
63+ ### 球面調和関数
64+ 球面調和関数として使う場合には $\phi$ 依存性は自分で与える必要がある。
65+ また、この標準関数は $m\ge0$ にしか対応していないので、$m < 0$ の時の球面調和関数を計算したければ自分で $Y_l^{|m|}(\theta,0)$ の値を調節して使う必要がある。
66+ ルジャンドル陪関数の性質 $P_l^{-m}(x) = (-1)^m [(l - m)!/(l + m)!] P_l^m(x)$ より、一般の $m$ の球面調和関数は
67+ $$
68+ \begin{align*}
69+ Y_l^m(\theta, \phi)
70+ &= (-1)^{(m+|m|)/2} \sqrt{\frac{2l + 1}{4\pi} \frac{(l - |m|)!}{(l + |m|)!}} P_l^{|m|}(\cos \theta) e^{i m \phi} \\
71+ &= \begin{cases}
72+ Y_l^{m}(\theta, 0) e^{im\phi}, & (0 \le m \le l), \\
73+ (-1)^{|m|} Y_l^{|m|}(\theta, 0) e^{im\phi}, & (-l \le m < 0).
74+ \end{cases}
75+ \end{align*}
76+ $$
77+ で与えられる。
78+
79+ ```cpp
80+ #include <cmath>
81+ #include <complex>
82+ #include <numbers>
83+
84+ // 球面調和関数の実装例
85+ std::complex<double> sph_harmonics(unsigned l, int m, double theta, double phi) {
86+ if (m >= 0)
87+ return std::sph_legendre(l, (unsigned) m, theta) * std::polar(1.0, m * phi);
88+ else
89+ return std::sph_legendre(l, (unsigned) -m, theta) * std::polar(1.0, m * (phi - std::numbers::pi));
90+ }
91+ ```
92+ * std::sph_legendre[ color ff0000]
93+ * std::polar[ link /reference/complex/complex/polar.md]
94+ * std::numbers::pi[ link /reference/numbers/pi.md]
95+
96+ また線形結合を取り直して実数にした、実数球面調和関数 $Y_ {lm}(\theta,\phi)$ を計算することもできる。
97+
98+ $$
99+ Y_{lm}(\theta,\phi)
100+ = \begin{cases}
101+ \frac{(-1)^m Y_l^{|m|}(\theta,\phi) - Y_l^{-|m|}(\theta,\phi)}{\sqrt{2} i} = \sqrt{2} (-1)^{|m|} Y_l^{|m|}(\theta, 0) \sin(|m|\phi), & (-l \le m < 0), \\
102+ Y_l^0 = Y_l^0(\theta, 0), & (m = 0), \\
103+ \frac{(-1)^m Y_l^{|m|}(\theta,\phi) + Y_l^{-|m|}(\theta,\phi)}{\sqrt{2}} = \sqrt{2} (-1)^{|m|} Y_l^{|m|}(\theta, 0) \cos(|m|\phi), & (0 < m \le l).
104+ \end{cases}
105+ $$
106+
107+ ``` cpp
108+ #include < cmath>
109+ #include < numbers>
110+
111+ // 実数球面調和関数の実装例
112+ double real_sph_harmonics (unsigned l, int m, double theta, double phi) {
113+ if (m == 0)
114+ return std::sph_legendre(l, 0u, theta);
115+ else if (m > 0)
116+ return std::numbers::sqrt2 * std::sph_legendre(l, (unsigned) m, theta) * std::cos(m * (phi - std::numbers::pi));
117+ else
118+ return std::numbers::sqrt2 * std::sph_legendre(l, (unsigned) -m, theta) * std::sin(-m * (phi - std::numbers::pi));
119+ }
120+ ```
121+ * std::sph_legendre[color ff0000]
122+ * std::numbers::pi[link /reference/numbers/pi.md]
123+ * std::numbers::sqrt2[link /reference/numbers/sqrt2.md]
64124
65125## 例
66126```cpp example
@@ -71,8 +131,11 @@ $P_l^m$ はルジャンドル陪関数 ([`assoc_legendre`](assoc_legendre.md))
71131constexpr double pi = 3.141592653589793;
72132
73133// 球面調和関数
74- std::complex<double> sph_harmonics(unsigned l, unsigned m, double theta, double phi) {
75- return std::sph_legendre(l, m, theta) * std::polar(1.0, m * phi);
134+ std::complex<double> sph_harmonics(unsigned l, int m, double theta, double phi) {
135+ if (m >= 0)
136+ return std::sph_legendre(l, (unsigned) m, theta) * std::polar(1.0, m * phi);
137+ else
138+ return std::sph_legendre(l, (unsigned) -m, theta) * std::polar(1.0, m * (phi - std::numbers::pi));
76139}
77140
78141int main() {
0 commit comments