Mercurial > octave-antonio
view scripts/specfun/ellipke.m @ 19095:4cf81bccaf1c
ellipke.m: Overhaul function.
* ellipke.m: Rewrite docstring to use TeX for integrals. Implement second argument
to function (tolerance) which can be used to decrease running time. Return an
output which is the same shape as the input. Add input validation checks for
second argument.
author | Rik <rik@octave.org> |
---|---|
date | Fri, 19 Sep 2014 11:30:05 -0700 |
parents | 0850b5212619 |
children | db92e7e28e1f |
line wrap: on
line source
## Copyright (C) 2001, 2013 David Billinghurst ## Copyright (C) 2001, 2013 Paul Kienzle ## Copyright (C) 2003, 2013 Jaakko Ruohio ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or (at ## your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{k} =} ellipke (@var{m}) ## @deftypefnx {Function File} {@var{k} =} ellipke (@var{m}, @var{tol}) ## @deftypefnx {Function File} {[@var{k}, @var{e}] =} ellipke (@dots{}) ## Compute complete elliptic integrals of the first K(@var{m}) and second ## E(@var{m}) kind. ## ## @var{m} must be a scalar or real array with -Inf @leq{} @var{m} @leq{} 1. ## ## The optional input @var{tol} controls the stopping tolerance of the ## algorithm and defaults to @code{eps (class (@var{m}))}. The tolerance can ## be increased to compute a faster, less accurate approximation. ## ## When called with one output only elliptic integrals of the first kind are ## returned. ## ## Mathematical Note: ## ## Elliptic integrals of the first kind are defined as ## ## @tex ## $$ ## {\rm K} (m) = \int_0^1 {dt \over \sqrt{(1 - t^2) (1 - m^2 t^2)}} ## $$ ## @end tex ## @ifnottex ## ## @example ## @group ## 1 ## / dt ## K (m) = | ------------------------------ ## / sqrt ((1 - t^2)*(1 - m^2*t^2)) ## 0 ## @end group ## @end example ## ## @end ifnottex ## ## Elliptic integrals of the second kind are defined as ## ## @tex ## $$ ## {\rm E} (m) = \int_0^1 {\sqrt{1 - m^2 t^2} \over \sqrt{1 - t^2}} dt ## $$ ## @end tex ## @ifnottex ## ## @example ## @group ## 1 ## / sqrt (1 - m^2*t^2) ## E (m) = | ------------------ dt ## / sqrt (1 - t^2) ## 0 ## @end group ## @end example ## ## @end ifnottex ## ## Reference: Milton @nospell{Abramowitz} and Irene A. @nospell{Stegun}, ## @cite{Handbook of Mathematical Functions}, Chapter 17, Dover, 1965. ## @seealso{ellipj} ## @end deftypefn ## Author: David Billinghurst <David.Billinghurst@riotinto.com> ## Author: Paul Kienzle <pkienzle@users.sf.net> ## Author: Jaakko Ruohio function [k, e] = ellipke (m, tol = []) if (nargin < 1 || nargin > 2) print_usage (); endif sz = size (m); m = m(:); if (! isreal (m)) error ("ellipke: M must be real"); elseif (any (m > 1)) error ("ellipke: M must be <= 1"); endif if (isempty (tol)) tol = eps (class (m)); elseif (! (isreal (tol) && isscalar (tol) && tol > 0)) error ("ellipke: TOL must be a real scalar > 0") endif k = e = zeros (sz); ## Handle extreme values idx_1 = (m == 1); k(idx_1) = Inf; e(idx_1) = 1; idx_neginf = (m == -Inf); k(idx_neginf) = 0; e(idx_neginf) = Inf; ## Arithmetic-Geometric Mean (AGM) algorithm ## ( Abramowitz and Stegun, Section 17.6 ) Nmax = 16; idx = !idx_1 & !idx_neginf; if (any (idx)) idx_neg = find (m < 0 & !idx_neginf); mult_k = 1./sqrt (1 - m(idx_neg)); mult_e = sqrt (1 - m(idx_neg)); m(idx_neg) = -m(idx_neg) ./ (1 - m(idx_neg)); a = ones (sum (idx), 1); b = sqrt (1 - m(idx)); c = sqrt (m(idx)); f = 0.5; sum = f*c.^2; n = 2; do t = (a + b)/2; c = (a - b)/2; b = sqrt (a .* b); a = t; f *= 2; sum += f*c.^2; until (all (c./a < tol) || (++n > Nmax)) if (n >= Nmax) error ("ellipke: algorithm did not converge in %d iterations", Nmax); endif k(idx) = 0.5*pi ./ a; e(idx) = 0.5*pi*(1 - sum) ./ a; k(idx_neg) = mult_k .* k(idx_neg); e(idx_neg) = mult_e .* e(idx_neg); endif endfunction ## Test complete elliptic functions of first and second kind ## against "exact" solution from Mathematica 3.0 %!test %! m = [0.0, 0.01; 0.1, 0.5; 0.9, 0.99; 1.0, 0.0]; %! [k,e] = ellipke (m); %! %! k_exp = [1.5707963267948966192, 1.5747455615173559527 %! 1.6124413487202193982, 1.8540746773013719184 %! 2.5780921133481731882, 3.6956373629898746778 %! Inf , 1.5707963267948966192 ]; %! e_exp = [1.5707963267948966192, 1.5668619420216682912 %! 1.5307576368977632025, 1.3506438810476755025 %! 1.1047747327040733261, 1.0159935450252239356 %! 1.0 , 1.5707963267948966192 ]; %! assert (k, k_exp, 8*eps); %! assert (e, e_exp, 8*eps); ## Test against A&S Table 17.1 %!test %! m = [0:5:50]'/100; %! k_exp = [1.570796326794897; %! 1.591003453790792; %! 1.612441348720219; %! 1.635256732264580; %! 1.659623598610528; %! 1.685750354812596; %! 1.713889448178791; %! 1.744350597225613; %! 1.777519371491253; %! 1.813883936816983; %! 1.854074677301372 ]; %! e_exp = [1.570796327; %! 1.550973352; %! 1.530757637; %! 1.510121831; %! 1.489035058; %! 1.467462209; %! 1.445363064; %! 1.422691133; %! 1.399392139; %! 1.375401972; %! 1.350643881 ]; %! [k,e] = ellipke (m); %! assert (k, k_exp, 1e-15); %! assert (e, e_exp, 1e-8); ## Test negative values against "exact" solution from Mathematica. %! m = [-0.01; -1; -5; -100; -1000; -Inf]; %! [k,e] = ellipke (m); %! %! k_exp = [1.5668912730681963584; %! 1.3110287771460599052; %! 0.9555039270640439337; %! 0.3682192486091410329; %! 0.1530293349884987857; %! 0]; %! e_exp = [1.5747159850169884130; %! 1.9100988945138560089; %! 2.8301982463458773125; %! 10.209260919814572009; %! 31.707204053711259719; %! Inf ]; %! assert (k, k_exp, 8*eps); %! assert (e, e_exp, 8*eps (e_exp)); ## Test input validation %!error ellipke () %!error ellipke (1,2,3) %!error <M must be real> ellipke (1i) %!error <M must be .= 1> ellipke (2) %!error <TOL must be a real scalar . 0> ellipke (1, i) %!error <TOL must be a real scalar . 0> ellipke (1, [1 1]) %!error <TOL must be a real scalar . 0> ellipke (1, -1)