1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10-*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
8 ;;; Copyright (c) 2001 by Raymond Toy. Replaced everything and added ;;;;;
9 ;;; support for symbolic manipulation of all 12 Jacobian elliptic ;;;;;
10 ;;; functions and the complete and incomplete elliptic integral ;;;;;
11 ;;; of the first, second and third kinds. ;;;;;
12 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15 ;;(macsyma-module ellipt)
17 (defvar 3//2 '((rat simp
) 3 2))
18 (defvar 1//2 '((rat simp
) 1 2))
19 (defvar -
1//2 '((rat simp
) -
1 2))
22 ;;; Jacobian elliptic functions and elliptic integrals.
26 ;;; [1] Abramowitz and Stegun
27 ;;; [2] Lawden, Elliptic Functions and Applications, Springer-Verlag, 1989
28 ;;; [3] Whittaker & Watson, A Course of Modern Analysis
30 ;;; We use the definitions from Abramowitz and Stegun where our
31 ;;; sn(u,m) is sn(u|m). That is, the second arg is the parameter,
32 ;;; instead of the modulus k or modular angle alpha.
34 ;;; Note that m = k^2 and k = sin(alpha).
37 ;; Setup noun/verb for elliptic functions
41 (let* ((s (string root
))
42 (forward (concatenate 'string
(string 'jacobi_
) s
))
43 (f-noun (intern (concatenate 'string
"%" forward
)))
44 (f-verb (intern (concatenate 'string
"$" forward
)))
45 (inverse (concatenate 'string
(string 'inverse_jacobi_
) s
))
46 (i-noun (intern (concatenate 'string
"%" inverse
)))
47 (i-verb (intern (concatenate 'string
"$" inverse
))))
49 (defprop ,f-verb
,f-noun verb
)
50 (defprop ,f-noun
,f-verb noun
)
51 (defprop ,f-verb
,f-noun alias
)
52 (defprop ,f-noun
,f-verb reversealias
)
53 (defprop ,i-verb
,i-noun verb
)
54 (defprop ,i-noun
,i-verb noun
)
55 (defprop ,i-verb
,i-noun alias
)
56 (defprop ,i-noun
,i-verb reversealias
)))))
70 (defprop $elliptic_f $elliptic_f verb
)
71 (defprop $elliptic_e $elliptic_e verb
)
73 ;; Routines for computing the basic elliptic functions sn, cn, and dn.
76 ;; A&S gives several methods for computing elliptic functions
77 ;; including the AGM method (16.4) and ascending and descending Landen
78 ;; transformations (16.12 and 16.14). The latter are actually quite
79 ;; fast, only requiring simple arithmetic and square roots for the
80 ;; transformation until the last step. The AGM requires evaluation of
81 ;; several trigonometric functions at each stage.
83 ;; However, the Landen transformations appear to have some round-off
84 ;; issues. For example, using the ascending transform to compute cn,
85 ;; cn(100,.7) > 1e10. This is clearly not right since |cn| <= 1.
88 (in-package #-gcl
#:bigfloat
#+gcl
"BIGFLOAT")
90 (declaim (inline descending-transform ascending-transform
))
92 (defun ascending-transform (u m
)
95 ;; Take care in computing this transform. For the case where
96 ;; m is complex, we should compute sqrt(mu1) first as
97 ;; (1-sqrt(m))/(1+sqrt(m)), and then square this to get mu1.
98 ;; If not, we may choose the wrong branch when computing
100 (let* ((root-m (sqrt m
))
102 (expt (1+ root-m
) 2)))
103 (root-mu1 (/ (- 1 root-m
) (+ 1 root-m
)))
104 (v (/ u
(1+ root-mu1
))))
105 (values v mu root-mu1
)))
107 (defun descending-transform (u m
)
108 ;; Note: Don't calculate mu first, as given in 16.12.1. We
109 ;; should calculate sqrt(mu) = (1-sqrt(m1)/(1+sqrt(m1)), and
110 ;; then compute mu = sqrt(mu)^2. If we calculate mu first,
111 ;; sqrt(mu) loses information when m or m1 is complex.
112 (let* ((root-m1 (sqrt (- 1 m
)))
113 (root-mu (/ (- 1 root-m1
) (+ 1 root-m1
)))
114 (mu (* root-mu root-mu
))
115 (v (/ u
(1+ root-mu
))))
116 (values v mu root-mu
)))
119 ;; This appears to work quite well for both real and complex values
121 (defun elliptic-sn-descending (u m
)
125 ((< (abs m
) (epsilon u
))
129 (multiple-value-bind (v mu root-mu
)
130 (descending-transform u m
)
131 (let* ((new-sn (elliptic-sn-descending v mu
)))
132 (/ (* (1+ root-mu
) new-sn
)
133 (1+ (* root-mu new-sn new-sn
))))))))
135 ;; AGM scale. See A&S 17.6
139 ;; a[n] = (a[n-1]+b[n-1])/2, b[n] = sqrt(a[n-1]*b[n-1]), c[n] = (a[n-1]-b[n-1])/2.
141 ;; We stop when abs(c[n]) <= 10*eps
143 ;; A list of (n a[n] b[n] c[n]) is returned.
144 (defun agm-scale (a b c
)
146 while
(> (abs c
) (* 10 (epsilon c
)))
147 collect
(list n a b c
)
148 do
(psetf a
(/ (+ a b
) 2)
152 ;; WARNING: This seems to have accuracy problems when u is complex. I
153 ;; (rtoy) do not know why. For example (jacobi-agm #c(1e0 1e0) .7e0)
156 ;; #C(1.134045970915582 0.3522523454566013)
157 ;; #C(0.57149659007575 -0.6989899153338323)
158 ;; #C(0.6229715431044184 -0.4488635962149656)
160 ;; But the actual value of sn(1+%i, .7) is .3522523469224946 %i +
161 ;; 1.134045971912365. We've lost about 7 digits of accuracy!
162 (defun jacobi-agm (u m
)
165 ;; Compute the AGM scale with a = 1, b = sqrt(1-m), c = sqrt(m).
167 ;; Then phi[N] = 2^N*a[N]*u and compute phi[n] from
169 ;; sin(2*phi[n-1] - phi[n]) = c[n]/a[n]*sin(phi[n])
173 ;; sn(u|m) = sin(phi[0]), cn(u|m) = cos(phi[0])
174 ;; dn(u|m) = cos(phi[0])/cos(phi[1]-phi[0])
176 ;; Returns the three values sn, cn, dn.
177 (let* ((agm-data (nreverse (rest (agm-scale 1 (sqrt (- 1 m
)) (sqrt m
)))))
178 (phi (destructuring-bind (n a b c
)
180 (declare (ignore b c
))
183 (dolist (agm agm-data
)
184 (destructuring-bind (n a b c
)
186 (declare (ignore n b
))
188 phi
(/ (+ phi
(asin (* (/ c a
) (sin phi
)))) 2))))
189 (values (sin phi
) (cos phi
) (/ (cos phi
) (cos (- phi1 phi
))))))
193 ;; jacobi_sn(u,0) = sin(u). Should we use A&S 16.13.1 if m
196 ;; sn(u,m) = sin(u) - 1/4*m(u-sin(u)*cos(u))*cos(u)
199 ;; jacobi_sn(u,1) = tanh(u). Should we use A&S 16.15.1 if m
200 ;; is close enough to 1?
202 ;; sn(u,m) = tanh(u) + 1/4*(1-m)*(sinh(u)*cosh(u)-u)*sech(u)^2
205 ;; Use the ascending Landen transformation to compute sn.
206 (let ((s (elliptic-sn-descending u m
)))
207 (if (and (realp u
) (realp m
))
213 ;; jacobi_dn(u,0) = 1. Should we use A&S 16.13.3 for small m?
215 ;; dn(u,m) = 1 - 1/2*m*sin(u)^2
218 ;; jacobi_dn(u,1) = sech(u). Should we use A&S 16.15.3 if m
219 ;; is close enough to 1?
221 ;; dn(u,m) = sech(u) + 1/4*(1-m)*(sinh(u)*cosh(u)+u)*tanh(u)*sech(u)
224 ;; Use the Gauss transformation from
225 ;; http://functions.wolfram.com/09.29.16.0013.01:
228 ;; dn((1+sqrt(m))*z, 4*sqrt(m)/(1+sqrt(m))^2)
229 ;; = (1-sqrt(m)*sn(z, m)^2)/(1+sqrt(m)*sn(z,m)^2)
233 ;; dn(y, mu) = (1-sqrt(m)*sn(z, m)^2)/(1+sqrt(m)*sn(z,m)^2)
235 ;; where z = y/(1+sqrt(m)) and mu=4*sqrt(m)/(1+sqrt(m))^2.
237 ;; Solve for m, and we get
239 ;; sqrt(m) = -(mu+2*sqrt(1-mu)-2)/mu or (-mu+2*sqrt(1-mu)+2)/mu.
241 ;; I don't think it matters which sqrt we use, so I (rtoy)
242 ;; arbitrarily choose the first one above.
244 ;; Note that (1-sqrt(1-mu))/(1+sqrt(1-mu)) is the same as
245 ;; -(mu+2*sqrt(1-mu)-2)/mu. Also, the former is more
246 ;; accurate for small mu.
247 (let* ((root (let ((root-1-m (sqrt (- 1 m
))))
251 (s (elliptic-sn-descending z
(* root root
)))
258 ;; jacobi_cn(u,0) = cos(u). Should we use A&S 16.13.2 for
261 ;; cn(u,m) = cos(u) + 1/4*m*(u-sin(u)*cos(u))*sin(u)
264 ;; jacobi_cn(u,1) = sech(u). Should we use A&S 16.15.3 if m
265 ;; is close enough to 1?
267 ;; cn(u,m) = sech(u) - 1/4*(1-m)*(sinh(u)*cosh(u)-u)*tanh(u)*sech(u)
270 ;; Use the ascending Landen transformation, A&S 16.14.3.
271 (multiple-value-bind (v mu root-mu1
)
272 (ascending-transform u m
)
274 (* (/ (+ 1 root-mu1
) mu
)
275 (/ (- (* d d
) root-mu1
)
281 ;; How this works, I think.
283 ;; $jacobi_sn is the user visible function JACOBI_SN. We put
284 ;; properties on this symbol so maxima can figure out what to do with
287 ;; Tell maxima how to simplify the functions $jacobi_sn, etc. This
288 ;; borrows heavily from trigi.lisp.
289 (defprop %jacobi_sn simp-%jacobi_sn operators
)
290 (defprop %jacobi_cn simp-%jacobi_cn operators
)
291 (defprop %jacobi_dn simp-%jacobi_dn operators
)
292 (defprop %inverse_jacobi_sn simp-%inverse_jacobi_sn operators
)
293 (defprop %inverse_jacobi_cn simp-%inverse_jacobi_cn operators
)
294 (defprop %inverse_jacobi_dn simp-%inverse_jacobi_dn operators
)
296 ;; Tell maxima what the derivatives are.
298 ;; Lawden says the derivative wrt to k but that's not what we want.
300 ;; Here's the derivation we used, based on how Lawden get's his results.
304 ;; diff(sn(u,m),m) = s
305 ;; diff(cn(u,m),m) = p
306 ;; diff(dn(u,m),m) = q
308 ;; From the derivatives of sn, cn, dn wrt to u, we have
310 ;; diff(sn(u,m),u) = cn(u)*dn(u)
311 ;; diff(cn(u,m),u) = -cn(u)*dn(u)
312 ;; diff(dn(u,m),u) = -m*sn(u)*cn(u)
315 ;; Differentiate these wrt to m:
317 ;; diff(s,u) = p*dn + cn*q
318 ;; diff(p,u) = -p*dn - q*dn
319 ;; diff(q,u) = -sn*cn - m*s*cn - m*sn*q
323 ;; sn(u)^2 + cn(u)^2 = 1
324 ;; dn(u)^2 + m*sn(u)^2 = 1
326 ;; Differentiate these wrt to m:
329 ;; 2*dn*q + sn^2 + 2*m*sn*s = 0
334 ;; q = -m*s*sn/dn - sn^2/dn/2
337 ;; diff(s,u) = -s*sn*dn/cn - m*s*sn*cn/dn - sn^2*cn/dn/2
341 ;; diff(s,u) + s*(sn*dn/cn + m*sn*cn/dn) = -1/2*sn^2*cn/dn
343 ;; diff(s,u) + s*sn/cn/dn*(dn^2 + m*cn^2) = -1/2*sn^2*cn/dn
345 ;; Multiply through by the integrating factor 1/cn/dn:
347 ;; diff(s/cn/dn, u) = -1/2*sn^2/dn^2 = -1/2*sd^2.
349 ;; Interate this to get
351 ;; s/cn/dn = C + -1/2*int sd^2
353 ;; It can be shown that C is zero.
355 ;; We know that (by differentiating this expression)
357 ;; int dn^2 = (1-m)*u+m*sn*cd + m*(1-m)*int sd^2
361 ;; int sd^2 = 1/m/(1-m)*int dn^2 - u/m - sn*cd/(1-m)
365 ;; s/cn/dn = u/(2*m) + sn*cd/(2*(1-m)) - 1/2/m/(1-m)*int dn^2
369 ;; s = 1/(2*m)*u*cn*dn + 1/(2*(1-m))*sn*cn^2 - 1/2/(m*(1-m))*cn*dn*E(u)
371 ;; where E(u) = int dn^2 = elliptic_e(am(u)) = elliptic_e(asin(sn(u)))
373 ;; This is our desired result:
375 ;; s = 1/(2*m)*cn*dn*[u - elliptic_e(asin(sn(u)),m)/(1-m)] + sn*cn^2/2/(1-m)
378 ;; Since diff(cn(u,m),m) = p = -s*sn/cn, we have
380 ;; p = -1/(2*m)*sn*dn[u - elliptic_e(asin(sn(u)),m)/(1-m)] - sn^2*cn/2/(1-m)
382 ;; diff(dn(u,m),m) = q = -m*s*sn/dn - sn^2/dn/2
384 ;; q = -1/2*sn*cn*[u-elliptic_e(asin(sn),m)/(1-m)] - m*sn^2*cn^2/dn/2/(1-m)
388 ;; = -1/2*sn*cn*[u-elliptic_e(asin(sn),m)/(1-m)] + dn*sn^2/2/(m-1)
392 ((mtimes) ((%jacobi_cn
) u m
) ((%jacobi_dn
) u m
))
394 ((mtimes simp
) ((rat simp
) 1 2)
395 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
396 ((mexpt simp
) ((%jacobi_cn simp
) u m
) 2) ((%jacobi_sn simp
) u m
))
397 ((mtimes simp
) ((rat simp
) 1 2) ((mexpt simp
) m -
1)
398 ((%jacobi_cn simp
) u m
) ((%jacobi_dn simp
) u m
)
400 ((mtimes simp
) -
1 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
401 (($elliptic_e simp
) ((%asin simp
) ((%jacobi_sn simp
) u m
)) m
))))))
406 ((mtimes simp
) -
1 ((%jacobi_sn simp
) u m
) ((%jacobi_dn simp
) u m
))
408 ((mtimes simp
) ((rat simp
) -
1 2)
409 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
410 ((%jacobi_cn simp
) u m
) ((mexpt simp
) ((%jacobi_sn simp
) u m
) 2))
411 ((mtimes simp
) ((rat simp
) -
1 2) ((mexpt simp
) m -
1)
412 ((%jacobi_dn simp
) u m
) ((%jacobi_sn simp
) u m
)
414 ((mtimes simp
) -
1 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
415 (($elliptic_e simp
) ((%asin simp
) ((%jacobi_sn simp
) u m
)) m
))))))
420 ((mtimes) -
1 m
((%jacobi_sn
) u m
) ((%jacobi_cn
) u m
))
422 ((mtimes simp
) ((rat simp
) -
1 2)
423 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
424 ((%jacobi_dn simp
) u m
) ((mexpt simp
) ((%jacobi_sn simp
) u m
) 2))
425 ((mtimes simp
) ((rat simp
) -
1 2) ((%jacobi_cn simp
) u m
)
426 ((%jacobi_sn simp
) u m
)
429 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
430 (($elliptic_e simp
) ((%asin simp
) ((%jacobi_sn simp
) u m
)) m
))))))
433 ;; The inverse elliptic functions.
435 ;; F(phi|m) = asn(sin(phi),m)
437 ;; so asn(u,m) = F(asin(u)|m)
438 (defprop %inverse_jacobi_sn
441 ;; inverse_jacobi_sn(x) = integrate(1/sqrt(1-t^2)/sqrt(1-m*t^2),t,0,x)
442 ;; -> 1/sqrt(1-x^2)/sqrt(1-m*x^2)
444 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
446 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
((mexpt simp
) x
2)))
448 ;; diff(F(asin(u)|m),m)
449 ((mtimes simp
) ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
452 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
454 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
((mexpt simp
) x
2)))
456 ((mtimes simp
) ((mexpt simp
) m -
1)
457 ((mplus simp
) (($elliptic_e simp
) ((%asin simp
) x
) m
)
458 ((mtimes simp
) -
1 ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
459 (($elliptic_f simp
) ((%asin simp
) x
) m
)))))))
462 ;; Let u = inverse_jacobi_cn(x). Then jacobi_cn(u) = x or
463 ;; sqrt(1-jacobi_sn(u)^2) = x. Or
465 ;; jacobi_sn(u) = sqrt(1-x^2)
467 ;; So u = inverse_jacobi_sn(sqrt(1-x^2),m) = inverse_jacob_cn(x,m)
469 (defprop %inverse_jacobi_cn
471 ;; Whittaker and Watson, 22.121
472 ;; inverse_jacobi_cn(u,m) = integrate(1/sqrt(1-t^2)/sqrt(1-m+m*t^2), t, u, 1)
473 ;; -> -1/sqrt(1-x^2)/sqrt(1-m+m*x^2)
475 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
478 ((mplus simp
) 1 ((mtimes simp
) -
1 m
)
479 ((mtimes simp
) m
((mexpt simp
) x
2)))
481 ((mtimes simp
) ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
486 ((mtimes simp
) -
1 m
((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))))
488 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2))) ((rat simp
) 1 2))
490 ((mtimes simp
) ((mexpt simp
) m -
1)
494 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2))) ((rat simp
) 1 2)))
496 ((mtimes simp
) -
1 ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
499 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2))) ((rat simp
) 1 2)))
503 ;; Let u = inverse_jacobi_dn(x). Then
505 ;; jacobi_dn(u) = x or
507 ;; x^2 = jacobi_dn(u)^2 = 1 - m*jacobi_sn(u)^2
509 ;; so jacobi_sn(u) = sqrt(1-x^2)/sqrt(m)
511 ;; or u = inverse_jacobi_sn(sqrt(1-x^2)/sqrt(m))
512 (defprop %inverse_jacobi_dn
514 ;; Whittaker and Watson, 22.121
515 ;; inverse_jacobi_dn(u,m) = integrate(1/sqrt(1-t^2)/sqrt(t^2-(1-m)), t, u, 1)
516 ;; -> -1/sqrt(1-x^2)/sqrt(x^2+m-1)
518 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
520 ((mexpt simp
) ((mplus simp
) -
1 m
((mexpt simp
) x
2)) ((rat simp
) -
1 2)))
522 ((mtimes simp
) ((rat simp
) -
1 2) ((mexpt simp
) m
((rat simp
) -
3 2))
525 ((mtimes simp
) -
1 ((mexpt simp
) m -
1)
526 ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))))
528 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
530 ((mexpt simp
) ((mabs simp
) x
) -
1))
531 ((mtimes simp
) ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
533 ((mtimes simp
) -
1 ((mexpt simp
) m
((rat simp
) -
1 2))
536 ((mtimes simp
) -
1 ((mexpt simp
) m -
1)
537 ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))))
539 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
541 ((mexpt simp
) ((mabs simp
) x
) -
1))
542 ((mtimes simp
) ((mexpt simp
) m -
1)
546 ((mtimes simp
) ((mexpt simp
) m
((rat simp
) -
1 2))
547 ((mexpt simp
) ((mplus simp
) 1
548 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
551 ((mtimes simp
) -
1 ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
554 ((mtimes simp
) ((mexpt simp
) m
((rat simp
) -
1 2))
555 ((mexpt simp
) ((mplus simp
) 1
556 ((mtimes simp
) -
1 ((mexpt simp
) x
2)))
562 ;; Define the actual functions for the user
563 (defmfun $jacobi_sn
(u m
)
564 (simplify (list '(%jacobi_sn
) (resimplify u
) (resimplify m
))))
566 (defmfun $jacobi_cn
(u m
)
567 (simplify (list '(%jacobi_cn
) (resimplify u
) (resimplify m
))))
569 (defmfun $jacobi_dn
(u m
)
570 (simplify (list '(%jacobi_dn
) (resimplify u
) (resimplify m
))))
572 (defmfun $inverse_jacobi_sn
(u m
)
573 (simplify (list '(%inverse_jacobi_sn
) (resimplify u
) (resimplify m
))))
575 (defmfun $inverse_jacobi_cn
(u m
)
576 (simplify (list '(%inverse_jacobi_cn
) (resimplify u
) (resimplify m
))))
578 (defmfun $inverse_jacobi_dn
(u m
)
579 (simplify (list '(%inverse_jacobi_dn
) (resimplify u
) (resimplify m
))))
581 ;; Possible forms of a complex number:
585 ;; ((mplus simp) 2.3 ((mtimes simp) 2.3 $%i))
586 ;; ((mplus simp) 2.3 $%i))
587 ;; ((mtimes simp) 2.3 $%i)
591 ;; Is argument u a complex number with real and imagpart satisfying predicate ntypep?
592 (defun complex-number-p (u &optional
(ntypep 'numberp
))
594 (labels ((a1 (x) (cadr x
))
597 (N (x) (funcall ntypep x
)) ; N
598 (i (x) (and (eq x
'$%i
) (N 1))) ; %i
599 (N+i
(x) (and (null (a3+ x
)) ; mplus test is precondition
601 (or (and (i (a2 x
)) (setq I
1) t
)
602 (and (mtimesp (a2 x
)) (N*i
(a2 x
))))))
603 (N*i
(x) (and (null (a3+ x
)) ; mtimes test is precondition
606 (declare (inline a1 a2 a3
+ N i N
+i N
*i
))
607 (cond ((N u
) (values t u
0)) ;2.3
608 ((atom u
) (if (i u
) (values t
0 1))) ;%i
609 ((mplusp u
) (if (N+i u
) (values t R I
))) ;N+%i, N+N*%i
610 ((mtimesp u
) (if (N*i u
) (values t R I
))) ;N*%i
613 (defun complexify (x)
614 ;; Convert a Lisp number to a maxima number
616 ((complexp x
) (add (realpart x
) (mul '$%i
(imagpart x
))))
617 (t (merror (intl:gettext
"COMPLEXIFY: argument must be a Lisp real or complex number.~%COMPLEXIFY: found: ~:M") x
))))
619 (defun kc-arg (exp m
)
620 ;; Replace elliptic_kc(m) in the expression with sym. Check to see
621 ;; if the resulting expression is linear in sym and the constant
622 ;; term is zero. If so, return the coefficient of sym, i.e, the
623 ;; coefficient of elliptic_kc(m).
624 (let* ((sym (gensym))
625 (arg (maxima-substitute sym
`((%elliptic_kc
) ,m
) exp
)))
626 (if (and (not (equalp arg exp
))
628 (zerop1 (coefficient arg sym
0)))
629 (coefficient arg sym
1)
632 (defun kc-arg2 (exp m
)
633 ;; Replace elliptic_kc(m) in the expression with sym. Check to see
634 ;; if the resulting expression is linear in sym and the constant
635 ;; term is zero. If so, return the coefficient of sym, i.e, the
636 ;; coefficient of elliptic_kc(m), and the constant term. Otherwise,
638 (let* ((sym (gensym))
639 (arg (maxima-substitute sym
`((%elliptic_kc
) ,m
) exp
)))
640 (if (and (not (equalp arg exp
))
642 (list (coefficient arg sym
1)
643 (coefficient arg sym
0))
646 ;; Tell maxima how to simplify the functions
648 ;; FORM is list containing the actual expression. I don't really know
649 ;; what Y and Z contain. Most of this modeled after SIMP-%SIN.
650 (defun simp-%jacobi_sn
(form unused z
)
651 (declare (ignore unused
))
653 (let ((u (simpcheck (cadr form
) z
))
654 (m (simpcheck (caddr form
) z
))
657 ((float-numerical-eval-p u m
)
658 (to (bigfloat::sn
(bigfloat:to
($float u
)) (bigfloat:to
($float m
)))))
659 ((setf args
(complex-float-numerical-eval-p u m
))
660 (destructuring-bind (u m
)
662 (to (bigfloat::sn
(bigfloat:to
($float u
)) (bigfloat:to
($float m
))))))
663 ((bigfloat-numerical-eval-p u m
)
664 (to (bigfloat::sn
(bigfloat:to
($bfloat u
)) (bigfloat:to
($bfloat m
)))))
665 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
666 (destructuring-bind (u m
)
668 (to (bigfloat::sn
(bigfloat:to
($bfloat u
)) (bigfloat:to
($bfloat m
))))))
678 ((and $trigsign
(mminusp* u
))
679 (neg (cons-exp '%jacobi_sn
(neg u
) m
)))
682 (member (caar u
) '(%inverse_jacobi_sn
694 (alike1 (third u
) m
))
695 (let ((inv-arg (second u
)))
698 ;; jacobi_sn(inverse_jacobi_sn(u,m), m) = u
701 ;; inverse_jacobi_ns(u,m) = inverse_jacobi_sn(1/u,m)
704 ;; sn(x)^2 + cn(x)^2 = 1 so sn(x) = sqrt(1-cn(x)^2)
705 (power (sub 1 (mul inv-arg inv-arg
)) 1//2))
707 ;; inverse_jacobi_nc(u) = inverse_jacobi_cn(1/u)
708 ($jacobi_sn
($inverse_jacobi_cn
(div 1 inv-arg
) m
)
711 ;; dn(x)^2 + m*sn(x)^2 = 1 so
712 ;; sn(x) = 1/sqrt(m)*sqrt(1-dn(x)^2)
713 (mul (div 1 (power m
1//2))
714 (power (sub 1 (mul inv-arg inv-arg
)) 1//2)))
716 ;; inverse_jacobi_nd(u) = inverse_jacobi_dn(1/u)
717 ($jacobi_sn
($inverse_jacobi_dn
(div 1 inv-arg
) m
)
720 ;; See below for inverse_jacobi_sc.
721 (div inv-arg
(power (add 1 (mul inv-arg inv-arg
)) 1//2)))
723 ;; inverse_jacobi_cs(u) = inverse_jacobi_sc(1/u)
724 ($jacobi_sn
($inverse_jacobi_sc
(div 1 inv-arg
) m
)
727 ;; See below for inverse_jacobi_sd
728 (div inv-arg
(power (add 1 (mul m
(mul inv-arg inv-arg
))) 1//2)))
730 ;; inverse_jacobi_ds(u) = inverse_jacobi_sd(1/u)
731 ($jacobi_sn
($inverse_jacobi_sd
(div 1 inv-arg
) m
)
735 (div (power (sub 1 (mul inv-arg inv-arg
)) 1//2)
736 (power (sub 1 (mul m
(mul inv-arg inv-arg
))) 1//2)))
738 ($jacobi_sn
($inverse_jacobi_cd
(div 1 inv-arg
) m
) m
)))))
739 ;; A&S 16.20.1 (Jacobi's Imaginary transformation)
740 ((and $%iargs
(multiplep u
'$%i
))
742 (cons-exp '%jacobi_sc
(coeff u
'$%i
1) (add 1 (neg m
)))))
743 ((setq coef
(kc-arg2 u m
))
747 (destructuring-bind (lin const
)
749 (cond ((integerp lin
)
752 ;; sn(4*m*K + u) = sn(u), sn(0) = 0
755 `((%jacobi_sn simp
) ,const
,m
)))
757 ;; sn(4*m*K + K + u) = sn(K+u) = cd(u)
761 `((%jacobi_cd simp
) ,const
,m
)))
763 ;; sn(4*m*K+2*K + u) = sn(2*K+u) = -sn(u)
767 (neg `((%jacobi_sn simp
) ,const
,m
))))
769 ;; sn(4*m*K+3*K+u) = sn(2*K + K + u) = -sn(K+u) = -cd(u)
773 (neg `((%jacobi_cd simp
) ,const
,m
))))))
774 ((and (alike1 lin
1//2)
778 ;; sn(1/2*K) = 1/sqrt(1+sqrt(1-m))
782 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
785 ((and (alike1 lin
3//2)
789 ;; sn(1/2*K + K) = cd(1/2*K,m)
791 `((%jacobi_cd
) ((mtimes) ((rat) 1 2) ((%elliptic_kc
) ,m
))
795 (eqtest (list '(%jacobi_sn
) u m
) form
)))))
798 (eqtest (list '(%jacobi_sn
) u m
) form
)))))
800 (defun simp-%jacobi_cn
(form unused z
)
801 (declare (ignore unused
))
803 (let ((u (simpcheck (cadr form
) z
))
804 (m (simpcheck (caddr form
) z
))
807 ((float-numerical-eval-p u m
)
808 (to (bigfloat::cn
(bigfloat:to
($float u
)) (bigfloat:to
($float m
)))))
809 ((setf args
(complex-float-numerical-eval-p u m
))
810 (destructuring-bind (u m
)
812 (to (bigfloat::cn
(bigfloat:to
($float u
)) (bigfloat:to
($float m
))))))
813 ((bigfloat-numerical-eval-p u m
)
814 (to (bigfloat::cn
(bigfloat:to
($bfloat u
)) (bigfloat:to
($bfloat m
)))))
815 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
816 (destructuring-bind (u m
)
818 (to (bigfloat::cn
(bigfloat:to
($bfloat u
)) (bigfloat:to
($bfloat m
))))))
828 ((and $trigsign
(mminusp* u
))
829 (cons-exp '%jacobi_cn
(neg u
) m
))
832 (member (caar u
) '(%inverse_jacobi_sn
844 (alike1 (third u
) m
))
845 (cond ((eq (caar u
) '%inverse_jacobi_cn
)
848 ;; I'm lazy. Use cn(x) = sqrt(1-sn(x)^2). Hope
850 (power (sub 1 (power ($jacobi_sn u
(third u
)) 2))
852 ;; A&S 16.20.2 (Jacobi's Imaginary transformation)
853 ((and $%iargs
(multiplep u
'$%i
))
854 (cons-exp '%jacobi_nc
(coeff u
'$%i
1) (add 1 (neg m
))))
855 ((setq coef
(kc-arg2 u m
))
859 (destructuring-bind (lin const
)
861 (cond ((integerp lin
)
864 ;; cn(4*m*K + u) = cn(u),
868 `((%jacobi_cn simp
) ,const
,m
)))
870 ;; cn(4*m*K + K + u) = cn(K+u) = -sqrt(m1)*sd(u)
876 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
878 ((%jacobi_sd simp
) ,const
,m
)))))
880 ;; cn(4*m*K + 2*K + u) = cn(2*K+u) = -cn(u)
884 (neg `((%jacobi_cn
) ,const
,m
))))
886 ;; cn(4*m*K + 3*K + u) = cn(2*K + K + u) =
887 ;; -cn(K+u) = sqrt(m1)*sd(u)
894 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
896 ((%jacobi_sd simp
) ,const
,m
))))))
897 ((and (alike1 lin
1//2)
900 ;; cn(1/2*K) = (1-m)^(1/4)/sqrt(1+sqrt(1-m))
902 ((mexpt simp
) ((mplus simp
) 1
903 ((mtimes simp
) -
1 ,m
))
909 ((mtimes simp
) -
1 ,m
))
913 (eqtest (list '(%jacobi_cn
) u m
) form
)))))
915 (eqtest (list '(%jacobi_cn
) u m
) form
)))))
917 (defun simp-%jacobi_dn
(form unused z
)
918 (declare (ignore unused
))
920 (let ((u (simpcheck (cadr form
) z
))
921 (m (simpcheck (caddr form
) z
))
924 ((float-numerical-eval-p u m
)
925 (to (bigfloat::dn
(bigfloat:to
($float u
)) (bigfloat:to
($float m
)))))
926 ((setf args
(complex-float-numerical-eval-p u m
))
927 (destructuring-bind (u m
)
929 (to (bigfloat::dn
(bigfloat:to
($float u
)) (bigfloat:to
($float m
))))))
930 ((bigfloat-numerical-eval-p u m
)
931 (to (bigfloat::dn
(bigfloat:to
($bfloat u
)) (bigfloat:to
($bfloat m
)))))
932 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
933 (destructuring-bind (u m
)
935 (to (bigfloat::dn
(bigfloat:to
($bfloat u
)) (bigfloat:to
($bfloat m
))))))
945 ((and $trigsign
(mminusp* u
))
946 (cons-exp '%jacobi_dn
(neg u
) m
))
949 (member (caar u
) '(%inverse_jacobi_sn
961 (alike1 (third u
) m
))
962 (cond ((eq (caar u
) '%inverse_jacobi_dn
)
963 ;; jacobi_dn(inverse_jacobi_dn(u,m), m) = u
966 ;; Express in terms of sn:
967 ;; dn(x) = sqrt(1-m*sn(x)^2)
969 (power ($jacobi_sn u m
) 2)))
971 ((zerop1 ($ratsimp
(sub u
(power (sub 1 m
) 1//2))))
973 ;; dn(sqrt(1-m),m) = K(m)
975 ;; A&S 16.20.2 (Jacobi's Imaginary transformation)
976 ((and $%iargs
(multiplep u
'$%i
))
977 (cons-exp '%jacobi_dc
(coeff u
'$%i
1)
979 ((setq coef
(kc-arg2 u m
))
982 ;; dn(m*K+u) has period 2K
984 (destructuring-bind (lin const
)
986 (cond ((integerp lin
)
989 ;; dn(2*m*K + u) = dn(u)
993 ;; dn(4*m*K+2*K + u) = dn(2*K+u) = dn(u)
994 `((%jacobi_dn
) ,const
,m
)))
996 ;; dn(2*m*K + K + u) = dn(K + u) = sqrt(1-m)*nd(u)
1000 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
1004 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
1006 ((%jacobi_nd simp
) ,const
,m
))))))
1007 ((and (alike1 lin
1//2)
1010 ;; dn(1/2*K) = (1-m)^(1/4)
1012 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
1015 (eqtest (list '(%jacobi_dn
) u m
) form
)))))
1016 (t (eqtest (list '(%jacobi_dn
) u m
) form
)))))
1018 ;; Should we simplify the inverse elliptic functions into the
1019 ;; appropriate incomplete elliptic integral? I think we should leave
1020 ;; it, but perhaps allow some way to do that transformation if
1023 (defun simp-%inverse_jacobi_sn
(form unused z
)
1024 (declare (ignore unused
))
1026 (let ((u (simpcheck (cadr form
) z
))
1027 (m (simpcheck (caddr form
) z
))
1029 ;; To numerically evaluate inverse_jacobi_sn (asn), use
1031 ;; asn(x,m) = F(asin(x),m)
1033 ;; But F(phi,m) = sin(phi)*rf(cos(phi)^2, 1-m*sin(phi)^2,1). Thus
1035 ;; asn(x,m) = F(asin(x),m)
1036 ;; = x*rf(1-x^2,1-m*x^2,1)
1038 ;; I (rtoy) am not 100% about the first identity above for all
1039 ;; complex values of x and m, but tests seem to indicate that it
1040 ;; produces the correct value as verified by verifying
1041 ;; jacobi_sn(inverse_jacobi_sn(x,m),m) = x.
1042 (cond ((float-numerical-eval-p u m
)
1043 (complexify (* u
(bigfloat::bf-rf
(bigfloat:to
(float (- 1 (* u u
))))
1044 (bigfloat:to
(float (- 1 (* m u u
))))
1046 ((setf args
(complex-float-numerical-eval-p u m
))
1047 (destructuring-bind (u m
)
1049 (let ((uu (bigfloat:to
($float u
)))
1050 (mm (bigfloat:to
($float m
))))
1051 (complexify (* uu
(bigfloat::bf-rf
(- 1 (* uu uu
))
1054 ((bigfloat-numerical-eval-p u m
)
1055 (let ((uu (bigfloat:to u
))
1056 (mm (bigfloat:to m
)))
1058 (bigfloat::bf-rf
(bigfloat:-
1 (bigfloat:* uu uu
))
1059 (bigfloat:-
1 (bigfloat:* mm uu uu
))
1061 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
1062 (destructuring-bind (u m
)
1064 (let ((uu (bigfloat:to u
))
1065 (mm (bigfloat:to m
)))
1067 (bigfloat::bf-rf
(bigfloat:-
1 (bigfloat:* uu uu
))
1068 (bigfloat:-
1 (bigfloat:* mm uu uu
))
1074 ;; asn(1,m) = elliptic_kc(m)
1076 ((and (numberp u
) (onep1 (- u
)))
1077 ;; asn(-1,m) = -elliptic_kc(m)
1078 (mul -
1 ($elliptic_kc m
)))
1080 ;; asn(x,0) = F(asin(x),0) = asin(x)
1083 ;; asn(x,1) = F(asin(x),1) = log(tan(pi/4+asin(x)/2))
1084 (take '($elliptic_f
) (take '(%asin
) u
) 1))
1085 ((and (eq $triginverses
'$all
)
1087 (eq (caar u
) '%jacobi_sn
)
1088 (alike1 (third u
) m
))
1089 ;; inverse_jacobi_sn(sn(u)) = u
1093 (eqtest (list '(%inverse_jacobi_sn
) u m
) form
)))))
1095 (defun simp-%inverse_jacobi_cn
(form unused z
)
1096 (declare (ignore unused
))
1098 (let ((u (simpcheck (cadr form
) z
))
1099 (m (simpcheck (caddr form
) z
))
1101 (cond ((float-numerical-eval-p u m
)
1102 ;; Numerically evaluate acn
1104 ;; acn(x,m) = F(acos(x),m)
1105 (to (elliptic-f (cl:acos
($float u
)) ($float m
))))
1106 ((setf args
(complex-float-numerical-eval-p u m
))
1107 (destructuring-bind (u m
)
1109 (to (elliptic-f (cl:acos
(bigfloat:to
($float u
)))
1110 (bigfloat:to
($float m
))))))
1111 ((bigfloat-numerical-eval-p u m
)
1112 (to (bigfloat::bf-elliptic-f
(bigfloat:acos
(bigfloat:to u
))
1114 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
1115 (destructuring-bind (u m
)
1117 (to (bigfloat::bf-elliptic-f
(bigfloat:acos
(bigfloat:to u
))
1120 ;; asn(x,0) = F(acos(x),0) = acos(x)
1121 `(($elliptic_f
) ((%acos
) ,u
) 0))
1123 ;; asn(x,1) = F(asin(x),1) = log(tan(pi/2+asin(x)/2))
1124 `(($elliptic_f
) ((%acos
) ,u
) 1))
1126 `((%elliptic_kc
) ,m
))
1129 ((and (eq $triginverses
'$all
)
1131 (eq (caar u
) '%jacobi_cn
)
1132 (alike1 (third u
) m
))
1133 ;; inverse_jacobi_cn(cn(u)) = u
1137 (eqtest (list '(%inverse_jacobi_cn
) u m
) form
)))))
1139 (defun simp-%inverse_jacobi_dn
(form unused z
)
1140 (declare (ignore unused
))
1142 (let ((u (simpcheck (cadr form
) z
))
1143 (m (simpcheck (caddr form
) z
))
1145 (cond ((float-numerical-eval-p u m
)
1146 (to (bigfloat::bf-inverse-jacobi-dn
(bigfloat:to
(float u
))
1147 (bigfloat:to
(float m
)))))
1148 ((setf args
(complex-float-numerical-eval-p u m
))
1149 (destructuring-bind (u m
)
1151 (let ((uu (bigfloat:to
($float u
)))
1152 (mm (bigfloat:to
($float m
))))
1153 (to (bigfloat::bf-inverse-jacobi-dn uu mm
)))))
1154 ((bigfloat-numerical-eval-p u m
)
1155 (let ((uu (bigfloat:to u
))
1156 (mm (bigfloat:to m
)))
1157 (to (bigfloat::bf-inverse-jacobi-dn uu mm
))))
1158 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
1159 (destructuring-bind (u m
)
1161 (to (bigfloat::bf-inverse-jacobi-dn
(bigfloat:to u
) (bigfloat:to m
)))))
1163 ;; x = dn(u,1) = sech(u). so u = asech(x)
1166 ;; jacobi_dn(0,m) = 1
1168 ((zerop1 ($ratsimp
(sub u
(power (sub 1 m
) 1//2))))
1169 ;; jacobi_dn(K(m),m) = sqrt(1-m) so
1170 ;; inverse_jacobi_dn(sqrt(1-m),m) = K(m)
1172 ((and (eq $triginverses
'$all
)
1174 (eq (caar u
) '%jacobi_dn
)
1175 (alike1 (third u
) m
))
1176 ;; inverse_jacobi_dn(dn(u)) = u
1180 (eqtest (list '(%inverse_jacobi_dn
) u m
) form
)))))
1182 ;;;; Elliptic integrals
1184 (let ((errtol (expt (* 4 flonum-epsilon
) 1/6))
1188 (declare (type flonum errtol c1 c2 c3
))
1190 "Compute Carlson's incomplete or complete elliptic integral of the
1196 RF(x, y, z) = I ----------------------------------- dt
1197 ] SQRT(x + t) SQRT(y + t) SQRT(z + t)
1201 x, y, and z may be complex.
1203 (declare (number x y z
))
1204 (let ((x (coerce x
'(complex flonum
)))
1205 (y (coerce y
'(complex flonum
)))
1206 (z (coerce z
'(complex flonum
))))
1207 (declare (type (complex flonum
) x y z
))
1209 (let* ((mu (/ (+ x y z
) 3))
1210 (x-dev (- 2 (/ (+ mu x
) mu
)))
1211 (y-dev (- 2 (/ (+ mu y
) mu
)))
1212 (z-dev (- 2 (/ (+ mu z
) mu
))))
1213 (when (< (max (abs x-dev
) (abs y-dev
) (abs z-dev
)) errtol
)
1214 (let ((e2 (- (* x-dev y-dev
) (* z-dev z-dev
)))
1215 (e3 (* x-dev y-dev z-dev
)))
1222 (let* ((x-root (sqrt x
))
1225 (lam (+ (* x-root
(+ y-root z-root
)) (* y-root z-root
))))
1226 (setf x
(* (+ x lam
) 1/4))
1227 (setf y
(* (+ y lam
) 1/4))
1228 (setf z
(* (+ z lam
) 1/4))))))))
1230 ;; Elliptic integral of the first kind (Legendre's form):
1236 ;; I ------------------- ds
1238 ;; / SQRT(1 - m SIN (s))
1241 (defun elliptic-f (phi-arg m-arg
)
1242 (flet ((base (phi-arg m-arg
)
1243 (cond ((and (realp m-arg
) (realp phi-arg
))
1244 (let ((phi (float phi-arg
))
1249 ;; F(phi|m) = 1/sqrt(m)*F(theta|1/m)
1251 ;; with sin(theta) = sqrt(m)*sin(phi)
1252 (/ (elliptic-f (cl:asin
(* (sqrt m
) (sin phi
))) (/ m
))
1260 (- (/ (elliptic-f (float (/ pi
2)) m
/m
+1)
1262 (/ (elliptic-f (- (float (/ pi
2)) phi
) m
/m
+1)
1270 1 ;; F(phi,1) = log(sec(phi)+tan(phi))
1271 ;; = log(tan(pi/4+pi/2))
1272 (log (cl:tan
(+ (/ phi
2) (float (/ pi
4))))))
1274 (- (elliptic-f (- phi
) m
)))
1277 (multiple-value-bind (s phi-rem
)
1278 (truncate phi
(float pi
))
1279 (+ (* 2 s
(elliptic-k m
))
1280 (elliptic-f phi-rem m
))))
1282 (let ((sin-phi (sin phi
))
1286 (bigfloat::bf-rf
(* cos-phi cos-phi
)
1287 (* (- 1 (* k sin-phi
))
1288 (+ 1 (* k sin-phi
)))
1291 (+ (* 2 (elliptic-k m
))
1292 (elliptic-f (- phi
(float pi
)) m
)))
1294 (error "Shouldn't happen! Unhandled case in elliptic-f: ~S ~S~%"
1297 (let ((phi (coerce phi-arg
'(complex flonum
)))
1298 (m (coerce m-arg
'(complex flonum
))))
1299 (let ((sin-phi (sin phi
))
1303 (crf (* cos-phi cos-phi
)
1304 (* (- 1 (* k sin-phi
))
1305 (+ 1 (* k sin-phi
)))
1307 ;; Elliptic F is quasi-periodic wrt to z:
1309 ;; F(z|m) = F(z - pi*round(Re(z)/pi)|m) + 2*round(Re(z)/pi)*K(m)
1310 (let ((period (round (realpart phi-arg
) pi
)))
1311 (+ (base (- phi-arg
(* pi period
)) m-arg
)
1315 (bigfloat:to
(elliptic-k m-arg
))))))))
1317 ;; Complete elliptic integral of the first kind
1318 (defun elliptic-k (m)
1326 (- (/ (elliptic-k m
/m
+1)
1328 (/ (elliptic-f 0.0 m
/m
+1)
1335 (intl:gettext
"elliptic_kc: elliptic_kc(1) is undefined.")))
1337 (bigfloat::bf-rf
0.0 (- 1 m
)
1340 (bigfloat::bf-rf
0.0 (- 1 m
)
1343 ;; Elliptic integral of the second kind (Legendre's form):
1349 ;; I SQRT(1 - m SIN (s)) ds
1354 (defun elliptic-e (phi m
)
1355 (declare (type flonum phi m
))
1356 (flet ((base (phi m
)
1364 (let* ((sin-phi (sin phi
))
1367 (y (* (- 1 (* k sin-phi
))
1368 (+ 1 (* k sin-phi
)))))
1370 (bigfloat::bf-rf
(* cos-phi cos-phi
) y
1.0))
1373 (bigfloat::bf-rd
(* cos-phi cos-phi
) y
1.0)))))))))
1374 ;; Elliptic E is quasi-periodic wrt to phi:
1376 ;; E(z|m) = E(z - %pi*round(Re(z)/%pi)|m) + 2*round(Re(z)/%pi)*E(m)
1377 (let ((period (round (realpart phi
) pi
)))
1378 (+ (base (- phi
(* pi period
)) m
)
1379 (* 2 period
(elliptic-ec m
))))))
1382 (defun elliptic-ec (m)
1383 (declare (type flonum m
))
1394 (to (- (bigfloat::bf-rf
0.0 y
1.0)
1396 (bigfloat::bf-rd
0.0 y
1.0))))))))
1399 ;; Define the elliptic integrals for maxima
1401 ;; We use the definitions given in A&S 17.2.6 and 17.2.8. In particular:
1406 ;; F(phi|m) = I ------------------- ds
1408 ;; / SQRT(1 - m SIN (s))
1416 ;; E(phi|m) = I SQRT(1 - m SIN (s)) ds
1421 ;; That is, we do not use the modular angle, alpha, as the second arg;
1422 ;; the parameter m = sin(alpha)^2 is used.
1426 (defprop $elliptic_f simp-$elliptic_f operators
)
1427 (defprop $elliptic_e simp-$elliptic_e operators
)
1429 ;; The derivative of F(phi|m) wrt to phi is easy. The derivative wrt
1430 ;; to m is harder. Here is a derivation. Hope I got it right.
1432 ;; diff(integrate(1/sqrt(1-m*sin(x)^2),x,0,phi), m);
1437 ;; I ------------------ dx
1439 ;; / (1 - m SIN (x))
1441 ;; --------------------------
1445 ;; Now use the following relationship that is easily verified:
1448 ;; (1 - m) SIN (x) COS (x) COS(x) SIN(x)
1449 ;; ------------------- = ------------------- - DIFF(-------------------, x)
1451 ;; SQRT(1 - m SIN (x)) SQRT(1 - m SIN (x)) SQRT(1 - m SIN (x))
1454 ;; Now integrate this to get:
1460 ;; (1 - m) I ------------------- dx =
1462 ;; / SQRT(1 - m SIN (x))
1469 ;; + I ------------------- dx
1471 ;; / SQRT(1 - m SIN (x))
1473 ;; COS(PHI) SIN(PHI)
1474 ;; - ---------------------
1476 ;; SQRT(1 - m SIN (PHI))
1478 ;; Use the fact that cos(x)^2 = 1 - sin(x)^2 to show that this
1479 ;; integral on the RHS is:
1482 ;; (1 - m) elliptic_F(PHI, m) + elliptic_E(PHI, m)
1483 ;; -------------------------------------------
1485 ;; So, finally, we have
1490 ;; 2 -- (elliptic_F(PHI, m)) =
1493 ;; elliptic_E(PHI, m) - (1 - m) elliptic_F(PHI, m) COS(PHI) SIN(PHI)
1494 ;; ---------------------------------------------- - ---------------------
1496 ;; SQRT(1 - m SIN (PHI))
1497 ;; ----------------------------------------------------------------------
1500 (defprop $elliptic_f
1503 ;; 1/sqrt(1-m*sin(phi)^2)
1505 ((mplus simp
) 1 ((mtimes simp
) -
1 m
((mexpt simp
) ((%sin simp
) phi
) 2)))
1508 ((mtimes simp
) ((rat simp
) 1 2)
1509 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
1511 ((mtimes simp
) ((mexpt simp
) m -
1)
1512 ((mplus simp
) (($elliptic_e simp
) phi m
)
1513 ((mtimes simp
) -
1 ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
1514 (($elliptic_f simp
) phi m
))))
1515 ((mtimes simp
) -
1 ((%cos simp
) phi
) ((%sin simp
) phi
)
1518 ((mtimes simp
) -
1 m
((mexpt simp
) ((%sin simp
) phi
) 2)))
1519 ((rat simp
) -
1 2))))))
1523 ;; The derivative of E(phi|m) wrt to m is much simpler to derive than F(phi|m).
1525 ;; Take the derivative of the definition to get
1530 ;; I ------------------- dx
1532 ;; / SQRT(1 - m SIN (x))
1534 ;; - ---------------------------
1537 ;; It is easy to see that
1542 ;; elliptic_F(PHI, m) - m I ------------------- dx = elliptic_E(PHI, m)
1544 ;; / SQRT(1 - m SIN (x))
1547 ;; So we finally have
1549 ;; d elliptic_E(PHI, m) - elliptic_F(PHI, m)
1550 ;; -- (elliptic_E(PHI, m)) = ---------------------------------------
1553 (defprop $elliptic_e
1555 ;; sqrt(1-m*sin(phi)^2)
1557 ((mplus simp
) 1 ((mtimes simp
) -
1 m
((mexpt simp
) ((%sin simp
) phi
) 2)))
1560 ((mtimes simp
) ((rat simp
) 1 2) ((mexpt simp
) m -
1)
1561 ((mplus simp
) (($elliptic_e simp
) phi m
)
1562 ((mtimes simp
) -
1 (($elliptic_f simp
) phi m
)))))
1565 (defmfun $elliptic_f
(phi m
)
1566 (simplify (list '($elliptic_f
) (resimplify phi
) (resimplify m
))))
1567 (defmfun $elliptic_e
(phi m
)
1568 (simplify (list '($elliptic_e
) (resimplify phi
) (resimplify m
))))
1570 (defun simp-$elliptic_f
(form unused z
)
1571 (declare (ignore unused
))
1573 (let ((phi (simpcheck (cadr form
) z
))
1574 (m (simpcheck (caddr form
) z
))
1576 (cond ((float-numerical-eval-p phi m
)
1577 ;; Numerically evaluate it
1578 (to (elliptic-f ($float phi
) ($float m
))))
1579 ((setf args
(complex-float-numerical-eval-p phi m
))
1580 (destructuring-bind (phi m
)
1582 (to (elliptic-f (bigfloat:to
($float phi
))
1583 (bigfloat:to
($float m
))))))
1584 ((bigfloat-numerical-eval-p phi m
)
1585 (to (bigfloat::bf-elliptic-f
(bigfloat:to
($bfloat phi
))
1586 (bigfloat:to
($bfloat m
)))))
1587 ((setf args
(complex-bigfloat-numerical-eval-p phi m
))
1588 (destructuring-bind (phi m
)
1590 (to (bigfloat::bf-elliptic-f
(bigfloat:to
($bfloat phi
))
1591 (bigfloat:to
($bfloat m
))))))
1598 ;; A&S 17.4.21. Let's pick the log tan form. But this
1599 ;; isn't right if we know that abs(phi) > %pi/2, where
1600 ;; elliptic_f is undefined (or infinity).
1601 (cond ((not (eq '$pos
(csign (sub ($abs phi
) (div '$%pi
2)))))
1603 ((mplus) ((mtimes) $%pi
((rat) 1 4))
1604 ((mtimes) ((rat) 1 2) ,phi
)))))
1606 (merror (intl:gettext
"elliptic_f: elliptic_f(~:M, ~:M) is undefined.")
1608 ((alike1 phi
'((mtimes) ((rat) 1 2) $%pi
))
1609 ;; Complete elliptic integral
1610 `((%elliptic_kc
) ,m
))
1613 (eqtest (list '($elliptic_f
) phi m
) form
)))))
1615 (defun simp-$elliptic_e
(form unused z
)
1616 (declare (ignore unused
))
1618 (let ((phi (simpcheck (cadr form
) z
))
1619 (m (simpcheck (caddr form
) z
))
1621 (cond ((float-numerical-eval-p phi m
)
1622 ;; Numerically evaluate it
1623 (elliptic-e ($float phi
) ($float m
)))
1624 ((complex-float-numerical-eval-p phi m
)
1625 (complexify (bigfloat::bf-elliptic-e
(complex ($float
($realpart phi
)) ($float
($imagpart phi
)))
1626 (complex ($float
($realpart m
)) ($float
($imagpart m
))))))
1627 ((bigfloat-numerical-eval-p phi m
)
1628 (to (bigfloat::bf-elliptic-e
(bigfloat:to
($bfloat phi
))
1629 (bigfloat:to
($bfloat m
)))))
1630 ((setf args
(complex-bigfloat-numerical-eval-p phi m
))
1631 (destructuring-bind (phi m
)
1633 (to (bigfloat::bf-elliptic-e
(bigfloat:to
($bfloat phi
))
1634 (bigfloat:to
($bfloat m
))))))
1641 ;; A&S 17.4.25, but handle periodicity:
1642 ;; elliptic_e(x,m) = elliptic_e(x-%pi*round(x/%pi), m)
1643 ;; + 2*round(x/%pi)*elliptic_ec(m)
1647 ;; elliptic_e(x,1) = sin(phi) + 2*round(x/%pi)*elliptic_ec(m)
1649 (add (take '(%sin
) phi
)
1651 (mul (take '(%round
) (div phi
'$%pi
))
1652 (take '(%elliptic_ec
) m
)))))
1653 ((alike1 phi
'((mtimes) ((rat) 1 2) $%pi
))
1654 ;; Complete elliptic integral
1655 `((%elliptic_ec
) ,m
))
1656 ((and ($numberp phi
)
1657 (let ((r ($round
(div phi
'$%pi
))))
1660 ;; Handle the case where phi is a number where we can apply
1661 ;; the periodicity property without blowing up the
1663 (add (take '($elliptic_e
)
1666 (take '(%round
) (div phi
'$%pi
))))
1669 (mul (take '(%round
) (div phi
'$%pi
))
1670 (take '(%elliptic_ec
) m
)))))
1673 (eqtest (list '($elliptic_e
) phi m
) form
)))))
1676 ;; Complete elliptic integrals
1678 ;; elliptic_kc(m) = elliptic_f(%pi/2, m)
1680 ;; elliptic_ec(m) = elliptic_e(%pi/2, m)
1682 (defmfun $elliptic_kc
(m)
1683 (simplify (list '(%elliptic_kc
) (resimplify m
))))
1684 (defmfun $elliptic_ec
(m)
1685 (simplify (list '(%elliptic_ec
) (resimplify m
))))
1688 (defprop %elliptic_kc simp-%elliptic_kc operators
)
1689 (defprop %elliptic_ec simp-%elliptic_ec operators
)
1691 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1693 ;;; We support a simplim%function. The function is looked up in simplimit and
1694 ;;; handles specific values of the function.
1696 (defprop %elliptic_kc simplim%elliptic_kc simplim%function
)
1698 (defun simplim%elliptic_kc
(expr var val
)
1699 ;; Look for the limit of the argument
1700 (let ((m (limit (cadr expr
) var val
'think
)))
1702 ;; For an argument 1 return $infinity.
1705 ;; All other cases are handled by the simplifier of the function.
1706 (simplify (list '(%elliptic_kc
) m
))))))
1708 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1710 (defun simp-%elliptic_kc
(form yy z
)
1711 (declare (ignore yy
))
1713 (let ((m (simpcheck (cadr form
) z
))
1716 ;; elliptic_kc(1) is complex infinity. Maxima can not handle
1717 ;; infinities correctly, throw a Maxima error.
1719 (intl:gettext
"elliptic_kc: elliptic_kc(~:M) is undefined.")
1721 ((float-numerical-eval-p m
)
1722 ;; Numerically evaluate it
1723 (to (elliptic-k ($float m
))))
1724 ((complex-float-numerical-eval-p m
)
1725 (complexify (bigfloat::bf-elliptic-k
(complex ($float
($realpart m
)) ($float
($imagpart m
))))))
1726 ((setf args
(complex-bigfloat-numerical-eval-p m
))
1727 (destructuring-bind (m)
1729 (to (bigfloat::bf-elliptic-k
(bigfloat:to
($bfloat m
))))))
1731 '((mtimes) ((rat) 1 2) $%pi
))
1733 ;; http://functions.wolfram.com/EllipticIntegrals/EllipticK/03/01/
1735 ;; elliptic_kc(1/2) = 8*%pi^(3/2)/gamma(-1/4)^2
1736 (div (mul 8 (power '$%pi
(div 3 2)))
1737 (power (gm (div -
1 4)) 2)))
1739 ;; elliptic_kc(-1) = gamma(1/4)^2/(4*sqrt(2*%pi))
1740 (div (power (gm (div 1 4)) 2)
1741 (mul 4 (power (mul 2 '$%pi
) 1//2))))
1742 ((alike1 m
(add 17 (mul -
12 (power 2 1//2))))
1743 ;; elliptic_kc(17-12*sqrt(2)) = 2*(2+sqrt(2))*%pi^(3/2)/gamma(-1/4)^2
1744 (div (mul 2 (mul (add 2 (power 2 1//2))
1745 (power '$%pi
(div 3 2))))
1746 (power (gm (div -
1 4)) 2)))
1749 (eqtest (list '(%elliptic_kc
) m
) form
)))))
1751 (defprop %elliptic_kc
1756 ((mplus) ((%elliptic_ec
) m
)
1759 ((mplus) 1 ((mtimes) -
1 m
))))
1760 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
1764 (defun simp-%elliptic_ec
(form yy z
)
1765 (declare (ignore yy
))
1767 (let ((m (simpcheck (cadr form
) z
))
1769 (cond ((float-numerical-eval-p m
)
1770 ;; Numerically evaluate it
1771 (elliptic-ec ($float m
)))
1772 ((setf args
(complex-float-numerical-eval-p m
))
1773 (destructuring-bind (m)
1775 (complexify (bigfloat::bf-elliptic-ec
(bigfloat:to
($float m
))))))
1776 ((setf args
(complex-bigfloat-numerical-eval-p m
))
1777 (destructuring-bind (m)
1779 (to (bigfloat::bf-elliptic-ec
(bigfloat:to
($bfloat m
))))))
1780 ;; Some special cases we know about.
1782 '((mtimes) ((rat) 1 2) $%pi
))
1786 ;; elliptic_ec(1/2). Use the identity
1788 ;; elliptic_ec(z)*elliptic_kc(1-z) - elliptic_kc(z)*elliptic_kc(1-z)
1789 ;; + elliptic_ec(1-z)*elliptic_kc(z) = %pi/2;
1791 ;; Let z = 1/2 to get
1793 ;; %pi^(3/2)*'elliptic_ec(1/2)/gamma(3/4)^2-%pi^3/(4*gamma(3/4)^4) = %pi/2
1795 ;; since we know that elliptic_kc(1/2) = %pi^(3/2)/(2*gamma(3/4)^2). Hence
1798 ;; = (2*%pi*gamma(3/4)^4+%pi^3)/(4*%pi^(3/2)*gamma(3/4)^2)
1799 ;; = gamma(3/4)^2/(2*sqrt(%pi))+%pi^(3/2)/(4*gamma(3/4)^2)
1801 (add (div (power (take '(%gamma
) (div 3 4)) 2)
1802 (mul 2 (power '$%pi
1//2)))
1803 (div (power '$%pi
(div 3 2))
1804 (mul 4 (power (take '(%gamma
) (div 3 4)) 2)))))
1806 ;; elliptic_ec(-1). Use the identity
1807 ;; http://functions.wolfram.com/08.01.17.0002.01
1810 ;; elliptic_ec(z) = sqrt(1 - z)*elliptic_ec(z/(z-1))
1812 ;; Let z = -1 to get
1814 ;; elliptic_ec(-1) = sqrt(2)*elliptic_ec(1/2)
1816 ;; Should we expand out elliptic_ec(1/2) using the above result?
1818 (take '($elliptic_ec
) 1//2)))
1821 (eqtest (list '(%elliptic_ec
) m
) form
)))))
1823 (defprop %elliptic_ec
1825 ((mtimes) ((rat) 1 2)
1826 ((mplus) ((%elliptic_ec
) m
)
1827 ((mtimes) -
1 ((%elliptic_kc
)
1833 ;; Elliptic integral of the third kind:
1840 ;; PI(n;phi|m) = I ----------------------------------- ds
1842 ;; / SQRT(1 - m SIN (s)) (1 - n SIN (s))
1845 ;; As with E and F, we do not use the modular angle alpha but the
1846 ;; parameter m = sin(alpha)^2.
1848 (defprop $elliptic_pi simp-$elliptic_pi operators
)
1850 (defmfun $elliptic_pi
(n phi m
)
1851 (simplify (list '($elliptic_pi
)
1852 (resimplify n
) (resimplify phi
) (resimplify m
))))
1854 (defun simp-$elliptic_pi
(form yy z
)
1855 (declare (ignore yy
))
1856 ;;(threeargcheck form)
1857 (let ((n (simpcheck (cadr form
) z
))
1858 (phi (simpcheck (caddr form
) z
))
1859 (m (simpcheck (cadddr form
) z
))
1862 ((float-numerical-eval-p n phi m
)
1863 ;; Numerically evaluate it
1864 (elliptic-pi ($float n
) ($float phi
) ($float m
)))
1865 ((setf args
(complex-float-numerical-eval-p n phi m
))
1866 (destructuring-bind (n phi m
)
1868 (elliptic-pi (bigfloat:to
($float n
))
1869 (bigfloat:to
($float phi
))
1870 (bigfloat:to
($float m
)))))
1871 ((bigfloat-numerical-eval-p n phi m
)
1872 (to (bigfloat::bf-elliptic-pi
(bigfloat:to n
)
1875 ((setq args
(complex-bigfloat-numerical-eval-p n phi m
))
1876 (destructuring-bind (n phi m
)
1878 (to (bigfloat::bf-elliptic-pi
(bigfloat:to n
)
1882 `(($elliptic_f
) ,phi
,m
))
1884 ;; 3 cases depending on n < 1, n > 1, or n = 1.
1885 (let ((s (asksign (resimplify `((mplus) -
1 ,n
)))))
1888 (div (take '(%atanh
) (mul (power (add n -
1) 1//2)
1889 (take '(%tan
) phi
)))
1890 (power (add n -
1) 1//2)))
1892 (div (take '(%atan
) (mul (power (sub 1 n
) 1//2)
1893 (take '(%tan
) phi
)))
1894 (power (sub 1 n
) 1//2)))
1896 (take '(%tan
) phi
)))))
1899 (eqtest (list '($elliptic_pi
) n phi m
) form
)))))
1901 ;; Complete elliptic-pi. That is phi = %pi/2. Then
1903 ;; = Rf(0, 1-m,1) + Rj(0,1-m,1-n)*n/3;
1904 (defun elliptic-pi-complete (n m
)
1905 (to (bigfloat:+ (bigfloat::bf-rf
0 (- 1 m
) 1)
1906 (bigfloat:* 1/3 n
(bigfloat::bf-rj
0 (- 1 m
) 1 (- 1 n
))))))
1908 ;; To compute elliptic_pi for all z, we use the property
1909 ;; (http://functions.wolfram.com/08.06.16.0002.01)
1911 ;; elliptic_pi(n, z + %pi*k, m)
1912 ;; = 2*k*elliptic_pi(n, %pi/2, m) + elliptic_pi(n, z, m)
1914 ;; So we are left with computing the integral for 0 <= z < %pi. Using
1915 ;; Carlson's formulation produces the wrong values for %pi/2 < z <
1916 ;; %pi. How to do that?
1920 ;; I(a,b) = integrate(1/(1-n*sin(x)^2)/sqrt(1 - m*sin(x)^2), x, a, b)
1922 ;; That is, I(a,b) is the integral for the elliptic_pi function but
1923 ;; with a lower limit of a and an upper limit of b.
1925 ;; Then, we want to compute I(0, z), with %pi <= z < %pi. Let w = z +
1926 ;; %pi/2, 0 <= w < %pi/2. Then
1928 ;; I(0, w+%pi/2) = I(0, %pi/2) + I(%pi/2, w+%pi/2)
1930 ;; To evaluate I(%pi/2, w+%pi/2), use a change of variables:
1932 ;; changevar('integrate(1/(1-n*sin(x)^2)/sqrt(1 - m*sin(x)^2), x, %pi/2, w + %pi/2),
1935 ;; = integrate(-1/(sqrt(1-m*sin(u)^2)*(1-n*sin(u)^2)),u,%pi/2-w,%pi/2)
1936 ;; = I(%pi/2-w,%pi/2)
1937 ;; = I(0,%pi/2) - I(0,%pi/2-w)
1941 ;; I(0,%pi/2+w) = 2*I(0,%pi/2) - I(0,%pi/2-w)
1943 ;; This allows us to compute the general result with 0 <= z < %pi
1945 ;; I(0, k*%pi + z) = 2*k*I(0,%pi/2) + I(0,z);
1947 ;; If 0 <= z < %pi/2, then the we are done. If %pi/2 <= z < %pi, let
1948 ;; z = w+%pi/2. Then
1950 ;; I(0,z) = 2*I(0,%pi/2) - I(0,%pi/2-w)
1952 ;; Or, since w = z-%pi/2:
1954 ;; I(0,z) = 2*I(0,%pi/2) - I(0,%pi-z)
1956 (defun elliptic-pi (n phi m
)
1957 ;; elliptic_pi(n, -phi, m) = -elliptic_pi(n, phi, m). That is, it
1958 ;; is an odd function of phi.
1959 (when (minusp (realpart phi
))
1960 (return-from elliptic-pi
(- (elliptic-pi n
(- phi
) m
))))
1962 ;; Note: Carlson's DRJ has n defined as the negative of the n given
1964 (flet ((base (n phi m
)
1965 ;; elliptic_pi(n,phi,m) =
1966 ;; sin(phi)*Rf(cos(phi)^2, 1-m*sin(phi)^2, 1)
1967 ;; - (-n / 3) * sin(phi)^3
1968 ;; * Rj(cos(phi)^2, 1-m*sin(phi)^2, 1, 1-n*sin(phi)^2)
1973 (k2sin (* (- 1 (* k sin-phi
))
1974 (+ 1 (* k sin-phi
)))))
1975 (- (* sin-phi
(bigfloat::bf-rf
(expt cos-phi
2) k2sin
1.0))
1976 (* (/ nn
3) (expt sin-phi
3)
1977 (bigfloat::bf-rj
(expt cos-phi
2) k2sin
1.0
1978 (- 1 (* n
(expt sin-phi
2)))))))))
1979 ;; FIXME: Reducing the arg by pi has significant round-off.
1980 ;; Consider doing something better.
1981 (let* ((cycles (round (realpart phi
) pi
))
1982 (rem (- phi
(* cycles pi
))))
1983 (let ((complete (elliptic-pi-complete n m
)))
1984 (to (+ (* 2 cycles complete
)
1985 (base n rem m
)))))))
1987 ;;; Deriviatives from functions.wolfram.com
1988 ;;; http://functions.wolfram.com/EllipticIntegrals/EllipticPi3/20/
1989 (defprop $elliptic_pi
1991 ;Derivative wrt first argument
1992 ((mtimes) ((rat) 1 2)
1993 ((mexpt) ((mplus) m
((mtimes) -
1 n
)) -
1)
1994 ((mexpt) ((mplus) -
1 n
) -
1)
1996 ((mtimes) ((mexpt) n -
1)
1997 ((mplus) ((mtimes) -
1 m
) ((mexpt) n
2))
1998 (($elliptic_pi
) n z m
))
2000 ((mtimes) ((mplus) m
((mtimes) -
1 n
)) ((mexpt) n -
1)
2001 (($elliptic_f
) z m
))
2002 ((mtimes) ((rat) -
1 2) n
2004 ((mplus) 1 ((mtimes) -
1 m
((mexpt) ((%sin
) z
) 2)))
2007 ((mplus) 1 ((mtimes) -
1 n
((mexpt) ((%sin
) z
) 2)))
2009 ((%sin
) ((mtimes) 2 z
)))))
2010 ;derivative wrt second argument
2013 ((mplus) 1 ((mtimes) -
1 m
((mexpt) ((%sin
) z
) 2)))
2016 ((mplus) 1 ((mtimes) -
1 n
((mexpt) ((%sin
) z
) 2))) -
1))
2017 ;Derivative wrt third argument
2018 ((mtimes) ((rat) 1 2)
2019 ((mexpt) ((mplus) ((mtimes) -
1 m
) n
) -
1)
2020 ((mplus) (($elliptic_pi
) n z m
)
2021 ((mtimes) ((mexpt) ((mplus) -
1 m
) -
1)
2022 (($elliptic_e
) z m
))
2023 ((mtimes) ((rat) -
1 2) ((mexpt) ((mplus) -
1 m
) -
1) m
2025 ((mplus) 1 ((mtimes) -
1 m
((mexpt) ((%sin
) z
) 2)))
2027 ((%sin
) ((mtimes) 2 z
))))))
2030 (in-package #-gcl
#:bigfloat
#+gcl
"BIGFLOAT")
2031 ;; Translation of Jim FitzSimons' bigfloat implementation of elliptic
2032 ;; integrals from http://www.getnet.com/~cherry/elliptbf3.mac.
2034 ;; The algorithms are based on B.C. Carlson's "Numerical Computation
2035 ;; of Real or Complex Elliptic Integrals". These are updated to the
2036 ;; algorithms in Journal of Computational and Applied Mathematics 118
2037 ;; (2000) 71-85 "Reduction Theorems for Elliptic Integrands with the
2038 ;; Square Root of two quadritic factors"
2041 ;; NOTE: Despite the names indicating these are for bigfloat numbers,
2042 ;; the algorithms and routines are generic and will work with floats
2045 (defun bferrtol (&rest args
)
2046 ;; Compute error tolerance as sqrt(2^(-fpprec)). Not sure this is
2047 ;; quite right, but it makes the routines more accurate as fpprec
2049 (sqrt (reduce #'min
(mapcar #'(lambda (x)
2051 maxima
::flonum-epsilon
2055 ;; rc(x,y) = integrate(1/2*(t+x)^(-1/2)/(t+y), t, 0, inf)
2057 ;; log(x) = (x-1)*rc(((1+x)/2)^2, x), x > 0
2058 ;; asin(x) = x * rc(1-x^2, 1), |x|<= 1
2059 ;; acos(x) = sqrt(1-x^2)*rc(x^2,1), 0 <= x <=1
2060 ;; atan(x) = x * rc(1,1+x^2)
2061 ;; asinh(x) = x * rc(1+x^2,1)
2062 ;; acosh(x) = sqrt(x^2-1) * rc(x^2,1), x >= 1
2063 ;; atanh(x) = x * rc(1,1-x^2), |x|<=1
2067 xn z w a an pwr4 n epslon lambda sn s
)
2068 (cond ((and (zerop (imagpart yn
))
2069 (minusp (realpart yn
)))
2073 (setf w
(sqrt (/ x xn
))))
2078 (setf a
(/ (+ xn yn yn
) 3))
2079 (setf epslon
(/ (abs (- a xn
)) (bferrtol x y
)))
2083 (loop while
(> (* epslon pwr4
) (abs an
))
2085 (setf pwr4
(/ pwr4
4))
2086 (setf lambda
(+ (* 2 (sqrt xn
) (sqrt yn
)) yn
))
2087 (setf an
(/ (+ an lambda
) 4))
2088 (setf xn
(/ (+ xn lambda
) 4))
2089 (setf yn
(/ (+ yn lambda
) 4))
2091 ;; c2=3/10,c3=1/7,c4=3/8,c5=9/22,c6=159/208,c7=9/8
2092 (setf sn
(/ (* pwr4
(- z a
)) an
))
2093 (setf s
(* sn sn
(+ 3/10
2098 (* sn
9/8))))))))))))
2104 ;; rd(x,y,z) = integrate(3/2/sqrt(t+x)/sqrt(t+y)/sqrt(t+z), t, 0, inf)
2106 ;; E(K) = rf(0, 1-K^2, 1) - (K^2/3)*rd(0,1-K^2,1)
2108 ;; B = integrate(s^2/sqrt(1-s^4), s, 0 ,1)
2109 ;; = beta(3/4,1/2)/4
2110 ;; = sqrt(%pi)*gamma(3/4)/gamma(1/4)
2112 (defun bf-rd (x y z
)
2116 (a (/ (+ xn yn
(* 3 zn
)) 5))
2117 (epslon (/ (max (abs (- a xn
))
2125 xnroot ynroot znroot lam
)
2126 (loop while
(> (* power4 epslon
) (abs an
))
2128 (setf xnroot
(sqrt xn
))
2129 (setf ynroot
(sqrt yn
))
2130 (setf znroot
(sqrt zn
))
2131 (setf lam
(+ (* xnroot ynroot
)
2134 (setf sigma
(+ sigma
(/ power4
2135 (* znroot
(+ zn lam
)))))
2136 (setf power4
(* power4
1/4))
2137 (setf xn
(* (+ xn lam
) 1/4))
2138 (setf yn
(* (+ yn lam
) 1/4))
2139 (setf zn
(* (+ zn lam
) 1/4))
2140 (setf an
(* (+ an lam
) 1/4))
2142 ;; c1=-3/14,c2=1/6,c3=9/88,c4=9/22,c5=-3/22,c6=-9/52,c7=3/26
2143 (let* ((xndev (/ (* (- a x
) power4
) an
))
2144 (yndev (/ (* (- a y
) power4
) an
))
2145 (zndev (- (* (+ xndev yndev
) 1/3)))
2146 (ee2 (- (* xndev yndev
) (* 6 zndev zndev
)))
2147 (ee3 (* (- (* 3 xndev yndev
)
2150 (ee4 (* 3 (- (* xndev yndev
) (* zndev zndev
)) zndev zndev
))
2151 (ee5 (* xndev yndev zndev zndev zndev
))
2159 (* -
1/16 ee2 ee2 ee2
)
2162 (* 45/272 ee2 ee2 ee3
)
2163 (* -
9/68 (+ (* ee2 ee5
) (* ee3 ee4
))))))
2168 (defun bf-rf (x y z
)
2172 (a (/ (+ xn yn zn
) 3))
2173 (epslon (/ (max (abs (- a xn
))
2180 xnroot ynroot znroot lam
)
2181 (loop while
(> (* power4 epslon
) (abs an
))
2183 (setf xnroot
(sqrt xn
))
2184 (setf ynroot
(sqrt yn
))
2185 (setf znroot
(sqrt zn
))
2186 (setf lam
(+ (* xnroot ynroot
)
2189 (setf power4
(* power4
1/4))
2190 (setf xn
(* (+ xn lam
) 1/4))
2191 (setf yn
(* (+ yn lam
) 1/4))
2192 (setf zn
(* (+ zn lam
) 1/4))
2193 (setf an
(* (+ an lam
) 1/4))
2195 ;; c1=-3/14,c2=1/6,c3=9/88,c4=9/22,c5=-3/22,c6=-9/52,c7=3/26
2196 (let* ((xndev (/ (* (- a x
) power4
) an
))
2197 (yndev (/ (* (- a y
) power4
) an
))
2198 (zndev (- (+ xndev yndev
)))
2199 (ee2 (- (* xndev yndev
) (* 6 zndev zndev
)))
2200 (ee3 (* xndev yndev zndev
))
2205 (* -
3/44 ee2 ee3
))))
2208 (defun bf-rj1 (x y z p
)
2219 (a (/ (+ xn yn zn pn pn
) 5))
2220 (epslon (/ (max (abs (- a xn
))
2224 (bferrtol x y z p
)))
2226 xnroot ynroot znroot pnroot lam dn
)
2227 (loop while
(> (* power4 epslon
) (abs an
))
2229 (setf xnroot
(sqrt xn
))
2230 (setf ynroot
(sqrt yn
))
2231 (setf znroot
(sqrt zn
))
2232 (setf pnroot
(sqrt pn
))
2233 (setf lam
(+ (* xnroot ynroot
)
2236 (setf dn
(* (+ pnroot xnroot
)
2239 (setf sigma
(+ sigma
2241 (bf-rc 1 (+ 1 (/ en
(* dn dn
)))))
2243 (setf power4
(* power4
1/4))
2245 (setf xn
(* (+ xn lam
) 1/4))
2246 (setf yn
(* (+ yn lam
) 1/4))
2247 (setf zn
(* (+ zn lam
) 1/4))
2248 (setf pn
(* (+ pn lam
) 1/4))
2249 (setf an
(* (+ an lam
) 1/4))
2251 (let* ((xndev (/ (* (- a x
) power4
) an
))
2252 (yndev (/ (* (- a y
) power4
) an
))
2253 (zndev (/ (* (- a z
) power4
) an
))
2254 (pndev (* -
0.5 (+ xndev yndev zndev
)))
2255 (ee2 (+ (* xndev yndev
)
2258 (* -
3 pndev pndev
)))
2259 (ee3 (+ (* xndev yndev zndev
)
2261 (* 4 pndev pndev pndev
)))
2262 (ee4 (* (+ (* 2 xndev yndev zndev
)
2264 (* 3 pndev pndev pndev
))
2266 (ee5 (* xndev yndev zndev pndev pndev
))
2274 (* -
1/16 ee2 ee2 ee2
)
2277 (* 45/272 ee2 ee2 ee3
)
2278 (* -
9/68 (+ (* ee2 ee5
) (* ee3 ee4
))))))
2281 (sqrt (* an an an
)))))))
2283 (defun bf-rj (x y z p
)
2288 (cond ((and (and (zerop (imagpart xn
)) (>= (realpart xn
) 0))
2289 (and (zerop (imagpart yn
)) (>= (realpart yn
) 0))
2290 (and (zerop (imagpart zn
)) (>= (realpart zn
) 0))
2291 (and (zerop (imagpart qn
)) (> (realpart qn
) 0)))
2292 (destructuring-bind (xn yn zn
)
2293 (sort (list xn yn zn
) #'<)
2294 (let* ((pn (+ yn
(* (- zn yn
) (/ (- yn xn
) (+ yn qn
)))))
2295 (s (- (* (- pn yn
) (bf-rj1 xn yn zn pn
))
2296 (* 3 (bf-rf xn yn zn
)))))
2297 (setf s
(+ s
(* 3 (sqrt (/ (* xn yn zn
)
2298 (+ (* xn zn
) (* pn qn
))))
2299 (bf-rc (+ (* xn zn
) (* pn qn
)) (* pn qn
)))))
2302 (bf-rj1 x y z p
)))))
2304 (defun bf-rg (x y z
)
2306 (+ (* z
(bf-rf x y z
))
2311 (sqrt (/ (* x y
) z
)))))
2313 ;; elliptic_f(phi,m) = sin(phi)*rf(cos(phi)^2, 1-m*sin(phi)^2,1)
2314 (defun bf-elliptic-f (phi m
)
2315 (flet ((base (phi m
)
2317 ;; F(z|1) = log(tan(z/2+%pi/4))
2318 (log (tan (+ (/ phi
2) (/ (%pi phi
) 4)))))
2322 (* s
(bf-rf (* c c
) (- 1 (* m s s
)) 1)))))))
2323 ;; Handle periodicity (see elliptic-f)
2324 (let* ((bfpi (%pi phi
))
2325 (period (round (realpart phi
) bfpi
)))
2326 (+ (base (- phi
(* bfpi period
)) m
)
2329 (* 2 period
(bf-elliptic-k m
)))))))
2331 ;; elliptic_kc(k) = rf(0, 1-k^2,1)
2334 ;; elliptic_kc(m) = rf(0, 1-m,1)
2336 (defun bf-elliptic-k (m)
2338 (if (maxima::$bfloatp m
)
2339 (maxima::$bfloat
(maxima::div
'maxima
::$%pi
2))
2340 (float (/ pi
2) 1e0
)))
2343 (intl:gettext
"elliptic_kc: elliptic_kc(1) is undefined.")))
2345 (bf-rf 0 (- 1 m
) 1))))
2347 ;; elliptic_e(phi, k) = sin(phi)*rf(cos(phi)^2,1-k^2*sin(phi)^2,1)
2348 ;; - (k^2/3)*sin(phi)^3*rd(cos(phi)^2, 1-k^2*sin(phi)^2,1)
2352 ;; elliptic_e(phi, m) = sin(phi)*rf(cos(phi)^2,1-m*sin(phi)^2,1)
2353 ;; - (m/3)*sin(phi)^3*rd(cos(phi)^2, 1-m*sin(phi)^2,1)
2355 (defun bf-elliptic-e (phi m
)
2356 (flet ((base (phi m
)
2357 (let* ((s (sin phi
))
2360 (s2 (- 1 (* m s s
))))
2361 (- (* s
(bf-rf c2 s2
1))
2362 (* (/ m
3) (* s s s
) (bf-rd c2 s2
1))))))
2363 ;; Elliptic E is quasi-periodic wrt to phi:
2365 ;; E(z|m) = E(z - %pi*round(Re(z)/%pi)|m) + 2*round(Re(z)/%pi)*E(m)
2366 (let* ((bfpi (%pi phi
))
2367 (period (round (realpart phi
) bfpi
)))
2368 (+ (base (- phi
(* bfpi period
)) m
)
2369 (* 2 period
(bf-elliptic-ec m
))))))
2372 ;; elliptic_ec(k) = rf(0,1-k^2,1) - (k^2/3)*rd(0,1-k^2,1);
2375 ;; elliptic_ec(m) = rf(0,1-m,1) - (m/3)*rd(0,1-m,1);
2377 (defun bf-elliptic-ec (m)
2379 (if (typep m
'bigfloat
)
2380 (bigfloat (maxima::$bfloat
(maxima::div
'maxima
::$%pi
2)))
2381 (float (/ pi
2) 1e0
)))
2383 (if (typep m
'bigfloat
)
2389 (* m
1/3 (bf-rd 0 m1
1)))))))
2391 (defun bf-elliptic-pi-complete (n m
)
2392 (+ (bf-rf 0 (- 1 m
) 1)
2393 (* 1/3 n
(bf-rj 0 (- 1 m
) 1 (- 1 n
)))))
2395 (defun bf-elliptic-pi (n phi m
)
2396 ;; Note: Carlson's DRJ has n defined as the negative of the n given
2398 (flet ((base (n phi m
)
2403 (k2sin (* (- 1 (* k sin-phi
))
2404 (+ 1 (* k sin-phi
)))))
2405 (- (* sin-phi
(bf-rf (expt cos-phi
2) k2sin
1.0))
2406 (* (/ nn
3) (expt sin-phi
3)
2407 (bf-rj (expt cos-phi
2) k2sin
1.0
2408 (- 1 (* n
(expt sin-phi
2)))))))))
2409 ;; FIXME: Reducing the arg by pi has significant round-off.
2410 ;; Consider doing something better.
2411 (let* ((bf-pi (%pi
(realpart phi
)))
2412 (cycles (round (realpart phi
) bf-pi
))
2413 (rem (- phi
(* cycles bf-pi
))))
2414 (let ((complete (bf-elliptic-pi-complete n m
)))
2415 (+ (* 2 cycles complete
)
2418 ;; Compute inverse_jacobi_sn, for float or bigfloat args.
2419 (defun bf-inverse-jacobi-sn (u m
)
2420 (* u
(bf-rf (- 1 (* u u
))
2424 ;; Compute inverse_jacobi_dn. We use the following identity
2425 ;; from Gradshteyn & Ryzhik, 8.153.6
2427 ;; w = dn(z|m) = cn(sqrt(m)*z, 1/m)
2429 ;; Solve for z to get
2431 ;; z = inverse_jacobi_dn(w,m)
2432 ;; = 1/sqrt(m) * inverse_jacobi_cn(w, 1/m)
2433 (defun bf-inverse-jacobi-dn (w m
)
2437 ;; jacobi_dn(x,1) = sech(x) so the inverse is asech(x)
2438 (maxima::take
'(maxima::%asech
) (maxima::to w
)))
2440 ;; We should do something better to make sure that things
2441 ;; that should be real are real.
2442 (/ (to (maxima::take
'(maxima::%inverse_jacobi_cn
)
2444 (maxima::to
(/ m
))))
2447 (in-package :maxima
)
2449 ;; Define Carlson's elliptic integrals so we can test their
2450 ;; implementation. We only support bigfloat
2452 (defmfun $carlson_rc
(x y
)
2453 (to (bigfloat::bf-rc
(bigfloat:bigfloat
($bfloat x
))
2454 (bigfloat:bigfloat
($bfloat y
)))))
2456 (defmfun $carlson_rd
(x y z
)
2457 (to (bigfloat::bf-rd
(bigfloat:bigfloat
($bfloat x
))
2458 (bigfloat:bigfloat
($bfloat y
))
2459 (bigfloat:bigfloat
($bfloat z
)))))
2461 (defmfun $carlson_rf
(x y z
)
2462 (to (bigfloat::bf-rf
(bigfloat:bigfloat
($bfloat x
))
2463 (bigfloat:bigfloat
($bfloat y
))
2464 (bigfloat:bigfloat
($bfloat z
)))))
2466 (defmfun $carlson_rj
(x y z p
)
2467 (to (bigfloat::bf-rj
(bigfloat:bigfloat
($bfloat x
))
2468 (bigfloat:bigfloat
($bfloat y
))
2469 (bigfloat:bigfloat
($bfloat z
))
2470 (bigfloat:bigfloat
($bfloat p
)))))
2473 ;;; Other Jacobian elliptic functions
2475 ;; jacobi_ns(u,m) = 1/jacobi_sn(u,m)
2476 (defmfun $jacobi_ns
(u m
)
2477 (simplify (list '(%jacobi_ns
) (resimplify u
) (resimplify m
))))
2479 (defprop %jacobi_ns simp-%jacobi_ns operators
)
2484 ((mtimes) -
1 ((%jacobi_cn
) u m
) ((%jacobi_dn
) u m
)
2485 ((mexpt) ((%jacobi_sn
) u m
) -
2))
2487 ((mtimes) -
1 ((mexpt) ((%jacobi_sn
) u m
) -
2)
2489 ((mtimes) ((rat) 1 2)
2490 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2491 ((mexpt) ((%jacobi_cn
) u m
) 2)
2493 ((mtimes) ((rat) 1 2) ((mexpt) m -
1)
2494 ((%jacobi_cn
) u m
) ((%jacobi_dn
) u m
)
2497 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2498 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
2502 (defun simp-%jacobi_ns
(form unused z
)
2503 (declare (ignore unused
))
2505 (let ((u (simpcheck (cadr form
) z
))
2506 (m (simpcheck (caddr form
) z
))
2509 ((float-numerical-eval-p u m
)
2510 (to (bigfloat:/ (bigfloat::sn
(bigfloat:to
($float u
))
2511 (bigfloat:to
($float m
))))))
2512 ((setf args
(complex-float-numerical-eval-p u m
))
2513 (destructuring-bind (u m
)
2515 (to (bigfloat:/ (bigfloat::sn
(bigfloat:to
($float u
))
2516 (bigfloat:to
($float m
)))))))
2517 ((bigfloat-numerical-eval-p u m
)
2518 (let ((uu (bigfloat:to
($bfloat u
)))
2519 (mm (bigfloat:to
($bfloat m
))))
2520 (to (bigfloat:/ (bigfloat::sn uu mm
)))))
2521 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
2522 (destructuring-bind (u m
)
2524 (let ((uu (bigfloat:to
($bfloat u
)))
2525 (mm (bigfloat:to
($bfloat m
))))
2526 (to (bigfloat:/ (bigfloat::sn uu mm
))))))
2534 (dbz-err1 'jacobi_ns
))
2535 ((and $trigsign
(mminusp* u
))
2537 (neg (cons-exp '%jacobi_ns
(neg u
) m
)))
2540 (member (caar u
) '(%inverse_jacobi_sn
2551 %inverse_jacobi_dc
))
2552 (alike1 (third u
) m
))
2553 (cond ((eq (caar u
) '%inverse_jacobi_ns
)
2556 ;; Express in terms of sn:
2558 (div 1 ($jacobi_sn u m
)))))
2559 ;; A&S 16.20 (Jacobi's Imaginary transformation)
2560 ((and $%iargs
(multiplep u
'$%i
))
2561 ;; ns(i*u) = 1/sn(i*u) = -i/sc(u,m1) = -i*cs(u,m1)
2563 (cons-exp '%jacobi_cs
(coeff u
'$%i
1) (add 1 (neg m
))))))
2564 ((setq coef
(kc-arg2 u m
))
2567 ;; ns(m*K+u) = 1/sn(m*K+u)
2569 (destructuring-bind (lin const
)
2571 (cond ((integerp lin
)
2574 ;; ns(4*m*K+u) = ns(u)
2577 (dbz-err1 'jacobi_ns
)
2578 `((%jacobi_ns simp
) ,const
,m
)))
2580 ;; ns(4*m*K + K + u) = ns(K+u) = dc(u)
2584 `((%jacobi_dc simp
) ,const
,m
)))
2586 ;; ns(4*m*K+2*K + u) = ns(2*K+u) = -ns(u)
2587 ;; ns(2*K) = infinity
2589 (dbz-err1 'jacobi_ns
)
2590 (neg `((%jacobi_ns simp
) ,const
,m
))))
2592 ;; ns(4*m*K+3*K+u) = ns(2*K + K + u) = -ns(K+u) = -dc(u)
2596 (neg `((%jacobi_dc simp
) ,const
,m
))))))
2597 ((and (alike1 lin
1//2)
2599 `((mexpt) ((%jacobi_sn
) ,u
,m
) -
1))
2601 (eqtest (list '(%jacobi_ns
) u m
) form
)))))
2604 (eqtest (list '(%jacobi_ns
) u m
) form
)))))
2606 ;; jacobi_nc(u,m) = 1/jacobi_cn(u,m)
2608 (defmfun $jacobi_nc
(u m
)
2609 (simplify (list '(%jacobi_nc
) (resimplify u
) (resimplify m
))))
2611 (defprop %jacobi_nc simp-%jacobi_nc operators
)
2616 ((mtimes) ((mexpt) ((%jacobi_cn
) u m
) -
2)
2617 ((%jacobi_dn
) u m
) ((%jacobi_sn
) u m
))
2619 ((mtimes) -
1 ((mexpt) ((%jacobi_cn
) u m
) -
2)
2621 ((mtimes) ((rat) -
1 2)
2622 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2623 ((%jacobi_cn
) u m
) ((mexpt) ((%jacobi_sn
) u m
) 2))
2624 ((mtimes) ((rat) -
1 2) ((mexpt) m -
1)
2625 ((%jacobi_dn
) u m
) ((%jacobi_sn
) u m
)
2627 ((mtimes) -
1 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2628 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
)) m
)))))))
2631 (defun simp-%jacobi_nc
(form unused z
)
2632 (declare (ignore unused
))
2634 (let ((u (simpcheck (cadr form
) z
))
2635 (m (simpcheck (caddr form
) z
))
2638 ((float-numerical-eval-p u m
)
2639 (to (bigfloat:/ (bigfloat::cn
(bigfloat:to
($float u
))
2640 (bigfloat:to
($float m
))))))
2641 ((setf args
(complex-float-numerical-eval-p u m
))
2642 (destructuring-bind (u m
)
2644 (to (bigfloat:/ (bigfloat::cn
(bigfloat:to
($float u
))
2645 (bigfloat:to
($float m
)))))))
2646 ((bigfloat-numerical-eval-p u m
)
2647 (let ((uu (bigfloat:to
($bfloat u
)))
2648 (mm (bigfloat:to
($bfloat m
))))
2649 (to (bigfloat:/ (bigfloat::cn uu mm
)))))
2650 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
2651 (destructuring-bind (u m
)
2653 (let ((uu (bigfloat:to
($bfloat u
)))
2654 (mm (bigfloat:to
($bfloat m
))))
2655 (to (bigfloat:/ (bigfloat::cn uu mm
))))))
2664 ((and $trigsign
(mminusp* u
))
2666 (cons-exp '%jacobi_nc
(neg u
) m
))
2669 (member (caar u
) '(%inverse_jacobi_sn
2680 %inverse_jacobi_dc
))
2681 (alike1 (third u
) m
))
2682 (cond ((eq (caar u
) '%inverse_jacobi_nc
)
2685 ;; Express in terms of cn:
2687 (div 1 ($jacobi_cn u m
)))))
2688 ;; A&S 16.20 (Jacobi's Imaginary transformation)
2689 ((and $%iargs
(multiplep u
'$%i
))
2690 ;; nc(i*u) = 1/cn(i*u) = 1/nc(u,1-m) = cn(u,1-m)
2691 (cons-exp '%jacobi_cn
(coeff u
'$%i
1) (add 1 (neg m
))))
2692 ((setq coef
(kc-arg2 u m
))
2697 (destructuring-bind (lin const
)
2699 (cond ((integerp lin
)
2702 ;; nc(4*m*K+u) = nc(u)
2706 `((%jacobi_nc simp
) ,const
,m
)))
2708 ;; nc(4*m*K+K+u) = nc(K+u) = -ds(u)/sqrt(1-m)
2711 (dbz-err1 'jacobi_nc
)
2712 (neg `((mtimes simp
)
2714 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
2716 ((%jacobi_ds simp
) ,const
,m
)))))
2718 ;; nc(4*m*K+2*K+u) = nc(2*K+u) = -nc(u)
2722 (neg `((%jacobi_nc
) ,const
,m
))))
2724 ;; nc(4*m*K+3*K+u) = nc(3*K+u) = nc(2*K+K+u) =
2725 ;; -nc(K+u) = ds(u)/sqrt(1-m)
2727 ;; nc(3*K) = infinity
2729 (dbz-err1 'jacobi_nc
)
2732 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
2734 ((%jacobi_ds simp
) ,const
,m
))))))
2735 ((and (alike1 1//2 lin
)
2737 `((mexpt) ((%jacobi_cn
) ,u
,m
) -
1))
2739 (eqtest (list '(%jacobi_nc
) u m
) form
)))))
2742 (eqtest (list '(%jacobi_nc
) u m
) form
)))))
2744 ;; jacobi_nd(u,m) = 1/jacobi_dn(u,m)
2745 (defmfun $jacobi_nd
(u m
)
2746 (simplify (list '(%jacobi_nd
) (resimplify u
) (resimplify m
))))
2748 (defprop %jacobi_nd simp-%jacobi_nd operators
)
2753 ((mtimes) m
((%jacobi_cn
) u m
)
2754 ((mexpt) ((%jacobi_dn
) u m
) -
2) ((%jacobi_sn
) u m
))
2756 ((mtimes) -
1 ((mexpt) ((%jacobi_dn
) u m
) -
2)
2758 ((mtimes) ((rat) -
1 2)
2759 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2761 ((mexpt) ((%jacobi_sn
) u m
) 2))
2762 ((mtimes) ((rat) -
1 2) ((%jacobi_cn
) u m
)
2766 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2767 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
2771 (defun simp-%jacobi_nd
(form unused z
)
2772 (declare (ignore unused
))
2774 (let ((u (simpcheck (cadr form
) z
))
2775 (m (simpcheck (caddr form
) z
))
2778 ((float-numerical-eval-p u m
)
2779 (to (bigfloat:/ (bigfloat::dn
(bigfloat:to
($float u
))
2780 (bigfloat:to
($float m
))))))
2781 ((setf args
(complex-float-numerical-eval-p u m
))
2782 (destructuring-bind (u m
)
2784 (to (bigfloat:/ (bigfloat::dn
(bigfloat:to
($float u
))
2785 (bigfloat:to
($float m
)))))))
2786 ((bigfloat-numerical-eval-p u m
)
2787 (let ((uu (bigfloat:to
($bfloat u
)))
2788 (mm (bigfloat:to
($bfloat m
))))
2789 (to (bigfloat:/ (bigfloat::dn uu mm
)))))
2790 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
2791 (destructuring-bind (u m
)
2793 (let ((uu (bigfloat:to
($bfloat u
)))
2794 (mm (bigfloat:to
($bfloat m
))))
2795 (to (bigfloat:/ (bigfloat::dn uu mm
))))))
2804 ((and $trigsign
(mminusp* u
))
2806 (cons-exp '%jacobi_nd
(neg u
) m
))
2809 (member (caar u
) '(%inverse_jacobi_sn
2820 %inverse_jacobi_dc
))
2821 (alike1 (third u
) m
))
2822 (cond ((eq (caar u
) '%inverse_jacobi_nd
)
2825 ;; Express in terms of dn:
2827 (div 1 ($jacobi_dn u m
)))))
2828 ;; A&S 16.20 (Jacobi's Imaginary transformation)
2829 ((and $%iargs
(multiplep u
'$%i
))
2830 ;; nd(i*u) = 1/dn(i*u) = 1/dc(u,1-m) = cd(u,1-m)
2831 (cons-exp '%jacobi_cd
(coeff u
'$%i
1) (add 1 (neg m
))))
2832 ((setq coef
(kc-arg2 u m
))
2835 (destructuring-bind (lin const
)
2837 (cond ((integerp lin
)
2841 ;; nd(2*m*K+u) = nd(u)
2845 `((%jacobi_nd
) ,const
,m
)))
2847 ;; nd(2*m*K+K+u) = nd(K+u) = dn(u)/sqrt(1-m)
2848 ;; nd(K) = 1/sqrt(1-m)
2851 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
2854 ((%jacobi_nd simp
) ,const
,m
)
2856 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
2857 ((rat simp
) -
1 2)))))))
2859 (eqtest (list '(%jacobi_nd
) u m
) form
)))))
2862 (eqtest (list '(%jacobi_nd
) u m
) form
)))))
2864 ;; jacobi_sc(u,m) = jacobi_sn/jacobi_cn
2865 (defmfun $jacobi_sc
(u m
)
2866 (simplify (list '(%jacobi_sc
) (resimplify u
) (resimplify m
))))
2868 (defprop %jacobi_sc simp-%jacobi_sc operators
)
2873 ((mtimes) ((mexpt) ((%jacobi_cn
) u m
) -
2)
2877 ((mtimes) ((mexpt) ((%jacobi_cn
) u m
) -
1)
2879 ((mtimes) ((rat) 1 2)
2880 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2881 ((mexpt) ((%jacobi_cn
) u m
) 2)
2883 ((mtimes) ((rat) 1 2) ((mexpt) m -
1)
2884 ((%jacobi_cn
) u m
) ((%jacobi_dn
) u m
)
2887 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2888 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
2890 ((mtimes) -
1 ((mexpt) ((%jacobi_cn
) u m
) -
2)
2893 ((mtimes) ((rat) -
1 2)
2894 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2896 ((mexpt) ((%jacobi_sn
) u m
) 2))
2897 ((mtimes) ((rat) -
1 2) ((mexpt) m -
1)
2898 ((%jacobi_dn
) u m
) ((%jacobi_sn
) u m
)
2901 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
2902 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
2906 (defun simp-%jacobi_sc
(form unused z
)
2907 (declare (ignore unused
))
2909 (let ((u (simpcheck (cadr form
) z
))
2910 (m (simpcheck (caddr form
) z
))
2913 ((float-numerical-eval-p u m
)
2914 (let ((fu (bigfloat:to
($float u
)))
2915 (fm (bigfloat:to
($float m
))))
2916 (to (bigfloat:/ (bigfloat::sn fu fm
) (bigfloat::cn fu fm
)))))
2917 ((setf args
(complex-float-numerical-eval-p u m
))
2918 (destructuring-bind (u m
)
2920 (let ((fu (bigfloat:to
($float u
)))
2921 (fm (bigfloat:to
($float m
))))
2922 (to (bigfloat:/ (bigfloat::sn fu fm
) (bigfloat::cn fu fm
))))))
2923 ((bigfloat-numerical-eval-p u m
)
2924 (let ((uu (bigfloat:to
($bfloat u
)))
2925 (mm (bigfloat:to
($bfloat m
))))
2926 (to (bigfloat:/ (bigfloat::sn uu mm
)
2927 (bigfloat::cn uu mm
)))))
2928 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
2929 (destructuring-bind (u m
)
2931 (let ((uu (bigfloat:to
($bfloat u
)))
2932 (mm (bigfloat:to
($bfloat m
))))
2933 (to (bigfloat:/ (bigfloat::sn uu mm
)
2934 (bigfloat::cn uu mm
))))))
2943 ((and $trigsign
(mminusp* u
))
2945 (neg (cons-exp '%jacobi_sc
(neg u
) m
)))
2948 (member (caar u
) '(%inverse_jacobi_sn
2959 %inverse_jacobi_dc
))
2960 (alike1 (third u
) m
))
2961 (cond ((eq (caar u
) '%inverse_jacobi_sc
)
2964 ;; Express in terms of sn and cn
2965 ;; sc(x) = sn(x)/cn(x)
2966 (div ($jacobi_sn u m
)
2967 ($jacobi_cn u m
)))))
2968 ;; A&S 16.20 (Jacobi's Imaginary transformation)
2969 ((and $%iargs
(multiplep u
'$%i
))
2970 ;; sc(i*u) = sn(i*u)/cn(i*u) = i*sc(u,m1)/nc(u,m1) = i*sn(u,m1)
2972 (cons-exp '%jacobi_sn
(coeff u
'$%i
1) (add 1 (neg m
)))))
2973 ((setq coef
(kc-arg2 u m
))
2975 ;; sc(2*m*K+u) = sc(u)
2976 (destructuring-bind (lin const
)
2978 (cond ((integerp lin
)
2981 ;; sc(2*m*K+ u) = sc(u)
2985 `((%jacobi_sc simp
) ,const
,m
)))
2987 ;; sc(2*m*K + K + u) = sc(K+u)= - cs(u)/sqrt(1-m)
2990 (dbz-err1 'jacobi_sc
)
2992 (div (cons-exp '%jacobi_cs const m
)
2993 (power (sub 1 m
) 1//2)))))))
2994 ((and (alike1 lin
1//2)
2996 ;; From A&S 16.3.3 and 16.5.2:
2997 ;; sc(1/2*K) = 1/(1-m)^(1/4)
2998 (power (sub 1 m
) (div -
1 4)))
3000 (eqtest (list '(%jacobi_sc
) u m
) form
)))))
3003 (eqtest (list '(%jacobi_sc
) u m
) form
)))))
3005 ;; jacobi_sd(u,m) = jacobi_sn/jacobi_dn
3006 (defmfun $jacobi_sd
(u m
)
3007 (simplify (list '(%jacobi_sd
) (resimplify u
) (resimplify m
))))
3009 (defprop %jacobi_sd simp-%jacobi_sd operators
)
3014 ((mtimes) ((%jacobi_cn
) u m
)
3015 ((mexpt) ((%jacobi_dn
) u m
) -
2))
3018 ((mtimes) ((mexpt) ((%jacobi_dn
) u m
) -
1)
3020 ((mtimes) ((rat) 1 2)
3021 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3022 ((mexpt) ((%jacobi_cn
) u m
) 2)
3024 ((mtimes) ((rat) 1 2) ((mexpt) m -
1)
3025 ((%jacobi_cn
) u m
) ((%jacobi_dn
) u m
)
3028 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3029 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3031 ((mtimes) -
1 ((mexpt) ((%jacobi_dn
) u m
) -
2)
3034 ((mtimes) ((rat) -
1 2)
3035 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3037 ((mexpt) ((%jacobi_sn
) u m
) 2))
3038 ((mtimes) ((rat) -
1 2) ((%jacobi_cn
) u m
)
3042 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3043 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3047 (defun simp-%jacobi_sd
(form unused z
)
3048 (declare (ignore unused
))
3050 (let ((u (simpcheck (cadr form
) z
))
3051 (m (simpcheck (caddr form
) z
))
3054 ((float-numerical-eval-p u m
)
3055 (let ((fu (bigfloat:to
($float u
)))
3056 (fm (bigfloat:to
($float m
))))
3057 (to (bigfloat:/ (bigfloat::sn fu fm
) (bigfloat::dn fu fm
)))))
3058 ((setf args
(complex-float-numerical-eval-p u m
))
3059 (destructuring-bind (u m
)
3061 (let ((fu (bigfloat:to
($float u
)))
3062 (fm (bigfloat:to
($float m
))))
3063 (to (bigfloat:/ (bigfloat::sn fu fm
) (bigfloat::dn fu fm
))))))
3064 ((bigfloat-numerical-eval-p u m
)
3065 (let ((uu (bigfloat:to
($bfloat u
)))
3066 (mm (bigfloat:to
($bfloat m
))))
3067 (to (bigfloat:/ (bigfloat::sn uu mm
)
3068 (bigfloat::dn uu mm
)))))
3069 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
3070 (destructuring-bind (u m
)
3072 (let ((uu (bigfloat:to
($bfloat u
)))
3073 (mm (bigfloat:to
($bfloat m
))))
3074 (to (bigfloat:/ (bigfloat::sn uu mm
)
3075 (bigfloat::dn uu mm
))))))
3084 ((and $trigsign
(mminusp* u
))
3086 (neg (cons-exp '%jacobi_sd
(neg u
) m
)))
3089 (member (caar u
) '(%inverse_jacobi_sn
3100 %inverse_jacobi_dc
))
3101 (alike1 (third u
) m
))
3102 (cond ((eq (caar u
) '%inverse_jacobi_sd
)
3105 ;; Express in terms of sn and dn
3106 (div ($jacobi_sn u m
)
3107 ($jacobi_dn u m
)))))
3108 ;; A&S 16.20 (Jacobi's Imaginary transformation)
3109 ((and $%iargs
(multiplep u
'$%i
))
3110 ;; sd(i*u) = sn(i*u)/dn(i*u) = i*sc(u,m1)/dc(u,m1) = i*sd(u,m1)
3112 (cons-exp '%jacobi_sd
(coeff u
'$%i
1) (add 1 (neg m
)))))
3113 ((setq coef
(kc-arg2 u m
))
3115 ;; sd(4*m*K+u) = sd(u)
3116 (destructuring-bind (lin const
)
3118 (cond ((integerp lin
)
3121 ;; sd(4*m*K+u) = sd(u)
3125 `((%jacobi_sd simp
) ,const
,m
)))
3127 ;; sd(4*m*K+K+u) = sd(K+u) = cn(u)/sqrt(1-m)
3128 ;; sd(K) = 1/sqrt(m1)
3130 `((mexpt) ((mplus) 1 ((mtimes) -
1 ,m
))
3134 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3136 ((%jacobi_cn simp
) ,const
,m
))))
3138 ;; sd(4*m*K+2*K+u) = sd(2*K+u) = -sd(u)
3142 (neg `((%jacobi_sd
) ,const
,m
))))
3144 ;; sd(4*m*K+3*K+u) = sd(3*K+u) = sd(2*K+K+u) =
3145 ;; -sd(K+u) = -cn(u)/sqrt(1-m)
3146 ;; sd(3*K) = -1/sqrt(m1)
3149 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3151 (neg `((mtimes simp
)
3153 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3155 ((%jacobi_cn simp
) ,const
,m
)))))))
3156 ((and (alike1 lin
1//2)
3158 ;; jacobi_sn/jacobi_dn
3160 ((%jacobi_sn
) ((mtimes) ((rat) 1 2)
3161 ((%elliptic_kc
) ,m
))
3164 ((%jacobi_dn
) ((mtimes) ((rat) 1 2)
3165 ((%elliptic_kc
) ,m
))
3169 (eqtest (list '(%jacobi_sd
) u m
) form
)))))
3172 (eqtest (list '(%jacobi_sd
) u m
) form
)))))
3174 ;; jacobi_cs(u,m) = jacobi_cn/jacobi_sn
3175 (defmfun $jacobi_cs
(u m
)
3176 (simplify (list '(%jacobi_cs
) (resimplify u
) (resimplify m
))))
3178 (defprop %jacobi_cs simp-%jacobi_cs operators
)
3183 ((mtimes) -
1 ((%jacobi_dn
) u m
)
3184 ((mexpt) ((%jacobi_sn
) u m
) -
2))
3187 ((mtimes) -
1 ((%jacobi_cn
) u m
)
3188 ((mexpt) ((%jacobi_sn
) u m
) -
2)
3190 ((mtimes) ((rat) 1 2)
3191 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3192 ((mexpt) ((%jacobi_cn
) u m
) 2)
3194 ((mtimes) ((rat) 1 2) ((mexpt) m -
1)
3195 ((%jacobi_cn
) u m
) ((%jacobi_dn
) u m
)
3198 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3199 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3201 ((mtimes) ((mexpt) ((%jacobi_sn
) u m
) -
1)
3203 ((mtimes) ((rat) -
1 2)
3204 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3206 ((mexpt) ((%jacobi_sn
) u m
) 2))
3207 ((mtimes) ((rat) -
1 2) ((mexpt) m -
1)
3208 ((%jacobi_dn
) u m
) ((%jacobi_sn
) u m
)
3211 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3212 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3216 (defun simp-%jacobi_cs
(form unused z
)
3217 (declare (ignore unused
))
3219 (let ((u (simpcheck (cadr form
) z
))
3220 (m (simpcheck (caddr form
) z
))
3223 ((float-numerical-eval-p u m
)
3224 (let ((fu (bigfloat:to
($float u
)))
3225 (fm (bigfloat:to
($float m
))))
3226 (to (bigfloat:/ (bigfloat::cn fu fm
) (bigfloat::sn fu fm
)))))
3227 ((setf args
(complex-float-numerical-eval-p u m
))
3228 (destructuring-bind (u m
)
3230 (let ((fu (bigfloat:to
($float u
)))
3231 (fm (bigfloat:to
($float m
))))
3232 (to (bigfloat:/ (bigfloat::cn fu fm
) (bigfloat::sn fu fm
))))))
3233 ((bigfloat-numerical-eval-p u m
)
3234 (let ((uu (bigfloat:to
($bfloat u
)))
3235 (mm (bigfloat:to
($bfloat m
))))
3236 (to (bigfloat:/ (bigfloat::cn uu mm
)
3237 (bigfloat::sn uu mm
)))))
3238 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
3239 (destructuring-bind (u m
)
3241 (let ((uu (bigfloat:to
($bfloat u
)))
3242 (mm (bigfloat:to
($bfloat m
))))
3243 (to (bigfloat:/ (bigfloat::cn uu mm
)
3244 (bigfloat::sn uu mm
))))))
3252 (dbz-err1 'jacobi_cs
))
3253 ((and $trigsign
(mminusp* u
))
3255 (neg (cons-exp '%jacobi_cs
(neg u
) m
)))
3258 (member (caar u
) '(%inverse_jacobi_sn
3269 %inverse_jacobi_dc
))
3270 (alike1 (third u
) m
))
3271 (cond ((eq (caar u
) '%inverse_jacobi_cs
)
3274 ;; Express in terms of cn an sn
3275 (div ($jacobi_cn u m
)
3276 ($jacobi_sn u m
)))))
3277 ;; A&S 16.20 (Jacobi's Imaginary transformation)
3278 ((and $%iargs
(multiplep u
'$%i
))
3279 ;; cs(i*u) = cn(i*u)/sn(i*u) = -i*nc(u,m1)/sc(u,m1) = -i*ns(u,m1)
3281 (cons-exp '%jacobi_ns
(coeff u
'$%i
1) (add 1 (neg m
))))))
3282 ((setq coef
(kc-arg2 u m
))
3285 ;; cs(2*m*K + u) = cs(u)
3286 (destructuring-bind (lin const
)
3288 (cond ((integerp lin
)
3291 ;; cs(2*m*K + u) = cs(u)
3294 (dbz-err1 'jacobi_cs
)
3295 `((%jacobi_cs simp
) ,const
,m
)))
3297 ;; cs(K+u) = -sqrt(1-m)*sc(u)
3303 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3305 ((%jacobi_sc simp
) ,const
,m
))))))
3306 ((and (alike1 lin
1//2)
3310 ((%jacobi_sc
) ((mtimes) ((rat) 1 2)
3311 ((%elliptic_kc
) ,m
)) ,m
)
3314 (eqtest (list '(%jacobi_cs simp
) u m
) form
)))))
3317 (eqtest (list '(%jacobi_cs simp
) u m
) form
)))))
3319 ;; jacobi_cd(u,m) = jacobi_cn/jacobi_dn
3320 (defmfun $jacobi_cd
(u m
)
3321 (simplify (list '(%jacobi_cd
) (resimplify u
) (resimplify m
))))
3323 (defprop %jacobi_cd simp-%jacobi_cd operators
)
3328 ((mtimes) ((mplus) -
1 m
)
3329 ((mexpt) ((%jacobi_dn
) u m
) -
2)
3333 ((mtimes) -
1 ((%jacobi_cn
) u m
)
3334 ((mexpt) ((%jacobi_dn
) u m
) -
2)
3336 ((mtimes) ((rat) -
1 2)
3337 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3339 ((mexpt) ((%jacobi_sn
) u m
) 2))
3340 ((mtimes) ((rat) -
1 2) ((%jacobi_cn
) u m
)
3344 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3345 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3347 ((mtimes) ((mexpt) ((%jacobi_dn
) u m
) -
1)
3349 ((mtimes) ((rat) -
1 2)
3350 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3352 ((mexpt) ((%jacobi_sn
) u m
) 2))
3353 ((mtimes) ((rat) -
1 2) ((mexpt) m -
1)
3354 ((%jacobi_dn
) u m
) ((%jacobi_sn
) u m
)
3357 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3358 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3362 (defun simp-%jacobi_cd
(form unused z
)
3363 (declare (ignore unused
))
3365 (let ((u (simpcheck (cadr form
) z
))
3366 (m (simpcheck (caddr form
) z
))
3369 ((float-numerical-eval-p u m
)
3370 (let ((fu (bigfloat:to
($float u
)))
3371 (fm (bigfloat:to
($float m
))))
3372 (to (bigfloat:/ (bigfloat::cn fu fm
) (bigfloat::dn fu fm
)))))
3373 ((setf args
(complex-float-numerical-eval-p u m
))
3374 (destructuring-bind (u m
)
3376 (let ((fu (bigfloat:to
($float u
)))
3377 (fm (bigfloat:to
($float m
))))
3378 (to (bigfloat:/ (bigfloat::cn fu fm
) (bigfloat::dn fu fm
))))))
3379 ((bigfloat-numerical-eval-p u m
)
3380 (let ((uu (bigfloat:to
($bfloat u
)))
3381 (mm (bigfloat:to
($bfloat m
))))
3382 (to (bigfloat:/ (bigfloat::cn uu mm
) (bigfloat::dn uu mm
)))))
3383 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
3384 (destructuring-bind (u m
)
3386 (let ((uu (bigfloat:to
($bfloat u
)))
3387 (mm (bigfloat:to
($bfloat m
))))
3388 (to (bigfloat:/ (bigfloat::cn uu mm
) (bigfloat::dn uu mm
))))))
3397 ((and $trigsign
(mminusp* u
))
3399 (cons-exp '%jacobi_cd
(neg u
) m
))
3402 (member (caar u
) '(%inverse_jacobi_sn
3413 %inverse_jacobi_dc
))
3414 (alike1 (third u
) m
))
3415 (cond ((eq (caar u
) '%inverse_jacobi_cd
)
3418 ;; Express in terms of cn and dn
3419 (div ($jacobi_cn u m
)
3420 ($jacobi_dn u m
)))))
3421 ;; A&S 16.20 (Jacobi's Imaginary transformation)
3422 ((and $%iargs
(multiplep u
'$%i
))
3423 ;; cd(i*u) = cn(i*u)/dn(i*u) = nc(u,m1)/dc(u,m1) = nd(u,m1)
3424 (cons-exp '%jacobi_nd
(coeff u
'$%i
1) (add 1 (neg m
))))
3425 ((setf coef
(kc-arg2 u m
))
3428 (destructuring-bind (lin const
)
3430 (cond ((integerp lin
)
3433 ;; cd(4*m*K + u) = cd(u)
3437 `((%jacobi_cd
) ,const
,m
)))
3439 ;; cd(4*m*K + K + u) = cd(K+u) = -sn(u)
3443 (neg `((%jacobi_sn
) ,const
,m
))))
3445 ;; cd(4*m*K + 2*K + u) = cd(2*K+u) = -cd(u)
3449 (neg `((%jacobi_cd
) ,const
,m
))))
3451 ;; cd(4*m*K + 3*K + u) = cd(2*K + K + u) =
3456 `((%jacobi_sn
) ,const
,m
)))))
3457 ((and (alike1 lin
1//2)
3459 ;; jacobi_cn/jacobi_dn
3461 ((%jacobi_cn
) ((mtimes) ((rat) 1 2)
3462 ((%elliptic_kc
) ,m
))
3465 ((%jacobi_dn
) ((mtimes) ((rat) 1 2)
3466 ((%elliptic_kc
) ,m
))
3471 (eqtest (list '(%jacobi_cd
) u m
) form
)))))
3474 (eqtest (list '(%jacobi_cd
) u m
) form
)))))
3476 ;; jacobi_ds(u,m) = jacobi_dn/jacobi_sn
3477 (defmfun $jacobi_ds
(u m
)
3478 (simplify (list '(%jacobi_ds
) (resimplify u
) (resimplify m
))))
3480 (defprop %jacobi_ds simp-%jacobi_ds operators
)
3485 ((mtimes) -
1 ((%jacobi_cn
) u m
)
3486 ((mexpt) ((%jacobi_sn
) u m
) -
2))
3489 ((mtimes) -
1 ((%jacobi_dn
) u m
)
3490 ((mexpt) ((%jacobi_sn
) u m
) -
2)
3492 ((mtimes) ((rat) 1 2)
3493 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3494 ((mexpt) ((%jacobi_cn
) u m
) 2)
3496 ((mtimes) ((rat) 1 2) ((mexpt) m -
1)
3497 ((%jacobi_cn
) u m
) ((%jacobi_dn
) u m
)
3500 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3501 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3503 ((mtimes) ((mexpt) ((%jacobi_sn
) u m
) -
1)
3505 ((mtimes) ((rat) -
1 2)
3506 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3508 ((mexpt) ((%jacobi_sn
) u m
) 2))
3509 ((mtimes) ((rat) -
1 2) ((%jacobi_cn
) u m
)
3513 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3514 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3518 (defun simp-%jacobi_ds
(form unused z
)
3519 (declare (ignore unused
))
3521 (let ((u (simpcheck (cadr form
) z
))
3522 (m (simpcheck (caddr form
) z
))
3525 ((float-numerical-eval-p u m
)
3526 (let ((fu (bigfloat:to
($float u
)))
3527 (fm (bigfloat:to
($float m
))))
3528 (to (bigfloat:/ (bigfloat::dn fu fm
) (bigfloat::sn fu fm
)))))
3529 ((setf args
(complex-float-numerical-eval-p u m
))
3530 (destructuring-bind (u m
)
3532 (let ((fu (bigfloat:to
($float u
)))
3533 (fm (bigfloat:to
($float m
))))
3534 (to (bigfloat:/ (bigfloat::dn fu fm
) (bigfloat::sn fu fm
))))))
3535 ((bigfloat-numerical-eval-p u m
)
3536 (let ((uu (bigfloat:to
($bfloat u
)))
3537 (mm (bigfloat:to
($bfloat m
))))
3538 (to (bigfloat:/ (bigfloat::dn uu mm
)
3539 (bigfloat::sn uu mm
)))))
3540 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
3541 (destructuring-bind (u m
)
3543 (let ((uu (bigfloat:to
($bfloat u
)))
3544 (mm (bigfloat:to
($bfloat m
))))
3545 (to (bigfloat:/ (bigfloat::dn uu mm
)
3546 (bigfloat::sn uu mm
))))))
3554 (dbz-err1 'jacobi_ds
))
3555 ((and $trigsign
(mminusp* u
))
3556 (neg (cons-exp '%jacobi_ds
(neg u
) m
)))
3559 (member (caar u
) '(%inverse_jacobi_sn
3570 %inverse_jacobi_dc
))
3571 (alike1 (third u
) m
))
3572 (cond ((eq (caar u
) '%inverse_jacobi_ds
)
3575 ;; Express in terms of dn and sn
3576 (div ($jacobi_dn u m
)
3577 ($jacobi_sn u m
)))))
3578 ;; A&S 16.20 (Jacobi's Imaginary transformation)
3579 ((and $%iargs
(multiplep u
'$%i
))
3580 ;; ds(i*u) = dn(i*u)/sn(i*u) = -i*dc(u,m1)/sc(u,m1) = -i*ds(u,m1)
3582 (cons-exp '%jacobi_ds
(coeff u
'$%i
1) (add 1 (neg m
))))))
3583 ((setf coef
(kc-arg2 u m
))
3585 (destructuring-bind (lin const
)
3587 (cond ((integerp lin
)
3590 ;; ds(4*m*K + u) = ds(u)
3593 (dbz-err1 'jacobi_ds
)
3594 `((%jacobi_ds
) ,const
,m
)))
3596 ;; ds(4*m*K + K + u) = ds(K+u) = sqrt(1-m)*nc(u)
3597 ;; ds(K) = sqrt(1-m)
3600 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3604 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3606 ((%jacobi_nc simp
) ,const
,m
))))
3608 ;; ds(4*m*K + 2*K + u) = ds(2*K+u) = -ds(u)
3611 (dbz-err1 'jacobi_ds
)
3612 (neg `((%jacobi_ds
) ,const
,m
))))
3614 ;; ds(4*m*K + 3*K + u) = ds(2*K + K + u) =
3615 ;; -ds(K+u) = -sqrt(1-m)*nc(u)
3616 ;; ds(3*K) = -sqrt(1-m)
3619 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3621 (neg `((mtimes simp
)
3623 ((mplus simp
) 1 ((mtimes simp
) -
1 ,m
))
3625 ((%jacobi_nc simp
) ,const
,m
)))))))
3626 ((and (alike1 lin
1//2)
3628 ;; jacobi_dn/jacobi_sn
3630 ((%jacobi_dn
) ((mtimes) ((rat) 1 2)
3631 ((%elliptic_kc
) ,m
))
3634 ((%jacobi_sn
) ((mtimes) ((rat) 1 2)
3635 ((%elliptic_kc
) ,m
))
3640 (eqtest (list '(%jacobi_ds
) u m
) form
)))))
3643 (eqtest (list '(%jacobi_ds
) u m
) form
)))))
3645 ;; jacobi_dc(u,m) = jacobi_dn/jacobi_cn
3646 (defmfun $jacobi_dc
(u m
)
3647 (simplify (list '(%jacobi_dc
) (resimplify u
) (resimplify m
))))
3649 (defprop %jacobi_dc simp-%jacobi_dc operators
)
3654 ((mtimes) ((mplus) 1 ((mtimes) -
1 m
))
3655 ((mexpt) ((%jacobi_cn
) u m
) -
2)
3659 ((mtimes) ((mexpt) ((%jacobi_cn
) u m
) -
1)
3661 ((mtimes) ((rat) -
1 2)
3662 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3664 ((mexpt) ((%jacobi_sn
) u m
) 2))
3665 ((mtimes) ((rat) -
1 2) ((%jacobi_cn
) u m
)
3669 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3670 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3672 ((mtimes) -
1 ((mexpt) ((%jacobi_cn
) u m
) -
2)
3675 ((mtimes) ((rat) -
1 2)
3676 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3678 ((mexpt) ((%jacobi_sn
) u m
) 2))
3679 ((mtimes) ((rat) -
1 2) ((mexpt) m -
1)
3680 ((%jacobi_dn
) u m
) ((%jacobi_sn
) u m
)
3683 ((mexpt) ((mplus) 1 ((mtimes) -
1 m
)) -
1)
3684 (($elliptic_e
) ((%asin
) ((%jacobi_sn
) u m
))
3688 (defun simp-%jacobi_dc
(form unused z
)
3689 (declare (ignore unused
))
3691 (let ((u (simpcheck (cadr form
) z
))
3692 (m (simpcheck (caddr form
) z
))
3695 ((float-numerical-eval-p u m
)
3696 (let ((fu (bigfloat:to
($float u
)))
3697 (fm (bigfloat:to
($float m
))))
3698 (to (bigfloat:/ (bigfloat::dn fu fm
) (bigfloat::cn fu fm
)))))
3699 ((setf args
(complex-float-numerical-eval-p u m
))
3700 (destructuring-bind (u m
)
3702 (let ((fu (bigfloat:to
($float u
)))
3703 (fm (bigfloat:to
($float m
))))
3704 (to (bigfloat:/ (bigfloat::dn fu fm
) (bigfloat::cn fu fm
))))))
3705 ((bigfloat-numerical-eval-p u m
)
3706 (let ((uu (bigfloat:to
($bfloat u
)))
3707 (mm (bigfloat:to
($bfloat m
))))
3708 (to (bigfloat:/ (bigfloat::dn uu mm
)
3709 (bigfloat::cn uu mm
)))))
3710 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
3711 (destructuring-bind (u m
)
3713 (let ((uu (bigfloat:to
($bfloat u
)))
3714 (mm (bigfloat:to
($bfloat m
))))
3715 (to (bigfloat:/ (bigfloat::dn uu mm
)
3716 (bigfloat::cn uu mm
))))))
3725 ((and $trigsign
(mminusp* u
))
3726 (cons-exp '%jacobi_dc
(neg u
) m
))
3729 (member (caar u
) '(%inverse_jacobi_sn
3740 %inverse_jacobi_dc
))
3741 (alike1 (third u
) m
))
3742 (cond ((eq (caar u
) '%inverse_jacobi_dc
)
3745 ;; Express in terms of dn and cn
3746 (div ($jacobi_dn u m
)
3747 ($jacobi_cn u m
)))))
3748 ;; A&S 16.20 (Jacobi's Imaginary transformation)
3749 ((and $%iargs
(multiplep u
'$%i
))
3750 ;; dc(i*u) = dn(i*u)/cn(i*u) = dc(u,m1)/nc(u,m1) = dn(u,m1)
3751 (cons-exp '%jacobi_dn
(coeff u
'$%i
1) (add 1 (neg m
))))
3752 ((setf coef
(kc-arg2 u m
))
3754 (destructuring-bind (lin const
)
3756 (cond ((integerp lin
)
3759 ;; dc(4*m*K + u) = dc(u)
3763 `((%jacobi_dc
) ,const
,m
)))
3765 ;; dc(4*m*K + K + u) = dc(K+u) = -ns(u)
3768 (dbz-err1 'jacobi_dc
)
3769 (neg `((%jacobi_ns simp
) ,const
,m
))))
3771 ;; dc(4*m*K + 2*K + u) = dc(2*K+u) = -dc(u)
3775 (neg `((%jacobi_dc
) ,const
,m
))))
3777 ;; dc(4*m*K + 3*K + u) = dc(2*K + K + u) =
3779 ;; dc(3*K) = ns(0) = inf
3781 (dbz-err1 'jacobi_dc
)
3782 `((%jacobi_dc simp
) ,const
,m
)))))
3783 ((and (alike1 lin
1//2)
3785 ;; jacobi_dn/jacobi_cn
3787 ((%jacobi_dn
) ((mtimes) ((rat) 1 2)
3788 ((%elliptic_kc
) ,m
))
3791 ((%jacobi_cn
) ((mtimes) ((rat) 1 2)
3792 ((%elliptic_kc
) ,m
))
3797 (eqtest (list '(%jacobi_dc
) u m
) form
)))))
3800 (eqtest (list '(%jacobi_dc
) u m
) form
)))))
3802 ;;; Other inverse Jacobian functions
3804 ;; inverse_jacobi_ns(x)
3806 ;; Let u = inverse_jacobi_ns(x). Then jacobi_ns(u) = x or
3807 ;; 1/jacobi_sn(u) = x or
3809 ;; jacobi_sn(u) = 1/x
3811 ;; so u = inverse_jacobi_sn(1/x)
3813 (defmfun $inverse_jacobi_ns
(u m
)
3814 (simplify (list '(%inverse_jacobi_ns
) (resimplify u
) (resimplify m
))))
3816 (defprop %inverse_jacobi_ns
3818 ;; Whittaker and Watson, example in 22.122
3819 ;; inverse_jacobi_ns(u,m) = integrate(1/sqrt(t^2-1)/sqrt(t^2-m), t, u, inf)
3820 ;; -> -1/sqrt(x^2-1)/sqrt(x^2-m)
3822 ((mexpt) ((mplus) -
1 ((mexpt) x
2)) ((rat) -
1 2))
3824 ((mplus) ((mtimes simp ratsimp
) -
1 m
) ((mexpt) x
2))
3827 ; ((%derivative) ((%inverse_jacobi_ns) x m) m 1)
3831 (defprop %inverse_jacobi_ns simp-%inverse_jacobi_ns operators
)
3833 (defun simp-%inverse_jacobi_ns
(form unused z
)
3834 (declare (ignore unused
))
3836 (let ((u (simpcheck (cadr form
) z
))
3837 (m (simpcheck (caddr form
) z
))
3840 ((float-numerical-eval-p u m
)
3841 ;; Numerically evaluate asn
3843 ;; ans(x,m) = asn(1/x,m) = F(asin(1/x),m)
3844 (to (elliptic-f (cl:asin
(/ ($float u
))) ($float m
))))
3845 ((complex-float-numerical-eval-p u m
)
3846 (to (elliptic-f (cl:asin
(/ (complex ($realpart
($float u
)) ($imagpart
($float u
)))))
3847 (complex ($realpart
($float m
)) ($imagpart
($float m
))))))
3848 ((bigfloat-numerical-eval-p u m
)
3849 (to (bigfloat::bf-elliptic-f
(bigfloat:asin
(bigfloat:/ (bigfloat:to
($bfloat u
))))
3850 (bigfloat:to
($bfloat m
)))))
3851 ((setf args
(complex-bigfloat-numerical-eval-p u m
))
3852 (destructuring-bind (u m
)
3854 (to (bigfloat::bf-elliptic-f
(bigfloat:asin
(bigfloat:/ (bigfloat:to
($bfloat u
))))
3855 (bigfloat:to
($bfloat m
))))))
3857 ;; ans(x,0) = F(asin(1/x),0) = asin(1/x)
3858 `(($elliptic_f
) ((%asin
) ((mexpt) ,u -
1)) 0))
3860 ;; ans(x,1) = F(asin(1/x),1) = log(tan(pi/2+asin(1/x)/2))
3861 `(($elliptic_f
) ((%asin
) ((mexpt) ,u -
1)) 1))
3863 `((%elliptic_kc
) ,m
))
3865 (neg `((%elliptic_kc
) ,m
)))
3866 ((and (eq $triginverses
'$all
)
3868 (eq (caar u
) '%jacobi_ns
)
3869 (alike1 (third u
) m
))
3870 ;; inverse_jacobi_ns(ns(u)) = u
3874 (eqtest (list '(%inverse_jacobi_ns
) u m
) form
)))))
3876 ;; inverse_jacobi_nc(x)
3878 ;; Let u = inverse_jacobi_nc(x). Then jacobi_nc(u) = x or
3879 ;; 1/jacobi_cn(u) = x or
3881 ;; jacobi_cn(u) = 1/x
3883 ;; so u = inverse_jacobi_cn(1/x)
3885 (defmfun $inverse_jacobi_nc
(u m
)
3886 (simplify (list '(%inverse_jacobi_nc
) (resimplify u
) (resimplify m
))))
3888 (defprop %inverse_jacobi_nc
3890 ;; Whittaker and Watson, example in 22.122
3891 ;; inverse_jacobi_nc(u,m) = integrate(1/sqrt(t^2-1)/sqrt((1-m)*t^2+m), t, 1, u)
3892 ;; -> 1/sqrt(x^2-1)/sqrt((1-m)*x^2+m)
3894 ((mexpt) ((mplus) -
1 ((mexpt) x
2)) ((rat) -
1 2))
3897 ((mtimes) -
1 ((mplus) -
1 m
) ((mexpt) x
2)))
3900 ; ((%derivative) ((%inverse_jacobi_nc) x m) m 1)
3904 (defprop %inverse_jacobi_nc simp-%inverse_jacobi_nc operators
)
3906 (defun simp-%inverse_jacobi_nc
(form unused z
)
3907 (declare (ignore unused
))
3909 (let ((u (simpcheck (cadr form
) z
))
3910 (m (simpcheck (caddr form
) z
)))
3911 (cond ((or (float-numerical-eval-p u m
)
3912 (complex-float-numerical-eval-p u m
)
3913 (bigfloat-numerical-eval-p u m
)
3914 (complex-bigfloat-numerical-eval-p u m
))
3916 ($inverse_jacobi_cn
($rectform
(div 1 u
)) m
))
3920 `((mtimes) 2 ((%elliptic_kc
) ,m
)))
3921 ((and (eq $triginverses
'$all
)
3923 (eq (caar u
) '%jacobi_nc
)
3924 (alike1 (third u
) m
))
3925 ;; inverse_jacobi_nc(nc(u)) = u
3929 (eqtest (list '(%inverse_jacobi_nc
) u m
) form
)))))
3931 ;; inverse_jacobi_nd(x)
3933 ;; Let u = inverse_jacobi_nd(x). Then jacobi_nd(u) = x or
3934 ;; 1/jacobi_dn(u) = x or
3936 ;; jacobi_dn(u) = 1/x
3938 ;; so u = inverse_jacobi_dn(1/x)
3940 (defmfun $inverse_jacobi_nd
(u m
)
3941 (simplify (list '(%inverse_jacobi_nd
) (resimplify u
) (resimplify m
))))
3943 (defprop %inverse_jacobi_nd
3945 ;; Whittaker and Watson, example in 22.122
3946 ;; inverse_jacobi_nd(u,m) = integrate(1/sqrt(t^2-1)/sqrt(1-(1-m)*t^2), t, 1, u)
3947 ;; -> 1/sqrt(u^2-1)/sqrt(1-(1-m)*t^2)
3949 ((mexpt) ((mplus) -
1 ((mexpt simp ratsimp
) x
2))
3953 ((mtimes) ((mplus) -
1 m
) ((mexpt simp ratsimp
) x
2)))
3956 ; ((%derivative) ((%inverse_jacobi_nd) x m) m 1)
3960 (defprop %inverse_jacobi_nd simp-%inverse_jacobi_nd operators
)
3962 (defun simp-%inverse_jacobi_nd
(form unused z
)
3963 (declare (ignore unused
))
3965 (let ((u (simpcheck (cadr form
) z
))
3966 (m (simpcheck (caddr form
) z
)))
3967 (cond ((or (float-numerical-eval-p u m
)
3968 (complex-float-numerical-eval-p u m
)
3969 (bigfloat-numerical-eval-p u m
)
3970 (complex-bigfloat-numerical-eval-p u m
))
3971 ($inverse_jacobi_dn
($rectform
(div 1 u
)) m
))
3974 ((onep1 ($ratsimp
(mul (power (sub 1 m
) 1//2) u
)))
3975 ;; jacobi_nd(1/sqrt(1-m),m) = K(m). This follows from
3976 ;; jacobi_dn(sqrt(1-m),m) = K(m).
3978 ((and (eq $triginverses
'$all
)
3980 (eq (caar u
) '%jacobi_nd
)
3981 (alike1 (third u
) m
))
3982 ;; inverse_jacobi_nd(nd(u)) = u
3986 (eqtest (list '(%inverse_jacobi_nd
) u m
) form
)))))
3988 ;; inverse_jacobi_sc(x)
3990 ;; Let u = inverse_jacobi_sc(x). Then jacobi_sc(u) = x or
3991 ;; x = jacobi_sn(u)/jacobi_cn(u)
3998 ;; sn^2 = x^2/(1+x^2)
4000 ;; sn(u) = x/sqrt(1+x^2)
4002 ;; u = inverse_sn(x/sqrt(1+x^2))
4005 (defmfun $inverse_jacobi_sc
(u m
)
4006 (simplify (list '(%inverse_jacobi_sc
) (resimplify u
) (resimplify m
))))
4008 (defprop %inverse_jacobi_sc
4010 ;; Whittaker and Watson, example in 22.122
4011 ;; inverse_jacobi_sc(u,m) = integrate(1/sqrt(1+t^2)/sqrt(1+(1-m)*t^2), t, 0, u)
4012 ;; -> 1/sqrt(1+x^2)/sqrt(1+(1-m)*x^2)
4014 ((mexpt) ((mplus) 1 ((mexpt) x
2))
4018 ((mtimes) -
1 ((mplus) -
1 m
) ((mexpt) x
2)))
4021 ; ((%derivative) ((%inverse_jacobi_sc) x m) m 1)
4025 (defprop %inverse_jacobi_sc simp-%inverse_jacobi_sc operators
)
4027 (defun simp-%inverse_jacobi_sc
(form unused z
)
4028 (declare (ignore unused
))
4030 (let ((u (simpcheck (cadr form
) z
))
4031 (m (simpcheck (caddr form
) z
)))
4032 (cond ((or (float-numerical-eval-p u m
)
4033 (complex-float-numerical-eval-p u m
)
4034 (bigfloat-numerical-eval-p u m
)
4035 (complex-bigfloat-numerical-eval-p u m
))
4037 ($rectform
(div u
(power (add 1 (mul u u
)) 1//2)))
4040 ;; jacobi_sc(0,m) = 0
4042 ((and (eq $triginverses
'$all
)
4044 (eq (caar u
) '%jacobi_sc
)
4045 (alike1 (third u
) m
))
4046 ;; inverse_jacobi_sc(sc(u)) = u
4050 (eqtest (list '(%inverse_jacobi_sc
) u m
) form
)))))
4052 ;; inverse_jacobi_sd(x)
4054 ;; Let u = inverse_jacobi_sd(x). Then jacobi_sd(u) = x or
4055 ;; x = jacobi_sn(u)/jacobi_dn(u)
4058 ;; = sn^2/(1-m*sn^2)
4062 ;; sn^2 = x^2/(1+m*x^2)
4064 ;; sn(u) = x/sqrt(1+m*x^2)
4066 ;; u = inverse_sn(x/sqrt(1+m*x^2))
4069 (defmfun $inverse_jacobi_sd
(u m
)
4070 (simplify (list '(%inverse_jacobi_sd
) (resimplify u
) (resimplify m
))))
4072 (defprop %inverse_jacobi_sd
4074 ;; Whittaker and Watson, example in 22.122
4075 ;; inverse_jacobi_sd(u,m) = integrate(1/sqrt(1-(1-m)*t^2)/sqrt(1+m*t^2), t, 0, u)
4076 ;; -> 1/sqrt(1-(1-m)*x^2)/sqrt(1+m*x^2)
4079 ((mplus) 1 ((mtimes) ((mplus) -
1 m
) ((mexpt) x
2)))
4081 ((mexpt) ((mplus) 1 ((mtimes) m
((mexpt) x
2)))
4084 ; ((%derivative) ((%inverse_jacobi_sd) x m) m 1)
4088 (defprop %inverse_jacobi_sd simp-%inverse_jacobi_sd operators
)
4090 (defun simp-%inverse_jacobi_sd
(form unused z
)
4091 (declare (ignore unused
))
4093 (let ((u (simpcheck (cadr form
) z
))
4094 (m (simpcheck (caddr form
) z
)))
4095 (cond ((or (float-numerical-eval-p u m
)
4096 (complex-float-numerical-eval-p u m
)
4097 (bigfloat-numerical-eval-p u m
)
4098 (complex-bigfloat-numerical-eval-p u m
))
4100 ($rectform
(div u
(power (add 1 (mul m
(mul u u
))) 1//2)))
4104 ((eql 0 ($ratsimp
(sub u
(div 1 (power (sub 1 m
) 1//2)))))
4105 ;; inverse_jacobi_sd(1/sqrt(1-m), m) = elliptic_kc(m)
4107 ;; We can see this from inverse_jacobi_sd(x,m) =
4108 ;; inverse_jacobi_sn(x/sqrt(1+m*x^2), m). So
4109 ;; inverse_jacobi_sd(1/sqrt(1-m),m) = inverse_jacobi_sn(1,m)
4111 ((and (eq $triginverses
'$all
)
4113 (eq (caar u
) '%jacobi_sd
)
4114 (alike1 (third u
) m
))
4115 ;; inverse_jacobi_sd(sd(u)) = u
4119 (eqtest (list '(%inverse_jacobi_sd
) u m
) form
)))))
4121 ;; inverse_jacobi_cs(x)
4123 ;; Let u = inverse_jacobi_cs(x). Then jacobi_cs(u) = x or
4124 ;; 1/x = 1/jacobi_cs(u) = jacobi_sc(u)
4126 ;; u = inverse_sc(1/x)
4129 (defmfun $inverse_jacobi_cs
(u m
)
4130 (simplify (list '(%inverse_jacobi_cs
) (resimplify u
) (resimplify m
))))
4132 (defprop %inverse_jacobi_cs
4134 ;; Whittaker and Watson, example in 22.122
4135 ;; inverse_jacobi_cs(u,m) = integrate(1/sqrt(t^2+1)/sqrt(t^2+(1-m)), t, u, inf)
4136 ;; -> -1/sqrt(x^2+1)/sqrt(x^2+(1-m))
4138 ((mexpt) ((mplus) 1 ((mexpt simp ratsimp
) x
2))
4141 ((mtimes simp ratsimp
) -
1 m
)
4142 ((mexpt simp ratsimp
) x
2))
4145 ; ((%derivative) ((%inverse_jacobi_cs) x m) m 1)
4149 (defprop %inverse_jacobi_cs simp-%inverse_jacobi_cs operators
)
4151 (defun simp-%inverse_jacobi_cs
(form unused z
)
4152 (declare (ignore unused
))
4154 (let ((u (simpcheck (cadr form
) z
))
4155 (m (simpcheck (caddr form
) z
)))
4156 (cond ((or (float-numerical-eval-p u m
)
4157 (complex-float-numerical-eval-p u m
)
4158 (bigfloat-numerical-eval-p u m
)
4159 (complex-bigfloat-numerical-eval-p u m
))
4160 ($inverse_jacobi_sc
($rectform
(div 1 u
)) m
))
4162 `((%elliptic_kc
) ,m
))
4165 (eqtest (list '(%inverse_jacobi_cs
) u m
) form
)))))
4167 ;; inverse_jacobi_cd(x)
4169 ;; Let u = inverse_jacobi_cd(x). Then jacobi_cd(u) = x or
4170 ;; x = jacobi_cn(u)/jacobi_dn(u)
4173 ;; = (1-sn^2)/(1-m*sn^2)
4177 ;; sn^2 = (1-x^2)/(1-m*x^2)
4179 ;; sn(u) = sqrt(1-x^2)/sqrt(1-m*x^2)
4181 ;; u = inverse_sn(sqrt(1-x^2)/sqrt(1-m*x^2))
4184 (defmfun $inverse_jacobi_cd
(u m
)
4185 (simplify (list '(%inverse_jacobi_cd
) (resimplify u
) (resimplify m
))))
4187 (defprop %inverse_jacobi_cd
4189 ;; Whittaker and Watson, example in 22.122
4190 ;; inverse_jacobi_cd(u,m) = integrate(1/sqrt(1-t^2)/sqrt(1-m*t^2), t, u, 1)
4191 ;; -> -1/sqrt(1-x^2)/sqrt(1-m*x^2)
4194 ((mplus) 1 ((mtimes) -
1 ((mexpt) x
2)))
4197 ((mplus) 1 ((mtimes) -
1 m
((mexpt) x
2)))
4200 ; ((%derivative) ((%inverse_jacobi_cd) x m) m 1)
4204 (defprop %inverse_jacobi_cd simp-%inverse_jacobi_cd operators
)
4206 (defun simp-%inverse_jacobi_cd
(form unused z
)
4207 (declare (ignore unused
))
4209 (let ((u (simpcheck (cadr form
) z
))
4210 (m (simpcheck (caddr form
) z
)))
4211 (cond ((or (complex-float-numerical-eval-p u m
)
4212 (complex-bigfloat-numerical-eval-p u m
))
4215 ($rectform
(div (power (mul (sub 1 u
) (add 1 u
)) 1//2)
4216 (power (sub 1 (mul m
(mul u u
))) 1//2)))
4221 `((%elliptic_kc
) ,m
))
4222 ((and (eq $triginverses
'$all
)
4224 (eq (caar u
) '%jacobi_cd
)
4225 (alike1 (third u
) m
))
4226 ;; inverse_jacobi_cd(cd(u)) = u
4230 (eqtest (list '(%inverse_jacobi_cd
) u m
) form
)))))
4232 ;; inverse_jacobi_ds(x)
4234 ;; Let u = inverse_jacobi_ds(x). Then jacobi_ds(u) = x or
4235 ;; 1/x = 1/jacobi_ds(u) = jacobi_sd(u)
4237 ;; u = inverse_sd(1/x)
4240 (defmfun $inverse_jacobi_ds
(u m
)
4241 (simplify (list '(%inverse_jacobi_ds
) (resimplify u
) (resimplify m
))))
4243 (defprop %inverse_jacobi_ds
4245 ;; Whittaker and Watson, example in 22.122
4246 ;; inverse_jacobi_ds(u,m) = integrate(1/sqrt(t^2-(1-m))/sqrt(t^2+m), t, u, inf)
4247 ;; -> -1/sqrt(x^2-(1-m))/sqrt(x^2+m)
4250 ((mplus) -
1 m
((mexpt simp ratsimp
) x
2))
4253 ((mplus) m
((mexpt simp ratsimp
) x
2))
4256 ; ((%derivative) ((%inverse_jacobi_ds) x m) m 1)
4260 (defprop %inverse_jacobi_ds simp-%inverse_jacobi_ds operators
)
4262 (defun simp-%inverse_jacobi_ds
(form unused z
)
4263 (declare (ignore unused
))
4265 (let ((u (simpcheck (cadr form
) z
))
4266 (m (simpcheck (caddr form
) z
)))
4267 (cond ((or (float-numerical-eval-p u m
)
4268 (complex-float-numerical-eval-p u m
)
4269 (bigfloat-numerical-eval-p u m
)
4270 (complex-bigfloat-numerical-eval-p u m
))
4271 ($inverse_jacobi_sd
($rectform
(div 1 u
)) m
))
4272 ((and $trigsign
(mminusp* u
))
4273 (neg (cons-exp '%inverse_jacobi_ds
(neg u
) m
)))
4274 ((eql 0 ($ratsimp
(sub u
(power (sub 1 m
) 1//2))))
4275 ;; inverse_jacobi_ds(sqrt(1-m),m) = elliptic_kc(m)
4277 ;; Since inverse_jacobi_ds(sqrt(1-m), m) =
4278 ;; inverse_jacobi_sd(1/sqrt(1-m),m). And we know from
4279 ;; above that this is elliptic_kc(m)
4281 ((and (eq $triginverses
'$all
)
4283 (eq (caar u
) '%jacobi_ds
)
4284 (alike1 (third u
) m
))
4285 ;; inverse_jacobi_ds(ds(u)) = u
4289 (eqtest (list '(%inverse_jacobi_ds
) u m
) form
)))))
4292 ;; inverse_jacobi_dc(x)
4294 ;; Let u = inverse_jacobi_dc(x). Then jacobi_dc(u) = x or
4295 ;; 1/x = 1/jacobi_dc(u) = jacobi_cd(u)
4297 ;; u = inverse_cd(1/x)
4300 (defmfun $inverse_jacobi_dc
(u m
)
4301 (simplify (list '(%inverse_jacobi_dc
) (resimplify u
) (resimplify m
))))
4303 (defprop %inverse_jacobi_dc
4305 ;; Note: Whittaker and Watson, example in 22.122 says
4306 ;; inverse_jacobi_dc(u,m) = integrate(1/sqrt(t^2-1)/sqrt(t^2-m),
4307 ;; t, u, 1) but that seems wrong. A&S 17.4.47 says
4308 ;; integrate(1/sqrt(t^2-1)/sqrt(t^2-m), t, a, u) =
4309 ;; inverse_jacobi_cd(x,m). Lawden 3.2.8 says the same.
4310 ;; functions.wolfram.com says the derivative is
4311 ;; 1/sqrt(t^2-1)/sqrt(t^2-m).
4314 ((mplus) -
1 ((mexpt simp ratsimp
) x
2))
4318 ((mtimes simp ratsimp
) -
1 m
)
4319 ((mexpt simp ratsimp
) x
2))
4322 ; ((%derivative) ((%inverse_jacobi_dc) x m) m 1)
4326 (defprop %inverse_jacobi_dc simp-%inverse_jacobi_dc operators
)
4328 (defun simp-%inverse_jacobi_dc
(form unused z
)
4329 (declare (ignore unused
))
4331 (let ((u (simpcheck (cadr form
) z
))
4332 (m (simpcheck (caddr form
) z
)))
4333 (cond ((or (complex-float-numerical-eval-p u m
)
4334 (complex-bigfloat-numerical-eval-p u m
))
4335 ($inverse_jacobi_cd
($rectform
(div 1 u
)) m
))
4338 ((and (eq $triginverses
'$all
)
4340 (eq (caar u
) '%jacobi_dc
)
4341 (alike1 (third u
) m
))
4342 ;; inverse_jacobi_dc(dc(u)) = u
4346 (eqtest (list '(%inverse_jacobi_dc
) u m
) form
)))))
4348 ;; Convert an inverse Jacobian function into the equivalent elliptic
4351 ;; See A&S 17.4.41-17.4.52.
4352 (defun make-elliptic-f (e)
4355 ((member (caar e
) '(%inverse_jacobi_sc %inverse_jacobi_cs
4356 %inverse_jacobi_nd %inverse_jacobi_dn
4357 %inverse_jacobi_sn %inverse_jacobi_cd
4358 %inverse_jacobi_dc %inverse_jacobi_ns
4359 %inverse_jacobi_nc %inverse_jacobi_ds
4360 %inverse_jacobi_sd %inverse_jacobi_cn
))
4361 ;; We have some inverse Jacobi function. Convert it to the F form.
4362 (destructuring-bind ((fn &rest ops
) u m
)
4364 (declare (ignore ops
))
4368 `(($elliptic_f
) ((%atan
) ,u
) ,m
))
4371 `(($elliptic_f
) ((%atan
) ((mexpt) ,u -
1)) ,m
))
4376 ((mexpt) ,m
((rat) -
1 2))
4378 ((mexpt) ((mplus) -
1 ((mexpt) ,u
2))
4385 ((mtimes) ((mexpt) ,m
((rat) -
1 2))
4386 ((mexpt) ((mplus) 1 ((mtimes) -
1 ((mexpt) ,u
2)))
4391 `(($elliptic_f
) ((%asin
) ,u
) ,m
))
4396 ((mexpt) ((mtimes) ((mplus) 1
4397 ((mtimes) -
1 ((mexpt) ,u
2)))
4399 ((mtimes) -
1 ,m
((mexpt) ,u
2)))
4408 ((mtimes) ((mplus) -
1 ((mexpt) ,u
2))
4409 ((mexpt) ((mplus) ((mtimes) -
1 ,m
) ((mexpt) ,u
2)) -
1))
4414 `(($elliptic_f
) ((%asin
) ((mexpt) ,u -
1)) ,m
))
4417 `(($elliptic_f
) ((%acos
) ((mexpt) ,u -
1)) ,m
))
4421 ((%asin
) ((mexpt) ((mplus) ,m
((mexpt) ,u
2))
4429 ((mexpt) ((mplus) 1 ((mtimes) ,m
((mexpt) ,u
2)))
4434 `(($elliptic_f
) ((%acos
) ,u
) ,m
)))))
4436 (recur-apply #'make-elliptic-f e
))))
4438 (defmfun $make_elliptic_f
(e)
4441 (simplify (make-elliptic-f e
))))
4443 (defun make-elliptic-e (e)
4445 ((eq (caar e
) '$elliptic_eu
)
4446 (destructuring-bind ((ffun &rest ops
) u m
) e
4447 (declare (ignore ffun ops
))
4448 `(($elliptic_e
) ((%asin
) ((%jacobi_sn
) ,u
,m
)) ,m
)))
4450 (recur-apply #'make-elliptic-e e
))))
4452 (defmfun $make_elliptic_e
(e)
4455 (simplify (make-elliptic-e e
))))
4458 ;; Eu(u,m) = integrate(jacobi_dn(v,m)^2,v,0,u)
4459 ;; = integrate(sqrt((1-m*t^2)/(1-t^2)),t,0,jacobi_sn(u,m))
4461 ;; Eu(u,m) = E(am(u),m)
4463 ;; where E(u,m) is elliptic-e above.
4466 ;; Lawden gives the following relationships
4468 ;; E(u+v) = E(u) + E(v) - m*sn(u)*sn(v)*sn(u+v)
4469 ;; E(u,0) = u, E(u,1) = tanh u
4471 ;; E(i*u,k) = i*sc(u,k')*dn(u,k') - i*E(u,k') + i*u
4473 ;; E(2*i*K') = 2*i*(K'-E')
4475 ;; E(u + 2*i*K') = E(u) + 2*i*(K' - E')
4477 ;; E(u+K) = E(u) + E - k^2*sn(u)*cd(u)
4478 (defun elliptic-eu (u m
)
4480 ;; E(u + 2*n*K) = E(u) + 2*n*E
4481 (let ((ell-k (to (elliptic-k m
)))
4482 (ell-e (elliptic-ec m
)))
4483 (multiple-value-bind (n u-rem
)
4484 (floor u
(* 2 ell-k
))
4487 (cond ((>= u-rem ell-k
)
4488 ;; 0 <= u-rem < K so
4489 ;; E(u + K) = E(u) + E - m*sn(u)*cd(u)
4490 (let ((u-k (- u ell-k
)))
4491 (- (+ (elliptic-e (cl:asin
(bigfloat::sn u-k m
)) m
)
4493 (/ (* m
(bigfloat::sn u-k m
) (bigfloat::cn u-k m
))
4494 (bigfloat::dn u-k m
)))))
4496 (elliptic-e (cl:asin
(bigfloat::sn u m
)) m
)))))))
4500 ;; E(u+i*v, m) = E(u,m) -i*E(v,m') + i*v + i*sc(v,m')*dn(v,m')
4501 ;; -i*m*sn(u,m)*sc(v,m')*sn(u+i*v,m)
4503 (let ((u-r (realpart u
))
4506 (+ (elliptic-eu u-r m
)
4509 (/ (* (bigfloat::sn u-i m1
) (bigfloat::dn u-i m1
))
4510 (bigfloat::cn u-i m1
)))
4511 (+ (elliptic-eu u-i m1
)
4512 (/ (* m
(bigfloat::sn u-r m
) (bigfloat::sn u-i m1
) (bigfloat::sn u m
))
4513 (bigfloat::cn u-i m1
))))))))))
4515 (defprop $elliptic_eu simp-$elliptic_eu operators
)
4516 (defprop $elliptic_eu
4518 ((mexpt) ((%jacobi_dn
) u m
) 2)
4523 (defun simp-$elliptic_eu
(form unused z
)
4524 (declare (ignore unused
))
4526 (let ((u (simpcheck (cadr form
) z
))
4527 (m (simpcheck (caddr form
) z
)))
4529 ;; as it stands, ELLIPTIC-EU can't handle bigfloats or complex bigfloats,
4530 ;; so handle only floats and complex floats here.
4531 ((float-numerical-eval-p u m
)
4532 (elliptic-eu ($float u
) ($float m
)))
4533 ((complex-float-numerical-eval-p u m
)
4534 (let ((u-r ($realpart u
))
4537 (complexify (elliptic-eu (complex u-r u-i
) m
))))
4539 (eqtest `(($elliptic_eu
) ,u
,m
) form
)))))
4541 (defmfun $elliptic_eu
(u m
)
4542 (simplify `(($elliptic_eu
) ,(resimplify u
) ,(resimplify m
))))
4544 (defprop %jacobi_am simp-%jacobi_am operators
)
4546 (defmfun $jacobi_am
(u m
)
4547 (simplify `((%jacobi_am
) ,(resimplify u
) ,(resimplify m
))))
4549 (defun simp-%jacobi_am
(form unused z
)
4550 (declare (ignore unused
))
4552 (let ((u (simpcheck (cadr form
) z
))
4553 (m (simpcheck (caddr form
) z
)))
4555 ;; as it stands, BIGFLOAT::SN can't handle bigfloats or complex bigfloats,
4556 ;; so handle only floats and complex floats here.
4557 ((float-numerical-eval-p u m
)
4558 (cl:asin
(bigfloat::sn
($float u
) ($float m
))))
4559 ((complex-float-numerical-eval-p u m
)
4560 (let ((u-r ($realpart
($float u
)))
4561 (u-i ($imagpart
($float u
)))
4563 (complexify (cl:asin
(bigfloat::sn
(complex u-r u-i
) m
)))))
4566 (eqtest (list '(%jacobi_am
) u m
) form
)))))
4568 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4569 ;; Integrals. At present with respect to first argument only.
4570 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4572 ;; A&S 16.24.1: integrate(jacobi_sn(u,m),u)
4573 ;; = log(jacobi_dn(u,m)-sqrt(m)*jacobi_cn(u,m))/sqrt(m)
4576 ((mtimes simp
) ((mexpt simp
) m
((rat simp
) -
1 2))
4579 ((mtimes simp
) -
1 ((mexpt simp
) m
((rat simp
) 1 2))
4580 ((%jacobi_cn simp
) u m
))
4581 ((%jacobi_dn simp
) u m
))))
4585 ;; A&S 16.24.2: integrate(jacobi_cn(u,m),u) = acos(jacobi_dn(u,m))/sqrt(m)
4588 ((mtimes simp
) ((mexpt simp
) m
((rat simp
) -
1 2))
4589 ((%acos simp
) ((%jacobi_dn simp
) u m
)))
4593 ;; A&S 16.24.3: integrate(jacobi_dn(u,m),u) = asin(jacobi_sn(u,m))
4596 ((%asin simp
) ((%jacobi_sn simp
) u m
))
4600 ;; A&S 16.24.4: integrate(jacobi_cd(u,m),u)
4601 ;; = log(jacobi_nd(u,m)+sqrt(m)*jacobi_sd(u,m))/sqrt(m)
4604 ((mtimes simp
) ((mexpt simp
) m
((rat simp
) -
1 2))
4606 ((mplus simp
) ((%jacobi_nd simp
) u m
)
4607 ((mtimes simp
) ((mexpt simp
) m
((rat simp
) 1 2))
4608 ((%jacobi_sd simp
) u m
)))))
4612 ;; integrate(jacobi_sd(u,m),u)
4614 ;; A&S 16.24.5 gives
4615 ;; asin(-sqrt(m)*jacobi_cd(u,m))/sqrt(m*m_1), where m + m_1 = 1
4616 ;; but this does not pass some simple tests.
4618 ;; functions.wolfram.com 09.35.21.001.01 gives
4619 ;; -asin(sqrt(m)*jacobi_cd(u,m))*sqrt(1-m*jacobi_cd(u,m)^2)*jacobi_dn(u,m)/((1-m)*sqrt(m))
4620 ;; and this does pass.
4624 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
4625 ((mexpt simp
) m
((rat simp
) -
1 2))
4628 ((mtimes simp
) -
1 $m
((mexpt simp
) ((%jacobi_cd simp
) u m
) 2)))
4630 ((%jacobi_dn simp
) u m
)
4632 ((mtimes simp
) ((mexpt simp
) m
((rat simp
) 1 2))
4633 ((%jacobi_cd simp
) u m
))))
4637 ;; integrate(jacobi_nd(u,m),u)
4639 ;; A&S 16.24.6 gives
4640 ;; acos(jacobi_cd(u,m))/sqrt(m_1), where m + m_1 = 1
4641 ;; but this does not pass some simple tests.
4643 ;; functions.wolfram.com 09.32.21.0001.01 gives
4644 ;; sqrt(1-jacobi_cd(u,m)^2)*acos(jacobi_cd(u,m))/((1-m)*jacobi_sd(u,m))
4645 ;; and this does pass.
4648 ((mtimes simp
) ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
)) -
1)
4651 ((mtimes simp
) -
1 ((mexpt simp
) ((%jacobi_cd simp
) u m
) 2)))
4653 ((mexpt simp
) ((%jacobi_sd simp
) u m
) -
1)
4654 ((%acos simp
) ((%jacobi_cd simp
) u m
)))
4658 ;; A&S 16.24.7: integrate(jacobi_dc(u,m),u) = log(jacobi_nc(u,m)+jacobi_sc(u,m))
4661 ((%log simp
) ((mplus simp
) ((%jacobi_nc simp
) u m
) ((%jacobi_sc simp
) u m
)))
4665 ;; A&S 16.24.8: integrate(jacobi_nc(u,m),u)
4666 ;; = log(jacobi_dc(u,m)+sqrt(m_1)*jacobi_sc(u,m))/sqrt(m_1), where m + m_1 = 1
4670 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
4673 ((mplus simp
) ((%jacobi_dc simp
) u m
)
4675 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
4677 ((%jacobi_sc simp
) u m
)))))
4681 ;; A&S 16.24.9: integrate(jacobi_sc(u,m),u)
4682 ;; = log(jacobi_dc(u,m)+sqrt(m_1)*jacobi_nc(u,m))/sqrt(m_1), where m + m_1 = 1
4686 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
4689 ((mplus simp
) ((%jacobi_dc simp
) u m
)
4691 ((mexpt simp
) ((mplus simp
) 1 ((mtimes simp
) -
1 m
))
4693 ((%jacobi_nc simp
) u m
)))))
4697 ;; A&S 16.24.10: integrate(jacobi_ns(u,m),u)
4698 ;; = log(jacobi_ds(u,m)-jacobi_cs(u,m))
4702 ((mplus simp
) ((mtimes simp
) -
1 ((%jacobi_cs simp
) u m
))
4703 ((%jacobi_ds simp
) u m
)))
4707 ;; integrate(jacobi_ds(u,m),u)
4709 ;; A&S 16.24.11 gives
4710 ;; log(jacobi_ds(u,m)-jacobi_cs(u,m))
4711 ;; but this does not pass some simple tests.
4713 ;; functions.wolfram.com 09.30.21.0001.01 gives
4714 ;; log((1-jacobi_cn(u,m))/jacobi_sn(u,m))
4720 ((mplus simp
) 1 ((mtimes simp
) -
1 ((%jacobi_cn simp
) u m
)))
4721 ((mexpt simp
) ((%jacobi_sn simp
) u m
) -
1)))
4725 ;; A&S 16.24.12: integrate(jacobi_cs(u,m),u) = log(jacobi_ns(u,m)-jacobi_ds(u,m))
4729 ((mplus simp
) ((mtimes simp
) -
1 ((%jacobi_ds simp
) u m
))
4730 ((%jacobi_ns simp
) u m
)))
4734 ;; functions.wolfram.com 09.48.21.0001.01
4735 ;; integrate(inverse_jacobi_sn(u,m),u) =
4736 ;; inverse_jacobi_sn(u,m)*u
4737 ;; - log( jacobi_dn(inverse_jacobi_sn(u,m),m)
4738 ;; -sqrt(m)*jacobi_cn(inverse_jacobi_sn(u,m),m)) / sqrt(m)
4739 (defprop %inverse_jacobi_sn
4741 ((mplus simp
) ((mtimes simp
) u
((%inverse_jacobi_sn simp
) u m
))
4742 ((mtimes simp
) -
1 ((mexpt simp
) m
((rat simp
) -
1 2))
4745 ((mtimes simp
) -
1 ((mexpt simp
) m
((rat simp
) 1 2))
4746 ((%jacobi_cn simp
) ((%inverse_jacobi_sn simp
) u m
) m
))
4747 ((%jacobi_dn simp
) ((%inverse_jacobi_sn simp
) u m
) m
)))))
4751 ;; functions.wolfram.com 09.38.21.0001.01
4752 ;; integrate(inverse_jacobi_cn(u,m),u) =
4753 ;; u*inverse_jacobi_cn(u,m)
4754 ;; -%i*log(%i*jacobi_dn(inverse_jacobi_cn(u,m),m)/sqrt(m)
4755 ;; -jacobi_sn(inverse_jacobi_cn(u,m),m))
4757 (defprop %inverse_jacobi_cn
4759 ((mplus simp
) ((mtimes simp
) u
((%inverse_jacobi_cn simp
) u m
))
4760 ((mtimes simp
) -
1 $%i
((mexpt simp
) m
((rat simp
) -
1 2))
4763 ((mtimes simp
) $%i
((mexpt simp
) m
((rat simp
) -
1 2))
4764 ((%jacobi_dn simp
) ((%inverse_jacobi_cn simp
) u m
) m
))
4766 ((%jacobi_sn simp
) ((%inverse_jacobi_cn simp
) u m
) m
))))))
4770 ;; functions.wolfram.com 09.41.21.0001.01
4771 ;; integrate(inverse_jacobi_dn(u,m),u) =
4772 ;; u*inverse_jacobi_dn(u,m)
4773 ;; - %i*log(%i*jacobi_cn(inverse_jacobi_dn(u,m),m)
4774 ;; +jacobi_sn(inverse_jacobi_dn(u,m),m))
4775 (defprop %inverse_jacobi_dn
4777 ((mplus simp
) ((mtimes simp
) u
((%inverse_jacobi_dn simp
) u m
))
4778 ((mtimes simp
) -
1 $%i
4782 ((%jacobi_cn simp
) ((%inverse_jacobi_dn simp
) u m
) m
))
4783 ((%jacobi_sn simp
) ((%inverse_jacobi_dn simp
) u m
) m
)))))
4788 ;; Real and imaginary part for Jacobi elliptic functions.
4789 (defprop %jacobi_sn risplit-sn-cn-dn risplit-function
)
4790 (defprop %jacobi_cn risplit-sn-cn-dn risplit-function
)
4791 (defprop %jacobi_dn risplit-sn-cn-dn risplit-function
)
4793 (defun risplit-sn-cn-dn (expr)
4794 (let* ((arg (second expr
))
4795 (param (third expr
)))
4796 ;; We only split on the argument, not the order
4797 (destructuring-bind (arg-r . arg-i
)
4801 (cons (take (first expr
) arg-r param
)
4804 (let* ((s (take '(%jacobi_sn
) arg-r param
))
4805 (c (take '(%jacobi_cn
) arg-r param
))
4806 (d (take '(%jacobi_dn
) arg-r param
))
4807 (s1 (take '(%jacobi_sn
) arg-i
(sub 1 param
)))
4808 (c1 (take '(%jacobi_cn
) arg-i
(sub 1 param
)))
4809 (d1 (take '(%jacobi_dn
) arg-i
(sub 1 param
)))
4810 (den (add (mul c1 c1
)
4814 ;; Let s = jacobi_sn(x,m)
4815 ;; c = jacobi_cn(x,m)
4816 ;; d = jacobi_dn(x,m)
4817 ;; s1 = jacobi_sn(y,1-m)
4818 ;; c1 = jacobi_cn(y,1-m)
4819 ;; d1 = jacobi_dn(y,1-m)
4823 ;; jacobi_sn(x+%i*y,m) =
4825 ;; s*d1 + %i*c*d*s1*c1
4826 ;; -------------------
4829 (cons (div (mul s d1
) den
)
4830 (div (mul c
(mul d
(mul s1 c1
)))
4837 ;; c*c1 - %i*s*d*s1*d1
4838 ;; -------------------
4840 (cons (div (mul c c1
) den
)
4842 (mul s
(mul d
(mul s1 d1
))))
4849 ;; d*c1*d1 - %i*m*s*c*s1
4850 ;; ---------------------
4852 (cons (div (mul d
(mul c1 d1
))
4854 (div (mul -
1 (mul param
(mul s
(mul c s1
))))