/* * complexjacobi.cpp --- 与えられた k に対し sn(z;k), cn(z;k), dn(z;k) * g++ -I/opt/local/include complexjacobi.cpp */ #include <iostream> #include <iomanip> #include <cmath> #include <boost/math/special_functions.hpp> // 面倒なので一気に using namespace std; using namespace boost::math; // M. Abramowitz and I. A. Stegun, Handbook of Mathematical Functions, §16.21 // 複素数版 Jacobi の sn(z;k) complex<double> jacobi_sn(double k, complex<double> z) { double kp,m,x,y,s,c,d,s1,c1,d1,numerator; x = z.real(); y = z.imag(); kp = sqrt(1 - k * k); m = k * k; s = jacobi_sn(k, x); c = jacobi_cn(k, x); d = jacobi_dn(k, x); s1 = jacobi_sn(kp, y); c1 = jacobi_cn(kp, y); d1 = jacobi_dn(kp, y); numerator = c1 * c1 + m * s * s * s1 * s1; return complex<double>(s * d1 / numerator, c * d * s1 * c1 / numerator); } // 複素数版 Jacobi の sn(), cn(), dn() complex<double> jacobi_elliptic(double k, complex<double> z, complex<double> *cn, complex<double> *dn) { double kp,m,x,y,s,c,d,s1,c1,d1,numerator; complex<double> sn; x = z.real(); y = z.imag(); kp = sqrt(1 - k * k); m = k * k; s = jacobi_sn(k, x); c = jacobi_cn(k, x); d = jacobi_dn(k, x); s1 = jacobi_sn(kp, y); c1 = jacobi_cn(kp, y); d1 = jacobi_dn(kp, y); numerator = c1 * c1 + m * s * s * s1 * s1; sn = complex<double>(s * d1 / numerator, c * d * s1 * c1 / numerator); *cn = complex<double>(c * c1 / numerator, - s * d * s1 * d1 / numerator); *dn = complex<double>(d * c1 * d1 / numerator, - m * s * c * s1 / numerator); return sn; } int main(int argc, char **argv) { double k; complex<double> z, sn, cn, dn; z = complex<double>(0.5, 0.5); cout << "z=" << z << endl; cout << "Jacobi sn" << endl; // Mathematica で験算 // z = 1/2 + I/2; // Table[JacobiSN[z,k^2], {k,0,0.9,0.1}] for (k = 0; k <= 0.9; k += 0.1) { sn = jacobi_sn(k, z); cout << "k=" << k << ", sn=" << sn << endl; } cout << "Jacobi sn,cn,dn" << endl; // Mathematica で験算 // z = 1/2 + I/2 // Table[{JacobiSN[z,k^2], JacobiCN[z,k^2], JacobiDN[z,k^2]}, {k,0,0.9,0.1}] for (k = 0; k <= 0.9; k += 0.1) { sn = jacobi_elliptic(k, z, &cn, &dn); cout << "k=" << k << ", sn=" << sn << ", cn=" << cn << ", dn=" << dn << endl; } return 0; }
簡単なテスト (Mathematica の結果と照らし合わせて一応パス) |
$ ./complexjacobi z=(0.5,0.5) Jacobi sn k=0, sn=(0.540613,0.457304) k=0.1, sn=(0.540868,0.45676) k=0.2, sn=(0.54163,0.455127) k=0.3, sn=(0.542892,0.45241) k=0.4, sn=(0.54464,0.448615) k=0.5, sn=(0.546858,0.443751) k=0.6, sn=(0.549523,0.437829) k=0.7, sn=(0.552609,0.430864) k=0.8, sn=(0.556086,0.422873) k=0.9, sn=(0.559922,0.413876) Jacobi sn,cn,dn k=0, sn=(0.540613,0.457304), cn=(0.989585,-0.249826), dn=(1,-0) k=0.1, sn=(0.540868,0.45676), cn=(0.989175,-0.24975), dn=(0.999583,-0.00247149) k=0.2, sn=(0.54163,0.455127), cn=(0.987946,-0.249518), dn=(0.998323,-0.00987698) k=0.3, sn=(0.542892,0.45241), cn=(0.985903,-0.249121), dn=(0.996186,-0.0221895) k=0.4, sn=(0.54464,0.448615), cn=(0.983055,-0.248545), dn=(0.993121,-0.0393642) k=0.5, sn=(0.546858,0.443751), cn=(0.979413,-0.247769), dn=(0.989054,-0.0613386) k=0.6, sn=(0.549523,0.437829), cn=(0.974994,-0.246768), dn=(0.983895,-0.0880327) k=0.7, sn=(0.552609,0.430864), cn=(0.969816,-0.24551), dn=(0.977535,-0.11935) k=0.8, sn=(0.556086,0.422873), cn=(0.963902,-0.24396), dn=(0.969854,-0.155176) k=0.9, sn=(0.559922,0.413876), cn=(0.957279,-0.24208), dn=(0.960717,-0.195384) $ |