ヤコビの楕円関数 sn cn dn
ヤコビの楕円関数 sn cn dnの計算プログラムです。
Mathematics Source Library C & ASM にあるプログラムをDelphi用に変換したものです。
sn,cn,dnの詳細については ヤコビの楕円関数を参照してください。
離心率(k)は1≧k≧-1の範囲で指定します。
パラメタ(m)は1≧m≧0の範囲で指定し、角度(α)は±π/2の範囲です。
snさえ計算出来れば、cn,dn は sn から簡単に変換が可能です。
プログラム
//------------------------------ // ヤコビの楕円関数 sn cn dn //------------------------------ unit Main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; type TForm1 = class(TForm) Memo1: TMemo; snukbtn: TButton; u_Edit: TLabeledEdit; K_Edit: TLabeledEdit; kRadioButton: TRadioButton; mRadioButton: TRadioButton; aRadioButton: TRadioButton; m_Edit: TLabeledEdit; a_Edit: TLabeledEdit; procedure snukbtnClick(Sender: TObject); private { Private 宣言 } function jacobi_sn(u: double; arg: char; x: double): double; function Jacobi_cn(u: double; arg: char; x: double): double; function Jacobi_dn(u: double; arg: char; x: double): double; function Jacobi_am(u: double; arg: char; x: double): double; public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} uses Math; // 振幅関数 function TForm1.Jacobi_am(u: double; arg: char; x: double): double; const KN = 30; EPSILON = 1E-14; var a: array of double; g: array of double; c: array of double; two_n : double; phi : double; k : double; i, j, N : integer; half : double; begin if x = 0 then begin result := u; exit; end; case arg of 'a' : k := sin(abs(x)); 'm' : k := sqrt(abs(x)); else k := abs(x); end; if k = 1 then begin result := 2 * arctan(exp(u)) - pi / 2; exit; end; half := 1 / 2; N := 1; setlength(a, N); setlength(g, N); setlength(c, N); a[0] := 1; g[0] := sqrt(1 - k * k); c[0] := k; two_n := 1; for i := 0 to KN do begin if abs(a[i] - g[i]) < a[i] * EPSILON then break; // if a[i] - g[i] = 0 then break; two_n := two_n + two_n; inc(N); setlength(a, N); setlength(g, N); setlength(c, N); a[i + 1] := half * (a[i] + g[i]); g[i + 1] := sqrt(a[i] * g[i]); c[i + 1] := half * (a[i] - g[i]); end; phi := two_n * a[i] * u; for j := i downto 1 do phi := half * (phi + arcsin(c[j] * sin(phi) / a[j])); result := phi; memo1.Lines.Add('Landen Loop='+ intTostr(N - 1)); end; // ヤコビ楕円関数 function TForm1.jacobi_sn(u: double; arg: char; x: double): double; begin result := sin(Jacobi_am(u, arg, x)); end; function TForm1.Jacobi_cn(u: double; arg: char; x: double): double; begin result := cos(Jacobi_am(u, arg, x) ); // result := sqrt(1 - jacobi_sn(u, arg, x) * jacobi_sn(u, arg, x)); end; function TForm1.Jacobi_dn(u: double; arg: char; x: double): double; var sn : double; begin sn := sin(Jacobi_am(u, arg, x)); case arg of 'm' : begin result := sqrt(1.0 - x * sn * sn); exit; end; 'a' : x := sin(x); end; x := x * sn; result := sqrt(1.0 - x * x ); end; // sn(u,k),cn(u,k),dn(u,k)計算 procedure TForm1.snukbtnClick(Sender: TObject); var x, u, snuk : double; cnuk, dnuk : double; ch : integer; arg : char; begin x := 0; if kradiobutton.Checked then val(k_edit.Text, x, ch); if mradiobutton.Checked then val(m_edit.Text, x, ch); if aradiobutton.Checked then val(a_edit.Text, x, ch); if ch <> 0 then begin application.MessageBox('parameterに間違いがあります。','注意',0); exit; end; val(u_edit.Text, u, ch); if ch <> 0 then begin application.MessageBox('値(u)に間違いがあります。','注意',0); exit; end; arg := '0'; if kradiobutton.Checked then begin if abs(x) > 1 then begin application.MessageBox('離心率の最大値は1です。','注意',0); exit; end; arg := 'k'; end; if mradiobutton.Checked then begin if x > 1 then begin application.MessageBox('mの最大値は1です。','注意',0); exit; end; if x < 0 then begin application.MessageBox('mの最小値は0です。','注意',0); exit; end; arg := 'm'; end; if aradiobutton.Checked then begin if abs(x) > pi / 2 then begin application.MessageBox(pchar('αの最大値は' + floattostrF(pi / 2, fffixed, 8,6) + 'です。'),'注意',0); exit; end; arg := 'a'; end; memo1.Clear; snuk := jacobi_sn(u, arg, x); cnuk := jacobi_cn(u, arg, x); dnuk := jacobi_dn(u, arg, x); if arg = 'a' then arg := 'α'; memo1.Lines.Add('sn(u,' + arg + ')=' + floatTostr(snuk)); memo1.Lines.Add(''); memo1.Lines.Add('cn(u,' + arg + ')=' + floatTostr(cnuk)); memo1.Lines.Add(''); memo1.Lines.Add('dn(u,' + arg + ')=' + floatTostr(dnuk)); end; end.