├── wiki ├── Elliptic-Curve.md ├── Weierstrass-Elliptic-Functions.md ├── Jacobi-Elliptic-Functions.md ├── Theta-Functions.md ├── Elliptic-Integrals.md ├── elliptic.md └── home.md ├── .circleci └── config.yml ├── nomeq.m ├── agm.m ├── inv_agm.m ├── ellipji.m ├── inversenomeq.m ├── theta.m ├── elliptic3.m ├── tests ├── testElliptic3.m ├── testElliptic12.m ├── testEllipj.m └── testThetaPrime.m ├── inverselliptic2.m ├── ellipj.m ├── theta_prime.m ├── elliptic12i.m ├── jacobiThetaEta.m ├── elliptic12.m ├── arclength_ellipse.m ├── README.md └── elliptic123.m /wiki/Elliptic-Curve.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | # Introduction 4 | 5 | Add your content here. 6 | 7 | 8 | # Details 9 | 10 | Add your content here. Format your content with: 11 | - Text in **bold** or *italic* 12 | - Headings, paragraphs, and lists 13 | - Automatic links to other wiki pages -------------------------------------------------------------------------------- /wiki/Weierstrass-Elliptic-Functions.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | # Introduction 4 | 5 | Add your content here. 6 | 7 | 8 | # Details 9 | 10 | Add your content here. Format your content with: 11 | - Text in **bold** or *italic* 12 | - Headings, paragraphs, and lists 13 | - Automatic links to other wiki pages -------------------------------------------------------------------------------- /wiki/Jacobi-Elliptic-Functions.md: -------------------------------------------------------------------------------- 1 | # Here we present some basic theory related the Jacobi's Elliptic function and give some examples of usage and problem solving. 2 | 3 | # Jacobi's Sine function `SN` 4 | 5 | Here we present some basic theory related the Jacobi's `SN` function and give some examples of usage and problem solving. 6 | 7 | # Theory 8 | 9 | # Examples 10 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | orbs: 3 | matlab: mathworks/matlab@0 4 | jobs: 5 | build: 6 | machine: 7 | image: 'ubuntu-2204:current' 8 | resource_class: large 9 | steps: 10 | - run: 11 | name: Checkout code via HTTPS 12 | command: | 13 | git clone https://github.com/moiseevigor/elliptic.git . 14 | git checkout $CIRCLE_SHA1 15 | - matlab/install 16 | - matlab/run-tests: 17 | test-results-junit: test-results/results.xml 18 | # test-results-html: test-results/results.html 19 | # code-coverage-html: test-results/coverage.html 20 | # code-coverage-cobertura: test-results/coverage-cobertura.xml 21 | logging-level: 'Detailed' 22 | select-by-folder: tests 23 | - store_test_results: 24 | path: test-results 25 | workflows: 26 | build: 27 | jobs: 28 | - build -------------------------------------------------------------------------------- /wiki/Theta-Functions.md: -------------------------------------------------------------------------------- 1 | # Jacobi Theta Functions, numerical methods and examples 2 | 3 | 4 | 5 | # Jacobi Theta Functions 6 | 7 | The Jacobi theta functions are the elliptic analogs of the exponential function, and may be used to express the Jacobi elliptic functions. The theta functions are quasi-doubly periodic. 8 | 9 | Whittaker and Watson (1990, p. 487) gives a table summarizing notations used by various earlier writers. 10 | 11 | 12 | In mathematics, theta functions are special functions of several complex variables. They are important in several areas, including the theories of abelian varieties and moduli spaces, and of quadratic forms. They have also been applied to soliton theory. When generalized to a Grassmann algebra, they also appear in quantum field theory, specifically string theory and D-branes. A theta function is graphed on a polar coordinate system. 13 | 14 | The most common form of theta function is that occurring in the theory of elliptic functions. With respect to one of the complex variables (conventionally called z), a theta function has a property expressing its behavior with respect to the addition of a period of the associated elliptic functions, making it a quasiperiodic function. In the abstract theory this comes from a line bundle condition of descent. 15 | 16 | # References 17 | -------------------------------------------------------------------------------- /nomeq.m: -------------------------------------------------------------------------------- 1 | function NomeQ = nomeq(m,tol) 2 | %NOMEQ gives the value of Nome q = q(m). 3 | % 4 | % NomeQ = nomeq(M,TOL), where 0<=M<=1 is the module and 5 | % TOL is the tolerance (optional). Default value for 6 | % the tolerance is eps = 2.220e-16. 7 | % 8 | % See also 9 | % Standard: ELLIPKE, ELLIPJ, 10 | % Moiseev's package: ELLIPTIC12I, ELLIPTIC3, THETA, AGM. 11 | % 12 | % References: 13 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 14 | % Functions" Dover Publications", 1965, Ch. 16-17.6. 15 | 16 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 17 | % http://www.gnu.org/licenses/gpl.html 18 | % Everyone is permitted to copy and distribute verbatim copies of this 19 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 20 | % 21 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 22 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 23 | % For support, please reply to 24 | % moiseev[at]sissa.it, moiseev.igor[at]gmail.com 25 | % Moiseev Igor, 26 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 27 | 28 | 29 | if nargin<2, tol = eps; end 30 | if nargin<1, error('Not enough input arguments.'); end 31 | 32 | if ~isreal(m) 33 | error('Input arguments must be real.') 34 | end 35 | 36 | NomeQ = exp(-pi*ellipke(1-m,tol)./ellipke(m,tol)); 37 | 38 | % END FUNCTION nomeq() -------------------------------------------------------------------------------- /agm.m: -------------------------------------------------------------------------------- 1 | function [a,b,c,n] = agm(a0,b0,c0,tol) 2 | % AGM calculates the Artihmetic Geometric Mean of A and B (see [1]). 3 | % The function is used by routines ELLIPJ and ELLIPTIC12. 4 | % 5 | % [A,B,C,N] = AGM(A0,B0,C0,TOL) carry out the process of the arithmetic geometric 6 | % mean, starting with a given positive numbers triple (A0,B0,C0) and returns in 7 | % (A,B,C) the generated sequence. N is a number of steps (returns in the type uint32). 8 | % 9 | % The general scheme of the process: 10 | % A(i) = 1/2*( A(i-1)+B(i-1) ); A(0) = A0; 11 | % B(i) = sqrt( A(i-1)*B(i-1) ); B(0) = B0; 12 | % C(i) = 1/2*( A(i-1)-B(i-1) ); C(0) = C0; 13 | % Stop at the N-th step when A(N) = B(N), i.e., when C(N) = 0. 14 | % 15 | % See also ELLIPKE, ELLIPJ, ELLIPTIC12, ELLIPTIC3, THETA. 16 | % 17 | % References: 18 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 19 | % Functions" Dover Publications", 1965, Ch. 17.1 - 17.6. 20 | 21 | 22 | if nargin<4, tol = eps; end 23 | if nargin<3, error('Not enough input arguments.'); end 24 | 25 | % pre-allocate space and augment if needed 26 | chunk = 8; mmax = numel(a0); 27 | a = zeros(chunk,mmax); 28 | c = a; 29 | b = a; 30 | a(1,:) = a0; 31 | b(1,:) = b0; 32 | c(1,:) = c0; 33 | n = uint32( zeros(1,mmax) ); 34 | i = 1; 35 | while any(abs(c(i,:)) > tol) 36 | i = i + 1; 37 | if i > size(a,1) 38 | a = [a; zeros(chunk,mmax)]; 39 | b = [b; zeros(chunk,mmax)]; 40 | c = [c; zeros(chunk,mmax)]; 41 | end 42 | a(i,:) = 0.5 * (a(i-1,:) + b(i-1,:)); 43 | b(i,:) = sqrt(a(i-1,:) .* b(i-1,:)); 44 | c(i,:) = 0.5 * (a(i-1,:) - b(i-1,:)); 45 | in = uint32( find((abs(c(i,:)) <= tol) & (abs(c(i-1,:)) > tol)) ); 46 | if ~isempty(in) 47 | [mi,ni] = size(in); 48 | n(in) = ones(mi,ni)*(i-1); 49 | end 50 | end 51 | 52 | % END FUNCTION AGM() 53 | -------------------------------------------------------------------------------- /inv_agm.m: -------------------------------------------------------------------------------- 1 | function [a,b,c,n] = inv_agm(a0,b0,c0,tol) 2 | % INV_AGM calculates the Inverse Artihmetic Geometric Mean of A and B (see [1]). 3 | % The function is used by routines ELLIPJ and ELLIPTIC12. 4 | % 5 | % [A,B,C,N] = AGM(A0,B0,C0,TOL) carry out the process of the arithmetic geometric 6 | % mean, starting with a given positive numbers triple (A0,B0,C0) and returns in 7 | % (A,B,C) the generated sequence. N is a number of steps (returns in the type uint32). 8 | % 9 | % The general scheme of the process: 10 | % A(i) = 1/2*( A(i-1)+B(i-1) ); A(0) = A0; 11 | % B(i) = sqrt( A(i-1)*B(i-1) ); B(0) = B0; 12 | % C(i) = 1/2*( A(i-1)+B(i-1) ); C(0) = C0; 13 | % Stop at the N-th step when A(N) = B(N), i.e., when C(N) = 0. 14 | % 15 | % See also ELLIPKE, ELLIPJ, ELLIPTIC12, ELLIPTIC3, THETA. 16 | % 17 | % References: 18 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 19 | % Functions" Dover Publications", 1965, Ch. 17.1 - 17.6. 20 | 21 | 22 | if nargin<4, tol = eps; end 23 | if nargin<3, error('Not enough input arguments.'); end 24 | 25 | % pre-allocate space and augment if needed 26 | chunk = 8; mmax = numel(a0); 27 | a = zeros(chunk,mmax); 28 | c = a; 29 | b = a; 30 | a(1,:) = a0; 31 | b(1,:) = b0; 32 | c(1,:) = c0; 33 | n = uint32( zeros(1,mmax) ); 34 | i = 1; 35 | while any(abs(c(i,:)) > tol) 36 | i = i + 1; 37 | if i > size(a,1) 38 | a = [a; zeros(chunk,mmax)]; 39 | b = [b; zeros(chunk,mmax)]; 40 | c = [c; zeros(chunk,mmax)]; 41 | end 42 | a(i,:) = 0.5 * (a(i-1,:) + b(i-1,:)); 43 | b(i,:) = sqrt(a(i-1,:) .* b(i-1,:)); 44 | c(i,:) = 0.5 * (a(i-1,:) - b(i-1,:)); 45 | in = uint32( find((abs(c(i,:)) <= tol) & (abs(c(i-1,:)) > tol)) ); 46 | if ~isempty(in) 47 | [mi,ni] = size(in); 48 | n(in) = ones(mi,ni)*(i-1); 49 | end 50 | end 51 | [a, b, c] 52 | 53 | % END FUNCTION AGM() -------------------------------------------------------------------------------- /ellipji.m: -------------------------------------------------------------------------------- 1 | function [sni,cni,dni] = ellipji(u,m,tol) 2 | %ELLIPJI Jacobi elliptic functions of complex phase u. 3 | % [Sni,Cni,Dni] = ELLIPJ(U,M) returns the values of the Jacobi 4 | % elliptic functions SNI, CNI and DNI evaluated for corresponding 5 | % elements of argument U and parameter M. The arrays U and M must 6 | % be the same size (or either can be scalar). As currently 7 | % implemented, M is real and limited to 0 <= M <= 1. 8 | % 9 | % [Sni,Cni,Dni] = ELLIPJ(U,M,TOL) computes the elliptic functions to 10 | % the accuracy TOL instead of the default TOL = EPS. 11 | % 12 | % Some definitions of the Jacobi elliptic functions use the modulus 13 | % k instead of the parameter m. They are related by m = k^2. 14 | % 15 | % Example: 16 | % [phi1,phi2] = meshgrid(-pi:3/20:pi, -pi:3/20:pi); 17 | % phi = phi1 + phi2*i; 18 | % [Sni,Cni,Dni] = ellipji(phi, 0.99); 19 | % 20 | % See also 21 | % Standard: ELLIPKE, ELLIPJ, 22 | % Moiseev's package: ELLIPTIC12, ELLIPTIC12I. 23 | % 24 | % References: 25 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions", 26 | % Dover Publications", 1965, Ch. 17.1 - 17.6 (by L.M. Milne-Thomson). 27 | 28 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 29 | % http://www.gnu.org/licenses/gpl.html 30 | % Everyone is permitted to copy and distribute verbatim copies of this 31 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 32 | % 33 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 34 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 35 | % For support, please reply to 36 | % moiseev.igor[at]gmail.com, moiseev[at]sissa.it 37 | % Moiseev Igor, 38 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 39 | 40 | if nargin<3, tol = eps; end 41 | if nargin<2, error('Not enough input arguments.'); end 42 | 43 | if ~isreal(m) 44 | error('The parameter m must be real.') 45 | end 46 | 47 | if any(m < 0) || any(m > 1) 48 | error('M must be in the range 0 <= M <= 1.'); 49 | end 50 | 51 | % if the input is real, evaluate the elliptic integrals with ELLIPJ 52 | if isreal(u) 53 | [sni,cni,dni] = ellipj(u,m,tol); 54 | return; 55 | end 56 | 57 | if length(m)==1, m = m(ones(size(u))); end 58 | if length(u)==1, u = u(ones(size(m))); end 59 | if ~isequal(size(m),size(u)) 60 | error('U and M must be the same size.'); 61 | end 62 | 63 | % capture memory and save the structure of input arrays 64 | sni = zeros(size(u)); 65 | cni = sni; 66 | dni = sni; 67 | 68 | % make a row vector 69 | m = m(:).'; 70 | u = u(:).'; 71 | 72 | % represent u in the form u = phi + i*psi 73 | phi = real(u); 74 | psi = imag(u); 75 | 76 | [s,c,d] = ellipj(phi,m,tol); 77 | [s1,c1,d1] = ellipj(psi,1-m,tol); 78 | 79 | % function evaluations 80 | delta = c1.^2 + m.*s.^2.*s1.^2; 81 | sni(:) = (s.*d1 + sqrt(-1).*c.*d.*s1.*c1)./delta; 82 | cni(:) = (c.*c1 - sqrt(-1).*s.*d.*s1.*d1)./delta; 83 | dni(:) = (d.*c1.*d1 - sqrt(-1).*m.*s.*c.*s1)./delta; 84 | 85 | % END FUNCTION ELLIPJI() 86 | -------------------------------------------------------------------------------- /inversenomeq.m: -------------------------------------------------------------------------------- 1 | function m = inversenomeq(q) 2 | %INVERSENOMEQ gives the value of Nome m = m(q). 3 | % 4 | % M = inversenomeq(q), where Q is the Nome of q-series. 5 | % 6 | % WARNING. The function INVERSENOMEQ does not return correct 7 | % values of M for Q > 0.6, because of computer precision limitation. 8 | % The function NomeQ(m) has an essential singularity at M = 1, so 9 | % it cannot be inverted at this point and actually is very hard to 10 | % fing and inverse in the neigborhood also. 11 | % More preciesly: 12 | % nomeq(1) = 1 13 | % nomeq(1-eps) = 0.77548641878026 14 | % 15 | % Example: 16 | % nomeq(inversenomeq([0.001 0.3 0.4 0.5 0.6 0.7 0.8])) 17 | % 18 | % See also 19 | % Standard: ELLIPKE, ELLIPJ 20 | % Moiseev's package: ELLIPTIC12I, ELLIPTIC3, THETA, AGM. 21 | % 22 | % References: 23 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 24 | % Functions" Dover Publications", 1965, Ch. 16-17.6. 25 | 26 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 27 | % http://www.gnu.org/licenses/gpl.html 28 | % Everyone is permitted to copy and distribute verbatim copies of this 29 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 30 | % 31 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 32 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 33 | % For support, please reply to 34 | % moiseev[at]sissa.it, moiseev.igor[at]gmail.com 35 | % Moiseev Igor, 36 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 37 | 38 | 39 | if nargin<1, error('Not enough input arguments.'); end 40 | 41 | if ~isreal(q) 42 | error('Input arguments must be real.') 43 | end 44 | 45 | m = zeros(size(q)); 46 | q = q(:).'; % make a row vector 47 | maxq = max(q); 48 | 49 | if ~all(q >= 0) || ~all(q <= 1) 50 | error('Input arguments must be from the interval [0,1].') 51 | end 52 | 53 | if any(q > 0.76) || any(q < 0.00001) 54 | warning('WarnTests:convertTest', ... 55 | 'The function INVERSENOMEQ does not return \ncorrect values of M for Q < 0.00001 and Q > 0.76, because of computer precision limitation.'); 56 | end 57 | 58 | I = find (q <= 0.4); 59 | J = find (q > 0.4 & q <= 0.6); 60 | P = find (q > 0.6); 61 | 62 | if (~isempty(I)) 63 | mm = 0:0.0001:1; 64 | K = ellipke(mm); 65 | KK = K(end:-1:1)./K; 66 | m(I) = interp1(KK, mm, -1/pi*log(q(I)), 'pchip','extrap'); 67 | end 68 | 69 | if (~isempty(J)) 70 | mm = 0.9996:0.0000001:1-eps; 71 | %K = 1/8*(-2+2*mm-2*(-5+mm)*log(4)+(-5+mm).*log(1-mm)); 72 | K = 1/128*(-53+74*mm-21*mm.^2+2*(89+mm.*(-34+9*mm))*log(4)+(-89+mm.*(34-9*mm)).*log(1-mm)); 73 | KK = pi/2./K; 74 | m(J) = interp1(KK, mm, -1/pi*log(q(J)), 'pchip','extrap'); 75 | end 76 | 77 | if (~isempty(P)) 78 | mm = (1-10^8*eps):1000*eps:1-eps; 79 | K = 1/128*(-53+74*mm-21*mm.^2+2*(89+mm.*(-34+9*mm))*log(4)+(-89+mm.*(34-9*mm)).*log(1-mm)); 80 | KK = pi/2./K; 81 | m(P) = interp1(KK, mm, -1/pi*log(q(P)), 'pchip','extrap'); 82 | % plot(mm,K*log(q(P))+pi*pi/2,'.'); 83 | end 84 | 85 | % END FUNCTION inversenomeq() 86 | -------------------------------------------------------------------------------- /theta.m: -------------------------------------------------------------------------------- 1 | function Th = theta(type,v,m,tol) 2 | %THETA evaluates theta functions of four types. 3 | % Th = THETA(TYPE,V,M) returns values of theta functions 4 | % evaluated for corresponding values of argument V and parameter M. 5 | % TYPE is a type of the theta function, there are four numbered types. 6 | % The arrays V and M must be the same size (or either can be scalar). 7 | % As currently implemented, M is limited to 0 <= M <= 1. 8 | % 9 | % Th = THETA(TYPE,V,M,TOL) computes the theta and eta 10 | % elliptic functions to the accuracy TOL instead of the default TOL = EPS. 11 | % 12 | % The parameter M is related to the nome Q as Q = exp(-pi*K(1-M)/K(M)). 13 | % Some definitions of the Jacobi elliptic functions use the modulus 14 | % k instead of the parameter m. They are related by m = k^2. 15 | % 16 | % Example: 17 | % [phi,alpha] = meshgrid(0:5:90, 0:2:90); 18 | % Th1 = theta(1, pi/180*phi, sin(pi/180*alpha).^2); 19 | % Th2 = theta(2, pi/180*phi, sin(pi/180*alpha).^2); 20 | % Th3 = theta(3, pi/180*phi, sin(pi/180*alpha).^2); 21 | % Th4 = theta(4, pi/180*phi, sin(pi/180*alpha).^2); 22 | % 23 | % See also 24 | % Standard: ELLIPKE, ELLIPJ, 25 | % Moiseev's package: ELLIPTIC12, ELLIPTIC12I, JACOBITHETAETA. 26 | % 27 | % References: 28 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 29 | % Functions" Dover Publications", 1965, Ch. 16-17.6. 30 | 31 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 32 | % http://www.gnu.org/licenses/gpl.html 33 | % Everyone is permitted to copy and distribute verbatim copies of this 34 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 35 | % 36 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 37 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 38 | % For support, please reply to 39 | % moiseev.igor[at]gmail.com, moiseev[at]sissa.it 40 | % Moiseev Igor, 41 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 42 | 43 | if nargin<4, tol = eps; end 44 | if nargin<3, error('Not enough input arguments.'); end 45 | 46 | if ~isreal(v) | ~isreal(m) 47 | error('Input arguments must be real.') 48 | end 49 | 50 | Th = zeros(size(v)); 51 | H = Th; 52 | 53 | if length(m)==1, m = m(ones(size(v))); end 54 | if length(v)==1, v = v(ones(size(m))); end 55 | if ~isequal(size(m),size(v)), error('V and M must be the same size.'); end 56 | 57 | % m = m(:).'; % make a row vector 58 | % v = v(:).'; 59 | 60 | if any(m < 0) | any(m > 1), 61 | error('M must be in the range 0 <= M <= 1.'); 62 | end 63 | 64 | K = ellipke(m); 65 | u = 2*K.*v/pi; 66 | 67 | switch type 68 | case { '1', 1 } 69 | [th, H] = jacobiThetaEta(u,m,tol); 70 | Th(:) = H; 71 | return; 72 | case { '2', 2 } 73 | [th, H] = jacobiThetaEta(u+K,m,tol); 74 | Th(:) = H; 75 | return; 76 | case { '3', 3 } 77 | Th(:) = jacobiThetaEta(u+K,m,tol); 78 | return; 79 | case { '4', 4 } 80 | Th(:) = jacobiThetaEta(u,m,tol); 81 | return; 82 | end 83 | 84 | % END FUNCTION theta() -------------------------------------------------------------------------------- /elliptic3.m: -------------------------------------------------------------------------------- 1 | function Pi = elliptic3(u,m,c); 2 | % ELLIPTIC3 evaluates incomplete elliptic integral of the third kind. 3 | % Pi = ELLIPTIC3(U,M,C) where U is a phase in radians, 0 1) || any(c < 0) || any(c > 1), 33 | error('M and C must be in the range [0, 1].'); 34 | end 35 | if any(u > pi/2) || any(u < 0), 36 | error('U must be in the range [0, pi/2].'); 37 | end 38 | 39 | [mm,nm] = size(m); 40 | [mu,nu] = size(u); 41 | if length(m)==1, m = m(ones(size(u))); end 42 | if length(c)==1, c = c(ones(size(u))); end 43 | if length(u)==1, u = u(ones(size(m))); end 44 | if ~isequal(size(m), size(c), size(u)), 45 | error('U, M and C must be the same size.'); 46 | end 47 | 48 | Pi = zeros(size(u)); 49 | m = m(:).'; % make a row vector 50 | u = u(:).'; 51 | c = c(:).'; 52 | 53 | I = find( u==pi/2 & m==1 | u==pi/2 & c==1 ); 54 | 55 | t = [ 0.9931285991850949, 0.9639719272779138,... % Base points 56 | 0.9122344282513259, 0.8391169718222188,... % for Gauss-Legendre integration 57 | 0.7463319064601508, 0.6360536807265150,... 58 | 0.5108670019508271, 0.3737060887154195,... 59 | 0.2277858511416451, 0.07652652113349734 ]; 60 | w = [ 0.01761400713915212, 0.04060142980038694,... % Weights 61 | 0.06267204833410907, 0.08327674157670475,... % for Gauss-Legendre integration 62 | 0.1019301198172404, 0.1181945319615184,... 63 | 0.1316886384491766, 0.1420961093183820,... 64 | 0.1491729864726037, 0.1527533871307258 ]; 65 | 66 | P = 0; i = 0; 67 | while i < 10 68 | i = i + 1; 69 | c0 = u.*t(i)/2; 70 | P = P + w(i).*(g(u/2+c0,m,c) + g(u/2-c0,m,c)); 71 | end 72 | P = u/2.*P; 73 | Pi(:) = P; % Incomplete elliptic integral of the third kind 74 | 75 | % special values u==pi/2 & m==1 | u==pi/2 & c==1 76 | Pi(I) = inf; 77 | return; 78 | 79 | 80 | function g = g(u,m,c) 81 | % g = 1/((1 - c*sin(u)^2)*sqrt(1 - m*sin(u)^2)); 82 | 83 | sn2 = sin(u).^2; 84 | g = 1./((1 - c.*sn2).*sqrt(1 - m.*sn2)); 85 | return; -------------------------------------------------------------------------------- /tests/testElliptic3.m: -------------------------------------------------------------------------------- 1 | %Test function for elliptic3.m 2 | 3 | % Test error handling 4 | %!test 5 | %! clear 6 | %! try 7 | %! elliptic3(0, 2, 1); % module out of range 8 | %! assert(false, "Module out of range didn't throw an error."); 9 | %! catch err 10 | % Verify that the error message contains the expected string 11 | %! assert(~isempty(strfind(err.message, 'M and C must be in the range [0, 1].')), ... 12 | %! 'Unexpected error message: %s', err.message); 13 | %! end 14 | 15 | %!test 16 | %! clear 17 | %! try 18 | %! elliptic3(0, 0.5i, 0.5); % complex input 19 | %! assert(false, "Complex input didn't throw an error."); 20 | %! catch err 21 | % Verify that the error message contains the expected string 22 | %! assert(~isempty(strfind(err.message, 'Input arguments must be real.')), ... 23 | %! 'Unexpected error message: %s', err.message); 24 | %! end 25 | 26 | % Test some simple inputs 27 | %!test 28 | %! clear 29 | %! Pi = elliptic3(0, 0.5, 1); 30 | %! assert(abs(Pi - 0) < 1e-12, 'Pi value is incorrect.'); 31 | 32 | % Test the output of elliptic3 for some inputs 33 | %!test 34 | %! clear 35 | %! Pi = elliptic3(pi/4, 0.5, 0.5); 36 | %! assert(abs(Pi - 0.919022739165697) < 1e-10, 'Unexpected value for K'); 37 | 38 | % Test a range of inputs 39 | %!test 40 | %! clear 41 | %! [phi,alpha,c] = meshgrid(0:25:90, 0:25:90, 0:0.4:1); 42 | %! Pi = elliptic3(pi/180*phi, sin(pi/180*alpha).^2, c); % values of integrals 43 | %! expectedPi = [ 44 | %! 0 0 0 45 | %! 0 0 0 46 | %! 0 0 0 47 | %! 0 0 0 48 | %! 0.436332312998582 0.447481674284817 0.459719055660277 49 | %! 0.438747923080541 0.450008007383737 0.462369007025916 50 | %! 0.444551505567130 0.456080142788474 0.468741143521980 51 | %! 0.449816440114804 0.461591818685859 0.474528668429618 52 | %! 0.872664625997165 0.962368261625533 1.094942500776336 53 | %! 0.890543879394498 0.983487876637982 1.121161300350779 54 | %! 0.940075683068702 1.042322814335382 1.194760969067305 55 | %! 0.997105354291443 1.110665166734768 1.281307083403909 56 | %! 1.308996938995747 1.597941344935833 2.305386400623875 57 | %! 1.360834669550633 1.668946178349462 2.428736708263183 58 | %! 1.534546187668256 1.911003257311173 2.863258220259662 59 | %! 1.871453962422796 2.397752070491359 3.803705851444642 60 | %! ]; 61 | %! assert(size(Pi) == [4 4 3], 'Pi size is incorrect.') 62 | %! Pi = reshape(Pi, [], size(Pi, 3)); 63 | %! assert(norm(Pi-expectedPi) < 1e-12, 'Pi value is incorrect.') 64 | 65 | % Benchmark time and memory 66 | %!test 67 | %! clear 68 | %! elapsedTime = []; 69 | %! mem = []; 70 | %! for i=1:10 71 | %! [phi,alpha,c] = meshgrid(0:0.5:90, 0:0.5:90, 0:0.1:1); 72 | %! tic 73 | %! mem1 = whos(); 74 | %! Pi = elliptic3(pi/180*phi, sin(pi/180*alpha).^2, c); % values of integrals 75 | %! mem2 = whos(); 76 | %! elapsedTime(i) = toc; 77 | %! mem(i) = sum([mem2.bytes]) - sum([mem1.bytes]); 78 | %! clear Pi phi alpha; 79 | %! end 80 | % fprintf('\nAverage execution time for elliptic3 calculations: %f seconds\n', mean(elapsedTime)); 81 | % fprintf('Average Mem: %f\n', mean(mem)); 82 | %! assert(mean(elapsedTime) < 0.38, 'Average execution time for elliptic3 calculations: %f seconds is greater than 0.15\n', mean(elapsedTime)) 83 | %! assert(mean(mem) < 2883013.7, 'Average memory used for elliptic3 run: %f bytes is greater than 2883013.7\n', mean(mem)) 84 | 85 | -------------------------------------------------------------------------------- /inverselliptic2.m: -------------------------------------------------------------------------------- 1 | function invE = inverselliptic2(E,m,tol) 2 | % INVERSELLIPTIC2 evaluates the value of the INVERSE Incomplete Elliptic Integrals 3 | % of the Second Kind. 4 | % 5 | % INVE = INVERSELLIPTIC2(E,M,TOL) where E is a value of the integral to 6 | % be inverted, 0 1), error('M must be in the range 0 <= M <= 1.'); end 89 | 90 | % inputs 91 | z = E; mu = 1-m; 92 | 93 | % complete integral initialization 94 | [~,E1] = ellipke(m,tol); 95 | 96 | zeta = 1 - z./E1; 97 | r = sqrt(zeta.*zeta+mu.*mu); 98 | theta = atan(mu./(z+eps)); 99 | 100 | % “Empirical” initialization [1] 101 | invE(:) = pi/2 + sqrt(r).*(theta - (pi/2)); 102 | 103 | for iter=1:4 104 | [~, E] = elliptic12(invE(:),m,tol); 105 | invE(:) = invE(:)-(E - z)./sqrt( 1-m.*sin(invE(:)).^2 ); 106 | end 107 | return; 108 | 109 | -------------------------------------------------------------------------------- /ellipj.m: -------------------------------------------------------------------------------- 1 | function [sn,cn,dn,am] = ellipj(u,m,tol) 2 | %ELLIPJ Jacobi elliptic functions and Jacobi's amplitude. 3 | % [Sn,Cn,Dn,Am] = ELLIPJ(U,M) returns the values of the Jacobi 4 | % elliptic functions SN, CN, DN and AM evaluated for corresponding 5 | % elements of argument U and parameter M. The arrays U and M must 6 | % be the same size (or either can be scalar). As currently 7 | % implemented, M is limited to 0 <= M <= 1. 8 | % 9 | % [Sn,Cn,Dn,Am] = ELLIPJ(U,M,TOL) computes the elliptic functions to 10 | % the accuracy TOL instead of the default TOL = EPS. 11 | % 12 | % Some definitions of the Jacobi elliptic functions use the modulus 13 | % k instead of the parameter m. They are related by m = k^2. 14 | % 15 | % See also ELLIPKE. 16 | 17 | % L. Shure 1-9-88 18 | % Copyright 1984-2001 The MathWorks, Inc. 19 | % $Revision: 5.14 $ $Date: 2001/04/15 12:01:40 $ 20 | % 21 | % Modified by Moiseev Igor, 22 | % moiseev[at]sissa.it 23 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 24 | % Date: 2005/10/04 25 | % 26 | % The modification of orginal script fixes the problem of slow convergence 27 | % of the AGM algorithm for the value of parameter M=1. 28 | 29 | 30 | % ELLIPJ uses the method of the arithmetic-geometric mean 31 | % described in [1]. 32 | % 33 | % References: 34 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 35 | % Functions" Dover Publications", 1965, Ch. 16-17.6. 36 | 37 | 38 | if nargin<3, tol = eps; end 39 | if nargin<2, error('Not enough input arguments.'); end 40 | 41 | if ~isreal(u) | ~isreal(m) 42 | error('Input arguments must be real. Use ELLIPJI for complex arguments') 43 | end 44 | 45 | if length(m)==1, m = m(ones(size(u))); end 46 | if length(u)==1, u = u(ones(size(m))); end 47 | if ~isequal(size(m),size(u)), error('U and M must be the same size.'); end 48 | 49 | am = zeros(size(u)); 50 | cn = zeros(size(u)); 51 | sn = cn; 52 | dn = sn; 53 | m = m(:).'; % make a row vector 54 | u = u(:).'; 55 | 56 | if any(m < 0) | any(m > 1), 57 | error('M must be in the range 0 <= M <= 1.'); 58 | end 59 | 60 | I = uint32( find(m ~= 1 & m ~= 0) ); 61 | if ~isempty(I) 62 | % Use standard uniquetol for numerical precision issues 63 | % This is the recommended MATLAB approach since R2015a 64 | m_vals = m(I); 65 | tol_unique = 1e-11; 66 | 67 | [mu, ~, K] = uniquetol(m_vals, tol_unique); 68 | K = uint32(K(:).'); % Ensure K is a row vector 69 | 70 | mumax = length(mu); 71 | 72 | % pre-allocate space and augment if needed 73 | chunk = 7; 74 | a = zeros(chunk,mumax); 75 | c = a; 76 | b = a; 77 | a(1,:) = ones(1,mumax); 78 | c(1,:) = sqrt(mu); 79 | b(1,:) = sqrt(1-mu); 80 | n = uint32( zeros(1,mumax) ); 81 | i = 1; 82 | while any(abs(c(i,:)) > tol) % Arithmetic-Geometric Mean of A, B and C 83 | i = i + 1; 84 | if i > size(a,1) 85 | a = [a; zeros(2,mumax)]; 86 | b = [b; zeros(2,mumax)]; 87 | c = [c; zeros(2,mumax)]; 88 | end 89 | a(i,:) = 0.5 * (a(i-1,:) + b(i-1,:)); 90 | b(i,:) = sqrt(a(i-1,:) .* b(i-1,:)); 91 | c(i,:) = 0.5 * (a(i-1,:) - b(i-1,:)); 92 | in = uint32( find((abs(c(i,:)) <= tol) & (abs(c(i-1,:)) > tol)) ); 93 | if ~isempty(in) 94 | [mi,ni] = size(in); 95 | n(in) = ones(mi,ni)*(i-1); 96 | end 97 | end 98 | 99 | mmax = length(I); 100 | phin = zeros(1,mmax); 101 | phin(:) = (2 .^ double(n(K))).*a(i,K).*u(I); 102 | while i > 1 103 | i = i - 1; 104 | in = uint32( find(n(K) >= i) ); 105 | if ~isempty(in) 106 | phin(in) = 0.5*(asin(c(i+1,K(in)).*sin(phin(in))./a(i+1,K(in))) + phin(in)); 107 | end 108 | end 109 | am(I) = phin; 110 | sn(I) = sin(phin); 111 | cn(I) = cos(phin); 112 | dn(I) = sqrt(1 - m(I).*sin(phin).^2); 113 | end 114 | 115 | % Special cases: m = {0, 1} 116 | m0 = find(m == 0); 117 | am(m0) = u(m0); 118 | sn(m0) = sin(u(m0)); 119 | cn(m0) = cos(u(m0)); 120 | dn(m0) = ones(size(m0)); 121 | 122 | m1 = find(m == 1); 123 | am(m1) = asin(tanh(u(m1))); 124 | sn(m1) = tanh(u(m1)); 125 | cn(m1) = sech(u(m1)); 126 | dn(m1) = sech(u(m1)); 127 | -------------------------------------------------------------------------------- /theta_prime.m: -------------------------------------------------------------------------------- 1 | function [th, thp] = theta_prime(j, z, m, tol) 2 | %THETA_PRIME evaluates theta functions and their derivatives. 3 | % [TH, THP] = THETA_PRIME(J, Z, M) returns values of the Jacobi theta 4 | % function TH and its derivative THP with respect to the argument Z. 5 | % J is the type of theta function (1, 2, 3, or 4), Z is the argument, 6 | % and M is the parameter (0 <= M <= 1). 7 | % 8 | % [TH, THP] = THETA_PRIME(J, Z, M, TOL) computes the theta function 9 | % and its derivative to the accuracy TOL instead of the default TOL = EPS. 10 | % 11 | % The arrays Z and M must be the same size (or either can be scalar). 12 | % As currently implemented, M is limited to 0 <= M <= 1. 13 | % 14 | % The theta functions are defined as: 15 | % θ₁(z|τ) = 2∑[n=0,∞] (-1)ⁿ q^((n+1/2)²) sin((2n+1)z) 16 | % θ₂(z|τ) = 2∑[n=0,∞] q^((n+1/2)²) cos((2n+1)z) 17 | % θ₃(z|τ) = 1 + 2∑[n=1,∞] q^(n²) cos(2nz) 18 | % θ₄(z|τ) = 1 + 2∑[n=1,∞] (-1)ⁿ q^(n²) cos(2nz) 19 | % 20 | % where q = exp(iπτ) is the nome and τ is related to parameter M. 21 | % 22 | % The derivatives are computed using the relation: 23 | % θ'ⱼ(z,m) = θⱼ(z,m) * (2K/π) * (Z + δⱼ) 24 | % where K is the complete elliptic integral, Z is the Jacobi zeta 25 | % function, and δⱼ depends on the theta function type. 26 | % 27 | % The parameter M is related to the nome Q as Q = exp(-π*K(1-M)/K(M)). 28 | % Some definitions of the Jacobi elliptic functions use the modulus 29 | % k instead of the parameter m. They are related by m = k². 30 | % 31 | % Example: 32 | % j = 1; z = 0.5; m = 0.8; 33 | % [th, thp] = theta_prime(j, z, m); 34 | % % Verify using numerical differentiation 35 | % dz = 1e-8; 36 | % th_plus = theta(j, z + dz, m); 37 | % th_minus = theta(j, z - dz, m); 38 | % thp_numerical = (th_plus - th_minus) / (2 * dz); 39 | % 40 | % Note: To reproduce results in Mathematica, use the inversenomeq function 41 | % to convert from Mathematica's nome parameter to the parameter m: 42 | % [th_4, thp_4] = theta_prime(4, z, inversenomeq(0.1)); 43 | % 44 | % See also THETA, ELLIPJ, ELLIPTIC12, ELLIPKE, JACOBITHETAETA, INVERSENOMEQ. 45 | % 46 | % References: 47 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 48 | % Functions" Dover Publications", 1965, Ch. 16-17.6. 49 | % [2] D. F. Lawden, "Elliptic Functions and Applications" 50 | % Springer-Verlag, vol. 80, 1989 51 | % [3] E. T. Whittaker and G. N. Watson, "A Course of Modern Analysis" 52 | % Cambridge University Press, 4th ed., 1996, Ch. 21. 53 | 54 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 55 | % http://www.gnu.org/licenses/gpl.html 56 | % Everyone is permitted to copy and distribute verbatim copies of this 57 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 58 | % 59 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 60 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 61 | % For support, please reply to 62 | % moiseev.igor[at]gmail.com, moiseev[at]sissa.it 63 | % Moiseev Igor, 64 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 65 | 66 | if nargin < 4, tol = eps; end 67 | if nargin < 3, error('Not enough input arguments.'); end 68 | 69 | if ~isreal(z) || ~isreal(m) 70 | error('Input arguments must be real.'); 71 | end 72 | 73 | if ~isscalar(j) || ~ismember(j, [1, 2, 3, 4]) 74 | error('J must be a scalar integer: 1, 2, 3, or 4.'); 75 | end 76 | 77 | if length(m) == 1 && length(z) > 1 78 | m = m(ones(size(z))); 79 | elseif length(z) == 1 && length(m) > 1 80 | z = z(ones(size(m))); 81 | end 82 | 83 | if ~isequal(size(m), size(z)) 84 | error('Z and M must be the same size.'); 85 | end 86 | 87 | if any(m < 0) || any(m > 1) 88 | error('M must be in the range 0 <= M <= 1.'); 89 | end 90 | 91 | K = ellipke(m); % complete elliptic integral K(m) 92 | u = (2 * K ./ pi) .* z; % base elliptic argument 93 | 94 | if j == 2 || j == 3 % shift for θ₂, θ₃ 95 | u_calc = u + K; 96 | else 97 | u_calc = u; 98 | end 99 | 100 | [sn, cn, dn, am] = ellipj(u_calc, m); 101 | [~, ~, Z] = elliptic12(am, m); % Jacobi zeta function at the same point 102 | th = theta(j, z, m); % Moiseev's θ-function 103 | 104 | switch j 105 | case 1, delta = cn .* dn ./ sn; 106 | case 2, delta = cn .* dn ./ sn; 107 | case 3, delta = 0; 108 | case 4, delta = 0; 109 | otherwise 110 | error('J must be 1, 2, 3, or 4.'); 111 | end 112 | 113 | thp = th .* (2 * K ./ pi) .* (Z + delta); 114 | 115 | end 116 | 117 | -------------------------------------------------------------------------------- /elliptic12i.m: -------------------------------------------------------------------------------- 1 | function [Fi,Ei,Zi] = elliptic12i(u,m,tol) 2 | % ELLIPTIC12i evaluates the Incomplete Elliptic Integrals 3 | % of the First, Second Kind and Jacobi's Zeta Function for the complex 4 | % value of phase U. Parameter M must be in the range 0 <= M <= 1. 5 | % 6 | % [Fi,Ei,Zi] = ELLIPTIC12i(U,M,TOL) where U is a complex phase in 7 | % radians, M is the real parameter and TOL is the tolerance (optional). 8 | % Default value for the tolerance is eps = 2.220e-16. 9 | % 10 | % ELLIPTIC12i uses the function ELLIPTIC12 to evaluate the values of 11 | % corresponding integrals. 12 | % 13 | % Example: 14 | % [phi1,phi2] = meshgrid(-2*pi:3/20:2*pi, -2*pi:3/20:2*pi); 15 | % phi = phi1 + phi2*i; 16 | % [Fi,Ei,Zi] = elliptic12i(phi, 0.5); 17 | % 18 | % See also ELLIPKE, ELLIPJ, ELLIPTIC12. 19 | % 20 | % References: 21 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions", 22 | % Dover Publications", 1965, Ch. 17.1 - 17.6 (by L.M. Milne-Thomson). 23 | 24 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 25 | % http://www.gnu.org/licenses/gpl.html 26 | % Everyone is permitted to copy and distribute verbatim copies of this 27 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 28 | % 29 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 30 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 31 | % For support, please reply to 32 | % moiseev.igor[at]gmail.com, moiseev[at]sissa.it 33 | % Moiseev Igor, 34 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 35 | 36 | if nargin<3, tol = eps; end 37 | if nargin<2, error('Not enough input arguments.'); end 38 | 39 | if ~isreal(m) 40 | error('The parameter M must be real.') 41 | end 42 | 43 | if any(m < 0) || any(m > 1) 44 | error('M must be in the range 0 <= M <= 1.'); 45 | end 46 | 47 | % if the input is real, evaluate the elliptic integrals with ELLIPTIC12 48 | % if isreal(u) 49 | % [Fi,Ei,Zi] = elliptic12(u,m,tol); 50 | % return; 51 | % end 52 | 53 | if length(m)==1, m = m(ones(size(u))); end 54 | if length(u)==1, u = u(ones(size(m))); end 55 | if ~isequal(size(m),size(u)) 56 | error('U and M must be the same size.'); 57 | end 58 | 59 | % capture memory and save the structure of input arrays 60 | F1 = zeros(size(u)); F2 = zeros(size(u)); 61 | E1 = F1; E2 = F1; 62 | Z1 = F1; Z2 = F1; 63 | Fi = F1; Ei = F1; 64 | Zi = F1; 65 | lambda = []; mu = []; 66 | I = []; J = []; 67 | 68 | % make a row vector 69 | m = m(:).'; 70 | u = u(:).'; 71 | 72 | % represent u in the form u = phi + i*psi 73 | phi = real(u); 74 | psi = imag(u); 75 | 76 | % to avoid singularity of COT(phi) at zero add EPS 77 | I = find (abs(phi) < eps); 78 | phi(I) = eps; 79 | I = []; 80 | 81 | % finding the roots of the equation 82 | % X^2 - (cot(phi)^2+m*sinh(psi)^2*csc(phi)^2-1+m)X - (1-m)*cot(phi)^2 = 0 83 | b = -(cot(phi).^2 + m.*sinh(psi).^2.*csc(phi).^2-1+m); 84 | c = -(1-m).*cot(phi).^2; 85 | 86 | X1 = -b/2 + sqrt(b.^2/4-c); 87 | I = find(X1>=0); 88 | 89 | if length(I) ~= length(u) 90 | X2 = -b/2 - sqrt(b.^2/4-c); 91 | J = find(X2>=0); 92 | end 93 | 94 | if( ~isempty(I) ) 95 | lambda(I) = acot( sqrt(X1(I)) ); 96 | mu(I) = atan( sqrt(1./m(I).*(tan(phi(I)).^2.*cot(lambda(I)).^2 - 1)) ); 97 | end 98 | if( ~isempty(J) ) 99 | lambda(J) = acot( sqrt(X2(J)) ); 100 | mu(J) = atan( sqrt(1./m(J).*(tan(phi(J)).^2.*cot(lambda(J)).^2 - 1)) ); 101 | end 102 | 103 | % change of variables taking into account periodicity ceil to the right 104 | lambda = (-1).^floor(phi/pi*2).*lambda + pi*ceil(phi/pi-0.5+eps); 105 | mu = sign(psi).*real(mu); 106 | 107 | [F1(:),E1(:)] = elliptic12(lambda, m, tol); 108 | [F2(:),E2(:)] = elliptic12(mu, 1-m, tol); 109 | 110 | % complex values of elliptic integral of the first kind 111 | Fi = F1 + sqrt(-1)*F2; 112 | 113 | % some calucation optimiziation 114 | sin_lam = sin(lambda); cos_lam = cos(lambda); 115 | sin_mu = sin(mu); cos_mu = cos(mu); 116 | 117 | b1 = m.*sin_lam.*cos_lam.*sin_mu.^2.*sqrt(1-m.*sin_lam.^2); 118 | b2 = sin_mu.*cos_mu.*(1-m.*sin_lam.^2).*sqrt(1-(1-m).*sin_mu.^2); 119 | b3 = cos_mu.^2 + m.*sin_lam.^2.*sin_mu.^2; 120 | 121 | % complex values of elliptic integral of the second kind 122 | Ei(:) = (b1 + sqrt(-1)*b2)./b3; 123 | Ei(:) = Ei(:) + E1(:) + sqrt(-1)*(-E2(:) + F2(:)); 124 | 125 | [K,Ee] = ellipke(m); 126 | % complex values of zeta function 127 | Zi(:) = Ei(:) - Ee(:)./K(:).*Fi(:); 128 | 129 | % END FUNCTION ELLIPTIC12i() 130 | -------------------------------------------------------------------------------- /tests/testElliptic12.m: -------------------------------------------------------------------------------- 1 | %Test function for elliptic12.m 2 | 3 | % Test error handling 4 | %!test 5 | %! clear 6 | %! try 7 | %! elliptic12(0, 2); % module out of range 8 | %! assert(false, "Module out of range didn't throw an error."); 9 | %! catch err 10 | % Verify that the error message contains the expected string 11 | %! assert(~isempty(strfind(err.message, 'M must be in the range 0 <= M <= 1')), ... 12 | %! 'Unexpected error message: %s', err.message); 13 | %! end 14 | 15 | %!test 16 | %! clear 17 | %! try 18 | %! elliptic12(0, 0.5i); % complex input 19 | %! assert(false, "Complex input didn't throw an error."); 20 | %! catch err 21 | % Verify that the error message contains the expected string 22 | %! assert(~isempty(strfind(err.message, 'Input arguments must be real. Use ELLIPTIC12i for complex arguments')), ... 23 | %! 'Unexpected error message: %s', err.message); 24 | %! end 25 | 26 | % Test some simple inputs 27 | %!test 28 | %! clear 29 | %! [F,E,Z] = elliptic12(0, 0.5); 30 | %! assert(abs(F - 0) < 1e-12, 'F value is incorrect.'); 31 | %! assert(abs(E - 0) < 1e-12, 'E value is incorrect.'); 32 | %! assert(abs(Z - 0) < 1e-12, 'Z value is incorrect.'); 33 | 34 | % Test the output of elliptic12 for some inputs 35 | %!test 36 | %! clear 37 | %! [F,E,Z] = elliptic12(1000*pi/e, 0.5); 38 | %! assert(abs(F - 1364.215673994739) < 1e-10, 'Unexpected value for F'); 39 | %! assert(abs(E - 993.6995958059659) < 1e-10, 'Unexpected value for E'); 40 | %! assert(abs(Z - (-9.508521098575250e-02)) < 1e-10, 'Unexpected value for Z'); 41 | 42 | % Test a range of inputs 43 | %!test 44 | %! clear 45 | %! [phi,alpha] = meshgrid(0:15:90, 0:20:90); 46 | %! [F,E,Z] = elliptic12(pi/180*phi, sin(pi/180*alpha).^2); 47 | %! expectedF = [ 48 | %! 0 0.261799387799149 0.523598775598299 0.785398163397448 1.047197551196598 1.308996938995747 1.570796326794897 49 | %! 0 0.262145681692449 0.526283990562203 0.793981429961732 1.065968913708522 1.341839009622797 1.620025899124204 50 | %! 0 0.263033690353369 0.533427451037688 0.818147652199543 1.122556669683242 1.447669376453414 1.786769134885021 51 | %! 0 0.264063548276829 0.542229109803553 0.851223749071185 1.212596615254979 1.649178665655556 2.156515647499643 52 | %! 0 0.264747663195422 0.548425344542772 0.877408330405700 1.301353213761152 1.946822305295344 3.153385251887838 53 | %! ]; 54 | %! assert(norm(F-expectedF) < 1e-12, 'F value is incorrect.') 55 | %! expectedE = [ 56 | %! 0 0.261799387799149 0.523598775598299 0.785398163397448 1.047197551196598 1.308996938995747 1.570796326794897 57 | %! 0 0.261453912906691 0.520937696463332 0.776974018512720 1.028972213953050 1.277421529463950 1.523799205259775 58 | %! 0 0.260575450957998 0.514088617513829 0.754888085407355 0.980134299660981 1.191010358808463 1.393140248523812 59 | %! 0 0.259569955098381 0.506092072465726 0.728224155457347 0.918393294316326 1.075856687976766 1.211056027568461 60 | %! 0 0.258909826877359 0.500742319367686 0.709723805114461 0.872755203912916 0.981407813910667 1.040114395706011 61 | %! ]; 62 | %! assert(norm(E-expectedE) < 1e-12, 'E value is incorrect.') 63 | %! expectedZ = [ 64 | %! 0 0 0 0 0 0 0 65 | %! 0 0.014879224414869 0.025914050857933 0.030153691368092 0.026319982023431 0.015285400927267 0.000000000000000 66 | %! 0 0.055488619316143 0.098176322411480 0.116980030437629 0.104879154913245 0.062265499992439 0.000000000000000 67 | %! 0 0.111277151300479 0.201587056463619 0.250193934198656 0.237423303852160 0.149710955672358 0.000000000000000 68 | %! 0 0.171585306172434 0.319849389939710 0.420318939400386 0.443516115310938 0.339266830849054 0.000000000000000 69 | %! ]; 70 | %! assert(norm(Z-expectedZ) < 1e-12, 'Z value is incorrect.') 71 | 72 | % Benchmark time and memory 73 | %!test 74 | %! clear 75 | %! elapsedTime = []; 76 | %! mem = []; 77 | %! for i=1:10 78 | %! [phi,alpha] = meshgrid(0:0.5:720, 0:0.5:90); 79 | %! tic 80 | %! mem1 = whos(); 81 | %! [F,E,Z] = elliptic12(pi/180*phi, sin(pi/180*alpha).^2); 82 | %! mem2 = whos(); 83 | %! elapsedTime(i) = toc; 84 | %! mem(i) = sum([mem2.bytes]) - sum([mem1.bytes]); 85 | %! clear F E Z phi alpha; 86 | %! end 87 | % fprintf('\nAverage execution time for elliptic12 calculations: %f seconds\n', mean(elapsedTime)); 88 | % fprintf('Average Mem: %f\n', mean(mem)); 89 | %! assert(mean(elapsedTime) < 0.15, 'Average execution time for elliptic12 calculations: %f seconds is greater than 0.15\n', mean(elapsedTime)) 90 | %! assert(mean(mem) < 6259742.2, 'Average memory used for elliptic12 run: %f bytes is greater than 6259742.1\n', mean(mem)) 91 | 92 | -------------------------------------------------------------------------------- /tests/testEllipj.m: -------------------------------------------------------------------------------- 1 | %Test function for ellipj.m 2 | 3 | %!test 4 | % Test error handling 5 | %! try 6 | %! ellipj(0, 2); % module out of range 7 | %! assert(false, "Module out of range didn't throw an error."); 8 | %! catch err 9 | % Verify that the error message contains the expected string 10 | %! assert(~isempty(strfind(err.message, 'M must be in the range 0 <= M <= 1')), ... 11 | %! 'Unexpected error message: %s', err.message); 12 | %! end 13 | 14 | %!test 15 | %! try 16 | %! ellipj(0, 0.5i); % complex input 17 | %! assert(false, "Complex input didn't throw an error."); 18 | %! catch err 19 | % Verify that the error message contains the expected string 20 | %! assert(~isempty(strfind(err.message, 'Input arguments must be real. Use ELLIPJI for complex arguments')), ... 21 | %! 'Unexpected error message: %s', err.message); 22 | %! end 23 | 24 | % Test some simple inputs 25 | %!test 26 | %! clear 27 | %! [Sn,Cn,Dn,Am] = ellipj(0, 0.5); 28 | %! assert(abs(Sn - 0) < 1e-12, 'Sn value is incorrect.'); 29 | %! assert(abs(Cn - 1) < 1e-12, 'Cn value is incorrect.'); 30 | %! assert(abs(Dn - 1) < 1e-12, 'Dn value is incorrect.'); 31 | %! assert(abs(Am - 0) < 1e-12, 'Am value is incorrect.'); 32 | 33 | % Test the output of ellipj for some inputs 34 | %!test 35 | %! clear 36 | %! [Sn,Cn,Dn,Am] = ellipj(1000*pi/e, 0.5); 37 | %! assert(abs(Sn - (-0.893107245788960)) < 1e-10, 'Unexpected value for K'); 38 | %! assert(abs(Cn - 0.449843803468780) < 1e-10, 'Unexpected value for E'); 39 | %! assert(abs(Dn - 0.775357803700736) < 1e-10, 'Unexpected value for Z'); 40 | %! assert(abs(Am - 979.0727020334380) < 1e-10, 'Unexpected value for Z'); 41 | 42 | % Test a range of inputs 43 | %!test 44 | %! clear 45 | %! [phi,alpha] = meshgrid(0:15:90, 0:20:90); 46 | %! [Sn,Cn,Dn,Am] = ellipj(pi/180*phi, sin(pi/180*alpha).^2); 47 | %! expectedSn = [ 48 | %! 0 0.258819045102521 0.500000000000000 0.707106781186547 0.866025403784439 0.965925826289068 1.000000000000000 49 | %! 0 0.258485846933824 0.497706885957617 0.701191670697569 0.856917551601736 0.957435470313559 0.998930065167356 50 | %! 0 0.257643148029390 0.491910673808747 0.686101163281922 0.832760104716736 0.931740623632570 0.986257941725294 51 | %! 0 0.256686588523966 0.485337929842327 0.668765263011419 0.803518357767476 0.895471762681560 0.953740968539957 52 | %! 0 0.256063227340115 0.481058968307780 0.657362920250267 0.783511105160983 0.868007911876281 0.922112134755733 53 | %! ]; 54 | %! assert(norm(Sn-expectedSn) < 1e-12, 'Sn value is incorrect.') 55 | %! expectedCn = [ 56 | %! 1.000000000000000e+00 9.659258262890683e-01 8.660254037844387e-01 7.071067811865476e-01 5.000000000000001e-01 2.588190451025207e-01 6.123233995736766e-17 57 | %! 1.000000000000000e+00 9.660150448802045e-01 8.673452920667593e-01 7.129728192184835e-01 5.154534991217790e-01 2.886473976765673e-01 4.624635017752995e-02 58 | %! 1.000000000000000e+00 9.662401400653494e-01 8.706456736198857e-01 7.275061468765697e-01 5.536340018389138e-01 3.631245107023065e-01 1.652128093816774e-01 59 | %! 1.000000000000000e+00 9.664946949010781e-01 8.743266516905247e-01 7.434736195651245e-01 5.952799750795065e-01 4.451183238645416e-01 3.006296141907273e-01 60 | %! 1.000000000000000e+00 9.666600351748098e-01 8.766882393477478e-01 7.535741443813213e-01 6.213777821015289e-01 4.965503649381184e-01 3.869227454366375e-01 61 | %! ]; 62 | %! assert(norm(Cn-expectedCn) < 1e-12, 'Cn value is incorrect.') 63 | %! expectedDn = [ 64 | %! 1.000000000000000 1.000000000000000 1.000000000000000 1.000000000000000 1.000000000000000 1.000000000000000 1.000000000000000 65 | %! 1.000000000000000 0.996084402831102 0.985405086075562 0.970816956928179 0.956086982289571 0.944864274158146 0.939825731105263 66 | %! 1.000000000000000 0.986191353863528 0.948694523992923 0.897498589139304 0.844669691993763 0.800815347517021 0.773370440262088 67 | %! 1.000000000000000 0.974978972313735 0.907378267533598 0.815208419511201 0.718170374317956 0.631345976212714 0.563723002631921 68 | %! 1.000000000000000 0.967682154467076 0.880659052891909 0.762170705697972 0.636098566344953 0.518923108487193 0.418746481137913 69 | %! ]; 70 | %! assert(norm(Dn-expectedDn) < 1e-12, 'Dn value is incorrect.') 71 | %! expectedAm = [ 72 | %! 0 0.261799387799149 0.523598775598299 0.785398163397448 1.047197551196598 1.308996938995747 1.570796326794897 73 | %! 0 0.261454451605330 0.520952933355633 0.777067537031822 1.029259540311595 1.277982525206070 1.524533476028350 74 | %! 0 0.260582207755167 0.514282943954731 0.756116234361404 0.984074582906969 1.199177202994081 1.404822544814828 75 | %! 0 0.259592357093799 0.506749629200109 0.732546776612366 0.933182286603689 1.109489934513660 1.265443589210165 76 | %! 0 0.258947441141085 0.501862231566958 0.717313966340025 0.900296375458400 1.051176287337344 1.173504260529473 77 | %! ]; 78 | %! assert(norm(Am-expectedAm) < 1e-12, 'Dn value is incorrect.') 79 | -------------------------------------------------------------------------------- /jacobiThetaEta.m: -------------------------------------------------------------------------------- 1 | function [Th,H] = jacobiThetaEta(u,m,tol) 2 | %JACOBITHETAETA evaluates Jacobi's theta and eta functions. 3 | % [Th, H] = JACOBITHETAETA(U,M) returns the values of the Jacobi's 4 | % theta and eta elliptic functions TH and H evaluated for corresponding 5 | % elements of argument U and parameter M. The arrays U and M must 6 | % be the same size (or either can be scalar). As currently 7 | % implemented, M is limited to 0 <= M <= 1. 8 | % 9 | % [Th, H] = JACOBITHETAETA(U,M,TOL) computes the theta and eta 10 | % elliptic functions to the accuracy TOL instead of the default TOL = EPS. 11 | % 12 | % Some definitions of the Jacobi elliptic functions use the modulus 13 | % k instead of the parameter m. They are related by m = k^2. 14 | % 15 | % Example: 16 | % [phi,alpha] = meshgrid(0:5:90, 0:2:90); 17 | % [Th, H] = jacobiThetaEta(pi/180*phi, sin(pi/180*alpha).^2); 18 | % 19 | % See also 20 | % Standard: ELLIPKE, ELLIPJ, 21 | % Moiseev's package: ELLIPTIC12, ELLIPTIC12I, THETA. 22 | % 23 | % ELLIPJ uses the method of the arithmetic-geometric mean 24 | % described in [1]. 25 | % 26 | % References: 27 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical 28 | % Functions" Dover Publications", 1965, Ch. 16-17.6. 29 | 30 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 31 | % http://www.gnu.org/licenses/gpl.html 32 | % Everyone is permitted to copy and distribute verbatim copies of this 33 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 34 | % 35 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 36 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 37 | % For support, please reply to 38 | % moiseev.igor[at]gmail.com, moiseev[at]sissa.it 39 | % Moiseev Igor, 40 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 41 | 42 | if nargin<3, tol = eps; end 43 | if nargin<2, error('Not enough input arguments.'); end 44 | 45 | if ~isreal(u) | ~isreal(m) 46 | error('Input arguments must be real.') 47 | end 48 | 49 | if length(m)==1, m = m(ones(size(u))); end 50 | if length(u)==1, u = u(ones(size(m))); end 51 | if ~isequal(size(m),size(u)), error('U and M must be the same size.'); end 52 | 53 | Th = zeros(size(u)); 54 | H = Th; 55 | m = m(:).'; % make a row vector 56 | u = u(:).'; 57 | 58 | if any(m < 0) | any(m > 1), 59 | error('M must be in the range 0 <= M <= 1.'); 60 | end 61 | 62 | KK = ellipke(m); 63 | period_condition = u./KK/2-floor(u./KK/2); 64 | 65 | I_odd = uint32( find( abs(m-1) > 10*eps & abs(m) > 10*eps & abs(period_condition - 0.5) < 10*eps ) ); 66 | % here we cheat, add some disturbance to avoid the AGM algorithm divergence 67 | % when the inputs are the ratios of complete elliptic integrals 68 | if ( ~isempty(I_odd) ) 69 | u(I_odd) = u(I_odd) + 100000*eps; 70 | m(I_odd) = m(I_odd) + 10000*eps; 71 | end 72 | 73 | I = uint32( find( abs(m-1) > 10*eps & ... 74 | abs(m) > 10*eps ... 75 | ) ... 76 | ); 77 | % abs(period_condition - 0.5) > 10*eps ... % odd period 78 | % abs(period_condition) > 10*eps ... % even period 79 | 80 | if ~isempty(I) 81 | % Use standard uniquetol for numerical precision issues 82 | % This is the recommended MATLAB approach since R2015a 83 | m_vals = m(I); 84 | tol_unique = 1e-11; 85 | 86 | [mu, ~, K] = uniquetol(m_vals, tol_unique); 87 | K = uint32(K(:).'); % Ensure K is a row vector 88 | 89 | % pre-allocate space and augment if needed 90 | chunk = 7; 91 | a = zeros(chunk,length(mu)); 92 | c = a; 93 | b = a; 94 | a(1,:) = ones(1,length(mu)); 95 | c(1,:) = sqrt(mu); 96 | b(1,:) = sqrt(1-mu); 97 | n = uint32( zeros(1,length(mu)) ); 98 | i = 1; 99 | 100 | % Arithmetic-Geometric Mean of A, B and C 101 | while any(abs(c(i,:)) > tol) 102 | i = i + 1; 103 | if i > size(a,1) 104 | a = [a; zeros(2,length(mu))]; 105 | b = [b; zeros(2,length(mu))]; 106 | c = [c; zeros(2,length(mu))]; 107 | end 108 | a(i,:) = 0.5 * (a(i-1,:) + b(i-1,:)); 109 | b(i,:) = sqrt(a(i-1,:) .* b(i-1,:)); 110 | c(i,:) = 0.5 * (a(i-1,:) - b(i-1,:)); 111 | in = uint32( find((abs(c(i,:)) <= tol) & (abs(c(i-1,:)) > tol)) ); 112 | if ~isempty(in) 113 | [mi,ni] = size(in); 114 | n(in) = ones(mi,ni)*(i-1); 115 | end 116 | end 117 | 118 | mmax = length(I); 119 | phin = zeros(1,mmax); 120 | prodth = ones(i,mmax); 121 | 122 | % Calculate phin 123 | phin(:) = (2 .^ double(n(K))).*a(i,K).*u(I); 124 | phin_pred = phin; 125 | while i > 1 126 | i = i - 1; 127 | in = uint32( find(n(K) >= i) ); 128 | if ~isempty(in) 129 | phin(in) = 0.5*(asin(c(i+1,K(in)).*sin(phin(in))./a(i+1,K(in))) + phin(in)); 130 | prodth(i,in) = ( sec(2*phin(in)-phin_pred(in)) ).^(1/2^(i+1)); 131 | if (i > 1) 132 | phin_pred = phin; 133 | end 134 | end 135 | end 136 | 137 | th_save = sqrt(2*sqrt(1-m(I)).* KK(I)/pi.* cos(phin_pred - phin)./cos(phin) ).* prod(prodth,1); 138 | Th(I) = th_save; 139 | H(I) = sqrt(sqrt(m(I))).* sin(phin).* th_save; 140 | end 141 | 142 | % special values of u = (2n+1)*KK, odd periods 143 | % I_odd = uint32( find( abs(m-1) > 10*eps & abs(m) > 10*eps & abs(period_condition - 0.5) < 10*eps ) ); 144 | % if ( ~isempty(I_odd) ) 145 | % Th(I_odd) = 1+2*(1./(1-exp(-pi*ellipke(1-m(I_odd))./KK(I_odd)))-1); 146 | % Th(I_odd) = sqrt(KK(I_odd)./ellipke(1-m(I_odd))); 147 | % H(I_odd) = (-1).^(floor(u(I_odd)./KK(I_odd)/2)).* sqrt(sqrt(m(I_odd))).* Th(I_odd); 148 | % end 149 | 150 | % Special cases: m = {0, 1} 151 | m0 = find(abs(m) < 10*eps); 152 | 153 | if ( ~isempty(m0) ) 154 | Th(m0) = 1; 155 | H(m0) = sqrt(sqrt(m(m0))).* sin(u(m0)); 156 | end 157 | 158 | m1 = find(abs(m-1) < 10*eps); 159 | if ( ~isempty(m0) ) 160 | Th(m1) = NaN; 161 | H(m1) = NaN; 162 | end -------------------------------------------------------------------------------- /elliptic12.m: -------------------------------------------------------------------------------- 1 | function [F,E,Z] = elliptic12(u,m,tol) 2 | % ELLIPTIC12 evaluates the value of the Incomplete Elliptic Integrals 3 | % of the First, Second Kind and Jacobi's Zeta Function. 4 | % 5 | % [F,E,Z] = ELLIPTIC12(U,M,TOL) where U is a phase in radians, 0 1), error('M must be in the range 0 <= M <= 1.'); end 65 | 66 | % check whether we've been asked to evaluate the integrals for values 67 | % smaller than eps = 2.220446049250313e-16, if so we suppose it equal zero 68 | m(m tol) % Arithmetic-Geometric Mean of A, B and C 93 | i = i + 1; 94 | if i > size(a,1) 95 | a = [a; zeros(2,mumax)]; 96 | b = [b; zeros(2,mumax)]; 97 | c = [c; zeros(2,mumax)]; 98 | end 99 | a(i,:) = 0.5 * (a(i-1,:) + b(i-1,:)); 100 | b(i,:) = sqrt(a(i-1,:) .* b(i-1,:)); 101 | c(i,:) = 0.5 * (a(i-1,:) - b(i-1,:)); 102 | in = uint32( find((abs(c(i,:)) <= tol) & (abs(c(i-1,:)) > tol)) ); 103 | if ~isempty(in) 104 | [mi,ni] = size(in); 105 | n(in) = ones(mi,ni)*(i-1); 106 | end 107 | end 108 | 109 | mmax = length(I); 110 | mn = double(max(n)); 111 | phin = zeros(1,mmax); C = zeros(1,mmax); 112 | Cp = C; e = uint32(C); phin(:) = signU.*u(I); 113 | i = 0; c2 = c.^2; 114 | while i < mn % Descending Landen Transformation 115 | i = i + 1; 116 | in = uint32(find(n(K) > i)); 117 | if ~isempty(in) 118 | phin(in) = atan(b(i,K(in))./a(i,K(in)).*tan(phin(in))) + ... 119 | pi.*ceil(phin(in)/pi - 0.5) + phin(in); 120 | e(in) = 2.^(i-1) ; 121 | C(in) = C(in) + double(e(in(1)))*c2(i,K(in)); 122 | Cp(in)= Cp(in) + c(i+1,K(in)).*sin(phin(in)); 123 | end 124 | end 125 | 126 | Ff = phin ./ (a(mn,K).*double(e)*2); 127 | F(I) = Ff.*signU; % Incomplete Ell. Int. of the First Kind 128 | Z(I) = Cp.*signU; % Jacobi Zeta Function 129 | E(I) = (Cp + (1 - 1/2*C) .* Ff).*signU; % Incomplete Ell. Int. of the Second Kind 130 | end 131 | 132 | % Special cases: m == {0, 1} 133 | m0 = find(m == 0); 134 | if ~isempty(m0), F(m0) = u(m0); E(m0) = u(m0); Z(m0) = 0; end 135 | 136 | m1 = find(m == 1); 137 | um1 = abs(u(m1)); 138 | if ~isempty(m1), 139 | N = floor( (um1+pi/2)/pi ); 140 | M = find(um1 < pi/2); 141 | 142 | F(m1(M)) = log(tan(pi/4 + u(m1(M))/2)); 143 | F(m1(um1 >= pi/2)) = Inf.*sign(u(m1(um1 >= pi/2))); 144 | 145 | E(m1) = ((-1).^N .* sin(um1) + 2*N).*sign(u(m1)); 146 | 147 | Z(m1) = (-1).^N .* sin(u(m1)); 148 | end -------------------------------------------------------------------------------- /wiki/Elliptic-Integrals.md: -------------------------------------------------------------------------------- 1 | # Elliptic integrals, numerical methods, Matlab examples of usage and problem solving. 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | # Elliptic Integrals 10 | 11 | If `R(x,y)` is a rational function of `x` and `y`, where `y`^2^ is equal to a cubic or quadratic polynomial in `x`, the integral 12 | 13 | ``` 14 | f(x) = Integral(R(x,y))dx 15 | ``` 16 | 17 | is called an **elliptic integral**. 18 | Elliptic integrals originally arose in the connection with the problem of giving the arc length of an ellipse. They were first studied by Giulio Fagnano and Leonhard Euler. 19 | 20 | In general, elliptic integrals cannot be expressed in terms of elementary functions. Exceptions to this general rule are when `P` has repeated roots, or when `R(x,y)` contains no odd powers of `y`. However, with the appropriate reduction formula, every elliptic integral can be brought into a form that involves integrals over rational functions and the three canonical forms (i.e. the elliptic integrals of the first, second and third kind). 21 | 22 | Elliptic integrals have many applications, for example in mathematics and physics 23 | 24 | - arc-length of plane curves (ellipse, hyperbola, Bernoulli's lemniscate) 25 | - surface area of ellipsoid in 3-dimensional space 26 | - electric and magnetic field associated with ellipsoid 27 | - periodicity of an anharmonic oscillator 28 | - mutual inductance of coaxial circles 29 | - age of the universe in the Friedman model 30 | - [Euler's three-body problem](http://en.wikipedia.org/wiki/Euler's_three-body_problem#Mathematical_solutions) 31 | - [and many others](http://arxiv.org/find/all/1/all:+AND+elliptic+integral/0/1/0/all/0/1). 32 | 33 | # Elliptic Integral of the First Kind 34 | 35 | ## Definition 36 | 37 | There are known different ways of noting the elliptic integral of the first kind, we follow here the Abramowitz et al notions. 38 | 39 | http://latex.codecogs.com/gif.latex?\begin{aligned}F(\varphi\backslash\alpha)=F(\varphi|m)=\int^\varphi_0\frac{d\theta}{\sqrt{1-\sin^2\alpha\sin^2\theta}}=\int_0^x\frac{dt}{\sqrt{(1-t^2)(1-mt^2)}}=\int_0^udw=u\end{aligned}%.png 40 | 41 | http://latex.codecogs.com/gif.latex?\mbox{where\,}m=\sin^2\alpha%.png 42 | 43 | 44 | where `m=sin`^2^`alpha` and `m` is the parameter, `alpha` is the modular angle. 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | ## Numerical evaluation 60 | 61 | Numerical evaluation of the elliptic integrals are based on various expansion in terms of elementary and transcendental functions. 62 | 63 | [The On-Line Encyclopedia of Integer Sequences](http://www.research.att.com/~njas/sequences/) 64 | 65 | ### The arithmetic-geometric mean 66 | 67 | The arithmetic-geometric mean (AGM) of two positive real numbers x and y is defined as follows: 68 | First compute the arithmetic mean of x and y and call it a1. Next compute the geometric mean of x and y and call it g1; this is the square root of the product xy: 69 | 70 | 71 | Then iterate this operation with a1 taking the place of x and g1 taking the place of y. In this way, two sequences (an) and (gn) are defined: 72 | 73 | 74 | These two sequences converge to the same number, which is the arithmetic-geometric mean of x and y; it is denoted by M(x, y), or sometimes by agm(x, y). 75 | This can be used for algorithmic purposes as in the AGM method. 76 | 77 | ### Landen's Transformation 78 | 79 | [Landen's transformation](http://en.wikipedia.org/wiki/Landen's_transformation), independently rediscovered by Gauss, is a mapping of the parameters of an elliptic integral, which leaves the value of the integral unchanged. 80 | 81 | ### Reduction and Computation of Elliptic Integrals by B. Carlson 82 | 83 | The conventional methods for computing elliptic integrals are Gauss and Landen transformations, which converge quadratically and work well for elliptic integrals of the first and second kinds. Unfortunately they suffer from loss of significant digits for the third kind. Carlson's algorithm, by contrast, provides a unified method for all three kinds of elliptic integrals with satisfactory precisions. 84 | 85 | 86 | 87 | 88 | # Elliptic Integral of the Second Kind 89 | 90 | Elliptic integral of the second kind ... is to appear 91 | 92 | ## Definition 93 | 94 | ## Numerical evaluation 95 | 96 | [Sequence A120362](http://www.research.att.com/~njas/sequences/A120362) represents the numerators of bivariate Taylor expansion of the incomplete elliptic integral of the second kind. 97 | 98 | # Elliptic Integral of the Third Kind 99 | 100 | Elliptic integral of the first kind ... 101 | 102 | ## Definition 103 | 104 | ## Numerical evaluation 105 | 106 | # Examples 107 | 108 | ## M. Abramowitz and I.A. Stegun Mathematical tables generation for elliptic integrals 109 | 110 | ## Conversion between differently defined elliptic integrals 111 | 112 | ## Elliptic integrals and derivatives 113 | 114 | # Problem Solving with Elliptic Integrals 115 | 116 | ## Period of the physical pendulum 117 | 118 | ## Complex arguments and visualisations 119 | 120 | 121 | 122 | # References 123 | 124 | 1. M. Abramowitz and I.A. Stegun, "[Handbook of Mathematical Functions](http://www.math.ucla.edu/~cbm/aands/)" Dover Publications", 1965, Ch. 17.1 - 17.6. 125 | 1. D. F. Lawden, "[Elliptic Functions and Applications](http://www.amazon.com/Elliptic-Functions-Applications-Mathematical-Sciences/dp/0387969659)" Springer-Verlag, vol. 80, 1989 126 | 1. S. Zhang, J. Jin, "[Computation of Special Functions](http://jin.ece.uiuc.edu/specfunc.html)" (Wiley, 1996). 127 | 1. B. Carlson, "[Three Improvements in Reduction and Computation of Elliptic Integrals](http://nvl.nist.gov/pub/nistpubs/jres/107/5/j75car.pdf)", J. Res. Natl. Inst. Stand. Technol. 107 (2002) 413-418. 128 | 129 | # Wiki references 130 | 131 | 1. [Landen's transformation](http://en.wikipedia.org/wiki/Landen's_transformation): Landen's-Gauss transformation used in the elliptic integral numerical evaluations. 132 | 1. [Elliptic integral](http://en.wikipedia.org/wiki/Elliptic_integral): the wiki community article on the theoretical aspects of elliptic intergral 133 | # External Links 134 | 135 | - [ALGLIB](http://www.alglib.net/) - Cross-platform numerical analysis and data processing library. 136 | - [Boost C++ Library](http://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/ellint/ellint_intro.htmlhttp://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/ellint/ellint_intro.html) - Elliptic Integral Overview. -------------------------------------------------------------------------------- /arclength_ellipse.m: -------------------------------------------------------------------------------- 1 | function [arclength] = arclength_ellipse(a, b, theta0, theta1) 2 | %ARCLENGTH_ELLIPSE Calculates the arclength of ellipse. 3 | % 4 | % ARCLENGTH_ELLIPSE(A, B, THETA0, THETA1) Calculates the arclength of ellipse 5 | % using the precise formulas based on the representation of 6 | % the arclength by the Elliptic integral of the second kind. 7 | % 8 | % Ellipse parameters: 9 | % T - measured in radians from 0 in the positive direction, 10 | % Period: 2*Pi 11 | % A - major axis 12 | % B - minor axis 13 | % 14 | % Parametric equations: 15 | % x(t) = a.cos(t) 16 | % y(t) = b.sin(t) 17 | % 18 | % Cartesian equation: 19 | % x^2/a^2 + y^2/b^2 = 1 20 | % 21 | % Eccentricity: 22 | % e = Sqrt(1 - (a/b)^2) 23 | % 24 | % Focal parameter: 25 | % b^2/Sqrt(a^2 - b^2) 26 | % 27 | % Foci: 28 | % (-Sqrt(a^2 - b^2), 0) OR (Sqrt(a^2 - b^2), 0) 29 | % 30 | % Arclength: 31 | % b*EllipticE( t, 1 - (a/b)^2 ) 32 | % 33 | % Mathematica Test 1: 34 | % In:= b = 10; a = 5; 35 | % SetPrecision[b*EllipticE[2Pi, 1.0- a^2/b^2],20] 36 | % Out:= 48.442241102738385905 37 | % 38 | % Mathematica Test 2: 39 | % In:= b = 10; a = 5; 40 | % SetPrecision[b*(EllipticE[Pi/2-Pi/10, 1.0- a^2/b^2]-EllipticE[Pi/10, 1.0- a^2/b^2]),20] 41 | % Out:= 7.3635807913930495516 42 | % 43 | % MATLAB Test 1: 44 | % % full ellipse 45 | % arclength = arclength_ellipse(5,10) 46 | % arclength = 47 | % 48.442241102738436 48 | % 49 | % MATLAB Test 2: 50 | % % arclength ellipse 51 | % arclength = arclength_ellipse(5,10,pi/10,pi/2) 52 | % arclength = 53 | % 7.363580791393055 54 | % 55 | % References: 56 | % @see http://mathworld.wolfram.com/Ellipse.html 57 | % @see http://www.wolframalpha.com/input/?i=ellipse+arc+length&lk=1&a=ClashPrefs_*PlaneCurve.Ellipse.PlaneCurveProperty.ArcLength- 58 | % 59 | 60 | % Special thanks to for bug correction 61 | % drbitboy (Brian Carcich) https://github.com/drbitboy 62 | % 2015-07-14 (New Horizons flyby of Pluto) 63 | % 64 | % 1) Old code returned values that were in error 65 | % 1.1) arclength_ellipse(1., .5, pi*.001, pi*.002) returned 0 66 | % 1.2) arclength_ellipse(1., .5, pi*.002, pi*.001) returned -.0003*pi instead of pi correct .0005*pi 67 | % 1.3) arclength_ellipse(1., .5, theta0, theta1) did not return the negative of the same call with the thetas reversed 68 | % 2) Angles theta0 and theta1 were always interpreted as measured from the semi-minor axis 69 | % 70 | % 3) Corrected code: 71 | % 3.1) Angle theta is measured from the positive a axis 72 | % 3.2) The standard form of the b*E(phi,m) arc length integral has m = 1 - (a/b)^2 73 | % 3.2.1) N.B. That only only works if b>a 74 | % 3.3) If a>b, then an alternate formula is used: a*E(PI/2 - phi, m') where m' = 1 - (b/a)^2 75 | % 3.4) A few simple cases will show that the new code is correct 76 | % arclength_ellipse(1, .5, pi*.001, pi*.002) ~ pi*.0005 77 | % arclength_ellipse(1, .5, pi*.002, pi*.001) = -arclength(1, .5, pi*.001, pi*.002) ~ -pi*.0005 78 | % arclength_ellipse(1., 2., pi*.001, pi*.002) ~ pi*.002 79 | % arclength_ellipse(1, .5, pi/2 - pi*.002, pi/2 - pi*.001) ~ -pi*.001 80 | % arclength_ellipse(1, 2., pi/2 - pi*.002, pi/2 - pi*.001) ~ -pi*.001 81 | % etc. 82 | 83 | % Copyright Elliptic Project 2011 84 | % For support, 85 | % moiseev.igor[at]gmail.com 86 | % Moiseev Igor 87 | 88 | %arguments 89 | if nargin ~= 2 && nargin ~= 4, 90 | error('ARCLENGTH_ELLIPSE: Requires two or four inputs.') 91 | return 92 | end 93 | 94 | if nargin == 2, 95 | theta0 = 0; 96 | theta1 = 2*pi; 97 | end 98 | 99 | % Default solution for a==b (circles) 100 | arclength = a.*(theta1-theta0); 101 | 102 | % Ellipses (ab) 103 | if(ab) 110 | % Theta measured from a axis = semi-MAJOR axis 111 | % Standard formulation will not work ((1-(a/b)^2) < 0); instead use PI/2 - phi and b/a instead of a/b 112 | [F1, E1] = elliptic12( pi/2 - theta1, 1 - (b./a).^2 ); 113 | [F0, E0] = elliptic12( pi/2 - theta0, 1 - (b./a).^2 ); 114 | % d(PI/2 - phi)/dphi = -1, so reverse operands in this difference to flip sign: 115 | arclength = a.*(E0 - E1); 116 | end 117 | 118 | return; 119 | 120 | 121 | 122 | function [F,E,Z] = elliptic12(u,m,tol) 123 | % ELLIPTIC12 evaluates the value of the Incomplete Elliptic Integrals 124 | % of the First, Second Kind and Jacobi's Zeta Function. 125 | % 126 | % [F,E,Z] = ELLIPTIC12(U,M,TOL) where U is a phase in radians, 0 1), error('M must be in the range 0 <= M <= 1.'); end 179 | 180 | I = uint32( find(m ~= 1 & m ~= 0) ); 181 | if ~isempty(I) 182 | % Use standard uniquetol for numerical precision issues 183 | % This is the recommended MATLAB approach since R2015a 184 | m_vals = m(I); 185 | tol_unique = 1e-11; 186 | 187 | [mu, ~, K] = uniquetol(m_vals, tol_unique); 188 | K = uint32(K(:).'); % Ensure K is a row vector 189 | mumax = length(mu); 190 | signU = sign(u(I)); 191 | 192 | % pre-allocate space and augment if needed 193 | chunk = 7; 194 | a = zeros(chunk,mumax); 195 | c = a; 196 | b = a; 197 | a(1,:) = ones(1,mumax); 198 | c(1,:) = sqrt(mu); 199 | b(1,:) = sqrt(1-mu); 200 | n = uint32( zeros(1,mumax) ); 201 | i = 1; 202 | while any(abs(c(i,:)) > tol) % Arithmetic-Geometric Mean of A, B and C 203 | i = i + 1; 204 | if i > size(a,1) 205 | a = [a; zeros(2,mumax)]; 206 | b = [b; zeros(2,mumax)]; 207 | c = [c; zeros(2,mumax)]; 208 | end 209 | a(i,:) = 0.5 * (a(i-1,:) + b(i-1,:)); 210 | b(i,:) = sqrt(a(i-1,:) .* b(i-1,:)); 211 | c(i,:) = 0.5 * (a(i-1,:) - b(i-1,:)); 212 | in = uint32( find((abs(c(i,:)) <= tol) & (abs(c(i-1,:)) > tol)) ); 213 | if ~isempty(in) 214 | [mi,ni] = size(in); 215 | n(in) = ones(mi,ni)*(i-1); 216 | end 217 | end 218 | 219 | mmax = length(I); 220 | mn = double(max(n)); 221 | phin = zeros(1,mmax); C = zeros(1,mmax); 222 | Cp = C; e = uint32(C); phin(:) = signU.*u(I); 223 | i = 0; c2 = c.^2; 224 | while i < mn % Descending Landen Transformation 225 | i = i + 1; 226 | in = uint32(find(n(K) > i)); 227 | if ~isempty(in) 228 | phin(in) = atan(b(i,K(in))./a(i,K(in)).*tan(phin(in))) + ... 229 | pi.*ceil(phin(in)/pi - 0.5) + phin(in); 230 | e(in) = 2.^(i-1) ; 231 | C(in) = C(in) + double(e(in(1)))*c2(i,K(in)); 232 | Cp(in)= Cp(in) + c(i+1,K(in)).*sin(phin(in)); 233 | end 234 | end 235 | 236 | Ff = phin ./ (a(mn,K).*double(e)*2); 237 | F(I) = Ff.*signU; % Incomplete Ell. Int. of the First Kind 238 | Z(I) = Cp.*signU; % Jacobi Zeta Function 239 | E(I) = (Cp + (1 - 1/2*C) .* Ff).*signU; % Incomplete Ell. Int. of the Second Kind 240 | end 241 | 242 | % Special cases: m == {0, 1} 243 | m0 = find(m == 0); 244 | if ~isempty(m0), F(m0) = u(m0); E(m0) = u(m0); Z(m0) = 0; end 245 | 246 | m1 = find(m == 1); 247 | um1 = abs(u(m1)); 248 | if ~isempty(m1), 249 | N = floor( (um1+pi/2)/pi ); 250 | M = find(um1 < pi/2); 251 | 252 | F(m1(M)) = log(tan(pi/4 + u(m1(M))/2)); 253 | F(m1(um1 >= pi/2)) = Inf.*sign(u(m1(um1 >= pi/2))); 254 | 255 | E(m1) = ((-1).^N .* sin(um1) + 2*N).*sign(u(m1)); 256 | 257 | Z(m1) = (-1).^N .* sin(u(m1)); 258 | end 259 | return; 260 | -------------------------------------------------------------------------------- /tests/testThetaPrime.m: -------------------------------------------------------------------------------- 1 | %Test function for theta_prime.m 2 | 3 | % Test error handling - invalid j parameter 4 | %!test 5 | %! clear 6 | %! try 7 | %! theta_prime(0, 0.5, 0.8); % j must be 1,2,3,4 8 | %! assert(false, "Invalid j parameter didn't throw an error."); 9 | %! catch err 10 | %! % Verify that the error message contains the expected string 11 | %! assert(~isempty(strfind(err.message, 'J must be a scalar integer: 1, 2, 3, or 4.')), ... 12 | %! 'Unexpected error message: %s', err.message); 13 | %! end 14 | 15 | %!test 16 | %! clear 17 | %! try 18 | %! theta_prime(5, 0.5, 0.8); % j must be 1,2,3,4 19 | %! assert(false, "Invalid j parameter didn't throw an error."); 20 | %! catch err 21 | %! % Verify that the error message contains the expected string 22 | %! assert(~isempty(strfind(err.message, 'J must be a scalar integer: 1, 2, 3, or 4.')), ... 23 | %! 'Unexpected error message: %s', err.message); 24 | %! end 25 | 26 | % Test error handling - module out of range 27 | %!test 28 | %! clear 29 | %! try 30 | %! theta_prime(1, 0.5, 2); % module out of range 31 | %! assert(false, "Module out of range didn't throw an error."); 32 | %! catch err 33 | %! % Verify that the error message contains the expected string 34 | %! assert(~isempty(strfind(err.message, 'M must be in the range 0 <= M <= 1')), ... 35 | %! 'Unexpected error message: %s', err.message); 36 | %! end 37 | 38 | %!test 39 | %! clear 40 | %! try 41 | %! theta_prime(1, 0.5, -0.1); % module out of range 42 | %! assert(false, "Module out of range didn't throw an error."); 43 | %! catch err 44 | %! % Verify that the error message contains the expected string 45 | %! assert(~isempty(strfind(err.message, 'M must be in the range 0 <= M <= 1')), ... 46 | %! 'Unexpected error message: %s', err.message); 47 | %! end 48 | 49 | % Test error handling - complex input 50 | %!test 51 | %! clear 52 | %! try 53 | %! theta_prime(1, 0.5i, 0.8); % complex input 54 | %! assert(false, "Complex input didn't throw an error."); 55 | %! catch err 56 | %! % Verify that the error message contains the expected string 57 | %! assert(~isempty(strfind(err.message, 'Input arguments must be real')), ... 58 | %! 'Unexpected error message: %s', err.message); 59 | %! end 60 | 61 | %!test 62 | %! clear 63 | %! try 64 | %! theta_prime(1, 0.5, 0.8i); % complex input 65 | %! assert(false, "Complex input didn't throw an error."); 66 | %! catch err 67 | %! % Verify that the error message contains the expected string 68 | %! assert(~isempty(strfind(err.message, 'Input arguments must be real')), ... 69 | %! 'Unexpected error message: %s', err.message); 70 | %! end 71 | 72 | % Test error handling - insufficient arguments 73 | %!test 74 | %! clear 75 | %! try 76 | %! theta_prime(1, 0.5); % not enough arguments 77 | %! assert(false, "Insufficient arguments didn't throw an error."); 78 | %! catch err 79 | %! % Verify that the error message contains the expected string 80 | %! assert(~isempty(strfind(err.message, 'Not enough input arguments')), ... 81 | %! 'Unexpected error message: %s', err.message); 82 | %! end 83 | 84 | % Test simple inputs - theta function values at z=0 85 | %!test 86 | %! clear 87 | %! [th1, thp1] = theta_prime(1, 0, 0.5); 88 | %! [th2, thp2] = theta_prime(2, 0, 0.5); 89 | %! [th3, thp3] = theta_prime(3, 0, 0.5); 90 | %! [th4, thp4] = theta_prime(4, 0, 0.5); 91 | %! 92 | %! % At z=0: θ₁(0) = 0, θ₂(0) = 2q^(1/4), θ₃(0) = θ₃(0), θ₄(0) = θ₄(0) 93 | %! assert(abs(th1) < 1e-12, 'θ₁(0) should be zero.'); 94 | %! assert(th2 > 0, 'θ₂(0) should be positive.'); 95 | %! assert(th3 > 0, 'θ₃(0) should be positive.'); 96 | %! assert(th4 > 0, 'θ₄(0) should be positive.'); 97 | 98 | % Test specific values with known results 99 | %!test 100 | %! clear 101 | %! j = 1; z = 0.5; m = 0.5; 102 | %! [th, thp] = theta_prime(j, z, m); 103 | %! 104 | %! % Verify using numerical differentiation 105 | %! dz = 1e-8; 106 | %! th_plus = theta(j, z + dz, m); 107 | %! th_minus = theta(j, z - dz, m); 108 | %! thp_numerical = (th_plus - th_minus) / (2 * dz); 109 | %! 110 | %! % The derivative should match numerical differentiation within tolerance 111 | %! assert(abs(thp - thp_numerical) < 1e-6, ... 112 | %! 'Analytical derivative does not match numerical differentiation for θ₁.'); 113 | 114 | %!test 115 | %! clear 116 | %! j = 2; z = 0.3; m = 0.7; 117 | %! [th, thp] = theta_prime(j, z, m); 118 | %! 119 | %! % Verify using numerical differentiation 120 | %! dz = 1e-8; 121 | %! th_plus = theta(j, z + dz, m); 122 | %! th_minus = theta(j, z - dz, m); 123 | %! thp_numerical = (th_plus - th_minus) / (2 * dz); 124 | %! 125 | %! % The derivative should match numerical differentiation within tolerance 126 | %! assert(abs(thp - thp_numerical) < 1e-6, ... 127 | %! 'Analytical derivative does not match numerical differentiation for θ₂.'); 128 | 129 | %!test 130 | %! clear 131 | %! j = 3; z = 0.2; m = 0.9; 132 | %! [th, thp] = theta_prime(j, z, m); 133 | %! 134 | %! % Verify using numerical differentiation 135 | %! dz = 1e-8; 136 | %! th_plus = theta(j, z + dz, m); 137 | %! th_minus = theta(j, z - dz, m); 138 | %! thp_numerical = (th_plus - th_minus) / (2 * dz); 139 | %! 140 | %! % The derivative should match numerical differentiation within tolerance 141 | %! assert(abs(thp - thp_numerical) < 1e-6, ... 142 | %! 'Analytical derivative does not match numerical differentiation for θ₃.'); 143 | 144 | %!test 145 | %! clear 146 | %! j = 4; z = 0.4; m = 0.3; 147 | %! [th, thp] = theta_prime(j, z, m); 148 | %! 149 | %! % Verify using numerical differentiation 150 | %! dz = 1e-8; 151 | %! th_plus = theta(j, z + dz, m); 152 | %! th_minus = theta(j, z - dz, m); 153 | %! thp_numerical = (th_plus - th_minus) / (2 * dz); 154 | %! 155 | %! % The derivative should match numerical differentiation within tolerance 156 | %! assert(abs(thp - thp_numerical) < 1e-6, ... 157 | %! 'Analytical derivative does not match numerical differentiation for θ₄.'); 158 | 159 | % Test array inputs with scalar j and m 160 | %!test 161 | %! clear 162 | %! j = 1; 163 | %! z = [0.1, 0.2, 0.3, 0.4, 0.5]; 164 | %! m = 0.6; 165 | %! [th, thp] = theta_prime(j, z, m); 166 | %! 167 | %! assert(length(th) == length(z), 'Output size mismatch for array z input.'); 168 | %! assert(length(thp) == length(z), 'Output size mismatch for array z input.'); 169 | %! 170 | %! % Verify each element using numerical differentiation 171 | %! for i = 1:length(z) 172 | %! dz = 1e-8; 173 | %! th_plus = theta(j, z(i) + dz, m); 174 | %! th_minus = theta(j, z(i) - dz, m); 175 | %! thp_numerical = (th_plus - th_minus) / (2 * dz); 176 | %! assert(abs(thp(i) - thp_numerical) < 1e-6, ... 177 | %! 'Analytical derivative does not match numerical differentiation at z(%d).', i); 178 | %! end 179 | 180 | % Test array inputs with scalar j and z 181 | %!test 182 | %! clear 183 | %! j = 2; 184 | %! z = 0.4; 185 | %! m = [0.1, 0.3, 0.5, 0.7, 0.9]; 186 | %! [th, thp] = theta_prime(j, z, m); 187 | %! 188 | %! assert(length(th) == length(m), 'Output size mismatch for array m input.'); 189 | %! assert(length(thp) == length(m), 'Output size mismatch for array m input.'); 190 | %! 191 | %! % Verify each element using numerical differentiation 192 | %! for i = 1:length(m) 193 | %! dz = 1e-8; 194 | %! th_plus = theta(j, z + dz, m(i)); 195 | %! th_minus = theta(j, z - dz, m(i)); 196 | %! thp_numerical = (th_plus - th_minus) / (2 * dz); 197 | %! assert(abs(thp(i) - thp_numerical) < 1e-6, ... 198 | %! 'Analytical derivative does not match numerical differentiation at m(%d).', i); 199 | %! end 200 | 201 | % Test array inputs with matching array sizes 202 | %!test 203 | %! clear 204 | %! j = 3; 205 | %! z = [0.1, 0.2, 0.3, 0.4]; 206 | %! m = [0.2, 0.4, 0.6, 0.8]; 207 | %! [th, thp] = theta_prime(j, z, m); 208 | %! 209 | %! assert(length(th) == length(z), 'Output size mismatch for matched array inputs.'); 210 | %! assert(length(thp) == length(z), 'Output size mismatch for matched array inputs.'); 211 | %! 212 | %! % Verify each element using numerical differentiation 213 | %! for i = 1:length(z) 214 | %! dz = 1e-8; 215 | %! th_plus = theta(j, z(i) + dz, m(i)); 216 | %! th_minus = theta(j, z(i) - dz, m(i)); 217 | %! thp_numerical = (th_plus - th_minus) / (2 * dz); 218 | %! assert(abs(thp(i) - thp_numerical) < 1e-6, ... 219 | %! 'Analytical derivative does not match numerical differentiation at index %d.', i); 220 | %! end 221 | 222 | % Test limit cases - m approaching 0 and 1 223 | %!test 224 | %! clear 225 | %! j = 1; z = 0.5; 226 | %! 227 | %! % Test m approaching 0 228 | %! m = 1e-10; 229 | %! [th, thp] = theta_prime(j, z, m); 230 | %! assert(isfinite(th) && isfinite(thp), 'Function should remain finite as m approaches 0.'); 231 | %! 232 | %! % Test m approaching 1 233 | %! m = 1 - 1e-10; 234 | %! [th, thp] = theta_prime(j, z, m); 235 | %! assert(isfinite(th) && isfinite(thp), 'Function should remain finite as m approaches 1.'); 236 | 237 | % Test special values and symmetries 238 | %!test 239 | %! clear 240 | %! % Test θ₁ odd symmetry: θ₁(-z) = -θ₁(z) 241 | %! j = 1; z = 0.3; m = 0.5; 242 | %! [th_pos, thp_pos] = theta_prime(j, z, m); 243 | %! [th_neg, thp_neg] = theta_prime(j, -z, m); 244 | %! 245 | %! assert(abs(th_pos + th_neg) < 1e-12, 'θ₁ should satisfy odd symmetry: θ₁(-z) = -θ₁(z).'); 246 | %! assert(abs(thp_pos - thp_neg) < 1e-12, 'θ₁'' should satisfy even symmetry: θ₁''(-z) = θ₁''(z).'); 247 | 248 | % Test with tolerance parameter 249 | %!test 250 | %! clear 251 | %! j = 1; z = 0.3; m = 0.7; tol = 1e-10; 252 | %! [th, thp] = theta_prime(j, z, m, tol); 253 | %! 254 | %! % Should produce same result as default tolerance for this simple case 255 | %! [th_default, thp_default] = theta_prime(j, z, m); 256 | %! assert(abs(th - th_default) < 1e-10, 'Results with custom tolerance should be close to default.'); 257 | %! assert(abs(thp - thp_default) < 1e-10, 'Results with custom tolerance should be close to default.'); 258 | 259 | % Benchmark test 260 | %!test 261 | %! clear 262 | %! elapsedTime = []; 263 | %! mem = []; 264 | %! for i = 1:10 265 | %! z_vals = linspace(0, 1, 100); 266 | %! m_vals = linspace(0.1, 0.9, 100); 267 | %! [Z, M] = meshgrid(z_vals, m_vals); 268 | %! 269 | %! tic 270 | %! mem1 = whos(); 271 | %! [th1, thp1] = theta_prime(1, Z, M); 272 | %! [th2, thp2] = theta_prime(2, Z, M); 273 | %! [th3, thp3] = theta_prime(3, Z, M); 274 | %! [th4, thp4] = theta_prime(4, Z, M); 275 | %! mem2 = whos(); 276 | %! elapsedTime(i) = toc; 277 | %! mem(i) = sum([mem2.bytes]) - sum([mem1.bytes]); 278 | %! clear th1 th2 th3 th4 thp1 thp2 thp3 thp4 Z M; 279 | %! end 280 | % fprintf('\nAverage execution time for theta_prime calculations: %f seconds\n', mean(elapsedTime)); 281 | % fprintf('Average Mem: %f bytes\n', mean(mem)); 282 | %! assert(mean(elapsedTime) < 2.0, 'Average execution time for theta_prime calculations: %f seconds is greater than 2.0\n', mean(elapsedTime)) 283 | %! assert(mean(mem) < 1e7, 'Average memory used for theta_prime run: %f bytes is greater than 10MB\n', mean(mem)) -------------------------------------------------------------------------------- /wiki/elliptic.md: -------------------------------------------------------------------------------- 1 | # elliptic package procedures, usage example and installation requirements 2 | 3 | 4 | 5 | # Elliptic Functions 6 | 7 | **[The Jacobi's elliptic functions](http://code.google.com/p/elliptic/wiki/JacobiEllipticFunctions)** are a set of basic elliptic functions, and auxiliary theta functions, that have historical importance with also many features that show up important structure, and have direct relevance to some applications (e.g. the equation of the pendulum). They also have useful analogies to the functions of trigonometry, as indicated by the matching notation `SN` for `SIN`. They are not the simplest way to develop a general theory, as now seen: that can be said for the Weierstrass elliptic functions. They are not, however, outmoded. They were introduced by Carl Gustav Jakob Jacobi, around 1830. 8 | 9 | **[Theta functions](http://code.google.com/p/elliptic/wiki/ThetaFunctions)** are special functions of several complex variables. They are important in several areas, including the theories of abelian varieties and moduli spaces, and of quadratic forms. They have also been applied to soliton theory. When generalized to a Grassmann algebra, they also appear in quantum field theory, specifically string theory and D-branes. 10 | 11 | ## ELLIPJ: Jacobi's elliptic functions 12 | 13 | [ELLIPJ](http://code.google.com/p/elliptic/source/browse/trunk/ellipj.m) evaluates the [Jacobi's elliptic functions](http://en.wikipedia.org/wiki/Jacobi%27s_elliptic_functions) and [Jacobi's amplitude](http://mathworld.wolfram.com/JacobiAmplitude.html). 14 | 15 | `[= ELLIPJ(U,M)` returns the values of the Jacobi elliptic functions `SN`, `CN`, `DN` and `AM` evaluated for corresponding elements of argument U and parameter M. The arrays U and M must be of the same size (or either can be scalar). As currently implemented, M is limited to `0 <= M <= 1`. 16 | 17 | *General definition:* 18 | ``` 19 | u = Integral(1/sqrt(1-m^2*sin(theta)^2), 0, phi); 20 | Sn(u) = sin(phi); 21 | Cn(u) = cos(phi); 22 | Dn(u) = sqrt(1-m^2*sin(phi)^2); 23 | ``` 24 | 25 | _Depends on_ `AGM`, `ELLIPKE`.
26 | _Used by_ `THETA`.
27 | _See also_ `ELLIPKE`. 28 | 29 | 30 | ## ELLIPJI: Jacobi's elliptic functions of the complex argument 31 | 32 | [http://code.google.com/p/elliptic/source/browse/trunk/ellipji.m ELLIPJI](Sn,Cn,Dn,Am]) evaluates the Jacobi elliptic functions of complex phase `U`. 33 | 34 | `[= ELLIPJ(U,M)` returns the values of the Jacobi elliptic functions `SNI`, `CNI` and `DNI` evaluated for corresponding elements of argument `U` and parameter `M`. The arrays `U` and `M` must be of the same size (or either can be scalar). As currently implemented, `M` is real and limited to `0 <= M <= 1`. 35 | 36 | 37 | *Example: 38 | ``` 39 | [phi1,phi2](Sni,Cni,Dni]) = meshgrid(-pi:3/20:pi, -pi:3/20:pi); 40 | phi = phi1 + phi2*i; 41 | [= ellipji(phi, 0.99); 42 | ``` 43 | 44 | _Depends on_ `AGM`, `ELLIPJ`, `ELLIPKE`
45 | _See also_ `ELLIPTIC12`, `ELLIPTIC12I` 46 | 47 | ## JACOBITHETAETA: Jacobi's Theta and Eta Functions 48 | 49 | [http://code.google.com/p/elliptic/source/browse/trunk/jacobiThetaEta.m JACOBITHETAETA](Sni,Cni,Dni]) evaluates Jacobi's theta and eta functions. 50 | 51 | `[H](Th,) = JACOBITHETAETA(U,M)` returns the values of the Jacobi's theta and eta elliptic functions `TH` and `H` evaluated for corresponding elements of argument `U` and parameter `M`. The arrays `U` and `M` must be the same size (or either can be scalar). As currently implemented, `M` is real and limited to `0 <= M <= 1`. 52 | 53 | *Example: 54 | ``` 55 | [= meshgrid(0:5:90, 0:2:90); 56 | [Th, H](phi,alpha]) = jacobiThetaEta(pi/180*phi, sin(pi/180*alpha).^2); 57 | ``` 58 | 59 | *Depends on* `AGM`, `ELLIPJ`, `ELLIPKE`
60 | *See also* `ELLIPTIC12`, `ELLIPTIC12I`, `THETA` 61 | 62 | ## THETA: Theta Functions of Four Types 63 | 64 | [THETA](http://code.google.com/p/elliptic/source/browse/trunk/theta.m) evaluates theta functions of four types. 65 | 66 | `Th = THETA(TYPE,V,M)` returns values of theta functions 67 | evaluated for corresponding values of argument `V` and parameter `M`. `TYPE` is a type of the theta function, there are four numbered types. The arrays `V` and `M` must be the same size (or either can be scalar). As currently implemented, `M` is limited to `0 <= M <= 1`. 68 | 69 | `Th = THETA(TYPE,V,M,TOL)` computes the theta and eta elliptic functions to the accuracy `TOL` instead of the default `TOL = EPS`. 70 | 71 | The parameter `M` is related to the nome `Q` as `Q = exp(-pi*K(1-M)/K(M))`. Some definitions of the Jacobi's elliptic functions use the modulus `k` instead of the parameter `m`. They are related by `m = k^2`. 72 | 73 | **Example: 74 | ``` 75 | [= meshgrid(0:5:90, 0:2:90); 76 | Th1 = theta(1, pi/180*phi, sin(pi/180*alpha).^2); 77 | Th2 = theta(2, pi/180*phi, sin(pi/180*alpha).^2); 78 | Th3 = theta(3, pi/180*phi, sin(pi/180*alpha).^2); 79 | Th4 = theta(4, pi/180*phi, sin(pi/180*alpha).^2); 80 | ``` 81 | 82 | _Depends on_ `AGM`, `ELLIPJ`, `ELLIPKE`, `JACOBITHETAETA`
83 | _See also_ `ELLIPTIC12`, `ELLIPTIC12I` 84 | 85 | # Elliptic Integrals 86 | 87 | *[http://code.google.com/p/elliptic/wiki/EllipticIntegrals Elliptic integrals](phi,alpha])** originally arose in connection with the problem of giving the arc length of an ellipse. They were first studied by Giulio Fagnano and Leonhard Euler. Modern mathematics defines an elliptic integral as any function f which can be expressed in the form 88 | ``` 89 | f(x) = Integral(R(t,P(t), c, x)dt, 90 | ``` 91 | where `R` is a rational function of its two arguments, `P` is the square root of a polynomial of degree `3` or `4` with no repeated roots, and `c` is a constant. 92 | In general, elliptic integrals cannot be expressed in terms of elementary functions. Exceptions to this general rule are when `P` has repeated roots, or when `R(x,y)` contains no odd powers of `y`. However, with the appropriate reduction formula, every elliptic integral can be brought into a form that involves integrals over rational functions and the three canonical forms (i.e. the elliptic integrals of the first, second and third kind). 93 | 94 | ## ELLIPTIC12: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function 95 | 96 | [ELLIPTIC12](http://code.google.com/p/elliptic/source/browse/trunk/elliptic12.m) evaluates the value of the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function. 97 | 98 | `[= ELLIPTIC12(U,M,TOL)` uses the method of the Arithmetic-Geometric Mean and Descending Landen Transformation described in [http://code.google.com/p/elliptic/#References 1](F,E,Z]) Ch. 17.6, to determine the value of the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function (see [1](http://code.google.com/p/elliptic/#References), [2](http://code.google.com/p/elliptic/#References)). 99 | 100 | **General definition:** 101 | ``` 102 | F(phi,m) = int(1/sqrt(1-m*sin(t)^2), t=0..phi); 103 | E(phi,m) = int(sqrt(1-m*sin(t)^2), t=0..phi); 104 | Z(phi,m) = E(u,m) - E(m)/K(m)*F(phi,m). 105 | ``` 106 | 107 | 108 | Tables generating code (see [1](http://code.google.com/p/elliptic/wiki/elliptic#References), pp. 613-621): 109 | ``` 110 | [= meshgrid(0:5:90, 0:2:90); % modulus and phase in degrees 111 | [F,E,Z](phi,alpha]) = elliptic12(pi/180*phi, sin(pi/180*alpha).^2); % values of integrals 112 | ``` 113 | 114 | *Depends on* `AGM`
115 | *See also* `ELLIPKE`, `ELLIPJ`, `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 116 | 117 | ## ELLIPTIC12I: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function of the complex argument 118 | 119 | [ELLIPTIC12i](http://code.google.com/p/elliptic/source/browse/trunk/elliptic12i.m) evaluates the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function for the complex value of phase `U`. Parameter `M` must be in the range `0 <= M <= 1`. 120 | 121 | `[= ELLIPTIC12i(U,M,TOL)` where `U` is a complex phase in radians, `M` is the real parameter and `TOL` is the tolerance (optional). Default value for the tolerance is `eps = 2.220e-16`. 122 | 123 | `ELLIPTIC12i` uses the function `ELLIPTIC12` to evaluate the values of corresponding integrals. 124 | 125 | *Example: 126 | ``` 127 | [phi1,phi2](Fi,Ei,Zi]) = meshgrid(-2*pi:3/20:2*pi, -2*pi:3/20:2*pi); 128 | phi = phi1 + phi2*i; 129 | [= elliptic12i(phi, 0.5); 130 | ``` 131 | 132 | _Depends on_ `ELLIPTIC12`, `AGM`
133 | _See also_ `ELLIPKE`, `ELLIPJ`, `ELLIPTIC3`, `THETA`. 134 | 135 | ## ELLIPTIC3: Incomplete Elliptic Integral of the Third Kind 136 | 137 | [http://code.google.com/p/elliptic/source/browse/trunk/elliptic3.m ELLIPTIC3](Fi,Ei,Zi]) evaluates incomplete elliptic integral of the third kind `Pi = ELLIPTIC3(U,M,C)` where `U` is a phase in radians, `0 < M < 1` is the module and `0 < C < 1` is a parameter. 138 | 139 | `ELLIPTIC3` uses Gauss-Legendre 10 points quadrature template described in `[to determine the value of the Incomplete Elliptic Integral of the Third Kind (see `[1, 2](3]`)`). 140 | 141 | *General definition: 142 | ``` 143 | Pi(u,m,c) = int(1/((1 - c*sin(t)^2)*sqrt(1 - m*sin(t)^2)), t=0..u) 144 | ``` 145 | 146 | Tables generating code ([1](http://code.google.com/p/elliptic/wiki/elliptic#References), pp. 625-626): 147 | ``` 148 | [= meshgrid(0:15:90, 0:15:90, 0:0.1:1); 149 | Pi = elliptic3(pi/180*phi, sin(pi/180*alpha).^2, c); % values of integrals 150 | ``` 151 | 152 | 153 | ## ELLIPTIC123: Complete and Incomplete Elliptic Integrals of the First, Second, and Third Kind 154 | 155 | [http://code.google.com/p/elliptic/source/browse/trunk/elliptic123.m ELLIPTIC123](phi,alpha,c]) is a wrapper around the different elliptic integral functions, providing a unified interface and greater range of input parameters. (Unlike ELLIPKE, ELLIPTIC12 and ELLIPTIC3, which all require a phase between zero and pi/2 and a parameter between zero and one.) 156 | 157 | `[= ELLIPTIC123(m)` — complete Elliptic Integrals of the first and second kind. 158 | 159 | `[F,E](F,E]) = ELLIPTIC123(b,m)` — incomplete Elliptic Integrals of the first and second kind. 160 | 161 | `[= ELLIPTIC123(m,n)` — complete Elliptic Integrals of the first to third kind. 162 | 163 | `[F,E,PI](F,E,PI]) = ELLIPTIC123(b,m,n)` — incomplete Elliptic Integrals of the first to third kind. 164 | 165 | The order of the input arguments has been chosen to be consistent with the pre-existing `elliptic12` and `elliptic3` functions. 166 | 167 | This function is still under development and its results are not always well-defined or even able to be calculated (especially for the third elliptic integral with n>1). Please see the documentation for further details. 168 | 169 | ## INVERSELLIPTIC2: INVERSE Incomplete Elliptic Integrals of the Second Kind 170 | 171 | [INVERSELLIPTIC2](http://code.google.com/p/elliptic/source/browse/trunk/inverselliptic2.m) evaluates the value of the INVERSE Incomplete Elliptic Integrals of the Second Kind. 172 | 173 | INVERSELLIPTIC2 uses the method described by Boyd J. P. to determine the value of the inverse Incomplete Elliptic Integrals of the Second Kind using the “Empirical” initialization to the Newton’s iteration method [7](http://code.google.com/p/elliptic/wiki/elliptic#References). 174 | 175 | Elliptic integral of the second kind: 176 | ``` 177 | E(phi,m) = int(sqrt(1-m*sin(t)^2), t=0..phi); 178 | ``` 179 | 180 | “Empirical” initialization [7](http://code.google.com/p/elliptic/wiki/elliptic#References): 181 | ``` 182 | T0(z,m) = pi/2 + sqrt(r)/(theta − pi/2) 183 | ``` 184 | 185 | where 186 | ``` 187 | z \in [E(pi/2,m)](−E(pi/2,m),)x[1](0,) - value of the entire parameter space 188 | r = sqrt((1-m)^2 + zeta^2) 189 | zeta = 1 - z/E(pi/2,m) 190 | theta = atan((1 - m)/zeta) 191 | ``` 192 | 193 | Example: 194 | ``` 195 | % modulus and phase in degrees 196 | [= meshgrid(0:5:90, 0:2:90); 197 | % values of integrals 198 | [F,E](phi,alpha]) = elliptic12(pi/180*phi, sin(pi/180*alpha).^2); 199 | % values of inverse 200 | invE = inverselliptic2(E, sin(pi/180*alpha).^2); 201 | % the difference between phase phi and invE should close to zero 202 | phi - invE * 180/pi 203 | ``` 204 | 205 | 206 | # Weierstrass's elliptic functions (in development) 207 | 208 | !IN DEVELOPMENT, help needed! See [forum discussion](http://groups.google.com/group/pelliptic/browse_frm/thread/f1eeff5553d3533b). 209 | 210 | **[Weierstrass's elliptic functions](http://code.google.com/p/elliptic/wiki/WeierstrassEllipticFunctions)** are elliptic functions that take a particularly simple form (cf Jacobi's elliptic functions); they are named for Karl Weierstrass. This class of functions are also referred to as p-functions and generally written using the symbol ℘ (a stylised letter p called Weierstrass p). 211 | 212 | The Weierstrass elliptic function can be defined in three closely related ways, each of which possesses certain advantages. One is as a function of a complex variable z and a lattice Λ in the complex plane. Another is in terms of z and two complex numbers ω1 and ω2 defining a pair of generators, or periods, for the lattice. The third is in terms z and of a modulus τ in the upper half-plane. This is related to the previous definition by τ = ω2 / ω1, which by the conventional choice on the pair of periods is in the upper half-plane. Using this approach, for fixed z the Weierstrass functions become modular functions of τ. 213 | 214 | 215 | # Elliptic Related Functions 216 | 217 | ## AGM: Artihmetic Geometric Mean 218 | 219 | [AGM](http://code.google.com/p/elliptic/source/browse/trunk/agm.m) calculates the [Artihmetic Geometric Mean](http://en.wikipedia.org/wiki/Arithmetic-geometric_mean) of `A` and `B` (see [1](http://code.google.com/p/elliptic/#References)). 220 | 221 | `[= AGM(A0,B0,C0,TOL)` carry out the process of the arithmetic geometric mean, starting with a given positive numbers triple `(A0, B0, C0)` and returns in 222 | `(A, B, C)` the generated sequence. `N` is a number of steps (returns in the value`uint32`). 223 | 224 | The general scheme of the procedure: 225 | ``` 226 | A(i) = 1/2*( A(i-1)+B(i-1) ); A(0) = A0; 227 | B(i) = sqrt( A(i-1)*B(i-1) ); B(0) = B0; 228 | C(i) = 1/2*( A(i-1)+B(i-1) ); C(0) = C0; 229 | ``` 230 | Stop at the `N`-th step when `A(N) = B(N)`, i.e., when `C(N) = 0`. 231 | 232 | _Used by_ `ELLIPJ` and `ELLIPTIC12`.
_See also_ `ELLIPKE`, `ELLIPTIC3`, `THETA`. 233 | 234 | ## NOMEQ: The Value of Nome `q = q(m)` 235 | 236 | [http://code.google.com/p/elliptic/source/browse/trunk/nomeq.m NOMEQ](A,B,C,N]) gives the value of Nome `q = q(m)`. 237 | 238 | Nome `Q = nomeq(M,TOL)`, where `0<=M<=1` is the module and `TOL` is the tolerance (optional). Default value for the tolerance is `eps = 2.220e-16`. 239 | 240 | *Used by* `ELLIPJ`.
241 | *Depends on* `ELLIPKE`
242 | *See also* `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 243 | 244 | ## INVERSENOMEQ: The Value of Nome `m = m(q)` 245 | 246 | [INVERSENOMEQ](http://code.google.com/p/elliptic/source/browse/trunk/inversenomeq.m) gives the value of Nome `m = m(q)`. 247 | 248 | `M = inversenomeq(q)`, where `Q` is the Nome of q-series. 249 | 250 | **WARNING**. The function `INVERSENOMEQ` does not return correct values of `M` for `Q > 0.6`, because of computer precision limitation. The function `NomeQ(m)` has an essential singularity at `M = 1`, so it cannot be inverted at this point and actually it is very hard to find and inverse in the neigborhood also. 251 | 252 | More preciesly: 253 | ``` 254 | nomeq(1) = 1 255 | nomeq(1-eps) = 0.77548641878026 256 | ``` 257 | 258 | *Example: 259 | ``` 260 | nomeq(inversenomeq([0.3 0.4 0.5 0.6 0.7 0.8](0.001))) 261 | ``` 262 | 263 | *Used by* `ELLIPJ`.
264 | *Depends on* `ELLIPKE`
265 | *See also* `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 266 | 267 | 268 | # References 269 | 270 | 1. [NIST Digital Library of Mathematical Functions](http://dlmf.nist.gov/) 271 | 1. M. Abramowitz and I.A. Stegun, "[Handbook of Mathematical Functions](http://www.nrbook.com/abramowitz_and_stegun/)" Dover Publications", 1965, Ch. 17.1 - 17.6. 272 | 1. D. F. Lawden, "[Elliptic Functions and Applications](http://www.amazon.com/Elliptic-Functions-Applications-Mathematical-Sciences/dp/0387969659)" Springer-Verlag, vol. 80, 1989 273 | 1. S. Zhang, J. Jin, "[Computation of Special Functions](http://jin.ece.uiuc.edu/specfunc.html)" (Wiley, 1996). 274 | 1. B. Carlson, "[Three Improvements in Reduction and Computation of Elliptic Integrals](http://nvl.nist.gov/pub/nistpubs/jres/107/5/j75car.pdf)", J. Res. Natl. Inst. Stand. Technol. 107 (2002) 413-418. 275 | 1. N. H. Abel, "[Studies on Elliptic Functions](http://mathdl.maa.org/mathDL/46/?pa=content&sa=viewDocument&nodeId=1557)", english translation from french by Marcus Emmanuel Barnes. Original "Recherches sur les fonctions elliptiques", Journal fr die reine und angewandte Mathematik, Vol. 2, 1827. pp. 101-181. 276 | 1. B. C. Berndt, H. H. Chan, S.-S. Huang, "[Incomplete Elliptic Integrals in Ramanujan's Lost Notebook](http://www.math.uiuc.edu/~berndt/articles/ellipticintegral.pdf)" in q-series from a Contemporary Perspective, M. E. H. Ismail and D. Stanton, eds., Amer. Math. Soc., 2000, pp. 79-126. 277 | 1. J. P. Boyd, "Numerical, Perturbative and Chebyshev Inversion of the Incomplete Elliptic Integral of the Second Kind", Applied Mathematics and Computation (January 2012) -------------------------------------------------------------------------------- /wiki/home.md: -------------------------------------------------------------------------------- 1 | # Elliptic integrals, Jacobi's elliptic functions and Theta function. 2 | 3 | 4 | 5 | 6 | 7 | 8 | The [Matlab](http://www.mathworks.com/) script implementations of [Elliptic integrals of three types](http://code.google.com/p/elliptic/wiki/EllipticIntegrals), [Jacobi's elliptic functions](http://en.wikipedia.org/wiki/Jacobi%27s_elliptic_functions) and [Jacobi theta functions](http://en.wikipedia.org/wiki/Theta_function) of four types. 9 | 10 | The main GOAL of the project is to provide the natural Matlab scripts WITHOUT external library calls like Maple and others. All scripts are developed to accept tensors as arguments and almost all of them have their complex versions. Performance and complete control on the execution are the main features. 11 | 12 | To download please go to [Routines list](https://elliptic.googlecode.com/svn/trunk/). 13 | 14 | Or checkout via [Subversion](http://subversion.tigris.org/) from [Checkout page](https://code.google.com/p/elliptic/source/checkout). 15 | 16 | 17 | [http://elliptic.googlecode.com/svn/trunk/imgs/elliptic.png](http://code.google.com/p/elliptic/wiki/elliptic) 18 | 19 | **[Elliptic integrals](http://code.google.com/p/elliptic/wiki/EllipticIntegrals)** originally arose in connection with the problem of giving the arc length of an ellipse. They were first studied by Giulio Fagnano and Leonhard Euler. Modern mathematics defines an elliptic integral as any function f which can be expressed in the form 20 | ``` 21 | f(x) = Integral(R(t,P(t), c, x)dt, 22 | ``` 23 | where `R` is a rational function of its two arguments, `P` is the square root of a polynomial of degree `3` or `4` with no repeated roots, and `c` is a constant. 24 | In general, elliptic integrals cannot be expressed in terms of elementary functions. Exceptions to this general rule are when `P` has repeated roots, or when `R(x,y)` contains no odd powers of `y`. However, with the appropriate reduction formula, every elliptic integral can be brought into a form that involves integrals over rational functions and the three canonical forms (i.e. the elliptic integrals of the first, second and third kind). 25 | 26 | **[The Jacobi's elliptic functions](http://code.google.com/p/elliptic/wiki/elliptic#Elliptic_Functions)** are a set of basic elliptic functions, and auxiliary theta functions, that have historical importance with also many features that show up important structure, and have direct relevance to some applications (e.g. the equation of the pendulum). They also have useful analogies to the functions of trigonometry, as indicated by the matching notation `SN` for `SIN`. They are not the simplest way to develop a general theory, as now seen: that can be said for the Weierstrass elliptic functions. They are not, however, outmoded. They were introduced by Carl Gustav Jakob Jacobi, around 1830. 27 | 28 | **[Theta functions](http://code.google.com/p/elliptic/wiki/elliptic#THETA:_Theta_Functions_of_Four_Types)** are special functions of several complex variables. They are important in several areas, including the theories of abelian varieties and moduli spaces, and of quadratic forms. They have also been applied to soliton theory. When generalized to a Grassmann algebra, they also appear in quantum field theory, specifically string theory and D-branes. 29 | 30 | **[Weierstrass's elliptic functions](http://code.google.com/p/elliptic/wiki/elliptic#Weierstrass's_elliptic_functions_(in_development))** are elliptic functions that take a particularly simple form (cf Jacobi's elliptic functions); they are named for Karl Weierstrass. This class of functions are also referred to as p-functions and generally written using the symbol ℘ (a stylised letter p called Weierstrass p). 31 | 32 | The Weierstrass elliptic function can be defined in three closely related ways, each of which possesses certain advantages. One is as a function of a complex variable z and a lattice Λ in the complex plane. Another is in terms of z and two complex numbers ω1 and ω2 defining a pair of generators, or periods, for the lattice. The third is in terms z and of a modulus τ in the upper half-plane. This is related to the previous definition by τ = ω2 / ω1, which by the conventional choice on the pair of periods is in the upper half-plane. Using this approach, for fixed z the Weierstrass functions become modular functions of τ. 33 | 34 | 35 | 36 | 41 | 45 | 46 |
37 | 38 | PayPal — donate 39 | 40 | 42 |
Any donation will be appreciated!
43 | Thank you. 44 |
47 | 48 |
49 | 50 | # Contents of the package 51 | 52 | - [Elliptic Functions](http://code.google.com/p/elliptic/wiki/elliptic#Elliptic_Functions) 53 | - [ELLIPJ: Jacobi's elliptic functions](http://code.google.com/p/elliptic/wiki/elliptic#ELLIPJ:_Jacobi's_elliptic_functions) 54 | - [ELLIPJI: Jacobi's elliptic functions of the complex argument](http://code.google.com/p/elliptic/wiki/elliptic?#ELLIPJI:_Jacobi's_elliptic_functions_of_the_complex_argumen) 55 | - [JACOBITHETAETA: Jacobi's Theta and Eta Functions](http://code.google.com/p/elliptic/wiki/elliptic#JACOBITHETAETA:_Jacobi's_Theta_and_Eta_Functions) 56 | - [THETA: Theta Functions of Four Types](http://code.google.com/p/elliptic/wiki/elliptic#THETA:_Theta_Functions_of_Four_Types) 57 | - [Elliptic Integrals](http://code.google.com/p/elliptic/wiki/elliptic#Elliptic_Integrals) 58 | - [ELLIPTIC12: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function](http://code.google.com/p/elliptic/wiki/elliptic#ELLIPTIC12:_Incomplete_Elliptic_Integrals_of_the_First,_Second_K) 59 | - [ELLIPTIC12I: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function of the complex argument](http://code.google.com/p/elliptic/wiki/elliptic#ELLIPTIC12I:_Incomplete_Elliptic_Integrals_of_the_First,_Second) 60 | - [ELLIPTIC3: Incomplete Elliptic Integral of the Third Kind](http://code.google.com/p/elliptic/wiki/elliptic#ELLIPTIC3:_Incomplete_Elliptic_Integral_of_the_Third_Kind) 61 | - [ELLIPTIC123: Complete and Incomplete Elliptic Integrals of the First, Second, and Third Kind](http://code.google.com/p/elliptic/wiki/elliptic#ELLIPTIC123:_Complete_and_Incomplete_Elliptic_Integrals_of_the_F) 62 | - [INVERSELLIPTIC2: INVERSE Incomplete Elliptic Integrals of the Second Kind](http://code.google.com/p/elliptic/wiki/elliptic#INVERSELLIPTIC2:_INVERSE_Incomplete_Elliptic_Integrals_of_the_Se) 63 | 64 | - [Weierstrass's elliptic functions (in development)](http://code.google.com/p/elliptic/wiki/elliptic#Weierstrass's_elliptic_functions_(in_development)) 65 | - [Elliptic Related Functions](http://code.google.com/p/elliptic/wiki/elliptic#Elliptic_Related_Functions) 66 | - [AGM: Artihmetic Geometric Mean](http://code.google.com/p/elliptic/wiki/elliptic#AGM:_Artihmetic_Geometric_Mean) 67 | - [NOMEQ: The Value of Nome q = q(m)](http://code.google.com/p/elliptic/wiki/elliptic#NOMEQ:_The_Value_of_Nome_q_=_q(m)) 68 | - [INVERSENOMEQ: The Value of Nome m = m(q)](http://code.google.com/p/elliptic/wiki/elliptic#INVERSENOMEQ:_The_Value_of_Nome_m_=_m(q)) 69 | - [References](http://code.google.com/p/elliptic/wiki/elliptic#References) 70 | 71 | 72 | # Contents of package 73 | 74 | 75 | 76 | ## Elliptic Functions 77 | 78 | ### ELLIPJ: Jacobi's elliptic functions 79 | 80 | [ELLIPJ](http://code.google.com/p/elliptic/source/browse/trunk/ellipj.m) evaluates the [Jacobi's elliptic functions](http://en.wikipedia.org/wiki/Jacobi%27s_elliptic_functions) and [Jacobi's amplitude](http://mathworld.wolfram.com/JacobiAmplitude.html). 81 | 82 | `[= ELLIPJ(U,M)` returns the values of the Jacobi elliptic functions `SN`, `CN`, `DN` and `AM` evaluated for corresponding elements of argument U and parameter M. The arrays U and M must be of the same size (or either can be scalar). As currently implemented, M is limited to `0 <= M <= 1`. 83 | 84 | *General definition:* 85 | ``` 86 | u = Integral(1/sqrt(1-m^2*sin(theta)^2), 0, phi); 87 | Sn(u) = sin(phi); 88 | Cn(u) = cos(phi); 89 | Dn(u) = sqrt(1-m^2*sin(phi)^2); 90 | ``` 91 | 92 | _Depends on_ `AGM`, `ELLIPKE`.
93 | _Used by_ `THETA`.
94 | _See also_ `ELLIPKE`. 95 | 96 | 97 | ### ELLIPJI: Jacobi's elliptic functions of the complex argument 98 | 99 | [http://code.google.com/p/elliptic/source/browse/trunk/ellipji.m ELLIPJI](Sn,Cn,Dn,Am]) evaluates the Jacobi elliptic functions of complex phase `U`. 100 | 101 | `[= ELLIPJ(U,M)` returns the values of the Jacobi elliptic functions `SNI`, `CNI` and `DNI` evaluated for corresponding elements of argument `U` and parameter `M`. The arrays `U` and `M` must be of the same size (or either can be scalar). As currently implemented, `M` is real and limited to `0 <= M <= 1`. 102 | 103 | 104 | *Example: 105 | ``` 106 | [phi1,phi2](Sni,Cni,Dni]) = meshgrid(-pi:3/20:pi, -pi:3/20:pi); 107 | phi = phi1 + phi2*i; 108 | [= ellipji(phi, 0.99); 109 | ``` 110 | 111 | _Depends on_ `AGM`, `ELLIPJ`, `ELLIPKE`
112 | _See also_ `ELLIPTIC12`, `ELLIPTIC12I` 113 | 114 | ### JACOBITHETAETA: Jacobi's Theta and Eta Functions 115 | 116 | [http://code.google.com/p/elliptic/source/browse/trunk/jacobiThetaEta.m JACOBITHETAETA](Sni,Cni,Dni]) evaluates Jacobi's theta and eta functions. 117 | 118 | `[H](Th,) = JACOBITHETAETA(U,M)` returns the values of the Jacobi's theta and eta elliptic functions `TH` and `H` evaluated for corresponding elements of argument `U` and parameter `M`. The arrays `U` and `M` must be the same size (or either can be scalar). As currently implemented, `M` is real and limited to `0 <= M <= 1`. 119 | 120 | *Example: 121 | ``` 122 | [= meshgrid(0:5:90, 0:2:90); 123 | [Th, H](phi,alpha]) = jacobiThetaEta(pi/180*phi, sin(pi/180*alpha).^2); 124 | ``` 125 | 126 | *Depends on* `AGM`, `ELLIPJ`, `ELLIPKE`
127 | *See also* `ELLIPTIC12`, `ELLIPTIC12I`, `THETA` 128 | 129 | ### THETA: Theta Functions of Four Types 130 | 131 | [THETA](http://code.google.com/p/elliptic/source/browse/trunk/theta.m) evaluates theta functions of four types. 132 | 133 | `Th = THETA(TYPE,V,M)` returns values of theta functions 134 | evaluated for corresponding values of argument `V` and parameter `M`. `TYPE` is a type of the theta function, there are four numbered types. The arrays `V` and `M` must be the same size (or either can be scalar). As currently implemented, `M` is limited to `0 <= M <= 1`. 135 | 136 | `Th = THETA(TYPE,V,M,TOL)` computes the theta and eta elliptic functions to the accuracy `TOL` instead of the default `TOL = EPS`. 137 | 138 | The parameter `M` is related to the nome `Q` as `Q = exp(-pi*K(1-M)/K(M))`. Some definitions of the Jacobi's elliptic functions use the modulus `k` instead of the parameter `m`. They are related by `m = k^2`. 139 | 140 | *Example: 141 | ``` 142 | [= meshgrid(0:5:90, 0:2:90); 143 | Th1 = theta(1, pi/180*phi, sin(pi/180*alpha).^2); 144 | Th2 = theta(2, pi/180*phi, sin(pi/180*alpha).^2); 145 | Th3 = theta(3, pi/180*phi, sin(pi/180*alpha).^2); 146 | Th4 = theta(4, pi/180*phi, sin(pi/180*alpha).^2); 147 | ``` 148 | 149 | _Depends on_ `AGM`, `ELLIPJ`, `ELLIPKE`, `JACOBITHETAETA`
150 | _See also_ `ELLIPTIC12`, `ELLIPTIC12I` 151 | 152 | ## Elliptic Intergrals 153 | 154 | ### ELLIPTIC12: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function 155 | 156 | [http://code.google.com/p/elliptic/source/browse/trunk/elliptic12.m ELLIPTIC12](phi,alpha]) evaluates the value of the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function. 157 | 158 | `[= ELLIPTIC12(U,M,TOL)` uses the method of the Arithmetic-Geometric Mean and Descending Landen Transformation described in [http://code.google.com/p/elliptic/#References 1](F,E,Z]) Ch. 17.6, to determine the value of the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function (see [1](http://code.google.com/p/elliptic/#References), [2](http://code.google.com/p/elliptic/#References)). 159 | 160 | **General definition:** 161 | ``` 162 | F(phi,m) = int(1/sqrt(1-m*sin(t)^2), t=0..phi); 163 | E(phi,m) = int(sqrt(1-m*sin(t)^2), t=0..phi); 164 | Z(phi,m) = E(u,m) - E(m)/K(m)*F(phi,m). 165 | ``` 166 | 167 | 168 | Tables generating code (see [1](http://code.google.com/p/elliptic/#References), pp. 613-621): 169 | ``` 170 | [= meshgrid(0:5:90, 0:2:90); % modulus and phase in degrees 171 | [F,E,Z](phi,alpha]) = elliptic12(pi/180*phi, sin(pi/180*alpha).^2); % values of integrals 172 | ``` 173 | 174 | *Depends on* `AGM`
175 | *See also* `ELLIPKE`, `ELLIPJ`, `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 176 | 177 | ### ELLIPTIC12I: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function of the complex argument 178 | 179 | [ELLIPTIC12i](http://code.google.com/p/elliptic/source/browse/trunk/elliptic12i.m) evaluates the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function for the complex value of phase `U`. Parameter `M` must be in the range `0 <= M <= 1`. 180 | 181 | `[= ELLIPTIC12i(U,M,TOL)` where `U` is a complex phase in radians, `M` is the real parameter and `TOL` is the tolerance (optional). Default value for the tolerance is `eps = 2.220e-16`. 182 | 183 | `ELLIPTIC12i` uses the function `ELLIPTIC12` to evaluate the values of corresponding integrals. 184 | 185 | *Example: 186 | ``` 187 | [phi1,phi2](Fi,Ei,Zi]) = meshgrid(-2*pi:3/20:2*pi, -2*pi:3/20:2*pi); 188 | phi = phi1 + phi2*i; 189 | [= elliptic12i(phi, 0.5); 190 | ``` 191 | 192 | _Depends on_ `ELLIPTIC12`, `AGM`
193 | _See also_ `ELLIPKE`, `ELLIPJ`, `ELLIPTIC3`, `THETA`. 194 | 195 | ### ELLIPTIC3: Incomplete Elliptic Integral of the Third Kind 196 | 197 | [http://code.google.com/p/elliptic/source/browse/trunk/elliptic3.m ELLIPTIC3](Fi,Ei,Zi]) evaluates incomplete elliptic integral of the third kind `Pi = ELLIPTIC3(U,M,C)` where `U` is a phase in radians, `0 < M < 1` is the module and `0 < C < 1` is a parameter. 198 | 199 | `ELLIPTIC3` uses Gauss-Legendre 10 points quadrature template described in `[to determine the value of the Incomplete Elliptic Integral of the Third Kind (see `[1, 2](3]`)`). 200 | 201 | *General definition: 202 | ``` 203 | Pi(u,m,c) = int(1/((1 - c*sin(t)^2)*sqrt(1 - m*sin(t)^2)), t=0..u) 204 | ``` 205 | 206 | Tables generating code ([pp. 625-626): 207 | ``` 208 | [phi,alpha,c](1],) = meshgrid(0:15:90, 0:15:90, 0:0.1:1); 209 | Pi = elliptic3(pi/180*phi, sin(pi/180*alpha).^2, c); % values of integrals 210 | ``` 211 | 212 | ## Weierstrass's elliptic functions (in development) 213 | 214 | !IN DEVELOPMENT, help needed! 215 | 216 | ## Elliptic Related Functions 217 | 218 | ### AGM: Artihmetic Geometric Mean 219 | 220 | [AGM](http://code.google.com/p/elliptic/source/browse/trunk/agm.m) calculates the [Artihmetic Geometric Mean](http://en.wikipedia.org/wiki/Arithmetic-geometric_mean) of `A` and `B` (see [1](http://code.google.com/p/elliptic/#References)). 221 | 222 | `[= AGM(A0,B0,C0,TOL)` carry out the process of the arithmetic geometric mean, starting with a given positive numbers triple `(A0, B0, C0)` and returns in 223 | `(A, B, C)` the generated sequence. `N` is a number of steps (returns in the value`uint32`). 224 | 225 | The general scheme of the procedure: 226 | ``` 227 | A(i) = 1/2*( A(i-1)+B(i-1) ); A(0) = A0; 228 | B(i) = sqrt( A(i-1)*B(i-1) ); B(0) = B0; 229 | C(i) = 1/2*( A(i-1)+B(i-1) ); C(0) = C0; 230 | ``` 231 | Stop at the `N`-th step when `A(N) = B(N)`, i.e., when `C(N) = 0`. 232 | 233 | _Used by_ `ELLIPJ` and `ELLIPTIC12`.
_See also_ `ELLIPKE`, `ELLIPTIC3`, `THETA`. 234 | 235 | ### NOMEQ: The Value of Nome `q = q(m)` 236 | 237 | [http://code.google.com/p/elliptic/source/browse/trunk/nomeq.m NOMEQ](A,B,C,N]) gives the value of Nome `q = q(m)`. 238 | 239 | Nome `Q = nomeq(M,TOL)`, where `0<=M<=1` is the module and `TOL` is the tolerance (optional). Default value for the tolerance is `eps = 2.220e-16`. 240 | 241 | *Used by* `ELLIPJ`.
242 | *Depends on* `ELLIPKE`
243 | *See also* `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 244 | 245 | ### INVERSENOMEQ: The Value of Nome `m = m(q)` 246 | 247 | [INVERSENOMEQ](http://code.google.com/p/elliptic/source/browse/trunk/inversenomeq.m) gives the value of Nome `m = m(q)`. 248 | 249 | `M = inversenomeq(q)`, where `Q` is the Nome of q-series. 250 | 251 | **WARNING**. The function `INVERSENOMEQ` does not return correct values of `M` for `Q > 0.6`, because of computer precision limitation. The function `NomeQ(m)` has an essential singularity at `M = 1`, so it cannot be inverted at this point and actually it is very hard to find and inverse in the neigborhood also. 252 | 253 | More preciesly: 254 | ``` 255 | nomeq(1) = 1 256 | nomeq(1-eps) = 0.77548641878026 257 | ``` 258 | 259 | *Example: 260 | ``` 261 | nomeq(inversenomeq([0.3 0.4 0.5 0.6 0.7 0.8](0.001))) 262 | ``` 263 | 264 | *Used by* `ELLIPJ`.
265 | *Depends on* `ELLIPKE`
266 | *See also* `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 267 | 268 | # References 269 | 270 | 1. M. Abramowitz and I.A. Stegun, "[Handbook of Mathematical Functions](http://www.math.ucla.edu/~cbm/aands/)" Dover Publications", 1965, Ch. 17.1 - 17.6. 271 | 1. D. F. Lawden, "[Elliptic Functions and Applications](http://www.amazon.com/Elliptic-Functions-Applications-Mathematical-Sciences/dp/0387969659)" Springer-Verlag, vol. 80, 1989 272 | 1. S. Zhang, J. Jin, "[Computation of Special Functions](http://jin.ece.uiuc.edu/specfunc.html)" (Wiley, 1996). 273 | 1. B. Carlson, "[Three Improvements in Reduction and Computation of Elliptic Integrals](http://nvl.nist.gov/pub/nistpubs/jres/107/5/j75car.pdf)", J. Res. Natl. Inst. Stand. Technol. 107 (2002) 413-418. 274 | 1. N. H. Abel, "[Studies on Elliptic Functions](http://mathdl.maa.org/mathDL/46/?pa=content&sa=viewDocument&nodeId=1557)", english translation from french by Marcus Emmanuel Barnes. Original "Recherches sur les fonctions elliptiques", Journal fr die reine und angewandte Mathematik, Vol. 2, 1827. pp. 101-181. 275 | 1. B. C. Berndt, H. H. Chan, S.-S. Huang, "[Incomplete Elliptic Integrals in Ramanujan's Lost Notebook](http://www.math.uiuc.edu/~berndt/articles/ellipticintegral.pdf)" in q-series from a Contemporary Perspective, M. E. H. Ismail and D. Stanton, eds., Amer. Math. Soc., 2000, pp. 79-126. 276 |
277 | 278 | 279 | 280 | # External Links 281 | 282 | - [Elliptic integrals](http://en.wikipedia.org/wiki/Elliptic_integral) and [Jacobi's elliptic functions](http://en.wikipedia.org/wiki/Jacobi's_elliptic_functions) from Wikipedia. 283 | - [ALGLIB](http://www.alglib.net/) - cross-platform numerical analysis and data processing library. 284 | - [Graphs by Kojocho2](http://www.youtube.com/user/kojocho2), Graph of complex functions and complex analysis. 285 | 286 | # Some interesting applications 287 | 288 | ### Fingerprints In The Sky Explained By 'Beautiful Mathematics'. [ScienceDaily (Nov. 23, 2004)](http://www.sciencedaily.com/releases/2004/11/041123112414.htm) 289 | 290 | *This is beautiful mathematics in the sky. Using elliptic integrals, we’ve been able to replace pages and pages of formulae with one very simple solution that predicts the pattern extremely well.* 291 | 292 | ### Mathematicians Solve 'Trillion Triangle' Problem. [ScienceDaily (Sep. 22, 2009)](http://www.sciencedaily.com/releases/2009/09/090922095651.htm) 293 | 294 | *According to Brian Conrey, Director of the American Institute of Mathematics, "Old problems like this may seem obscure, but they generate a lot of interesting and useful research as people develop new ways to attack them."* 295 | 296 | ### Elliptic-Function Filter Properties. [Connexions](http://cnx.org/content/m16925/latest/) 297 | 298 | *...In order to develop analytical expressions for equal-ripple rational functions, an interesting class of transcendental functions, called the Jacobian elliptic functions, is outlined.* 299 | 300 | 301 | 302 |
303 |
304 | 305 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Elliptic functions for Matlab and Octave 3 | 4 | [![CircleCI](https://dl.circleci.com/status-badge/img/gh/moiseevigor/elliptic/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/moiseevigor/elliptic/tree/master) [![DOI](https://zenodo.org/badge/5762/moiseevigor/elliptic.svg)](https://zenodo.org/badge/latestdoi/5762/moiseevigor/elliptic) 5 | 6 | 7 | The Matlab/Octave implementation of [Elliptic integrals of three types](http://en.wikipedia.org/wiki/Elliptic_integral), [Jacobi's elliptic functions](http://en.wikipedia.org/wiki/Jacobi%27s_elliptic_functions) and [Jacobi theta functions](http://en.wikipedia.org/wiki/Theta_function) of four types with their derivatives. 8 | 9 | The main *GOAL* of the project is to provide the natural Matlab scripts *WITHOUT* external library calls like Maple and others. All scripts are developed to accept tensors as arguments and almost all of them have their complex versions. Performance and complete control on the execution are the main features. 10 | 11 | # Citations and references 12 | 13 | If you've used any of the routines in this package please cite and support the effort. Here is the example of the BibTeX entry 14 | 15 | ``` 16 | @misc{elliptic, 17 | author = {Moiseev I.}, 18 | title = {Elliptic functions for Matlab and Octave}, 19 | year = {2008}, 20 | publisher = {GitHub}, 21 | journal = {GitHub repository}, 22 | howpublished = {\url{https://github.com/moiseevigor/elliptic}}, 23 | commit = {98181c4c0d8992746bcc6bea75740bb11b74b51b}, 24 | doi = {10.5281/zenodo.48264}, 25 | url = {http://dx.doi.org/10.5281/zenodo.48264} 26 | } 27 | ``` 28 | 29 | or simply 30 | 31 | ``` 32 | Moiseev I., Elliptic functions for Matlab and Octave, (2008), GitHub repository, DOI: http://dx.doi.org/10.5281/zenodo.48264 33 | ``` 34 | 35 | # Contents of the package 36 | 37 | - [Elliptic Functions](#elliptic-functions) 38 | - [ELLIPJ: Jacobi's elliptic functions](#ellipj-jacobis-elliptic-functions) 39 | - [ELLIPJI: Jacobi's elliptic functions of the complex argument](#ellipji-jacobis-elliptic-functions-of-the-complex-argument) 40 | - [JACOBITHETAETA: Jacobi's Theta and Eta Functions](#jacobithetaeta-jacobis-theta-and-eta-functions) 41 | - [THETA: Theta Functions of Four Types](#theta-theta-functions-of-four-types) 42 | - [THETA_PRIME: Theta Functions and Their Derivatives](#theta_prime-theta-functions-and-their-derivatives) 43 | - [Elliptic Integrals](#elliptic-integrals) 44 | - [ELLIPTIC12: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function](#elliptic12-incomplete-elliptic-integrals-of-the-first-second-kind-and-jacobis-zeta-function) 45 | - [ELLIPTIC12I: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function of the complex argument](#elliptic12i-incomplete-elliptic-integrals-of-the-first-second-kind-and-jacobis-zeta-function-of-the-complex-argument) 46 | - [ELLIPTIC3: Incomplete Elliptic Integral of the Third Kind](#elliptic3-incomplete-elliptic-integral-of-the-third-kind) 47 | - [ELLIPTIC123: Complete and Incomplete Elliptic Integrals of the First, Second, and Third Kind](#elliptic123-complete-and-incomplete-elliptic-integrals-of-the-first-second-and-third-kind) 48 | - [INVERSELLIPTIC2: INVERSE Incomplete Elliptic Integrals of the Second Kind](#inverselliptic2-inverse-incomplete-elliptic-integrals-of-the-second-kind) 49 | 50 | - [Weierstrass's elliptic functions (in development)](#weierstrasss-elliptic-functions-in-development) 51 | - [Elliptic Related Functions](#elliptic-related-functions) 52 | - [AGM: Artihmetic Geometric Mean](#agm-artihmetic-geometric-mean) 53 | - [NOMEQ: The Value of Nome q = q(m)](#nomeq-the-value-of-nome-q--qm) 54 | - [INVERSENOMEQ: The Value of Nome m = m(q)](#inversenomeq-the-value-of-nome-m--mq) 55 | - [Contributors](#contributors) 56 | - [References](#references) 57 | 58 | # Elliptic Functions 59 | 60 | **The Jacobi's elliptic functions** are a set of basic elliptic functions, and auxiliary theta functions, that have historical importance with also many features that show up important structure, and have direct relevance to some applications (e.g. the equation of the pendulum). They also have useful analogies to the functions of trigonometry, as indicated by the matching notation `SN` for `SIN`. They are not the simplest way to develop a general theory, as now seen: that can be said for the Weierstrass elliptic functions. They are not, however, outmoded. They were introduced by Carl Gustav Jakob Jacobi, around 1830. 61 | 62 | **Theta functions** are special functions of several complex variables. They are important in several areas, including the theories of abelian varieties and moduli spaces, and of quadratic forms. They have also been applied to soliton theory. When generalized to a Grassmann algebra, they also appear in quantum field theory, specifically string theory and D-branes. 63 | 64 | ## ELLIPJ: Jacobi's elliptic functions 65 | 66 | `ELLIPJ` evaluates the [Jacobi's elliptic functions](http://en.wikipedia.org/wiki/Jacobi%27s_elliptic_functions) and [Jacobi's amplitude](http://mathworld.wolfram.com/JacobiAmplitude.html). 67 | 68 | `[Sn,Cn,Dn,Am] = ELLIPJ(U,M)` returns the values of the Jacobi elliptic functions `SN`, `CN`, `DN` and `AM` evaluated for corresponding elements of argument U and parameter M. The arrays U and M must be of the same size (or either can be scalar). As currently implemented, M is limited to `0 <= M <= 1`. 69 | 70 | *General definition:* 71 | ``` 72 | u = Integral(1/sqrt(1-m*sin(theta)^2), 0, phi); 73 | Sn(u) = sin(phi); 74 | Cn(u) = cos(phi); 75 | Dn(u) = sqrt(1-m*sin(phi)^2); 76 | ``` 77 | 78 | _Depends on_ `AGM`, `ELLIPKE`.
79 | _Used by_ `THETA`.
80 | _See also_ `ELLIPKE`. 81 | 82 | 83 | ## ELLIPJI: Jacobi's elliptic functions of the complex argument 84 | 85 | `ELLIPJI` evaluates the Jacobi elliptic functions of complex phase `U`. 86 | 87 | `[Sni,Cni,Dni] = ELLIPJ(U,M)` returns the values of the Jacobi elliptic functions `SNI`, `CNI` and `DNI` evaluated for corresponding elements of argument `U` and parameter `M`. The arrays `U` and `M` must be of the same size (or either can be scalar). As currently implemented, `M` is real and limited to `0 <= M <= 1`. 88 | 89 | 90 | ### Example: 91 | 92 | ``` 93 | [phi1,phi2] = meshgrid(-pi:3/20:pi, -pi:3/20:pi); 94 | phi = phi1 + phi2*i; 95 | [Sni,Cni,Dni]= ellipji(phi, 0.99); 96 | ``` 97 | 98 | _Depends on_ `AGM`, `ELLIPJ`, `ELLIPKE`
99 | _See also_ `ELLIPTIC12`, `ELLIPTIC12I` 100 | 101 | ## JACOBITHETAETA: Jacobi's Theta and Eta Functions 102 | 103 | `JACOBITHETAETA` evaluates Jacobi's theta and eta functions. 104 | 105 | `[Th, H] = JACOBITHETAETA(U,M)` returns the values of the Jacobi's theta and eta elliptic functions `TH` and `H` evaluated for corresponding elements of argument `U` and parameter `M`. The arrays `U` and `M` must be the same size (or either can be scalar). As currently implemented, `M` is real and limited to `0 <= M <= 1`. 106 | 107 | ### Example: 108 | ``` 109 | [phi,alpha]= meshgrid(0:5:90, 0:2:90); 110 | [Th, H] = jacobiThetaEta(pi/180*phi, sin(pi/180*alpha).^2); 111 | ``` 112 | 113 | *Depends on* `AGM`, `ELLIPJ`, `ELLIPKE`
114 | *See also* `ELLIPTIC12`, `ELLIPTIC12I`, `THETA` 115 | 116 | ## THETA: Theta Functions of Four Types 117 | 118 | `THETA` evaluates theta functions of four types. 119 | 120 | `Th = THETA(TYPE,V,M)` returns values of theta functions 121 | evaluated for corresponding values of argument `V` and parameter `M`. `TYPE` is a type of the theta function, there are four numbered types. The arrays `V` and `M` must be the same size (or either can be scalar). As currently implemented, `M` is limited to `0 <= M <= 1`. 122 | 123 | `Th = THETA(TYPE,V,M,TOL)` computes the theta and eta elliptic functions to the accuracy `TOL` instead of the default `TOL = EPS`. 124 | 125 | The parameter `M` is related to the nome `Q` as `Q = exp(-pi*K(1-M)/K(M))`. Some definitions of the Jacobi's elliptic functions use the modulus `k` instead of the parameter `m`. They are related by `m = k^2`. 126 | 127 | ### Example: 128 | ``` 129 | [phi,alpha] = meshgrid(0:5:90, 0:2:90); 130 | Th1 = theta(1, pi/180*phi, sin(pi/180*alpha).^2); 131 | Th2 = theta(2, pi/180*phi, sin(pi/180*alpha).^2); 132 | Th3 = theta(3, pi/180*phi, sin(pi/180*alpha).^2); 133 | Th4 = theta(4, pi/180*phi, sin(pi/180*alpha).^2); 134 | ``` 135 | 136 | _Depends on_ `AGM`, `ELLIPJ`, `ELLIPKE`, `JACOBITHETAETA`
137 | _See also_ `ELLIPTIC12`, `ELLIPTIC12I` 138 | 139 | ## THETA_PRIME: Theta Functions and Their Derivatives 140 | 141 | `THETA_PRIME` evaluates theta functions and their derivatives with respect to the argument. 142 | 143 | `[TH, THP] = THETA_PRIME(J, Z, M)` returns values of the Jacobi theta function `TH` and its derivative `THP` with respect to the argument `Z`. `J` is the type of theta function (1, 2, 3, or 4), `Z` is the argument, and `M` is the parameter (0 <= M <= 1). 144 | 145 | `[TH, THP] = THETA_PRIME(J, Z, M, TOL)` computes the theta function and its derivative to the accuracy `TOL` instead of the default `TOL = EPS`. 146 | 147 | The arrays `Z` and `M` must be the same size (or either can be scalar). As currently implemented, `M` is limited to `0 <= M <= 1`. 148 | 149 | The derivatives are computed using the relation: 150 | ``` 151 | θ'ⱼ(z,m) = θⱼ(z,m) * (2K/π) * (Z + δⱼ) 152 | ``` 153 | where `K` is the complete elliptic integral, `Z` is the Jacobi zeta function, and `δⱼ` depends on the theta function type. 154 | 155 | ### Example: 156 | ``` 157 | j = 1; z = 0.5; m = 0.8; 158 | [th, thp] = theta_prime(j, z, m); 159 | ``` 160 | 161 | **Note:** To reproduce results in Mathematica, use the `inversenomeq` function to convert from Mathematica's nome parameter to the parameter `m`: 162 | ``` 163 | [th_4, thp_4] = theta_prime(4, z, inversenomeq(0.1)); 164 | ``` 165 | 166 | _Depends on_ `THETA`, `ELLIPJ`, `ELLIPTIC12`, `ELLIPKE`
167 | _See also_ `THETA`, `JACOBITHETAETA`, `INVERSENOMEQ` 168 | 169 | # Elliptic Integrals 170 | 171 | Elliptic integrals originally arose in connection with the problem of giving the arc length of an ellipse. They were first studied by Giulio Fagnano and Leonhard Euler. Modern mathematics defines an elliptic integral as any function f which can be expressed in the form 172 | 173 | ``` 174 | f(x) = Integral(R(t,P(t), c, x)dt, 175 | ``` 176 | 177 | where `R` is a rational function of its two arguments, `P` is the square root of a polynomial of degree `3` or `4` with no repeated roots, and `c` is a constant. 178 | In general, elliptic integrals cannot be expressed in terms of elementary functions. Exceptions to this general rule are when `P` has repeated roots, or when `R(x,y)` contains no odd powers of `y`. However, with the appropriate reduction formula, every elliptic integral can be brought into a form that involves integrals over rational functions and the three canonical forms (i.e. the elliptic integrals of the first, second and third kind). 179 | 180 | ## ELLIPTIC12: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function 181 | 182 | `ELLIPTIC12` evaluates the value of the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function. 183 | 184 | `[F,E,Z] = ELLIPTIC12(U,M,TOL)` uses the method of the Arithmetic-Geometric Mean and Descending Landen Transformation described in [1](#references) Ch. 17.6, to determine the value of the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function (see [1](#references), [2](#references)). 185 | 186 | ### General definition: 187 | 188 | ``` 189 | F(phi,m) = int(1/sqrt(1-m*sin(t)^2), t=0..phi); 190 | E(phi,m) = int(sqrt(1-m*sin(t)^2), t=0..phi); 191 | Z(phi,m) = E(u,m) - E(m)/K(m)*F(phi,m). 192 | ``` 193 | 194 | Tables generating code (see [1](#references), pp. 613-621): 195 | 196 | ``` 197 | [phi,alpha] = meshgrid(0:5:90, 0:2:90); % modulus and phase in degrees 198 | [F,E,Z] = elliptic12(pi/180*phi, sin(pi/180*alpha).^2); % values of integrals 199 | ``` 200 | 201 | *Depends on* `AGM`
202 | *See also* `ELLIPKE`, `ELLIPJ`, `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 203 | 204 | ## ELLIPTIC12I: Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function of the complex argument 205 | 206 | `ELLIPTIC12i` evaluates the Incomplete Elliptic Integrals of the First, Second Kind and Jacobi's Zeta Function for the complex value of phase `U`. Parameter `M` must be in the range `0 <= M <= 1`. 207 | 208 | `[Fi,Ei,Zi] = ELLIPTIC12i(U,M,TOL)` where `U` is a complex phase in radians, `M` is the real parameter and `TOL` is the tolerance (optional). Default value for the tolerance is `eps = 2.220e-16`. 209 | 210 | `ELLIPTIC12i` uses the function `ELLIPTIC12` to evaluate the values of corresponding integrals. 211 | 212 | ### Example: 213 | 214 | ``` 215 | [phi1,phi2] = meshgrid(-2*pi:3/20:2*pi, -2*pi:3/20:2*pi); 216 | phi = phi1 + phi2*i; 217 | [Fi,Ei,Zi] = elliptic12i(phi, 0.5); 218 | ``` 219 | 220 | _Depends on_ `ELLIPTIC12`, `AGM`
221 | _See also_ `ELLIPKE`, `ELLIPJ`, `ELLIPTIC3`, `THETA`. 222 | 223 | ## ELLIPTIC3: Incomplete Elliptic Integral of the Third Kind 224 | 225 | `ELLIPTIC3` evaluates incomplete elliptic integral of the third kind `Pi = ELLIPTIC3(U,M,C)` where `U` is a phase in radians, `0 < M < 1` is the module and `0 < C < 1` is a parameter. 226 | 227 | `ELLIPTIC3` uses Gauss-Legendre 10 points quadrature template described in [3] to determine the value of the Incomplete Elliptic Integral of the Third Kind (see [1, 2]). 228 | 229 | ### General definition: 230 | 231 | ``` 232 | Pi(u,m,c) = int(1/((1 - c*sin(t)^2)*sqrt(1 - m*sin(t)^2)), t=0..u) 233 | ``` 234 | 235 | Tables generating code ([1](#references), pp. 625-626): 236 | ``` 237 | [phi,alpha,c] = meshgrid(0:15:90, 0:15:90, 0:0.1:1); 238 | Pi = elliptic3(pi/180*phi, sin(pi/180*alpha).^2, c); % values of integrals 239 | ``` 240 | 241 | ## ELLIPTIC123: Complete and Incomplete Elliptic Integrals of the First, Second, and Third Kind 242 | 243 | `ELLIPTIC123` is a wrapper around the different elliptic integral functions, providing a unified interface and greater range of input parameters. (Unlike ELLIPKE, ELLIPTIC12 and ELLIPTIC3, which all require a phase between zero and pi/2 and a parameter between zero and one.) 244 | 245 | `[F,E] = ELLIPTIC123(m)` — complete Elliptic Integrals of the first and second kind. 246 | 247 | `[F,E] = ELLIPTIC123(b,m)` — incomplete Elliptic Integrals of the first and second kind. 248 | 249 | `[F,E,PI] = ELLIPTIC123(m,n)` — complete Elliptic Integrals of the first to third kind. 250 | 251 | `[F,E,PI] = ELLIPTIC123(b,m,n)` — incomplete Elliptic Integrals of the first to third kind. 252 | 253 | The order of the input arguments has been chosen to be consistent with the pre-existing `elliptic12` and `elliptic3` functions. 254 | 255 | This function is still under development and its results are not always well-defined or even able to be calculated (especially for the third elliptic integral with `n>1`). Please see the documentation for further details. 256 | 257 | ## INVERSELLIPTIC2: INVERSE Incomplete Elliptic Integrals of the Second Kind 258 | 259 | `INVERSELLIPTIC2` evaluates the value of the INVERSE Incomplete Elliptic Integrals of the Second Kind. 260 | 261 | `INVERSELLIPTIC2` uses the method described by Boyd J. P. to determine the value of the inverse Incomplete Elliptic Integrals of the Second Kind using the “Empirical” initialization to the Newton’s iteration method [7](#references). 262 | 263 | Elliptic integral of the second kind: 264 | 265 | ``` 266 | E(phi,m) = int(sqrt(1-m*sin(t)^2), t=0..phi); 267 | ``` 268 | 269 | “Empirical” initialization [7](#references): 270 | 271 | ``` 272 | T0(z,m) = pi/2 + sqrt(r)/(theta − pi/2) 273 | ``` 274 | 275 | where 276 | 277 | ``` 278 | z \in [E(pi/2,m)](−E(pi/2,m),)x[1](0,) - value of the entire parameter space 279 | r = sqrt((1-m)^2 + zeta^2) 280 | zeta = 1 - z/E(pi/2,m) 281 | theta = atan((1 - m)/zeta) 282 | ``` 283 | 284 | Example: 285 | ``` 286 | % modulus and phase in degrees 287 | [phi,alpha] = meshgrid(0:5:90, 0:2:90); 288 | % values of integrals 289 | [F,E] = elliptic12(pi/180*phi, sin(pi/180*alpha).^2); 290 | % values of inverse 291 | invE = inverselliptic2(E, sin(pi/180*alpha).^2); 292 | % the difference between phase phi and invE should close to zero 293 | phi - invE * 180/pi 294 | ``` 295 | 296 | # Weierstrass's elliptic functions (in development) 297 | 298 | !IN DEVELOPMENT, help needed!. 299 | 300 | Weierstrass's elliptic functions are elliptic functions that take a particularly simple form (cf Jacobi's elliptic functions); they are named for Karl Weierstrass. This class of functions are also referred to as p-functions and generally written using the symbol `℘` (a stylised letter p called Weierstrass p). 301 | 302 | The Weierstrass elliptic function can be defined in three closely related ways, each of which possesses certain advantages. One is as a function of a complex variable z and a lattice Λ in the complex plane. Another is in terms of z and two complex numbers ω1 and ω2 defining a pair of generators, or periods, for the lattice. The third is in terms z and of a modulus τ in the upper half-plane. This is related to the previous definition by `τ = ω2 / ω1`, which by the conventional choice on the pair of periods is in the upper half-plane. Using this approach, for fixed z the Weierstrass functions become modular functions of τ. 303 | 304 | 305 | # Elliptic Related Functions 306 | 307 | ## AGM: Artihmetic Geometric Mean 308 | 309 | `AGM` calculates the [Artihmetic Geometric Mean](http://en.wikipedia.org/wiki/Arithmetic-geometric_mean) of `A` and `B` (see [1](#references)). 310 | 311 | `[A,B,C,N]= AGM(A0,B0,C0,TOL)` carry out the process of the arithmetic geometric mean, starting with a given positive numbers triple `(A0, B0, C0)` and returns in 312 | `(A, B, C)` the generated sequence. `N` is a number of steps (returns in the value`uint32`). 313 | 314 | The general scheme of the procedure: 315 | 316 | ``` 317 | A(i) = 1/2*( A(i-1)+B(i-1) ); A(0) = A0; 318 | B(i) = sqrt( A(i-1)*B(i-1) ); B(0) = B0; 319 | C(i) = 1/2*( A(i-1)-B(i-1) ); C(0) = C0; 320 | ``` 321 | 322 | Stop at the `N`-th step when `A(N) = B(N)`, i.e., when `C(N) = 0`. 323 | 324 | _Used by_ `ELLIPJ` and `ELLIPTIC12`.
_See also_ `ELLIPKE`, `ELLIPTIC3`, `THETA`. 325 | 326 | ## NOMEQ: The Value of Nome `q = q(m)` 327 | 328 | `NOMEQ` gives the value of Nome `q = q(m)`. 329 | 330 | Nome `Q = nomeq(M,TOL)`, where `0<=M<=1` is the module and `TOL` is the tolerance (optional). Default value for the tolerance is `eps = 2.220e-16`. 331 | 332 | *Used by* `ELLIPJ`.
333 | *Depends on* `ELLIPKE`
334 | *See also* `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 335 | 336 | ## INVERSENOMEQ: The Value of Nome `m = m(q)` 337 | 338 | `INVERSENOMEQ` gives the value of Nome `m = m(q)`. 339 | 340 | `M = inversenomeq(q)`, where `Q` is the Nome of q-series. 341 | 342 | **WARNING**. The function `INVERSENOMEQ` does not return correct values of `M` for `Q > 0.6`, because of computer precision limitation. The function `NomeQ(m)` has an essential singularity at `M = 1`, so it cannot be inverted at this point and actually it is very hard to find and inverse in the neigborhood also. 343 | 344 | More preciesly: 345 | 346 | ``` 347 | nomeq(1) = 1 348 | nomeq(1-eps) = 0.77548641878026 349 | ``` 350 | 351 | ### Example: 352 | 353 | ``` 354 | nomeq(inversenomeq([0.3 0.4 0.5 0.6 0.7 0.8])) 355 | warning: The function INVERSENOMEQ does not return 356 | correct values of M for Q < 0.00001 and Q > 0.76, because of computer precision limitation. 357 | warning: called from 358 | inversenomeq at line 54 column 5 359 | 360 | ans = 361 | 362 | 0.3000 0.4000 0.5000 0.5948 0.7000 0.7447 363 | ``` 364 | 365 | *Used by* `ELLIPJ`.
366 | *Depends on* `ELLIPKE`
367 | *See also* `ELLIPTIC12I`, `ELLIPTIC3`, `THETA`. 368 | 369 | # Running tests 370 | 371 | From root folder run `runtests` or check the CI build status [![CircleCI](https://dl.circleci.com/status-badge/img/gh/moiseevigor/elliptic/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/moiseevigor/elliptic/tree/master) 372 | 373 | ``` 374 | runtests("tests") 375 | Processing files in /home/igor/Work/elliptic/tests: 376 | 377 | testEllipj.m ................................................ PASS 5/5 378 | testElliptic12.m ............................................ PASS 5/5 379 | testElliptic3.m ............................................. PASS 5/5 380 | testThetaPrime.m ............................................ PASS 15/15 381 | ``` 382 | 383 | # Contributors 384 | 385 | Contributors 386 | 387 | - [@moiseevigor](http://github.com/moiseevigor/) - maintainer (Igor Moiseev) 388 | - [@drbitboy](https://github.com/drbitboy) (Brian Carcich) 389 | - [@wspr](https://github.com/wspr) (Will Robertson) 390 | 391 | 392 | # References 393 | 394 | 1. [NIST Digital Library of Mathematical Functions](http://dlmf.nist.gov/) 395 | 1. M. Abramowitz and I.A. Stegun, "[Handbook of Mathematical Functions](http://www.nrbook.com/abramowitz_and_stegun/)" Dover Publications", 1965, Ch. 17.1 - 17.6. 396 | 1. D. F. Lawden, "[Elliptic Functions and Applications](http://www.amazon.com/Elliptic-Functions-Applications-Mathematical-Sciences/dp/0387969659)" Springer-Verlag, vol. 80, 1989 397 | 1. S. Zhang, J. Jin, "[Computation of Special Functions](http://jin.ece.uiuc.edu/specfunc.html)" (Wiley, 1996). 398 | 1. B. Carlson, "[Three Improvements in Reduction and Computation of Elliptic Integrals](http://nvl.nist.gov/pub/nistpubs/jres/107/5/j75car.pdf)", J. Res. Natl. Inst. Stand. Technol. 107 (2002) 413-418. 399 | 1. N. H. Abel, "[Studies on Elliptic Functions](http://mathdl.maa.org/mathDL/46/?pa=content&sa=viewDocument&nodeId=1557)", english translation from french by Marcus Emmanuel Barnes. Original "Recherches sur les fonctions elliptiques", Journal fr die reine und angewandte Mathematik, Vol. 2, 1827. pp. 101-181. 400 | 1. B. C. Berndt, H. H. Chan, S.-S. Huang, "[Incomplete Elliptic Integrals in Ramanujan's Lost Notebook](http://www.math.uiuc.edu/~berndt/articles/ellipticintegral.pdf)" in q-series from a Contemporary Perspective, M. E. H. Ismail and D. Stanton, eds., Amer. Math. Soc., 2000, pp. 79-126. 401 | 1. J. P. Boyd, "Numerical, Perturbative and Chebyshev Inversion of the Incomplete Elliptic Integral of the Second Kind", Applied Mathematics and Computation (January 2012) 402 | -------------------------------------------------------------------------------- /elliptic123.m: -------------------------------------------------------------------------------- 1 | function [F,E,P]=elliptic123(a1,a2,a3) 2 | %ELLIPTIC123 computes the first, second and third elliptic integrals for 3 | % both the complete and incomplete cases and no restriction on the input 4 | % arguments. (Modulo some bugs; see below.) 5 | % 6 | % [F,E]=elliptic123(b,m) 7 | % Calculates incomplete elliptic integrals of the first and second kind, 8 | % F and E, respectively. 9 | % - Phase angle b may be any real or complex number 10 | % - Parameter m can be any real number 11 | % 12 | % [K,E]=elliptic123(m) 13 | % Calculate complete elliptic integrals of the first and second kind, 14 | % K and E, respectively. 15 | % - Equivalent to [K,E]=elliptic12(pi/2,m) but calculated more 16 | % efficiently 17 | % 18 | % [K,E,P]=elliptic123(m,n) 19 | % Calculates the complete elliptic integrals of the first, second and 20 | % third kind, K, E and P respectively 21 | % The n parameter is only used for the elliptic PI case (third case) 22 | % 23 | % [F,E,P]=elliptic123(b,m,n) 24 | % Calculates the incomplete elliptic integrals of the first, second and 25 | % third kind, F, E and P respectively 26 | % The n parameter is only used for the elliptic PI case (third case) 27 | % 28 | % There is a bug in the incomplete case for F and E: 29 | % when complex numbers are expected in the output, the complex part will 30 | % not be calculated correctly when m>M where M=1/sin(b)^2. 31 | % 32 | % There are many bugs in the calculations for EllipticPi. Results are 33 | % correct for n<1 & m M 51 | % 52 | % b<0 Pass Real 53 | % 0pi/2 Pass Real 55 | % 56 | % 57 | % PI(m,n): m<=1 m>1 58 | % 59 | % n<0 Pass Fail1 60 | % 0M 65 | % 66 | % n<0 Pass Pass Fail1 67 | % 0pi/2 72 | % m<1 m=1 1M 73 | % 74 | % n<0 Pass Pass Pass Fail1 75 | % 0 83 | % 84 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 85 | % http://www.gnu.org/licenses/gpl.html 86 | % Everyone is permitted to copy and distribute verbatim copies of this 87 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 88 | 89 | if nargout<3 90 | 91 | if nargin==1 92 | [F,E] = elliptic12c(a1); % == elliptic12(m) 93 | elseif nargin==2 94 | [F,E] = elliptic12x(a1,a2); % == elliptic12(b,m) 95 | else 96 | error('Wrong number of input arguments') 97 | end 98 | 99 | elseif nargout==3 100 | 101 | if nargin==2 102 | [F,E] = elliptic12c(a1); % == elliptic12(m) 103 | P=elliptic3c(a1,a2); % == elliptic3(m,n) 104 | elseif nargin==3 105 | [F,E] = elliptic12x(a1,a2); % == elliptic12(b,m) 106 | P=elliptic3x(a1,a2,a3); % == elliptic3(b,m,n) 107 | else 108 | error('Wrong number of input arguments') 109 | end 110 | 111 | else 112 | error('Wrong number of output arguments') 113 | end 114 | 115 | % multidimensional input reshape 116 | F = reshape(F,size(a1)); 117 | E = reshape(E,size(a1)); 118 | if nargin==3, P = reshape(P,size(a1)); end 119 | 120 | end 121 | 122 | function [F,E]=elliptic12c(m) 123 | %ELLIPTIC12c computes the first and second Elliptic integrals for the 124 | % complete cases and no restriction on the input arguments. 125 | % 126 | % [K,E]=elliptic12(m) 127 | % Calculate complete elliptic integrals of the first and second kind, 128 | % K and E, respectively. 129 | % - Equivalent to [K,E]=elliptic12(pi/2,m) but calculated more 130 | % efficiently 131 | 132 | N=size(m); 133 | F=nan(size(m)); 134 | 135 | % Imaginary-modulus transformation: http://dlmf.nist.gov/19.7#E5 136 | if any(m<0) 137 | mm=m(m<0); 138 | F(m<0)=(1./sqrt(1-mm)).*ellipke(-mm./(1-mm)); 139 | end 140 | 141 | 142 | % Reciprocal-modulus transformation: http://dlmf.nist.gov/19.7#E4 143 | if any(m>1) 144 | mm=m(m>1); 145 | F(m>1)=(1./sqrt(mm)).*(elliptic12i(asin(sqrt(mm)),1./mm)); 146 | end 147 | 148 | if any(m<=1&m>=0) 149 | mm=m(m<=1&m>=0); 150 | F(m<=1&m>=0)=ellipke(mm); 151 | end 152 | 153 | if nargout>1 154 | 155 | E=nan(size(m)); 156 | 157 | % Imaginary-modulus transformation: http://dlmf.nist.gov/19.7#E5 158 | if any(m<0) 159 | mm=m(m<0); 160 | [FF,EE]= ellipke(-mm./(1-mm)); %to define if your using the F output in elliptic12 or the E output 161 | E(m<0)=sqrt(1-mm).*EE; 162 | end 163 | 164 | % Reciprocal-modulus transformation: http://dlmf.nist.gov/19.7#E4 165 | if any(m>1) 166 | mm=m(m>1); 167 | [FF,EE]=elliptic12i(asin(sqrt(mm)),1./mm); 168 | E(m>1)=((1./sqrt(mm))-sqrt(mm)).*FF+sqrt(mm).*EE; 169 | end 170 | 171 | if any(m<=1&m>=0) 172 | mm=m(m<=1&m>=0); 173 | [FF,E(m<=1&m>=0)]=ellipke(mm); 174 | end 175 | end 176 | 177 | end 178 | 179 | 180 | function [F,E]=elliptic12x(b,m) 181 | %ELLIPTIC12x computes the first and second Elliptic integrals for the 182 | % incomplete cases and no restriction on the input arguments. 183 | % 184 | % [F,E]=elliptic12(b,m) 185 | % Calculate incomplete elliptic integrals of the first and second kind, 186 | % F and E, respectively. 187 | % - Phase angle b may be any real or complex number 188 | % - Parameter m can be any real number 189 | % 190 | % There is a bug: (!) 191 | % when complex numbers are expected in the output, the complex part will 192 | % not be calculated correctly when m>(1/sin(b))^2. 193 | 194 | 195 | if length(b)==1, b=b(ones(size(m))); end 196 | if length(m)==1, m=m(ones(size(b))); end 197 | if ~isequal(size(b),size(m)) 198 | error('m and b must be equal sizes') 199 | end 200 | 201 | % Periodicity: http://dlmf.nist.gov/19.2#E10 202 | phase_ind = b>pi/2 | b<0; 203 | mone_ind= m==1; 204 | if any(phase_ind & ~mone_ind) 205 | 206 | mm = m(phase_ind); 207 | bb = b(phase_ind); 208 | 209 | phi = mod(bb+pi/2,pi)-pi/2; 210 | a = round(bb./pi); 211 | F(phase_ind) = 2.*a.*elliptic12c(mm) + sign(phi).*elliptic12x(abs(phi),mm); 212 | 213 | end 214 | 215 | % Special case: http://dlmf.nist.gov/19.6#E1 216 | if any(mone_ind) 217 | F(mone_ind)=inf; 218 | end 219 | 220 | % Imaginary-modulus transformation: http://dlmf.nist.gov/19.7#E5 221 | mneg_ind = m<0 & ~phase_ind; 222 | if any(mneg_ind) 223 | 224 | mm=m(mneg_ind); 225 | bb=b(mneg_ind); 226 | 227 | t=asin((sin(bb).*sqrt(1-mm))./sqrt(1-mm.*(sin(bb)).^2)); 228 | F(mneg_ind)=(1./sqrt(1-mm)).*elliptic12i(t,-mm./(1-mm)); 229 | 230 | end 231 | 232 | % Reciprocal-modulus transformation: http://dlmf.nist.gov/19.7#E4 233 | mpos_ind = m>1 & ~phase_ind; 234 | if any(mpos_ind) 235 | 236 | mm=m(mpos_ind); 237 | bb=b(mpos_ind); 238 | 239 | F(mpos_ind)=(1./sqrt(mm)).*(elliptic12i(asin(sqrt(mm).*sin(bb)),1./mm)); 240 | warning('elliptic123:F_bm_largem','Complex part may be missing and/or incorrect for ellipticF(b,m>1).'); 241 | 242 | end 243 | 244 | % Regular old calculation 245 | mreg_ind=m<=1&m>=0 & ~phase_ind; 246 | if any(mreg_ind) 247 | 248 | mm=m(mreg_ind); 249 | bb=b(mreg_ind); 250 | F(mreg_ind)=elliptic12i(bb,mm); 251 | 252 | end 253 | 254 | 255 | if nargout>1 256 | 257 | % Periodicity: http://dlmf.nist.gov/19.2#E10 258 | phase_ind = b>pi/2 | b<0; 259 | if any(phase_ind) 260 | mm = m(phase_ind); 261 | bb = b(phase_ind); 262 | 263 | phi = mod(bb+pi/2,pi)-pi/2; 264 | a = round(bb./pi); 265 | [F1,E1]=elliptic12c(mm); 266 | [FF,EE]=elliptic12x(abs(phi),mm); 267 | E(phase_ind) = 2*a.*E1 + sign(phi).*EE; 268 | end 269 | 270 | % Special case: http://dlmf.nist.gov/19.6#E9 271 | mz_ind = m==0 & ~phase_ind; 272 | if any(mz_ind) 273 | bb=b(mz_ind); 274 | E(mz_ind)=bb; 275 | end 276 | 277 | % Imaginary-modulus transformation: http://dlmf.nist.gov/19.7#E5 278 | mneg_ind = m<0 & ~phase_ind; 279 | if any(mneg_ind) 280 | mm=m(mneg_ind); 281 | bb=b(mneg_ind); 282 | 283 | t=asin((sin(bb).*sqrt(1-mm))./sqrt(1-mm.*(sin(bb)).^2)); 284 | [FF,EE]= elliptic12i(t,-mm./(1-mm)); %to define if your using the F output in elliptic12 or the E output 285 | E(mneg_ind)=mm.*(sin(t).*cos(t)./sqrt(1-mm.*(cos(t)).^2))+sqrt(1-mm).*EE; 286 | end 287 | 288 | % Reciprocal-modulus transformation: http://dlmf.nist.gov/19.7#E4 289 | mpos_ind = m>1 & ~phase_ind; 290 | if any(mpos_ind) 291 | mm=m(mpos_ind); 292 | bb=b(mpos_ind); 293 | 294 | [FF,EE]=elliptic12i(asin(sqrt(mm).*sin(bb)),1./mm); %cannot display complex part 295 | E(mpos_ind)=((1./sqrt(mm))-sqrt(mm)).*FF+sqrt(mm).*EE; 296 | warning('elliptic123:BadComplex','Complex part may be missing'); 297 | 298 | end 299 | 300 | % Regular calculation: 301 | mreg_ind=m<=1&m>0 & ~phase_ind; 302 | if any(mreg_ind) 303 | mm=m(mreg_ind); 304 | bb=b(mreg_ind); 305 | [FF,E(mreg_ind)]=elliptic12i(bb,mm); %note the elliptic12i function cannot evaluate at m=0 for E 306 | end 307 | 308 | end 309 | 310 | end 311 | 312 | 313 | 314 | function [P]=elliptic3c(m,n) 315 | 316 | % For the complete case P=elliptic3(m,n) 317 | % simpler equations implemented (ellippi and ellippin) 318 | % n>1 possible but complex part of solution not shown 319 | 320 | 321 | if length(m)==1, m=m(ones(size(n))); end 322 | if length(n)==1, n=n(ones(size(m))); end 323 | 324 | if ~isequal(size(n),size(m)) 325 | error('Inputs m and b must be equal sizes') 326 | end 327 | 328 | % Special case: http://dlmf.nist.gov/19.6#E3 329 | mz_ind = m==0; 330 | if any(mz_ind) 331 | nn=n(mz_ind); 332 | P(mz_ind)=pi./(2.*sqrt(1-nn)); 333 | end 334 | 335 | % Imaginary-modulus transformation: http://dlmf.nist.gov/19.7#E5 336 | mlnl_ind = m~=0 & m<=1 & n<=1; 337 | if any(mlnl_ind) 338 | nn=n(mlnl_ind); 339 | mm=m(mlnl_ind); 340 | P(mlnl_ind)=ellippi(nn,mm); 341 | end 342 | 343 | % Reciprocal-modulus transformation: http://dlmf.nist.gov/19.7#E4 344 | mgnl_ind=m>1 & n<=1; 345 | if any(mgnl_ind) %% this doesnt work as b becomes complex 346 | mm=m(mgnl_ind); 347 | nn=n(mgnl_ind); 348 | P(mgnl_ind)=1./sqrt(mm).*elliptic3ic(asin(sqrt(mm)),1./mm,nn./mm); 349 | end 350 | 351 | % Normal calculation: 352 | mlng_ind=n>1 & m<=1; 353 | if any(mlng_ind) %%only gives real 354 | mm=m(mlng_ind); 355 | nn=n(mlng_ind); 356 | P(mlng_ind)=ellippin(nn,mm); 357 | warning('elliptic123:MissingComplex','Cannot compute complex part for elliptic3(m,n) with m<=1 and n>1') 358 | end 359 | 360 | % Problem: 361 | mgng_ind=n>1 & m>1; 362 | if any(mgng_ind) 363 | warning('elliptic123:PI_mn_large','Cannot calculate elliptic3(m,n) for n>1 and m>1.') 364 | end 365 | 366 | end 367 | 368 | 369 | 370 | function [P]=elliptic3x(b,m,n) 371 | 372 | isize=max(max(size(b),size(m)),size(n)); 373 | 374 | if length(n)==1, n=n(ones(isize)); end 375 | if length(m)==1, m=m(ones(isize)); end 376 | if length(b)==1, b=b(ones(isize)); end 377 | 378 | if ~isequal(size(n),size(m)) || ~isequal(size(n),size(b)) 379 | error('Inputs m and b and n must be equal sizes.') 380 | end 381 | 382 | phase_ind = b>pi/2 | b<0; 383 | mone_ind= m==1; 384 | 385 | % Periodicity for n>1 386 | % 387 | % This is not documented anywhere, but plotting the function in Mathematica 388 | % shows clearly that it's (anti-)symmetric around zero and pi/2. 389 | 390 | phasen_ind=phase_ind & n>1; 391 | if any(phasen_ind) 392 | 393 | mm = m(phasen_ind); 394 | bb = b(phasen_ind); 395 | nn = n(phasen_ind); 396 | 397 | if any(b>pi/2 & bpi) 403 | 404 | P(phasen_ind)=conj(elliptic3x(bb-pi,mm,nn)); 405 | 406 | elseif any(b<-pi/2 & b>-pi) 407 | 408 | cc=-pi/2-bb; 409 | P(phasen_ind)=conj(-elliptic3x(-pi/2+cc,mm,nn)); 410 | 411 | elseif any(bM) 443 | warning('elliptic123:PI_bmn_large_m','Cannot calculate elliptic3(b,m,n) with m greater than the critical value.') 444 | end 445 | 446 | % Special case m==n: http://dlmf.nist.gov/19.6#E13 447 | mnequal_ind = m==n & ~phase_ind; 448 | if any(mnequal_ind) 449 | 450 | bb=b(mnequal_ind); 451 | mm=m(mnequal_ind); 452 | nn=n(mnequal_ind); 453 | 454 | [FF,EE]= elliptic12x(bb,mm); 455 | 456 | P(mnequal_ind)=(1./(1-mm)).*(EE-((mm./sqrt(1-mm.*(sin(bb)).^2)).*sin(bb).*cos(bb))); 457 | 458 | end 459 | 460 | % Reciprocal-modulus transformation: http://dlmf.nist.gov/19.7#E4 461 | mgnl_ind = m>1 & n<1 & ~phase_ind; 462 | if any(mgnl_ind) 463 | 464 | bb=b(mgnl_ind); 465 | mm=m(mgnl_ind); 466 | nn=n(mgnl_ind); 467 | 468 | P(mgnl_ind)=1./sqrt(mm).*elliptic3ic(asin(sqrt(mm).*sin(bb)),1./mm,nn./mm); 469 | 470 | end 471 | 472 | % Imaginary-modulus transformation: http://dlmf.nist.gov/19.7#E5 473 | mlnl_ind = m~=n & m<0 & n<1 & ~phase_ind; 474 | if any(mlnl_ind) 475 | 476 | bb=b(mlnl_ind); 477 | mm=m(mlnl_ind); 478 | nn=n(mlnl_ind); 479 | 480 | t=asin((sin(bb).*sqrt(1-mm))./sqrt(1-mm.*(sin(bb)).^2)); 481 | 482 | P(mlnl_ind)=1./((nn-mm).*sqrt(1-mm)).*(-mm.*elliptic12x(t,-mm./(1-mm))+nn.*elliptic3ic(t,-mm./(1-mm),(nn-mm)./(1-mm))); 483 | 484 | end 485 | 486 | % Normal ranges: 487 | mnormnl_ind=n<1 & ~phase_ind & m>=0 & m<=1; 488 | if any(mnormnl_ind) 489 | 490 | bb=b(mnormnl_ind); 491 | mm=m(mnormnl_ind); 492 | nn=n(mnormnl_ind); 493 | 494 | P(mnormnl_ind)=elliptic3ic(bb,mm,nn); 495 | 496 | end 497 | 498 | % Refer to 17.7.8 in Abramowitz: 499 | ng_ind=n>1 & m1 but m1 & ~phase_ind & m>n) 515 | warning('elliptic123:PI_bmn_large','Cannot calculate elliptic3(b,m,n) for n>1 and m>n.') 516 | end 517 | 518 | end 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | function [Fi,Ei,Zi] = elliptic12i(u,m,tol) 527 | 528 | % ELLIPTIC12i evaluates the Incomplete Elliptic Integrals 529 | % of the First, Second Kind and Jacobi's Zeta Function for the complex 530 | % value of phase U. Parameter M must be in the range 0 <= M <= 1. 531 | % 532 | % [Fi,Ei,Zi] = ELLIPTIC12i(U,M,TOL) where U is a complex phase in 533 | % radians, M is the real parameter and TOL is the tolerance (optional). 534 | % Default value for the tolerance is eps = 2.220e-16. 535 | % 536 | % ELLIPTIC12i uses the function ELLIPTIC12 to evaluate the values of 537 | % corresponding integrals. 538 | % 539 | % Example: 540 | % [phi1,phi2] = meshgrid(-2*pi:3/20:2*pi, -2*pi:3/20:2*pi); 541 | % phi = phi1 + phi2*i; 542 | % [Fi,Ei,Zi] = elliptic12i(phi, 0.5); 543 | % 544 | % See also ELLIPKE, ELLIPJ, ELLIPTIC12. 545 | % 546 | % References: 547 | % [1] M. Abramowitz and I.A. Stegun, "Handbook of Mathematical Functions", 548 | % Dover Publications", 1965, Ch. 17.1 - 17.6 (by L.M. Milne-Thomson). 549 | 550 | % GNU GENERAL PUBLIC LICENSE Version 2, June 1991 551 | % http://www.gnu.org/licenses/gpl.html 552 | % Everyone is permitted to copy and distribute verbatim copies of this 553 | % script under terms and conditions of GNU GENERAL PUBLIC LICENSE. 554 | % 555 | % Copyright (C) 2007 by Moiseev Igor. All rights reserved. 556 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 557 | % For support, please reply to 558 | % moiseev.igor[at]gmail.com, moiseev[at]sissa.it 559 | % Moiseev Igor, 560 | % 34106, SISSA, via Beirut n. 2-4, Trieste, Italy 561 | 562 | if nargin<3, tol = eps; end 563 | if nargin<2, error('Not enough input arguments.'); end 564 | 565 | if ~isreal(m) 566 | error('The parameter M must be real.') 567 | end 568 | 569 | if any(m < 0) || any(m > 1) 570 | error('M must be in the range 0 <= M <= 1.'); 571 | end 572 | 573 | % if the input is real, evaluate the elliptic integrals with ELLIPTIC12 574 | % if isreal(u) 575 | % [Fi,Ei,Zi] = elliptic12(u,m,tol); 576 | % return; 577 | % end 578 | 579 | if length(m)==1, m = m(ones(size(u))); end 580 | if length(u)==1, u = u(ones(size(m))); end 581 | if ~isequal(size(m),size(u)) 582 | error('U and M must be the same size.'); 583 | end 584 | 585 | % capture memory and save the structure of input arrays 586 | F1 = zeros(size(u)); F2 = zeros(size(u)); 587 | E1 = F1; E2 = F1; 588 | Z1 = F1; Z2 = F1; 589 | Fi = F1; Ei = F1; 590 | Zi = F1; 591 | lambda = []; mu = []; 592 | I = []; J = []; 593 | 594 | % make a row vector 595 | m = m(:).'; 596 | u = u(:).'; 597 | 598 | % represent u in the form u = phi + i*psi 599 | phi = real(u); 600 | psi = imag(u); 601 | 602 | % to avoid singularity of COT(phi) at zero add EPS 603 | I = find (abs(phi) < eps); 604 | phi(I) = eps; 605 | I = []; 606 | 607 | % finding the roots of the equation 608 | % X^2 - (cot(phi)^2+m*sinh(psi)^2*csc(phi)^2-1+m)X - (1-m)*cot(phi)^2 = 0 609 | b = -(cot(phi).^2 + m.*sinh(psi).^2.*csc(phi).^2-1+m); 610 | c = -(1-m).*cot(phi).^2; 611 | 612 | X1 = -b/2 + sqrt(b.^2/4-c); 613 | I = find(X1>=0); 614 | 615 | if length(I) ~= length(u) 616 | X2 = -b/2 - sqrt(b.^2/4-c); 617 | J = find(X2>=0); 618 | end 619 | 620 | if( ~isempty(I) ) 621 | lambda(I) = acot( sqrt(X1(I)) ); 622 | mu(I) = atan( sqrt(1./m(I).*(tan(phi(I)).^2.*cot(lambda(I)).^2 - 1)) ); 623 | end 624 | if( ~isempty(J) ) 625 | lambda(J) = acot( sqrt(X2(J)) ); 626 | mu(J) = atan( sqrt(1./m(J).*(tan(phi(J)).^2.*cot(lambda(J)).^2 - 1)) ); 627 | end 628 | 629 | % change of variables taking into account periodicity ceil to the right 630 | lambda = (-1).^floor(phi/pi*2).*lambda + pi*ceil(phi/pi-0.5+eps); 631 | mu = sign(psi).*real(mu); 632 | 633 | [F1(:),E1(:)] = elliptic12ic(lambda, m, tol); 634 | [F2(:),E2(:)] = elliptic12ic(mu, 1-m, tol); 635 | 636 | % complex values of elliptic integral of the first kind 637 | Fi = F1 + sqrt(-1)*F2; 638 | 639 | % some calucation optimiziation 640 | sin_lam = sin(lambda); cos_lam = cos(lambda); 641 | sin_mu = sin(mu); cos_mu = cos(mu); 642 | 643 | b1 = m.*sin_lam.*cos_lam.*sin_mu.^2.*sqrt(1-m.*sin_lam.^2); 644 | b2 = sin_mu.*cos_mu.*(1-m.*sin_lam.^2).*sqrt(1-(1-m).*sin_mu.^2); 645 | b3 = cos_mu.^2 + m.*sin_lam.^2.*sin_mu.^2; 646 | 647 | % complex values of elliptic integral of the second kind 648 | Ei(:) = (b1 + sqrt(-1)*b2)./b3; 649 | Ei(:) = Ei(:) + E1(:) + sqrt(-1)*(-E2(:) + F2(:)); 650 | 651 | [K,Ee] = ellipke(m); 652 | % complex values of zeta function 653 | Zi(:) = Ei(:) - Ee(:)./K(:).*Fi(:); 654 | end 655 | 656 | % END FUNCTION ELLIPTIC12i() 657 | 658 | function [F,E,Z] = elliptic12ic(u,m,tol) 659 | % 660 | % Bug fix for the elliptic12 in the main distribution. 661 | % This function should disappear when the fixes appear there. 662 | 663 | if nargin<3, tol = eps; end 664 | if nargin<2, error('Not enough input arguments.'); end 665 | 666 | if ~isreal(u) || ~isreal(m) 667 | error('Input arguments must be real. Use ELLIPTIC12i for complex arguments.'); 668 | end 669 | 670 | if length(m)==1, m = m(ones(size(u))); end 671 | if length(u)==1, u = u(ones(size(m))); end 672 | if ~isequal(size(m),size(u)), error('U and M must be the same size.'); end 673 | 674 | F = zeros(size(u)); 675 | E = F; 676 | Z = E; 677 | m = m(:).'; % make a row vector 678 | u = u(:).'; 679 | 680 | if any(m < 0) || any(m > 1), error('M must be in the range 0 <= M <= 1.'); end 681 | 682 | I = uint32( find(m ~= 1 & m ~= 0) ); 683 | if ~isempty(I) 684 | % Use standard uniquetol for numerical precision issues 685 | % This is the recommended MATLAB approach since R2015a 686 | m_vals = m(I); 687 | tol_unique = 1e-11; 688 | 689 | [mu, ~, K] = uniquetol(m_vals, tol_unique); 690 | K = uint32(K(:).'); % Ensure K is a row vector 691 | mumax = length(mu); 692 | signU = sign(u(I)); 693 | 694 | % pre-allocate space and augment if needed 695 | chunk = 7; 696 | a = zeros(chunk,mumax); 697 | c = a; 698 | b = a; 699 | a(1,:) = ones(1,mumax); 700 | c(1,:) = sqrt(mu); 701 | b(1,:) = sqrt(1-mu); 702 | n = uint32( zeros(1,mumax) ); 703 | i = 1; 704 | while any(abs(c(i,:)) > tol) % Arithmetic-Geometric Mean of A, B and C 705 | i = i + 1; 706 | if i > size(a,1) 707 | a = [a; zeros(2,mumax)]; 708 | b = [b; zeros(2,mumax)]; 709 | c = [c; zeros(2,mumax)]; 710 | end 711 | a(i,:) = 0.5 * (a(i-1,:) + b(i-1,:)); 712 | b(i,:) = sqrt(a(i-1,:) .* b(i-1,:)); 713 | c(i,:) = 0.5 * (a(i-1,:) - b(i-1,:)); 714 | in = uint32( find((abs(c(i,:)) <= tol) & (abs(c(i-1,:)) > tol)) ); 715 | if ~isempty(in) 716 | [mi,ni] = size(in); 717 | n(in) = ones(mi,ni)*(i-1); 718 | end 719 | end 720 | 721 | mmax = length(I); 722 | mn = double(max(n)); 723 | phin = zeros(1,mmax); C = zeros(1,mmax); 724 | Cp = C; e = uint32(C); phin(:) = signU.*u(I); 725 | i = 0; c2 = c.^2; 726 | while i < mn % Descending Landen Transformation 727 | i = i + 1; 728 | in = uint32(find(n(K) > i)); 729 | if ~isempty(in) 730 | phin(in) = atan(b(i,K(in))./a(i,K(in)).*tan(phin(in))) + ... 731 | pi.*ceil(phin(in)/pi - 0.5) + phin(in); 732 | e(in) = 2.^(i-1) ; 733 | C(in) = C(in) + double(e(in(1)))*c2(i,K(in)); 734 | Cp(in)= Cp(in) + c(i+1,K(in)).*sin(phin(in)); 735 | end 736 | end 737 | 738 | Ff = phin ./ (a(mn,K).*double(e)*2); 739 | F(I) = Ff.*signU; % Incomplete Ell. Int. of the First Kind 740 | Z(I) = Cp.*signU; % Jacobi Zeta Function 741 | E(I) = (Cp + (1 - 1/2*C) .* Ff).*signU; % Incomplete Ell. Int. of the Second Kind 742 | end 743 | 744 | % Special cases: m == {0, 1} 745 | m0 = find(m == 0); 746 | if ~isempty(m0), F(m0) = u(m0); E(m0) = u(m0); Z(m0) = 0; end 747 | 748 | m1 = find(m == 1); 749 | um1 = abs(u(m1)); 750 | if ~isempty(m1), 751 | N = floor( (um1+pi/2)/pi ); 752 | M = find(um1 < pi/2); 753 | 754 | F(m1(M)) = log(tan(pi/4 + u(m1(M))/2)); 755 | F(m1(um1 >= pi/2)) = Inf.*sign(u(m1(um1 >= pi/2))); 756 | 757 | E(m1) = ((-1).^N .* sin(um1) + 2*N).*sign(u(m1)); 758 | 759 | Z(m1) = (-1).^N .* sin(u(m1)); 760 | end 761 | end 762 | 763 | 764 | function Pi = elliptic3ic(u,m,c) 765 | % 766 | % Bug fix for the elliptic12 in the main distribution. 767 | % This function should disappear when the fixes appear there. 768 | 769 | if nargin<3, error('Not enough input arguments.'); end 770 | if ~isreal(u) | ~isreal(m) | ~isreal(c) 771 | error('Input arguments must be real.') 772 | end 773 | if any(m < 0) | any(m > 1), 774 | error('M must be in the range [0, 1].'); 775 | end 776 | if any(c > 1), 777 | error('C must be in the range [-inf, 1].'); 778 | end 779 | if any(u > pi/2) | any(u < 0), 780 | error('U must be in the range [0, pi/2].'); 781 | end 782 | 783 | [mm,nm] = size(m); 784 | [mu,nu] = size(u); 785 | if length(m)==1, m = m(ones(size(u))); end 786 | if length(c)==1, c = c(ones(size(u))); end 787 | if length(u)==1, u = u(ones(size(m))); end 788 | if ~isequal(size(m), size(c), size(u)), 789 | error('U, M and C must be the same size.'); 790 | end 791 | 792 | Pi = zeros(size(u)); 793 | m = m(:).'; % make a row vector 794 | u = u(:).'; 795 | c = c(:).'; 796 | 797 | I = find( u==pi/2 & m==1 | u==pi/2 & c==1 ); 798 | 799 | t = [ 0.9931285991850949, 0.9639719272779138,... % Base points 800 | 0.9122344282513259, 0.8391169718222188,... % for Gauss-Legendre integration 801 | 0.7463319064601508, 0.6360536807265150,... 802 | 0.5108670019508271, 0.3737060887154195,... 803 | 0.2277858511416451, 0.07652652113349734 ]; 804 | w = [ 0.01761400713915212, 0.04060142980038694,... % Weights 805 | 0.06267204833410907, 0.08327674157670475,... % for Gauss-Legendre integration 806 | 0.1019301198172404, 0.1181945319615184,... 807 | 0.1316886384491766, 0.1420961093183820,... 808 | 0.1491729864726037, 0.1527533871307258 ]; 809 | 810 | P = 0; i = 0; 811 | while i < 10 812 | i = i + 1; 813 | c0 = u.*t(i)/2; 814 | P = P + w(i).*(g(u/2+c0,m,c) + g(u/2-c0,m,c)); 815 | end 816 | P = u/2.*P; 817 | Pi(:) = P; % Incomplete elliptic integral of the third kind 818 | 819 | % special values u==pi/2 & m==1 | u==pi/2 & c==1 820 | Pi(I) = inf; 821 | return; 822 | 823 | 824 | function g = g(u,m,c) 825 | % g = 1/((1 - c*sin(u)^2)*sqrt(1 - m*sin(u)^2)); 826 | 827 | sn2 = sin(u).^2; 828 | g = 1./((1 - c.*sn2).*sqrt(1 - m.*sn2)); 829 | return; 830 | 831 | end 832 | 833 | end 834 | 835 | 836 | 837 | function PI = ellippi(n,m) 838 | 839 | % Complete elliptic integrals calculated with the arithmetric-geometric mean 840 | % algorithms contained here: http://dlmf.nist.gov/19.8 841 | % 842 | % Valid for n <= 1 and m <= 1 843 | 844 | 845 | a0 = 1; 846 | g0 = sqrt(1-m); 847 | s0 = m; 848 | nn = 0; 849 | 850 | p0 = sqrt(1-n); 851 | Q0 = 1; 852 | QQ = Q0; 853 | 854 | ss = ones(size(m)); 855 | Q1 = ones(size(m)); 856 | 857 | while max(abs([ss(:);Q1(:)])) > eps 858 | 859 | % for Elliptic I 860 | a1 = (a0+g0)/2; 861 | g1 = sqrt(a0.*g0); 862 | 863 | % for Elliptic II 864 | nn = nn + 1; 865 | c1 = (a0-g0)/2; 866 | ss = 2^nn*c1.^2; 867 | s0 = s0 + ss; 868 | 869 | % for Elliptic III 870 | rr = p0.^2+a0.*g0; 871 | p1 = rr./(2.*p0); 872 | Q1 = 0.5*Q0.*(p0.^2-a0.*g0)./rr; 873 | QQ = QQ+Q1; 874 | 875 | a0 = a1; 876 | g0 = g1; 877 | Q0 = Q1; 878 | p0 = p1; 879 | 880 | end 881 | 882 | PI = pi./(4.*a1).*(2+n./(1-n).*QQ); 883 | 884 | im = find(m == 1); 885 | if ~isempty(im) 886 | PI(im) = inf; 887 | end 888 | 889 | end 890 | 891 | 892 | 893 | function PI = ellippin(n,m) 894 | 895 | % Complete elliptic integrals calculated with the arithmetric-geometric mean 896 | % algorithms contained here: http://dlmf.nist.gov/19.8 897 | % 898 | % Valid for n > 1 and m <= 1 899 | 900 | a0 = 1; 901 | g0 = sqrt(1-m); 902 | s0 = m; 903 | nn = 0; 904 | 905 | p0 = sqrt(1-(m./n)); 906 | Q0 = 1; 907 | QQ = Q0; 908 | 909 | ss = ones(size(m)); 910 | Q1 = ones(size(m)); 911 | 912 | while max(abs([ss(:);Q1(:)])) > eps 913 | 914 | % for Elliptic I 915 | a1 = (a0+g0)/2; 916 | g1 = sqrt(a0.*g0); 917 | 918 | % for Elliptic II 919 | nn = nn + 1; 920 | c1 = (a0-g0)/2; 921 | ss = 2^nn*c1.^2; 922 | s0 = s0 + ss; 923 | 924 | % for Elliptic III 925 | rr = p0.^2+a0.*g0; 926 | p1 = rr./(2.*p0); 927 | Q1 = 0.5*Q0.*(p0.^2-a0.*g0)./rr; 928 | QQ = QQ+Q1; 929 | 930 | a0 = a1; 931 | g0 = g1; 932 | Q0 = Q1; 933 | p0 = p1; 934 | 935 | end 936 | 937 | PI = pi/(4*a1).*m./(m-n).*QQ; 938 | 939 | im = find(m == 1); 940 | if ~isempty(im) 941 | PI(im) = inf; 942 | end 943 | 944 | end 945 | 946 | --------------------------------------------------------------------------------