View Javadoc
1   /*
2    * Licensed to the Hipparchus project under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.hipparchus.special.elliptic.carlson;
18  
19  import org.hipparchus.random.RandomGenerator;
20  import org.hipparchus.random.Well19937a;
21  import org.hipparchus.random.Well19937c;
22  import org.hipparchus.util.FastMath;
23  import org.junit.Assert;
24  import org.junit.Test;
25  
26  public class CarlsonEllipticIntegralRealTest {
27  
28      @Test
29      public void testNoConvergenceRf() {
30          Assert.assertTrue(Double.isNaN(CarlsonEllipticIntegral.rF(1, 2, Double.NaN)));
31      }
32  
33      @Test
34      public void testDlmfRf() {
35          double rf = CarlsonEllipticIntegral.rF(1, 2, 4);
36          Assert.assertEquals(0.6850858166, rf, 1.0e-10);
37      }
38  
39      @Test
40      public void testCarlson1995rF() {
41  
42          double rf1 = CarlsonEllipticIntegral.rF(1, 2, 0);
43          Assert.assertEquals( 1.3110287771461, rf1, 1.0e-13);
44  
45          double rf2 = CarlsonEllipticIntegral.rF(0.5, 1, 0);
46          Assert.assertEquals( 1.8540746773014, rf2, 1.0e-13);
47  
48          double rf4 = CarlsonEllipticIntegral.rF(2, 3, 4);
49          Assert.assertEquals( 0.58408284167715, rf4, 1.0e-13);
50  
51      }
52  
53      @Test
54      public void testCarlson1995ConsistencyRf() {
55          RandomGenerator random = new Well19937c(0x57f2689b3f4028b4l);
56          for (int i = 0; i < 10000; ++i) {
57              double x      = random.nextDouble() * 3;
58              double y      = random.nextDouble() * 3;
59              double lambda = random.nextDouble() * 3;
60              double mu     = x * y / lambda;
61              double rfL    = CarlsonEllipticIntegral.rF(x + lambda, y + lambda, lambda);
62              double rfM    = CarlsonEllipticIntegral.rF(x + mu,     y + mu,     mu);
63              double rf0    = CarlsonEllipticIntegral.rF(x,             y,             0);
64              Assert.assertEquals(0.0, FastMath.abs(rfL + rfM - rf0), 2.0e-14);
65          }
66      }
67  
68      @Test
69      public void testNoConvergenceRc() {
70          Assert.assertTrue(Double.isNaN(CarlsonEllipticIntegral.rC(1, Double.NaN)));
71      }
72  
73      @Test
74      public void testCarlson1995rC() {
75  
76          double rc1 = CarlsonEllipticIntegral.rC(0, 0.25);
77          Assert.assertEquals(FastMath.PI, rc1, 1.0e-15);
78  
79          double rc2 = CarlsonEllipticIntegral.rC(2.25, 2);
80          Assert.assertEquals(FastMath.log(2), rc2, 1.0e-15);
81  
82          double rc5 = CarlsonEllipticIntegral.rC(0.25, -2);
83          Assert.assertEquals(FastMath.log(2) / 3.0, rc5, 1.0e-15);
84  
85      }
86  
87      @Test
88      public void testCarlson1995ConsistencyRc() {
89          RandomGenerator random = new Well19937c(0xf1170b6fc1a199cal);
90          for (int i = 0; i < 10000; ++i) {
91              double x      = random.nextDouble() * 3;
92              double lambda = random.nextDouble() * 3;
93              double mu     = x * x / lambda;
94              double rcL    = CarlsonEllipticIntegral.rC(lambda,          x + lambda);
95              double rcM    = CarlsonEllipticIntegral.rC(mu,              x + mu);
96              double rc0    = CarlsonEllipticIntegral.rC(0, x);
97              Assert.assertEquals(0.0, FastMath.abs(rcL + rcM - rc0), 3.0e-14);
98          }
99      }
100 
101     @Test
102     public void testRfRc() {
103         RandomGenerator random = new Well19937a(0x7e8041334a8c20edl);
104         for (int i = 0; i < 10000; ++i) {
105             final double x = 3 * random.nextDouble();
106             final double y = 3 * random.nextDouble();
107             final double rf = CarlsonEllipticIntegral.rF(x, y, y);
108             final double rc = CarlsonEllipticIntegral.rC(x, y);
109             Assert.assertEquals(0.0, FastMath.abs(rf - rc), 4.0e-15);
110         }
111     }
112 
113     @Test
114     public void testNoConvergenceRj() {
115         Assert.assertTrue(Double.isNaN(CarlsonEllipticIntegral.rJ(1, 1, 1, Double.NaN)));
116     }
117 
118     @Test
119     public void testCarlson1995rJ() {
120 
121         double rj01 = CarlsonEllipticIntegral.rJ(0, 1, 2, 3);
122         Assert.assertEquals(0.77688623778582, rj01, 1.0e-13);
123 
124         double rj02 = CarlsonEllipticIntegral.rJ(2, 3, 4, 5);
125         Assert.assertEquals( 0.14297579667157, rj02, 1.0e-13);
126 
127     }
128 
129     @Test
130     public void testCarlson1995ConsistencyRj() {
131         RandomGenerator random = new Well19937c(0x4af7bb722712e64el);
132         for (int i = 0; i < 10000; ++i) {
133             double x      = random.nextDouble() * 3;
134             double y      = random.nextDouble() * 3;
135             double p      = random.nextDouble() * 3;
136             double lambda = random.nextDouble() * 3;
137             double mu     = x * y / lambda;
138             double a      = p * p * (lambda + mu + x + y);
139             double b      = p * (p + lambda) * (p + mu);
140             double rjL    = CarlsonEllipticIntegral.rJ(x + lambda, y + lambda, lambda,  p + lambda);
141             double rjM    = CarlsonEllipticIntegral.rJ(x + mu,     y + mu,     mu,      p + mu);
142             double rj0    = CarlsonEllipticIntegral.rJ(x,          y,          0,       p);
143             double rc     = CarlsonEllipticIntegral.rC(a, b);
144             Assert.assertEquals(0.0, FastMath.abs(rjL + rjM - (rj0 - rc * 3)), 3.0e-13);
145         }
146     }
147 
148     @Test
149     public void testNoConvergenceRd() {
150         Assert.assertTrue(Double.isNaN(CarlsonEllipticIntegral.rD(1, 1, Double.NaN)));
151     }
152 
153     @Test
154     public void testCarlson1995rD() {
155 
156         double rd1 = CarlsonEllipticIntegral.rD(0, 2, 1);
157         Assert.assertEquals(1.7972103521034, rd1, 1.0e-13);
158 
159         double rd2 = CarlsonEllipticIntegral.rD(2, 3, 4);
160         Assert.assertEquals( 0.16510527294261, rd2, 1.0e-13);
161 
162     }
163 
164     @Test
165     public void testCarlson1995ConsistencyRd() {
166         RandomGenerator random = new Well19937c(0x17dea97eeb78206al);
167         for (int i = 0; i < 10000; ++i) {
168             double x      = random.nextDouble() * 3;
169             double y      = random.nextDouble() * 3;
170             double lambda = random.nextDouble() * 3;
171             double mu     = x * y / lambda;
172             double rdL    = CarlsonEllipticIntegral.rD(lambda,          x + lambda, y + lambda);
173             double rdM    = CarlsonEllipticIntegral.rD(mu,              x + mu,     y + mu);
174             double rd0    = CarlsonEllipticIntegral.rD(0,               x,          y);
175             double frac   = 3 / (y * FastMath.sqrt(x + y + lambda + mu));
176             Assert.assertEquals(0.0, FastMath.abs(rdL + rdM - rd0 + frac), 9.0e-12);
177         }
178     }
179 
180     @Test
181     public void testRdNonSymmetry1() {
182         RandomGenerator random = new Well19937c(0x66db170b5ee1afc2l);
183         for (int i = 0; i < 10000; ++i) {
184             double x = random.nextDouble();
185             double y = random.nextDouble();
186             double z = random.nextDouble();
187             if (x == 0 || y == 0) {
188                 continue;
189             }
190             // this is DLMF equation 19.21.7
191             double lhs = (x - y) * CarlsonEllipticIntegral.rD(y, z, x) + (z - y) * CarlsonEllipticIntegral.rD(x, y, z);
192             double rhs = (CarlsonEllipticIntegral.rF(x, y, z) - FastMath.sqrt(y / (x * z))) * 3;
193             Assert.assertEquals(0.0, FastMath.abs(lhs - rhs), 1.0e-10);
194         }
195     }
196 
197     @Test
198     public void testRdNonSymmetry2() {
199         RandomGenerator random = new Well19937c(0x1a8994acc807438dl);
200         for (int i = 0; i < 10000; ++i) {
201             double x = random.nextDouble();
202             double y = random.nextDouble();
203             double z = random.nextDouble();
204             if (x == 0 || y == 0 || z == 0) {
205                 continue;
206             }
207             // this is DLMF equation 19.21.8
208             double lhs = CarlsonEllipticIntegral.rD(y, z, x) + CarlsonEllipticIntegral.rD(z, x, y) + CarlsonEllipticIntegral.rD(x, y, z);
209             double rhs = 3 / FastMath.sqrt(x * y * z);
210             Assert.assertEquals(0.0, FastMath.abs(lhs - rhs), 2.0e-11);
211         }
212     }
213 
214     @Test
215     public void testCarlson1995rG() {
216 
217         double rg1 = CarlsonEllipticIntegral.rG(0, 16, 16);
218         Assert.assertEquals(FastMath.PI, rg1, 1.0e-13);
219 
220         double rg2 = CarlsonEllipticIntegral.rG(2, 3, 4);
221         Assert.assertEquals(1.7255030280692, rg2, 1.0e-13);
222 
223         double rg6 = CarlsonEllipticIntegral.rG(0, 0.0796, 4);
224         Assert.assertEquals( 1.0284758090288, rg6, 1.0e-13);
225 
226     }
227 
228     @Test
229     public void testAlternateRG() {
230         RandomGenerator random = new Well19937c(0xa2946e4a55d133a6l);
231         for (int i = 0; i < 10000; ++i) {
232             double x = random.nextDouble() * 3;
233             double y = random.nextDouble() * 3;
234             double z = random.nextDouble() * 3;
235             Assert.assertEquals(0.0, FastMath.abs(CarlsonEllipticIntegral.rG(x, y, z) - rgAlternateImplementation(x, y, z)), 2.0e-15);
236         }
237     }
238 
239     private double rgAlternateImplementation(final double x, final double y, final double z) {
240         // this implementation uses DLFM equation 19.21.11
241         return (d(x, y, z) + d(y, z, x) + d(z, x, y)) / 6;
242     }
243 
244     private double d(final double u, final double v, final double w) {
245         return u == 0 ? u : u * (v + w) * (new RdRealDuplication(v, w, u).integral());
246     }
247 
248 }