comparison libinterp/corefcn/ellipj.cc @ 17502:578805a293e5

ellipj: Move numerical code into liboctave * lo-specfun.cc, lo-specfun.h (ellipj): New functions, adapted from Fellipj. * ellipj.cc (Fellipj): Call ellipj. (do_ellipj): Delete.
author Mike Miller <mtmiller@ieee.org>
date Thu, 26 Sep 2013 21:34:26 -0400
parents 991c7c812e38
children 5b916efea542
comparison
equal deleted inserted replaced
17501:55680de6a897 17502:578805a293e5
24 #include <config.h> 24 #include <config.h>
25 #endif 25 #endif
26 26
27 #include "defun.h" 27 #include "defun.h"
28 #include "error.h" 28 #include "error.h"
29 #include "lo-ieee.h" 29 #include "lo-specfun.h"
30 30
31 static void 31 static void
32 gripe_ellipj_arg (const char *arg) 32 gripe_ellipj_arg (const char *arg)
33 { 33 {
34 error ("ellipj: expecting scalar or matrix as %s argument", arg); 34 error ("ellipj: expecting scalar or matrix as %s argument", arg);
35 }
36
37 static void
38 do_ellipj (const double u, const double m, double& sn, double& cn, double& dn, double& err)
39 {
40 static const int Nmax = 16;
41 double m1, t=0, si_u, co_u, se_u, ta_u, b, c[Nmax], a[Nmax], phi;
42 int n, Nn, ii;
43
44 if (m < 0 || m > 1)
45 {
46 warning ("ellipj: expecting 0 <= M <= 1"); // -lc-
47 sn = cn = dn = lo_ieee_nan_value ();
48 return;
49 }
50
51 double sqrt_eps = sqrt (std::numeric_limits<double>::epsilon ());
52 if (m < sqrt_eps)
53 {
54 // For small m, ( Abramowitz and Stegun, Section 16.13 )
55 si_u = sin (u);
56 co_u = cos (u);
57 t = 0.25*m*(u - si_u*co_u);
58 sn = si_u - t * co_u;
59 cn = co_u + t * si_u;
60 dn = 1 - 0.5*m*si_u*si_u;
61 }
62 else if ((1 - m) < sqrt_eps)
63 {
64 // For m1 = (1-m) small ( Abramowitz and Stegun, Section 16.15 )
65 m1 = 1 - m;
66 si_u = sinh (u);
67 co_u = cosh (u);
68 ta_u = tanh (u);
69 se_u = 1/co_u;
70 sn = ta_u + 0.25*m1*(si_u*co_u - u)*se_u*se_u;
71 cn = se_u - 0.25*m1*(si_u*co_u - u)*ta_u*se_u;
72 dn = se_u + 0.25*m1*(si_u*co_u + u)*ta_u*se_u;
73 }
74 else
75 {
76 /*
77 // Arithmetic-Geometric Mean (AGM) algorithm
78 // ( Abramowitz and Stegun, Section 16.4 )
79 */
80
81 a[0] = 1;
82 b = sqrt (1 - m);
83 c[0] = sqrt (m);
84 for (n = 1; n < Nmax; ++n)
85 {
86 a[n] = (a[n - 1] + b)/2;
87 c[n] = (a[n - 1] - b)/2;
88 b = sqrt (a[n - 1]*b);
89 if (c[n]/a[n] < std::numeric_limits<double>::epsilon ()) break;
90 }
91 if (n >= Nmax - 1)
92 {
93 err = 1;
94 return;
95 }
96 Nn = n;
97 for (ii = 1; n > 0; ii = ii*2, --n) ; // ii = pow(2,Nn)
98 phi = ii*a[Nn]*u;
99 for (n = Nn; n > 0; --n)
100 {
101 t = phi;
102 phi = (asin ((c[n]/a[n])* sin (phi)) + phi)/2;
103 }
104 sn = sin (phi);
105 cn = cos (phi);
106 dn = cn/cos (t - phi);
107 }
108 }
109
110 static void
111 do_ellipj (const Complex& u, const double m, Complex& sn, Complex& cn, Complex& dn,
112 double& err)
113 {
114 double m1 = 1 - m, ss1, cc1, dd1;
115
116 do_ellipj (imag (u), m1, ss1, cc1, dd1, err);
117 if (real (u) == 0)
118 {
119 // u is pure imag: Jacoby imag. transf.
120 sn = Complex (0, ss1/cc1);
121 cn = 1/cc1; // cn.imag = 0;
122 dn = dd1/cc1; // dn.imag = 0;
123 }
124 else
125 {
126 // u is generic complex
127 double ss, cc, dd, ddd;
128
129 do_ellipj (real (u), m, ss, cc, dd, err);
130 ddd = cc1*cc1 + m*ss*ss*ss1*ss1;
131 sn = Complex (ss*dd1/ddd, cc*dd*ss1*cc1/ddd);
132 cn = Complex (cc*cc1/ddd, -ss*dd*ss1*dd1/ddd);
133 dn = Complex (dd*cc1*dd1/ddd, -m*ss*cc*ss1/ddd);
134 }
135 } 35 }
136 36
137 DEFUN (ellipj, args, nargout, 37 DEFUN (ellipj, args, nargout,
138 "-*- texinfo -*-\n\ 38 "-*- texinfo -*-\n\
139 @deftypefn {Built-in Function} {[@var{sn}, @var{cn}, @var{dn}, @var{err}] =} ellipj (@var{u}, @var{m})\n\ 39 @deftypefn {Built-in Function} {[@var{sn}, @var{cn}, @var{dn}, @var{err}] =} ellipj (@var{u}, @var{m})\n\
210 } 110 }
211 111
212 double sn, cn, dn; 112 double sn, cn, dn;
213 double err = 0; 113 double err = 0;
214 114
215 do_ellipj (u, m, sn, cn, dn, err); 115 ellipj (u, m, sn, cn, dn, err);
216 116
217 if (nargout > 3) 117 if (nargout > 3)
218 retval(3) = err; 118 retval(3) = err;
219 retval(2) = dn; 119 retval(2) = dn;
220 retval(1) = cn; 120 retval(1) = cn;
231 } 131 }
232 132
233 Complex sn, cn, dn; 133 Complex sn, cn, dn;
234 double err = 0; 134 double err = 0;
235 135
236 do_ellipj (u, m, sn, cn, dn, err); 136 ellipj (u, m, sn, cn, dn, err);
237 137
238 if (nargout > 3) 138 if (nargout > 3)
239 retval(3) = err; 139 retval(3) = err;
240 retval(2) = dn; 140 retval(2) = dn;
241 retval(1) = cn; 141 retval(1) = cn;
263 Complex *pdn = dn.fortran_vec (); 163 Complex *pdn = dn.fortran_vec ();
264 double *perr = err.fortran_vec (); 164 double *perr = err.fortran_vec ();
265 octave_idx_type nel = u.numel (); 165 octave_idx_type nel = u.numel ();
266 166
267 for (octave_idx_type i = 0; i < nel; i++) 167 for (octave_idx_type i = 0; i < nel; i++)
268 do_ellipj (pu[i], m, psn[i], pcn[i], pdn[i], perr[i]); 168 ellipj (pu[i], m, psn[i], pcn[i], pdn[i], perr[i]);
269 169
270 if (nargout > 3) 170 if (nargout > 3)
271 retval(3) = err; 171 retval(3) = err;
272 retval(2) = dn; 172 retval(2) = dn;
273 retval(1) = cn; 173 retval(1) = cn;
307 double *pdn = dn.fortran_vec (); 207 double *pdn = dn.fortran_vec ();
308 double *perr = err.fortran_vec (); 208 double *perr = err.fortran_vec ();
309 octave_idx_type nel = m.numel (); 209 octave_idx_type nel = m.numel ();
310 210
311 for (octave_idx_type i = 0; i < nel; i++) 211 for (octave_idx_type i = 0; i < nel; i++)
312 do_ellipj (u, pm[i], psn[i], pcn[i], pdn[i], perr[i]); 212 ellipj (u, pm[i], psn[i], pcn[i], pdn[i], perr[i]);
313 213
314 if (nargout > 3) 214 if (nargout > 3)
315 retval(3) = err; 215 retval(3) = err;
316 retval(2) = dn; 216 retval(2) = dn;
317 retval(1) = cn; 217 retval(1) = cn;
336 Complex *pdn = dn.fortran_vec (); 236 Complex *pdn = dn.fortran_vec ();
337 double *perr = err.fortran_vec (); 237 double *perr = err.fortran_vec ();
338 octave_idx_type nel = m.numel (); 238 octave_idx_type nel = m.numel ();
339 239
340 for (octave_idx_type i = 0; i < nel; i++) 240 for (octave_idx_type i = 0; i < nel; i++)
341 do_ellipj (u, pm[i], psn[i], pcn[i], pdn[i], perr[i]); 241 ellipj (u, pm[i], psn[i], pcn[i], pdn[i], perr[i]);
342 242
343 if (nargout > 3) 243 if (nargout > 3)
344 retval(3) = err; 244 retval(3) = err;
345 retval(2) = dn; 245 retval(2) = dn;
346 retval(1) = cn; 246 retval(1) = cn;
374 const double *pu = u.data (); 274 const double *pu = u.data ();
375 const double *pm = m.data (); 275 const double *pm = m.data ();
376 276
377 for (octave_idx_type j = 0; j < mc; j++) 277 for (octave_idx_type j = 0; j < mc; j++)
378 for (octave_idx_type i = 0; i < ur; i++) 278 for (octave_idx_type i = 0; i < ur; i++)
379 do_ellipj (pu[i], pm[j], sn(i,j), cn(i,j), dn(i,j), err(i,j)); 279 ellipj (pu[i], pm[j], sn(i,j), cn(i,j), dn(i,j), err(i,j));
380 280
381 if (nargout > 3) 281 if (nargout > 3)
382 retval(3) = err; 282 retval(3) = err;
383 retval(2) = dn; 283 retval(2) = dn;
384 retval(1) = cn; 284 retval(1) = cn;
396 double *pdn = dn.fortran_vec (); 296 double *pdn = dn.fortran_vec ();
397 double *perr = err.fortran_vec (); 297 double *perr = err.fortran_vec ();
398 octave_idx_type nel = m.numel (); 298 octave_idx_type nel = m.numel ();
399 299
400 for (octave_idx_type i = 0; i < nel; i++) 300 for (octave_idx_type i = 0; i < nel; i++)
401 do_ellipj (pu[i], pm[i], psn[i], pcn[i], pdn[i], perr[i]); 301 ellipj (pu[i], pm[i], psn[i], pcn[i], pdn[i], perr[i]);
402 302
403 if (nargout > 3) 303 if (nargout > 3)
404 retval(3) = err; 304 retval(3) = err;
405 retval(2) = dn; 305 retval(2) = dn;
406 retval(1) = cn; 306 retval(1) = cn;
434 const Complex *pu = u.data (); 334 const Complex *pu = u.data ();
435 const double *pm = m.data (); 335 const double *pm = m.data ();
436 336
437 for (octave_idx_type j = 0; j < mc; j++) 337 for (octave_idx_type j = 0; j < mc; j++)
438 for (octave_idx_type i = 0; i < ur; i++) 338 for (octave_idx_type i = 0; i < ur; i++)
439 do_ellipj (pu[i], pm[j], sn(i,j), cn(i,j), dn(i,j), err(i,j)); 339 ellipj (pu[i], pm[j], sn(i,j), cn(i,j), dn(i,j), err(i,j));
440 340
441 if (nargout > 3) 341 if (nargout > 3)
442 retval(3) = err; 342 retval(3) = err;
443 retval(2) = dn; 343 retval(2) = dn;
444 retval(1) = cn; 344 retval(1) = cn;
456 Complex *pdn = dn.fortran_vec (); 356 Complex *pdn = dn.fortran_vec ();
457 double *perr = err.fortran_vec (); 357 double *perr = err.fortran_vec ();
458 octave_idx_type nel = m.numel (); 358 octave_idx_type nel = m.numel ();
459 359
460 for (octave_idx_type i = 0; i < nel; i++) 360 for (octave_idx_type i = 0; i < nel; i++)
461 do_ellipj (pu[i], pm[i], psn[i], pcn[i], pdn[i], perr[i]); 361 ellipj (pu[i], pm[i], psn[i], pcn[i], pdn[i], perr[i]);
462 362
463 if (nargout > 3) 363 if (nargout > 3)
464 retval(3) = err; 364 retval(3) = err;
465 retval(2) = dn; 365 retval(2) = dn;
466 retval(1) = cn; 366 retval(1) = cn;