1 /* Tests of Jacobi elliptic functions and elliptic integrals */
7 diff(jacobi_sn(u,m),u);
8 jacobi_cn(u,m)*jacobi_dn(u,m);
10 diff(jacobi_sn(u,m),m);
11 jacobi_cn(u,m)*jacobi_dn(u,m)*(u-elliptic_e(asin(jacobi_sn(u,m)),m)/(1-m))
13 +jacobi_cn(u,m)^2*jacobi_sn(u,m)/(2*(1-m));
15 diff(jacobi_cn(u,m),u);
16 -jacobi_dn(u,m)*jacobi_sn(u,m);
18 diff(jacobi_cn(u,m),m);
19 -(jacobi_dn(u,m)*jacobi_sn(u,m)*(u-elliptic_e(asin(jacobi_sn(u,m)),m)/(1-m))/(2*m))
20 -(jacobi_cn(u,m)*jacobi_sn(u,m)^2/(2*(1-m)));
22 diff(jacobi_dn(u,m),u);
23 -m*jacobi_cn(u,m)*jacobi_sn(u,m);
25 diff(jacobi_dn(u,m),m);
26 -(jacobi_cn(u,m)*jacobi_sn(u,m)*(u-elliptic_e(asin(jacobi_sn(u,m)),m)/(1-m))/2)
27 -(jacobi_dn(u,m)*'jacobi_sn(u,m)^2/(2*(1-m)));
29 diff(inverse_jacobi_sn(u,m),u);
30 1/(sqrt(1-u^2)*sqrt(1-m*u^2));
32 diff(inverse_jacobi_sn(u,m),m);
33 ((elliptic_e(asin(u),m)-(1-m)*elliptic_f(asin(u),m))/m-(u*sqrt(1-u^2)/sqrt(1-m*u^2)))/(1-m);
35 diff(inverse_jacobi_cn(u,m),u);
36 -(1/(sqrt(1-u^2)*sqrt(m*u^2-m+1)));
38 diff(inverse_jacobi_cn(u,m),m);
39 ((elliptic_e(asin(sqrt(1-u^2)),m)-(1-m)*elliptic_f(asin(sqrt(1-u^2)),m))/m
40 -(sqrt(1-u^2)*abs(u)/sqrt(1-m*(1-u^2))))/(1-m);
42 diff(inverse_jacobi_dn(u,m),u);
43 1/(sqrt(1-u^2)*sqrt(u^2+m-1));
45 diff(inverse_jacobi_dn(u,m),m);
46 ((elliptic_e(asin(sqrt(1-u^2)/sqrt(m)),m)-(1-m)*elliptic_f(asin(sqrt(1-u^2)/sqrt(m)),m))/m
47 -sqrt(1-(1-u^2)/m)*sqrt(1-u^2)/(sqrt(m)*abs(u)))/(1-m)
48 -(sqrt(1-u^2)/(2*m^(3/2)*sqrt(1-(1-u^2)/m)*abs(u)));
50 diff(elliptic_e(phi,m),phi);
53 diff(elliptic_e(phi,m),m);
54 (elliptic_e(phi,m)-elliptic_f(phi,m))/(2*m);
56 diff(elliptic_f(phi,m),phi);
57 1/sqrt(1-m*sin(phi)^2);
59 diff(elliptic_f(phi,m),m);
60 ((elliptic_e(phi,m)-(1-m)*elliptic_f(phi,m))/m
61 -(cos(phi)*sin(phi)/sqrt(1-m*sin(phi)^2)))
64 diff(elliptic_pi(n,phi,m),n);
65 ((-(n*sqrt(1-m*sin(phi)^2)*sin(2*phi))/(2*(1-n*sin(phi)^2)))
66 +((m-n)*elliptic_f(phi,m))/n+elliptic_e(phi,m)
67 +((n^2-m)*elliptic_pi(n,phi,m))/n)
70 diff(elliptic_pi(n,phi,m),phi);
71 1/(sqrt(1-m*sin(phi)^2)*(1-n*sin(phi)^2));
73 diff(elliptic_pi(n,phi,m),m);
74 ((-(m*sin(2*phi))/(2*(m-1)*sqrt(1-m*sin(phi)^2)))
75 +elliptic_e(phi,m)/(m-1)+elliptic_pi(n,phi,m))
78 diff(elliptic_kc(m),m);
79 (elliptic_ec(m)-(1-m)*elliptic_kc(m))/(2*(1-m)*m);
81 diff(elliptic_ec(m),m);
82 (elliptic_ec(m)-elliptic_kc(m))/(2*m);
86 integrate(jacobi_sn(u,m),u); /* A&S 16.24.1 */
87 log(jacobi_dn(u,m)-sqrt(m)*jacobi_cn(u,m))/sqrt(m);
89 integrate(jacobi_cn(u,m),u); /* A&S 16.24.2 */
90 acos(jacobi_dn(u,m))/sqrt(m);
92 integrate(jacobi_dn(u,m),u); /* A&S 16.24.3 */
95 integrate(jacobi_cd(u,m),u); /* A&S 16.24.4 */
96 log(sqrt(m)*jacobi_sd(u,m)+jacobi_nd(u,m))/sqrt(m);
98 /* Use functions.wolfram.com 09.35.21.001.01, not A&S 16.24.5 */
99 integrate(jacobi_sd(u,m),u);
100 -(sqrt(1-m*jacobi_cd(u,m)^2)*jacobi_dn(u,m)*asin(sqrt(m)*jacobi_cd(u,m))
103 /* Use functions.wolfram.com 09.32.21.0001.01, not A&S 16.24.6 */
104 integrate(jacobi_nd(u,m),u);
105 sqrt(1-jacobi_cd(u,m)^2)*acos(jacobi_cd(u,m))/((1-m)*jacobi_sd(u,m));
107 integrate(jacobi_dc(u,m),u); /* A&S 16.24.7 */
108 log(jacobi_sc(u,m)+jacobi_nc(u,m));
110 integrate(jacobi_nc(u,m),u); /* A&S 16.24.8 */
111 log(sqrt(1-m)*jacobi_sc(u,m)+jacobi_dc(u,m))/sqrt(1-m);
113 integrate(jacobi_sc(u,m),u); /* A&S 16.24.9 */
114 log(sqrt(1-m)*jacobi_nc(u,m)+jacobi_dc(u,m))/sqrt(1-m);
116 integrate(jacobi_ns(u,m),u); /* A&S 16.24.10 */
117 log(jacobi_ds(u,m)-jacobi_cs(u,m));
119 /* Use functions.wolfram.com 09.30.21.0001.01, not A&S 16.24.11 */
120 integrate(jacobi_ds(u,m),u);
121 log((1-jacobi_cn(u,m))/jacobi_sn(u,m));
123 integrate(jacobi_cs(u,m),u); /* A&S 16.24.12 */
124 log(jacobi_ns(u,m)-jacobi_ds(u,m));
126 /* Check the integrals and derivatives by confirming
128 f(x,m)-diff(integral(x,m),x),x) = constant
130 Look at Taylor expansion about zero, rather than messing about with
131 elliptic function. This was sufficient to find several errors */
134 -diff(integrate(f(x,m),x),x),x,0,n)),
136 taylor(integrate(f(x,m),x),x,0,n)
137 -integrate(taylor(f(x,m),x,0,n-1),x)),
139 taylor(diff(f(x,m),x),x,0,n)
140 -diff(taylor(f(x,m),x,0,n+1),x)),
141 /* Compare analytic and numerical integral */
142 ni(f,x1,x2,m):= block(
143 [x,n,I,In,Ia,key:1,eps:1.0e-14],
144 I:integrate(f(x,n),x),
145 In:quad_qag(f(x,m),x,x1,x2,key),
146 Ia:subst([x=float(x2),n=float(m)],I)-subst([x=float(x1),n=float(m)],I),
147 if ( abs(Ia-In[1]) < eps ) then
167 assume(m>0,m<1); /* also ok for m<0 and m>0 */
186 /* jacobi_ns, jacobi_ds and jacobi_cs are singular at x=0
187 Compare numerical and analytic integrals for a single case.
190 ni(jacobi_ns,1,2,1/2);
193 ni(jacobi_ds,1,2,1/2);
196 ni(jacobi_cs,1,2,1/2);
202 /* Slightly modified version of test_table taken from rtest_expintegral.mac */
204 (test_table(func,table,eps) :=
205 block([badpoints : [],
208 for entry in table do
211 z : expand(rectform(bfloat(entry[1]))),
212 result : rectform(apply(func, z)),
213 answer : expand(rectform(bfloat(entry[2]))),
214 abserr : abs(result-answer),
215 maxerr : max(maxerr,abserr),
217 badpoints : cons ([z,result,answer,abserr],badpoints)
219 if badpoints # [] then
220 cons(maxerr,reverse(badpoints))
226 /* These test values come from http://getnet.net/~cherry/testrf.mac */
229 * rf(1,2,0) = (gamma(1/4)^2/4/sqrt(2*%pi)
230 * rf(%i,-%i,0) = 1/2*integrate(1/sqrt(t^2+1)/sqrt(t),t,0,inf) = beta(1/4,1/4)/4;
231 * rf(1/2,1,0) = 1/sqrt(1/2)*rf(1,2,0) (See https://dlmf.nist.gov/19.20.E1)
233 (mrf:[[[1,2,0], gamma(1/4)^2/4/sqrt(2*%pi)],
234 [[0.5,1,0], gamma(1/4)^2/(4*sqrt(%pi))]],
238 (mrf2:[[[%i,-%i,0], beta(1/4,1/4)/4],
239 [[%i-1,%i,0],0.79612586584234b0-%i*(1.2138566698365b0)],
240 [[%i,-%i,2],1.0441445654064b0],
241 [[2,3,4],0.58408284167715b0],
242 [[%i-1,%i,1-%i],0.93912050218619b0-%i*(0.53296252018635b0)]],
246 test_table('carlson_rf, mrf, 8.3267b-17);
249 test_table('carlson_rf, mrf2, 1.2102b-8);
253 * rc(0,1/4) = 1/2*integrate(1/sqrt(t)/(t+1/4), t, 0, inf)
256 * rc(9/4,2) = 1/2*integrate(1/sqrt(t+9/4)/(t+2), t, 0, inf)
258 * After doing a logcontract.
260 * rc(0,%i) = 1/2*integrate(1/sqrt(t)/(t+%i), t, 0, inf);
261 * = (1-%i)*%pi/2^(3/2)
263 * rc(2,1) = 1/2*integrate(1/sqrt(t+2)/(t+1), t, 0, inf)
264 * = (log(sqrt(2)+1)-log(sqrt(2)-1))/2
267 * After doing a logcontract, ratsimp/algebraic, and logcontract with
268 * logconcoeffp, and a sqrtdenest
270 * rc(0,1) = 1/2*integrate(1/sqrt(t)/(t+1), t, 0, inf)
272 * rc(%i, %i+1) = 1/2*integrate(1/sqrt(t+%i)/(t+%i+1), t, 0, inf)
273 * = (%pi-2*atan((-1)^(1/4)))/2
274 * = %pi/4+%i/2*log(sqrt(2)-1)
276 * After applying rectform, ratsimp, logcontract, then another
277 * logcontract with logconcoeffp set to featurep(m) or ratnump(m).
280 (mrc:[[[0b0,1/4],bfloat(%pi)],
281 [[9/4,2b0],log(2b0)],
282 [[0b0,%i],(1-%i)*%pi/2^(3/2)],
283 [[-%i,%i],1.2260849569072b0-%i*(0.34471136988768b0)],
284 [[1/4,-2],log(2b0)/3],
285 [[%i,-1],0.77778596920447b0+%i*(0.19832484993429b0)],
288 [[2,1],-log(sqrt(2)-1)],
289 [[-%i,%i],-log(sqrt(2)-1)/2+ %pi/4-%i*(log(sqrt(2)-1)/2+%pi/4)],
291 [[%i,-1],sqrt(sqrt(2)/4-1/4)*atan(sqrt(sqrt(2)-1))-
292 sqrt(sqrt(2)/16+1/16)*log(-sqrt(2*sqrt(2)+2)+sqrt(2)+1)+
293 %i*(sqrt(sqrt(2)/4+1/4)*atan(sqrt(sqrt(2)-1))+sqrt(sqrt(2)/16-
294 1/16)*log(-sqrt(2*sqrt(2)+2)+sqrt(2)+1))],
296 [[%i,%i+1],%pi/4+%i*log(sqrt(2)-1)/2]],
300 test_table('carlson_rc, mrc, 2.5b-14);
303 (mrj:[[[0,1,2,3],0.77688623778582b0],
304 [[2,3,4,5],0.14297579667157b0],
305 [[2,3,4,-1+%i],0.13613945827771b0-%i*(0.38207561624427b0)],
306 [[-1+%i,-1-%i,1,2],0.9414835884122b0],
307 [[-1+%i,-1-%i,1,-3+%i],-0.61127970812028b0-%i*(1.0684038390007b0)],
308 [[-1+%i,-2-%i,-%i,-1+%i],1.8249027393704b0-%i*(1.2218475784827b0)],
309 [[2,3,4,-0.5],0.24723819703052b0],
310 [[2,3,4,-5],-0.12711230042964b0]],
314 (mrj2:[[[%i,-%i,0,2],1.6490011662711b0],
315 [[%i,-%i,0,1-%i],1.8260115229009b0+%i*(1.2290661908643b0)]],
319 test_table('carlson_rj, mrj, 1b-13);
322 test_table('carlson_rj, mrj2, 2.3452b-8);
326 * rd(0,2,1) = (3*gamma(3/4)^2)/(sqrt(2)*sqrt(%pi))
328 (mrd:[[[0,2,1],(3*gamma(3/4)^2)/(sqrt(2)*sqrt(%pi))],
329 [[2,3,4],0.16510527294261b0],
330 [[-2-%i,-%i,-1+%i],1.8249027393704b0-%i*(1.2218475784827b0)]],
334 (mrd2:[[[%i,-%i,2],0.6593385415422b0],
335 [[0,%i,-%i],1.270819627191b0+%i*(2.7811120159521b0)],
336 [[0,%i-1,%i],-1.8577235439239b0-%i*(0.96193450888839b0)]],
340 test_table('carlson_rd, mrd, 6e-14);
343 test_table('carlson_rd, mrd2, 4.7818b-8);
346 /* Some tests of the Jacobian elliptic functions.
347 * Just some tests at random points, to verify that we are accurate.
348 * The reference values were obtained from Mathematica, but we could
349 * also just compute the values using a much larger fpprec.
352 test_table('jacobi_sn,
353 [[[1b0+%i*1b0, .7b0], 1.134045971912365274954b0 + 0.352252346922494477621b0*%i],
354 [[1b0+%i*1b0, 2b0], 0.98613318109123804740b0 + 0.09521910819727230780b0*%i],
355 [[1b0+%i*1b0, 2b0+3b0*%i], 0.94467077879445294981b0 - 0.19586410083100945528b0* %i],
356 [[1.785063352082689082581887b0 *%i + 8.890858759528509578661528b-1,
357 9.434463451695984398149033b-1 - 1.476052973708684178844821b-1 * %i],
358 1.345233534539675700312281b0 - 7.599023926615176284214056b-2 * %i]],
362 test_table('jacobi_cn,
363 [[[1b0+%i*1b0, .7b0], 0.571496591371764254029b0 - 0.698989917271916772991b0*%i ],
364 [[1b0+%i*1b0, 2b0], 0.33759463268642431412b0 - 0.27814044708010806377b0*%i],
365 [[1b0+%i*1b0, 2b0+3b0*%i], -0.52142079485827170824b0 - 0.35485177134179601850b0*%i],
366 [[100b0, .7b0], 0.93004753815774770476196b0]],
370 test_table('jacobi_dn,
371 [[[1b0+%i*1b0, .7b0], 0.62297154372331777630564880787568b0 - 0.448863598031509643267241389621738b0 *%i ],
372 [[1b0+%i*1b0, 2b0], 0.1913322443206041462495606602242b0 - 0.9815253294150083432282549919753b0 * %i],
373 [[1b0+%i*1b0, 2b0+3b0*%i], 0.6147387452173944656984656771134b0 - 1.4819401302071697495918834416787b0 * %i],
374 [[100b0, .7b0], 0.95157337933724324055428565654872978b0],
375 [[1.785063352082689082581887b0 *%i + 8.890858759528509578661528b-1,
376 9.434463451695984398149033b-1 - 1.476052973708684178844821b-1 * %i],
377 -8.617730683333292717095686b-1 *%i - 2.663978258141280808361839b-1]],
381 /* These routines for cn and dn work well for small (<= 1?) values of
382 * u and m. They have known issues for large real values of u.
384 (ascending_transform(u,m) :=
385 block([root_m : expand(rectform(sqrt(m))), mu, root_mu1, v],
386 mu : expand(rectform(4*root_m/(1+root_m)^2)),
387 root_mu1 : expand(rectform((1-root_m)/(1+root_m))),
388 v : expand(rectform(u/(1+root_mu1))),
390 elliptic_dn_ascending(u,m) :=
391 if is(abs(m-1) < 4*10^(-fpprec)) then sech(u)
393 block([v, mu, root_mu1, new],
394 [v, mu, root_mu1] : ascending_transform(u,m),
395 new : elliptic_dn_ascending(v, mu),
396 expand(rectform((1-root_mu1)/mu*(new^2 + root_mu1)/new))),
397 elliptic_cn_ascending(u,m) :=
398 if is(abs(m-1) < 4*10^(-fpprec)) then sech(u)
400 block([v, mu, root_mu1, new],
401 [v, mu, root_mu1] : ascending_transform(u,m),
402 new : elliptic_dn_ascending(v, mu),
403 expand(rectform((1+root_mu1)/mu*(new^2-root_mu1)/new))),
407 /* Test with random values for the argument and parameter. */
408 (test_random(n, eps, testf, truef) :=
409 block([badpoints : [], maxerr : -1],
411 block([z : bfloat(1-2*random(1d0) + %i * (1-2*random(1d0))),
412 m : bfloat(1-2*random(1d0) + %i * (1-2*random(1d0))),
413 ans, expected, abserr],
415 expected : truef(z, m),
416 abserr : abs(ans-expected),
417 maxerr : max(maxerr, abserr),
419 badpoints : cons([[z,m], ans, expected, abserr], badpoints)),
420 if badpoints # [] then
421 cons(maxerr, badpoints)
427 test_random(50, 2b-15, 'jacobi_dn, 'elliptic_dn_ascending);
430 test_random(50, 2b-15, 'jacobi_cn, 'elliptic_cn_ascending);
433 /* Test elliptic_f by using the fact that
435 inverse_jacobi_sn(x,m) = elliptic_f(asin(x), m)
438 (test_ef(x,m) := jacobi_sn(elliptic_f(asin(x),m), m), id(x,m):=x, done);
441 test_random(100, 6b-13, 'test_ef, 'id);
444 /* Test elliptic_kc These values are from
446 * http://functions.wolfram.com/EllipticIntegrals/EllipticK/03/01/
449 block([oldfpprec : fpprec, fpprec:100],
450 test_table('elliptic_kc,
451 [[[1/2], 8*%pi^(3/2)/gamma(-1/4)^2],
452 [[17-12*sqrt(2)], 2*(2+sqrt(2))*%pi^(3/2)/gamma(-1/4)^2],
453 [[-1], gamma(1/4)^2/4/sqrt(2*%pi)]],
457 /* Some tests for specific values */
458 inverse_jacobi_sn(1,m);
461 inverse_jacobi_sn(x,0);
464 inverse_jacobi_sn(x,1);
465 log(tan(asin(x)/2 + %pi/4));
467 inverse_jacobi_sd(1/sqrt(1-m),m);
470 inverse_jacobi_ds(sqrt(1-m),m);
473 /* elliptic_kc(1) is undefined */
474 errcatch(elliptic_kc(1));
476 errcatch(elliptic_kc(1.0));
478 errcatch(elliptic_kc(1.0b0));
481 /* Test noun/verb results from elliptic functions */
482 diff(inverse_jacobi_sn(x,0),x);
485 diff(elliptic_pi(4/3,phi,0),phi);
486 sec(phi)^2/(1-tan(phi)^2/3);
488 diff(elliptic_pi(3/4,phi,0),phi);
489 sec(phi)^2/(1+tan(phi)^2/4);
491 diff(elliptic_pi(1,phi,0),phi);
494 /* signbfloat:false provokes "Is 0 positive, negative, or zero?" */
496 diff(elliptic_pi(1,phi,0),phi));
499 (reset (signbfloat), 0);
510 gamma(3/4)^2/(2*sqrt(%pi))+%pi^(3/2)/(4*gamma(3/4)^2);
513 sqrt(2)*elliptic_ec(1/2);
515 /* Test periodicity of elliptic_e */
517 2*round(x/%pi)+sin(x-%pi*round(x/%pi));
520 elliptic_e(3-%pi,1/3)+2*elliptic_ec(1/3);
522 /* Bug #2629: elliptic_kc(3.0) not accurate */
523 test_table('elliptic_kc, [[[3.0], elliptic_kc(3b0)]], 1b-15);
526 /* Bug #2630: inverse_jacobi_cn(-2.0, 3.0) generates an error */
527 test_table('inverse_jacobi_cn, [[[-2.0, 3.0], 2.002154760912212-3.202503914656527*%i]],
531 /* Bug #2615: Numeric evaluation of inverse Jacobi elliptic functions is wrong for some inputs
533 is(abs(jacobi_dn(inverse_jacobi_dn(-2.0,3.0), 3.0) + 2) < 1d-14);
536 /* elliptical functions handling of non-rectangular complex numbers
537 * mailing list 2016-07-14 "Jacobi elliptic functions, maxima 5.38.1"
538 * mailing list 2020-05-28 "Unexpected result from ev"
541 /* list of functions here is everything that has a SIMP-[$%](ELLIPTIC|JACOBI)_FOO in sr/ellipt.lisp */
544 [ elliptic_e, elliptic_ec, elliptic_eu, elliptic_f, elliptic_kc, elliptic_pi,
545 inverse_jacobi_cd, inverse_jacobi_cn, inverse_jacobi_cs, inverse_jacobi_dc,
546 inverse_jacobi_dn, inverse_jacobi_ds, inverse_jacobi_nc, inverse_jacobi_nd,
547 inverse_jacobi_ns, inverse_jacobi_sc, inverse_jacobi_sd, inverse_jacobi_sn,
549 jacobi_cd, jacobi_cn, jacobi_cs, jacobi_dc, jacobi_dn, jacobi_ds,
550 jacobi_nc, jacobi_nd, jacobi_ns, jacobi_sc, jacobi_sd, jacobi_sn ];
553 /* code to generate test cases below
555 elliptic_fcns_1 : sublist (elliptic_fcns, lambda ([f], errcatch(f('a)) # []));
556 elliptic_fcns_2 : sublist (elliptic_fcns, lambda ([f], errcatch(f('a, 'b)) # []));
557 elliptic_fcns_3 : sublist (elliptic_fcns, lambda ([f], errcatch(f('a, 'b, 'c)) # []));
561 with_stdout ("/tmp/foo.mac",
563 for f in elliptic_fcns_1
564 do block ([a : f('rectform(u1))],
565 print ('complex_floatp(a), ";"),
569 for f in elliptic_fcns_2
570 do block ([a : f('rectform(u1), k1)],
571 print ('complex_floatp(a), ";"),
575 for f in elliptic_fcns_3
576 do block ([a : f(n1, 'rectform(u1), k1)],
577 print ('complex_floatp(a), ";"),
582 (u1 : 0.5*(1.0 - 0.25*%i)^2,
585 complex_floatp(e) := floatnump(realpart(e)) and floatnump(imagpart(e)),
589 complex_floatp(elliptic_ec(rectform(u1))) ;
592 complex_floatp(elliptic_kc(rectform(u1))) ;
595 complex_floatp(elliptic_e(rectform(u1), k1)) ;
598 complex_floatp(elliptic_eu(rectform(u1), k1)) ;
601 complex_floatp(elliptic_f(rectform(u1), k1)) ;
604 complex_floatp(inverse_jacobi_cd(rectform(u1), k1)) ;
607 complex_floatp(inverse_jacobi_cn(rectform(u1), k1)) ;
610 complex_floatp(inverse_jacobi_cs(rectform(u1), k1)) ;
613 complex_floatp(inverse_jacobi_dc(rectform(u1), k1)) ;
616 complex_floatp(inverse_jacobi_dn(rectform(u1), k1)) ;
619 complex_floatp(inverse_jacobi_ds(rectform(u1), k1)) ;
622 complex_floatp(inverse_jacobi_nc(rectform(u1), k1)) ;
625 complex_floatp(inverse_jacobi_nd(rectform(u1), k1)) ;
628 complex_floatp(inverse_jacobi_ns(rectform(u1), k1)) ;
631 complex_floatp(inverse_jacobi_sc(rectform(u1), k1)) ;
634 complex_floatp(inverse_jacobi_sd(rectform(u1), k1)) ;
637 complex_floatp(inverse_jacobi_sn(rectform(u1), k1)) ;
640 complex_floatp(jacobi_am(rectform(u1), k1)) ;
643 complex_floatp(jacobi_cd(rectform(u1), k1)) ;
646 complex_floatp(jacobi_cn(rectform(u1), k1)) ;
649 complex_floatp(jacobi_cs(rectform(u1), k1)) ;
652 complex_floatp(jacobi_dc(rectform(u1), k1)) ;
655 complex_floatp(jacobi_dn(rectform(u1), k1)) ;
658 complex_floatp(jacobi_ds(rectform(u1), k1)) ;
661 complex_floatp(jacobi_nc(rectform(u1), k1)) ;
664 complex_floatp(jacobi_nd(rectform(u1), k1)) ;
667 complex_floatp(jacobi_ns(rectform(u1), k1)) ;
670 complex_floatp(jacobi_sc(rectform(u1), k1)) ;
673 complex_floatp(jacobi_sd(rectform(u1), k1)) ;
676 complex_floatp(jacobi_sn(rectform(u1), k1)) ;
679 complex_floatp(elliptic_pi(n1, rectform(u1), k1)) ;
683 with_stdout ("/tmp/bar.mac",
685 for f in elliptic_fcns_1
686 do block ([a : f('rectform(u1))],
687 print ('complex_bfloatp(a), ";"),
691 for f in elliptic_fcns_2
692 do block ([a : f('rectform(u1), k1)],
693 print ('complex_bfloatp(a), ";"),
697 for f in elliptic_fcns_3
698 do block ([a : f(n1, 'rectform(u1), k1)],
699 print ('complex_bfloatp(a), ";"),
704 (u1 : 0.5b0*(1.0b0 - 0.25b0*%i)^2,
707 complex_bfloatp(e) := bfloatp(realpart(e)) and bfloatp(imagpart(e)),
711 complex_bfloatp(elliptic_ec(rectform(u1))) ;
714 complex_bfloatp(elliptic_kc(rectform(u1))) ;
717 complex_bfloatp(elliptic_e(rectform(u1), k1)) ;
720 complex_bfloatp(elliptic_eu(rectform(u1), k1)) ;
723 complex_bfloatp(elliptic_f(rectform(u1), k1)) ;
726 complex_bfloatp(inverse_jacobi_cd(rectform(u1), k1)) ;
729 complex_bfloatp(inverse_jacobi_cn(rectform(u1), k1)) ;
732 complex_bfloatp(inverse_jacobi_cs(rectform(u1), k1)) ;
735 complex_bfloatp(inverse_jacobi_dc(rectform(u1), k1)) ;
738 complex_bfloatp(inverse_jacobi_dn(rectform(u1), k1)) ;
741 complex_bfloatp(inverse_jacobi_ds(rectform(u1), k1)) ;
744 complex_bfloatp(inverse_jacobi_nc(rectform(u1), k1)) ;
747 complex_bfloatp(inverse_jacobi_nd(rectform(u1), k1)) ;
750 complex_bfloatp(inverse_jacobi_ns(rectform(u1), k1)) ;
753 complex_bfloatp(inverse_jacobi_sc(rectform(u1), k1)) ;
756 complex_bfloatp(inverse_jacobi_sd(rectform(u1), k1)) ;
759 complex_bfloatp(inverse_jacobi_sn(rectform(u1), k1)) ;
762 complex_bfloatp(jacobi_am(rectform(u1), k1)) ;
765 complex_bfloatp(jacobi_cd(rectform(u1), k1)) ;
768 complex_bfloatp(jacobi_cn(rectform(u1), k1)) ;
771 complex_bfloatp(jacobi_cs(rectform(u1), k1)) ;
774 complex_bfloatp(jacobi_dc(rectform(u1), k1)) ;
777 complex_bfloatp(jacobi_dn(rectform(u1), k1)) ;
780 complex_bfloatp(jacobi_ds(rectform(u1), k1)) ;
783 complex_bfloatp(jacobi_nc(rectform(u1), k1)) ;
786 complex_bfloatp(jacobi_nd(rectform(u1), k1)) ;
789 complex_bfloatp(jacobi_ns(rectform(u1), k1)) ;
792 complex_bfloatp(jacobi_sc(rectform(u1), k1)) ;
795 complex_bfloatp(jacobi_sd(rectform(u1), k1)) ;
798 complex_bfloatp(jacobi_sn(rectform(u1), k1)) ;
801 complex_bfloatp(elliptic_pi(n1, rectform(u1), k1)) ;
804 /* Test derivatives at a few random points using numerical differentiation
807 df - deriviative of func wrt p-th argument
808 p - derivative wrt p-th argument
809 vars - variables in expression deriv
810 table - table of points to evaluate
811 eps - report errors > eps
812 delta - offset for numerical derivative
814 (test_deriv(func,df,vars,p,table,eps,delta) :=
815 block([badpoints : [],
819 block([%z0, %z1, deriv, nderiv],
820 %z1:makelist(if i=p then %z[i]+delta else %z[i],i,1,length(%z)),
821 %z0:makelist(if i=p then %z[i]-delta else %z[i],i,1,length(%z)),
822 nderiv: float((apply(func,%z1)-apply(func,%z0))/(2*delta)),
823 deriv : float(subst(maplist("=",vars,%z),df)),
824 abserr : abs(nderiv-deriv),
825 maxerr : max(maxerr,abserr),
827 badpoints : cons ([%z,deriv,nderiv,abserr],badpoints)
829 if badpoints # [] then
830 cons(maxerr,badpoints)
836 /* test points for two-arg functions */
837 (l2: [[0.2, 0.3], [0.2, 0.5], [1.5, 0.7], [0.5, 0.99], [1.5, 0.8],
838 [1.57, 0.8], [1.5707, 0.8], [-1.0, 0.8], [2.0, 0.8]],done);
841 /* test points for three-arg functions */
842 /* bug #3221 elliptic_pi() wrong for 2nd arg > float(%pi/2) */
843 (l3: [[0.1,0.2,0.3],[0.1,0.2,0.5],[0.2,1.5,0.7],[0.001,0.5,0.99],
844 [0.2,1.5,0.8],[0.2,1.57,0.8],[0.2,1.5707,0.8]],done);
847 test_deriv('elliptic_f,diff(elliptic_f(z,m),z),[z,m],1,l2,2.0e-7,1.0e-8);
850 test_deriv('elliptic_f,diff(elliptic_f(z,m),m),[z,m],2,l2,2.0e-7,1.0e-8);
853 test_deriv('elliptic_e,diff(elliptic_e(z,m),z),[z,m],1,l2,2.0e-7,1.0e-8);
856 test_deriv('elliptic_e,diff(elliptic_e(z,m),m),[z,m],2,l2,2.0e-7,1.0e-8);
859 test_deriv('elliptic_pi,diff(elliptic_pi(n,z,m),n),[n,z,m],1,l3,2.0e-7,1.0e-8);
862 test_deriv('elliptic_pi,diff(elliptic_pi(n,z,m),z),[n,z,m],2,l3,2.0e-7,1.0e-8);
865 test_deriv('elliptic_pi,diff(elliptic_pi(n,z,m),m),[n,z,m],3,l3,2.0e-7,1.0e-8);
868 closeto(e,tol):=block([numer:true,abse],abse:abs(e),if(abse<tol) then true else abse);
869 closeto(e,tol):=block([numer:true,abse],abse:abs(e),if(abse<tol) then true else abse);
872 * Some additional tests for complex values. Use the fact that
873 * elliptic_pi(0, phi, m) = elliptic_f(phi,m);
875 closeto(elliptic_pi(0, 0.5, 0.25)- elliptic_f(0.5, 0.25), 1e-15);
877 closeto(elliptic_pi(0, 0.5*%i, 0.25)- elliptic_f(0.5*%i, 0.25), 1e-15);
880 closeto(elliptic_pi(0, 0.5b0, 0.25b0)- elliptic_f(0.5b0, 0.25b0), 1e-15);
882 closeto(elliptic_pi(0, 0.5b0*%i, 0.25b0)- elliptic_f(0.5b0*%i, 0.25b0), 1e-15);
885 /* Test for Bug 3221 */
887 closeto(elliptic_pi(0.2,1.57,0.8) - 2.5770799919605668, 1e-14);
889 closeto(elliptic_pi(0.2,1.58,0.8) - 2.60502920656026151, 1e-14);
891 closeto(elliptic_pi(0.20,2.00,0.80) - 3.6543835090829025, 7.47e-11);
894 (oldfpprec:fpprec,fpprec:32);
896 closeto(elliptic_pi(0.2b0,1.57b0,0.8b0) - 2.5770799919605668058849721013196b0, 3.09b-32);
898 closeto(elliptic_pi(0.2b0,1.58b0,0.8b0) - 2.6050292065602615145481924917132b0, 1.24b-32);
900 closeto(elliptic_pi(0.2b0,2.0b0,0.8b0) - 3.6543835090082902501670624830938b0, 1b-32);
903 /* Test for #3733 $gamma vs %gamma confusion */
904 elliptic_ec(1/2) - gamma(3/4)^2/(2*sqrt(%pi))- %pi^(3/2)/(4*gamma(3/4)^2);
907 /* #3745 Quoting either elliptic_f [or elliptic_e] inhibits simplification */
914 /* #3967 elliptic_e(5*%pi/4,1) inconsistent with numerical evaluation */
915 elliptic_e(5*%pi/4, 1);
918 closeto(elliptic_e(5*%pi/4,1) - elliptic_e(float(5*%pi/4),1), 1e-16);
921 /* #3746 derivative of inverse_jacobi_sn is noun/verb confused.
922 The same is true for inverse_jacobi_cn and inverse_jacobi_dn, but the
923 remaining nine inverse Jacobi functions ns, nc, nd, sc, cs, sd, ds, cd,
924 and dc don't have defined m derivatives.*/
925 subst(u=0, diff(inverse_jacobi_sn(u,m),m));
928 subst(u=1, diff(inverse_jacobi_cn(u,m),m));
931 subst(u=1, diff(inverse_jacobi_dn(u,m),m));
934 /* Carlson's integrals */
936 (assume(xp > 0), done);
951 carlson_rc(%i, %i+1);
952 %pi/4 + %i*log(sqrt(2)-1)/2$
955 ((1-%i)*%pi)/2^(3/2)$
957 carlson_rc(((1+xp)/2)^2, xp);
960 /* log(x) = (x-1)*carlson_rc(((1+x)/2)^2,x) */
961 closeto((2-1)*carlson_rc(((1+2)/2)^2,2.0) - log(2.0), 1e-16);
964 /* asin(x) = x*carlson_rc(1-x^2,1) */
965 closeto(1/2*carlson_rc(1-1/4,1.0) - asin(0.5), 2.2205e-16);
968 /* acos(x) = sqrt(1-x^2)*carlson_rc(x^2,1) */
969 closeto(sqrt(1.0-1/4)*carlson_rc(1/4,1.0) - acos(0.5), 2.2205e-16);
972 /* atan(x) = x*carlson_rc(1,1+x^2) */
973 closeto(1*carlson_rc(1.0,1+1^2) - atan(1.0), 1.1103e-16);
976 /* asinh(x) = x*carlson_rc(1+x^2,1) */
977 closeto(1*carlson_rc(1+1^2,1.0) - asinh(1.0), 2.2205e-16);
980 /* acosh(x) = sqrt(x^2-1)*carlson_rc(x^2,1) */
981 closeto(sqrt(2^2-1.0)*carlson_rc(2^2,1.0) - acosh(2.0), 2.2205e-16);
984 /* atanh(x) = x*carlson_rc(1,1-x^2) */
985 closeto(1/2*carlson_rc(1.0,1-(1/2)^2) - atanh(0.5), 1.1103e-16);
992 3*sqrt(%pi)*gamma(3/4)/gamma(1/4)$
995 3*sqrt(%pi)*gamma(3/4)/gamma(1/4)$
997 closeto(carlson_rd(0, 2, 1.0) - float(3*sqrt(%pi)*gamma(3/4)/gamma(1/4)), 6.66134e-16);
1004 * Rf(1,2,0) has an analytic solution. Check some of the permutations too.
1007 gamma(1/4)^2/(4*sqrt(2*%pi))$
1010 gamma(1/4)^2/(4*sqrt(2*%pi))$
1013 gamma(1/4)^2/(4*sqrt(2*%pi))$
1015 /* Check permutations of Rf(%i, -%i, 0) too */
1016 carlson_rf(%i,-%i,0);
1017 gamma(1/4)^2/(4*sqrt(%pi))$
1019 carlson_rf(-%i,%i,0);
1020 gamma(1/4)^2/(4*sqrt(%pi))$
1022 carlson_rf(0, %i,-%i);
1023 gamma(1/4)^2/(4*sqrt(%pi))$
1026 carlson_rj(x,x,x,x);
1029 carlson_rj(x,y,z,z);
1032 (assume(pp>0,yp>0), done);
1035 carlson_rj(xp,xp,xp,pp);
1036 3*(1/sqrt(xp)-carlson_rc(xp,pp))/(pp-xp)$
1038 carlson_rj(0,yp,yp,pp);
1039 3*%pi/(2*(yp*sqrt(pp)+pp*sqrt(yp)))$
1041 carlson_rj(x,yp,yp,pp);
1042 3/(pp-yp)*(carlson_rc(x,yp) - carlson_rc(x,pp))$
1044 carlson_rj(x,yp,yp,yp);
1045 (3*(carlson_rc(x,yp)-sqrt(x)/yp))/(2*(yp-x))$
1051 2*atan(exp(z))-%pi/2;
1057 * A few numerical values of jacobi_am to test that we return the
1058 * correct values. The expected values were produced from
1059 * functions.wolfram.com
1062 closeto(jacobi_am(1, .5) - 0.93231507988385386595, 1e-18);
1065 closeto(jacobi_am(100, .5) - 84.703112724113824403, 1e-18);
1068 closeto(jacobi_am(0.5, 1.5) - 0.47071978970469916313, 4.4409e-16);
1071 closeto(jacobi_am(1.5, 1.5+%i) - (0.93405421687007830327 - 0.37239604521460716554*%i), 5.4673e-16);
1074 closeto(jacobi_am(2.0-.5*%i, .5+.5*%i) - (1.4693733607922556333 - 0.7245711235745948013*%i), 8.9510e-16);
1077 closeto(jacobi_am(1b0, .5b0) - 0.932315079883853865951695610516257727b0, 1.5408b-33);
1080 closeto(jacobi_am(100b0, .5b0) - 84.7031127241138244025523773764166798b0, 1b-35);
1083 closeto(jacobi_am(0.5b0, 1.5b0) - 0.470719789704699163132257860869655024b0, 7.7038b-34);
1086 closeto(jacobi_am(1.5b0, 1.5b0+%i) - (0.934054216870078303274350830308588452b0 - 0.372396045214607165539500260724230487b0*%i), 2.3112b-32);
1089 closeto(jacobi_am(2.0b0-.5b0*%i, .5b0+.5b0*%i) - (1.46937336079225563334301589326200829b0 - 0.72457112357459480134743514393673164b0*%i), 1.2422b-32);
1093 * Test consistency of jacobi_am with jacobi_sn via
1094 * sin(jacobi_am(u,m)) = jacobi_sn(u,m).
1096 makelist(block([z : 2*k, m : .5],
1097 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 1.5544e-15)),
1099 [true, true, true, true, true, true, true, true, true, true, true];
1101 makelist(block([z : 2*k, m : 2.5],
1102 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 2.2205e-16)),
1104 [true, true, true, true, true, true, true, true, true, true, true];
1106 makelist(block([z : 2*k, m : 1+.5*%i],
1107 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 4.9651e-16)),
1109 [true, true, true, true, true, true, true, true, true, true, true];
1111 makelist(block([z : 2*k*%i, m : .75],
1112 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 3.1087e-14)),
1114 [true, true, true, true, true, true, true, true, true, true, true];
1116 makelist(block([z : 2*k*%i, m : 1.75],
1117 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 3.5528e-15)),
1119 [true, true, true, true, true, true, true, true, true, true, true];
1121 makelist(block([z : 2*k*%i, m : 1.75+%i],
1122 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 4.9651e-16)),
1124 [true, true, true, true, true, true, true, true, true, true, true];
1126 /* Do the same tests as above, but for bfloats */
1127 makelist(block([z : 2*k, m : .5b0],
1128 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 1.8489b-32)),
1130 [true, true, true, true, true, true, true, true, true, true, true];
1132 makelist(block([z : 2*k, m : 2.5b0],
1133 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 1.5408b-32)),
1135 [true, true, true, true, true, true, true, true, true, true, true];
1137 makelist(block([z : 2*k, m : 1+.5b0*%i],
1138 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 2.5271b-32)),
1140 [true, true, true, true, true, true, true, true, true, true, true];
1142 makelist(block([z : 2*k*%i, m : .75b0],
1143 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 5.5467b-32)),
1145 [true, true, true, true, true, true, true, true, true, true, true];
1147 makelist(block([z : 2*k*%i, m : 1.75b0],
1148 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 2.2187b-31)),
1150 [true, true, true, true, true, true, true, true, true, true, true];
1152 makelist(block([z : 2*k*%i, m : 1.75b0+%i],
1153 closeto(sin(jacobi_am(z, m))-jacobi_sn(z, m), 4.8135b-32)),
1155 [true, true, true, true, true, true, true, true, true, true, true];
1158 * #4352 elliptic_e signals an error due to elliptic_ec returning a
1159 * Maxima complex instead of Lisp complex.
1161 closeto(elliptic_e(1,1.23) - 0.7935821331230606, 1e-15);
1164 closeto(elliptic_e(1,2.0) - (0.09311292177217778*%i+0.5990701173677968), 1e-15);
1167 closeto(elliptic_e(1,1.23b0)- 7.9358213312306066216147457280131b-1, 1b-32);
1170 closeto(elliptic_e(1,2b0) - (9.3112921772178507209815461615034b-2*%i+5.9907011736779610371996124614016b-1), 3.1055b-33);
1173 (fpprec:oldfpprec,kill(l2,l3,test_deriv,oldfpprec),done);