1
+ package com .wildbitsfoundry .etk4j .math .specialfunctions ;
2
+
3
+ public final class Elliptic {
4
+
5
+ /**
6
+ * Complete Elliptic integral of the first kind ({@code K}).
7
+ * @param k The parameter of the elliptic integral. The absolute value of {@code K(k<sup>2</sup>} has to be less
8
+ * than 1.
9
+ * @return The complete elliptic integral of the first kind {@code K(k)}.
10
+ * @see <a href="https://www.codeproject.com/Articles/566614/Elliptic-integrals">Elliptic Integrals</a>
11
+ */
12
+ public static double completeEllipticIntegralFirstKind (double k ) {
13
+ double sum ;
14
+ double term ;
15
+ double above ;
16
+ double below ;
17
+ sum = 1 ;
18
+ term = 1 ;
19
+
20
+ above = 1 ;
21
+ below = 2 ;
22
+
23
+ for (int i = 1 ; i <= 100 ; i ++) {
24
+ term *= above / below ;
25
+ sum += Math .pow (k , i ) * Math .pow (term , 2 );
26
+ above += 2 ;
27
+ below += 2 ;
28
+ }
29
+ sum *= 0.5 * Math .PI ;
30
+ return sum ;
31
+ }
32
+
33
+ /**
34
+ * Complete Elliptic integral of the second kind ({@code E}).
35
+ * @param k The parameter of the elliptic integral. The absolute value of {@code E(k<sup>2</sup>} has to be less
36
+ * than 1.
37
+ * @return The complete elliptic integral of the second kind {@code E(k)}.
38
+ * @see <a href="https://www.codeproject.com/Articles/566614/Elliptic-integrals">Elliptic Integrals</a>
39
+ */
40
+ public static double completeEllipticIntegralSecondKind (double k ) {
41
+ double sum ;
42
+ double term ;
43
+ double above ;
44
+ double below ;
45
+ sum = 1 ;
46
+ term = 1 ;
47
+
48
+ above = 1 ;
49
+ below = 2 ;
50
+
51
+ for (int i = 1 ; i <= 100 ; i ++) {
52
+ term *= above / below ;
53
+ sum -= Math .pow (k , i ) * Math .pow (term , 2 ) / above ;
54
+ above += 2 ;
55
+ below += 2 ;
56
+ }
57
+ sum *= 0.5 * Math .PI ;
58
+ return sum ;
59
+ }
60
+
61
+ /**
62
+ * Incomplete Elliptic integral of the first kind ({@code K<sub>inc</sub>}).
63
+ * @param angle The angle in rad/s. The angle should be between {@code 0} and {@code π/2}
64
+ * @param k The parameter is taken as {@code k<sup>2</sup>}.
65
+ * @return The incomplete elliptic integral of the first kind {@code K<sub>inc</sub>(k)}.
66
+ * @see <a href="https://www.codeproject.com/Articles/566614/Elliptic-integrals">Elliptic Integrals</a>
67
+ */
68
+ public static double incompleteEllipticIntegralFirstKind (double angle , double k ) {
69
+ double result ;
70
+ result = Math .sin (angle ) * RF (Math .pow (Math .cos (angle ), 2 ), 1 - k * Math .pow (Math .sin (angle ), 2 ), 1 );
71
+ return result ;
72
+ }
73
+
74
+ /**
75
+ * Incomplete Elliptic integral of the second kind ({@code E<sub>inc</sub>}).
76
+ * @param angle The angle in rad/s. The angle should be between {@code 0} and {@code π/2}
77
+ * @param k The parameter is taken as {@code k<sup>2</sup>}.
78
+ * @return The incomplete elliptic integral of the first kind {@code E<sub>inc</sub>(k)}.
79
+ * @see <a href="https://www.codeproject.com/Articles/566614/Elliptic-integrals">Elliptic Integrals</a>
80
+ */
81
+ public static double incompleteEllipticIntegralSecondKind (double angle , double k ) {
82
+ double y = 1 - k * Math .pow (Math .sin (angle ), 2 );
83
+ return Math .sin (angle ) * RF (Math .pow (Math .cos (angle ), 2 ), y , 1 ) + (-1.0 / 3.0 ) * k * Math .pow (Math .sin (angle ),
84
+ (3.0 )) * RD (Math .pow (Math .cos (angle ), 2 ), y , 1 );
85
+ }
86
+
87
+ /**
88
+ * Carlson's Elliptic integral of the first kind
89
+ * @see <a href="http://en.wikipedia.org/wiki/Carlson_symmetric_form#Series_Expansion">Series Expansion</a>
90
+ */
91
+ private static double RF (double x , double y , double z ) {
92
+ double dx , dy , dz ;
93
+ double lambda ;
94
+ double n = 1.0 / 3.0 ;
95
+ double mean ;
96
+ double tmp ;
97
+ do {
98
+ lambda = Math .sqrt (x * y ) + Math .sqrt (y * z ) + Math .sqrt (z * x );
99
+ x = 0.25 * (x + lambda );
100
+ y = 0.25 * (y + lambda );
101
+ z = 0.25 * (z + lambda );
102
+ mean = (x + y + z ) * n ;
103
+ tmp = 1 / mean ;
104
+ dx = (mean - x ) * tmp ;
105
+ dy = (mean - y ) * tmp ;
106
+ dz = (mean - z ) * tmp ;
107
+ } while (Math .max (Math .max (Math .abs (dx ), Math .abs (dy )), Math .abs (dz )) > 1e-7 );
108
+ double e2 = dx * dy - dz * dz ;
109
+ double e3 = dx * dy * dz ;
110
+ double c1 = 1.0 / 24.0 ;
111
+ double c2 = 0.1 ;
112
+ double c3 = 3.0 / 44.0 ;
113
+ double c4 = 1.0 / 14.0 ;
114
+
115
+ double result = 1.0 + (c1 * e2 - c2 - c3 * e3 ) * e2 + c4 * e3 ;
116
+ return result / Math .sqrt (mean );
117
+ }
118
+
119
+ /**
120
+ * Carlson's Elliptic integral of the second kind
121
+ * @see <a href="http://en.wikipedia.org/wiki/Carlson_symmetric_form#Series_Expansion">Series Expansion</a>
122
+ */
123
+ private static double RD (double x , double y , double z ) {
124
+ double dx , dy , dz ;
125
+ double lambda ;
126
+ double mu ;
127
+ double muInv ;
128
+ double sum = 0.0 ;
129
+ double pow4 = 1.0 ;
130
+
131
+ do {
132
+ lambda = Math .sqrt (x * y ) + Math .sqrt (y * z ) + Math .sqrt (z * x );
133
+ sum += pow4 / (Math .sqrt (z ) * (z + lambda ));
134
+
135
+ pow4 *= 0.25 ;
136
+
137
+ x = 0.25 * (x + lambda );
138
+ y = 0.25 * (y + lambda );
139
+ z = 0.25 * (z + lambda );
140
+ mu = (x + y + 3.0 * z ) * 0.2 ;
141
+ muInv = 1.0 / mu ;
142
+
143
+ dx = 1 - x * muInv ;
144
+ dy = 1 - y * muInv ;
145
+ dz = 1 - z * muInv ;
146
+ } while (Math .max (Math .max (Math .abs (dx ), Math .abs (dy )), Math .abs (dz )) > 1e-7 );
147
+ double C1 = 3.0 / 14.0 ;
148
+ double C2 = 1.0 / 6.0 ;
149
+ double C3 = 9.0 / 22.0 ;
150
+ double C4 = 3.0 / 26.0 ;
151
+ double EA = dx * dy ;
152
+ double EB = dz * dz ;
153
+ double EC = EA - EB ;
154
+ double ED = EA - 6.0 * EB ;
155
+ double EF = ED + EC + EC ;
156
+ double S1 = ED * (-C1 + 0.25 * C3 * ED - 1.50 * C4 * dz * EF );
157
+ double S2 = dz * (C2 * EF + dz * (-C3 * EC + dz * C4 * EA ));
158
+
159
+ return 3.0 * sum + pow4 * (1.0 + S1 + S2 ) / (mu * Math .sqrt (mu ));
160
+ }
161
+ }
0 commit comments