-
Notifications
You must be signed in to change notification settings - Fork 5
/
elliptic.js
131 lines (98 loc) · 3.5 KB
/
elliptic.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* The arithmetic-geometric mean of two non-negative numbers */
Math.agm = function(a0,g0)
{
var maxIter = 50;
var an = (a0+g0)/2;
var gn = Math.sqrt(a0*g0);
for (var iter = 0; (iter < maxIter) && (Math.abs(an-gn) > 1e-15); iter++)
{
a0 = 0.5 * (an + gn);
g0 = Math.sqrt(an*gn);
an = a0;
gn = g0;
};
if (iter == maxIter)
console.warn("Math.agm hit iteration limit of " + maxIter + ", probably didn't converge.");
return an;
};
/* EllipticK(m) - The complete elliptic integral of the first type.
* The argument is the *parameter* m = k^2, where k is the *modulus*.
* The parameter must satisfy m < 1.
* In terms of the integral definition, we have
* K(m) = \int_0^{\pi/2} \frac{d\theta}{\sqrt{1 - m (\sin\theta)^2}}
* See http://dlmf.nist.gov/19.8.E5 for this method.
*/
Math.EllipticK = function( m )
{
var kprime = Math.sqrt(1 - m);
return 0.5 * Math.PI / Math.agm(1, kprime);
};
/* EllipticE(m) - The complete elliptic integral of the second type.
* The argument is the *parameter* m = k^2, where k is the *modulus*.
* The parameter must satisfy m < 1.
* In terms of the integral definition, we have
* E(m) = \int_0^{\pi/2} \sqrt{1 - m (\sin\theta)^2} d\theta
* This algorithm comes from:
* http://scitation.aip.org/content/aip/journal/jap/34/9/10.1063/1.1729771
* Garrett, Milan Wayne. "Calculation of fields, forces, and mutual
* inductances of current systems by elliptic integrals." Journal of
* Applied Physics 34.9 (1963): 2567-2573.
* See Eqs. (18)-(21)
*/
Math.EllipticE = function( m )
{
var iter = 0, maxIter = 50;
var kprime = Math.sqrt(1. - m);
var a0 = 1., g0 = kprime;
var an = a0, gn = g0;
var twoPow = 0.25;
var partialSum = 1. - 0.5 * m;
do {
partialSum -= twoPow * (an - gn)*(an - gn);
twoPow *= 2.;
a0 = 0.5 * (an + gn);
g0 = Math.sqrt(an*gn);
an = a0;
gn = g0;
iter++;
} while ((Math.abs(an-gn) > 1e-15) && (iter < maxIter));
if (iter == maxIter)
console.warn("Math.EllipticE hit iteration limit of " + maxIter + ", probably didn't converge.");
return 0.5 * Math.PI * partialSum / an;
};
/* EllipticPi(n,m) - The complete elliptic integral of the third type.
* The arguments are the characteristic n,
* and the *parameter* m = k^2, where k is the *modulus*.
* The arguments must satisfy n < 1, m < 1.
* In terms of the integral definition, we have
* Pi(n,m) = \int_0^{\pi/2} \frac{1}{(1-n(\sin\theta)^2)\sqrt{1 - m (\sin\theta)^2}} d\theta
* This algorithm comes from:
* http://scitation.aip.org/content/aip/journal/jap/34/9/10.1063/1.1729771
* Garrett, Milan Wayne. "Calculation of fields, forces, and mutual
* inductances of current systems by elliptic integrals." Journal of
* Applied Physics 34.9 (1963): 2567-2573.
* See Eqs. (18)-(21)
*/
Math.EllipticPi = function( n, m )
{
var iter = 0, maxIter = 50;
var kprime = Math.sqrt(1. - m);
var a0 = 1., g0 = kprime, zeta0 = 0.;
var an = a0, gn = g0,
deltan = (1. - n)/kprime,
epsn = n/(1. - n), zetan = zeta0;
do {
zeta0 = 0.5 * (epsn + zetan);
epsn = (deltan*epsn + zetan)/(1. + deltan);
zetan = zeta0;
a0 = 0.5 * (an + gn);
g0 = Math.sqrt(an*gn);
an = a0;
gn = g0;
deltan = 0.25 * gn / an * (2. + deltan + 1./deltan);
iter++;
} while (((Math.abs(an-gn) > 1e-15) || (Math.abs(deltan - 1.) > 1e-15)) && (iter < maxIter));
if (iter == maxIter)
console.warn("Math.EllipticPi hit iteration limit of " + maxIter + ", probably didn't converge.");
return 0.5 * Math.PI / an * (1. + zetan);
};