1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.hipparchus.special;
19
20 import org.hipparchus.Field;
21 import org.hipparchus.UnitTestUtils;
22 import org.hipparchus.util.Binary64;
23 import org.hipparchus.util.Binary64Field;
24 import org.hipparchus.util.FastMath;
25 import org.junit.Assert;
26 import org.junit.Test;
27
28
29
30 public class ErfTest {
31 final Field<Binary64> field = Binary64Field.getInstance();
32 final Binary64 zero = field.getZero();
33 final Binary64 one = field.getOne();
34
35 @Test
36 public void testErf0() {
37 double actual = Erf.erf(0.0);
38 double expected = 0.0;
39 Assert.assertEquals(expected, actual, 1.0e-15);
40 Assert.assertEquals(1 - expected, Erf.erfc(0.0), 1.0e-15);
41 }
42
43 @Test
44 public void testErf0Field() {
45 Binary64 actual = Erf.erf(zero);
46 Binary64 expected = zero;
47 Assert.assertEquals(zero.getReal(), actual.getReal(), 1.0e-15);
48 Assert.assertEquals(one.subtract(expected).getReal(), Erf.erfc(zero).getReal(), 1.0e-15);
49 }
50
51 @Test
52 public void testErf1960() {
53 double x = 1.960 / FastMath.sqrt(2.0);
54 double actual = Erf.erf(x);
55 double expected = 0.95;
56 Assert.assertEquals(expected, actual, 1.0e-5);
57 Assert.assertEquals(1 - actual, Erf.erfc(x), 1.0e-15);
58
59 actual = Erf.erf(-x);
60 expected = -expected;
61 Assert.assertEquals(expected, actual, 1.0e-5);
62 Assert.assertEquals(1 - actual, Erf.erfc(-x), 1.0e-15);
63 }
64
65 @Test
66 public void testErf1960Field() {
67 Binary64 x = one.multiply(1.960).divide(FastMath.sqrt(2.0));
68 Binary64 actual = Erf.erf(x);
69 Binary64 expected = one.multiply(0.95);
70 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
71 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x).getReal(), 1.0e-15);
72
73 actual = Erf.erf(x.negate());
74 expected = expected.negate();
75 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
76 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x.negate()).getReal(), 1.0e-15);
77 }
78
79 @Test
80 public void testErf2576() {
81 double x = 2.576 / FastMath.sqrt(2.0);
82 double actual = Erf.erf(x);
83 double expected = 0.99;
84 Assert.assertEquals(expected, actual, 1.0e-5);
85 Assert.assertEquals(1 - actual, Erf.erfc(x), 1e-15);
86
87 actual = Erf.erf(-x);
88 expected = -expected;
89 Assert.assertEquals(expected, actual, 1.0e-5);
90 Assert.assertEquals(1 - actual, Erf.erfc(-x), 1.0e-15);
91 }
92
93 @Test
94 public void testErf2576Field() {
95 Binary64 x = one.multiply(2.576).divide(FastMath.sqrt(2.0));
96 Binary64 actual = Erf.erf(x);
97 Binary64 expected = one.multiply(0.99);
98 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
99 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x).getReal(), 1.0e-15);
100
101 actual = Erf.erf(x.negate());
102 expected = expected.negate();
103 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
104 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x.negate()).getReal(), 1.0e-15);
105 }
106
107 @Test
108 public void testErf2807() {
109 double x = 2.807 / FastMath.sqrt(2.0);
110 double actual = Erf.erf(x);
111 double expected = 0.995;
112 Assert.assertEquals(expected, actual, 1.0e-5);
113 Assert.assertEquals(1 - actual, Erf.erfc(x), 1.0e-15);
114
115 actual = Erf.erf(-x);
116 expected = -expected;
117 Assert.assertEquals(expected, actual, 1.0e-5);
118 Assert.assertEquals(1 - actual, Erf.erfc(-x), 1.0e-15);
119 }
120
121 @Test
122 public void testErf2807Field() {
123 Binary64 x = one.multiply(2.807).divide(FastMath.sqrt(2.0));
124 Binary64 actual = Erf.erf(x);
125 Binary64 expected = one.multiply(0.995);
126 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
127 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x).getReal(), 1.0e-15);
128
129 actual = Erf.erf(x.negate());
130 expected = expected.negate();
131 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
132 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x.negate()).getReal(), 1.0e-15);
133 }
134
135 @Test
136 public void testErf3291() {
137 double x = 3.291 / FastMath.sqrt(2.0);
138 double actual = Erf.erf(x);
139 double expected = 0.999;
140 Assert.assertEquals(expected, actual, 1.0e-5);
141 Assert.assertEquals(1 - expected, Erf.erfc(x), 1.0e-5);
142
143 actual = Erf.erf(-x);
144 expected = -expected;
145 Assert.assertEquals(expected, actual, 1.0e-5);
146 Assert.assertEquals(1 - expected, Erf.erfc(-x), 1.0e-5);
147 }
148
149 @Test
150 public void testErf3291Field() {
151 Binary64 x = one.multiply(3.291).divide(FastMath.sqrt(2.0));
152 Binary64 actual = Erf.erf(x);
153 Binary64 expected = one.multiply(0.999);
154 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
155 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x).getReal(), 1.0e-15);
156
157 actual = Erf.erf(x.negate());
158 expected = expected.negate();
159 Assert.assertEquals(expected.getReal(), actual.getReal(), 1.0e-5);
160 Assert.assertEquals(one.subtract(actual).getReal(), Erf.erfc(x.negate()).getReal(), 1.0e-15);
161 }
162
163
164
165
166 @Test
167 public void testLargeValues() {
168 for (int i = 1; i < 200; i*=10) {
169 double result = Erf.erf(i);
170 Assert.assertFalse(Double.isNaN(result));
171 Assert.assertTrue(result > 0 && result <= 1);
172 result = Erf.erf(-i);
173 Assert.assertFalse(Double.isNaN(result));
174 Assert.assertTrue(result >= -1 && result < 0);
175 result = Erf.erfc(i);
176 Assert.assertFalse(Double.isNaN(result));
177 Assert.assertTrue(result >= 0 && result < 1);
178 result = Erf.erfc(-i);
179 Assert.assertFalse(Double.isNaN(result));
180 Assert.assertTrue(result >= 1 && result <= 2);
181 }
182 Assert.assertEquals(-1, Erf.erf(Double.NEGATIVE_INFINITY), 0);
183 Assert.assertEquals(1, Erf.erf(Double.POSITIVE_INFINITY), 0);
184 Assert.assertEquals(2, Erf.erfc(Double.NEGATIVE_INFINITY), 0);
185 Assert.assertEquals(0, Erf.erfc(Double.POSITIVE_INFINITY), 0);
186 }
187
188
189
190
191 @Test
192 public void testLargeValuesField() {
193 for (int i = 1; i < 200; i*=10) {
194 final Binary64 iField = new Binary64(i);
195 Binary64 result = Erf.erf(iField);
196 Assert.assertFalse(result.isNaN());
197 Assert.assertTrue(result.getReal() > 0 && result.getReal() <= 1);
198 result = Erf.erf(iField.negate());
199 Assert.assertFalse(result.isNaN());
200 Assert.assertTrue(result.getReal() >= -1 && result.getReal() < 0);
201 result = Erf.erfc(iField);
202 Assert.assertFalse(result.isNaN());
203 Assert.assertTrue(result.getReal() >= 0 && result.getReal() < 1);
204 result = Erf.erfc(iField.negate());
205 Assert.assertFalse(result.isNaN());
206 Assert.assertTrue(result.getReal() >= 1 && result.getReal() <= 2);
207 }
208 Assert.assertEquals(one.negate().getReal(), Erf.erf(new Binary64(Double.NEGATIVE_INFINITY)).getReal(), 0);
209 Assert.assertEquals(one.getReal(), Erf.erf(new Binary64(Double.POSITIVE_INFINITY)).getReal(), 0);
210 Assert.assertEquals(one.multiply(2).getReal(), new Binary64(Erf.erfc(Double.NEGATIVE_INFINITY)).getReal(), 0);
211 Assert.assertEquals(zero.getReal(), Erf.erfc(new Binary64(Double.POSITIVE_INFINITY)).getReal(), 0);
212 }
213
214
215
216
217
218 @Test
219 public void testErfGnu() {
220 final double tol = 1E-15;
221 final double[] gnuValues = new double[] {-1, -1, -1, -1, -1,
222 -1, -1, -1, -0.99999999999999997848,
223 -0.99999999999999264217, -0.99999999999846254017, -0.99999999980338395581, -0.99999998458274209971,
224 -0.9999992569016276586, -0.99997790950300141459, -0.99959304798255504108, -0.99532226501895273415,
225 -0.96610514647531072711, -0.84270079294971486948, -0.52049987781304653809, 0,
226 0.52049987781304653809, 0.84270079294971486948, 0.96610514647531072711, 0.99532226501895273415,
227 0.99959304798255504108, 0.99997790950300141459, 0.9999992569016276586, 0.99999998458274209971,
228 0.99999999980338395581, 0.99999999999846254017, 0.99999999999999264217, 0.99999999999999997848,
229 1, 1, 1, 1,
230 1, 1, 1, 1};
231 double x = -10d;
232 for (int i = 0; i < 41; i++) {
233 Assert.assertEquals(gnuValues[i], Erf.erf(x), tol);
234 x += 0.5d;
235 }
236 }
237
238
239
240
241
242 @Test
243 public void testErfGnuField() {
244 final double tol = 1E-15;
245 final Binary64[] gnuValues = new Binary64[] {one.negate(), one.negate(), one.negate(), one.negate(), one.negate(),
246 one.negate(), one.negate(), one.negate(), new Binary64(-0.99999999999999997848),
247 new Binary64(-0.99999999999999264217), new Binary64(-0.99999999999846254017), new Binary64(-0.99999999980338395581), new Binary64(-0.99999998458274209971),
248 new Binary64(-0.9999992569016276586), new Binary64(-0.99997790950300141459), new Binary64(-0.99959304798255504108), new Binary64(-0.99532226501895273415),
249 new Binary64(-0.96610514647531072711), new Binary64(-0.84270079294971486948), new Binary64(-0.52049987781304653809), zero,
250 new Binary64(0.52049987781304653809), new Binary64(0.84270079294971486948), new Binary64(0.96610514647531072711), new Binary64(0.99532226501895273415),
251 new Binary64(0.99959304798255504108), new Binary64(0.99997790950300141459), new Binary64(0.9999992569016276586), new Binary64(0.99999998458274209971),
252 new Binary64(0.99999999980338395581), new Binary64(0.99999999999846254017), new Binary64(0.99999999999999264217), new Binary64(0.99999999999999997848),
253 one, one, one, one,
254 one, one, one, one};
255 Binary64 x = one.multiply(-10d);
256 for (int i = 0; i < 41; i++) {
257 Assert.assertEquals(gnuValues[i].getReal(), Erf.erf(x).getReal(), tol);
258 x = x.add(0.5d);
259 }
260 }
261
262
263
264
265
266 @Test
267 public void testErfcGnu() {
268 final double tol = 1E-15;
269 final double[] gnuValues = new double[] { 2, 2, 2, 2, 2,
270 2, 2, 2, 1.9999999999999999785,
271 1.9999999999999926422, 1.9999999999984625402, 1.9999999998033839558, 1.9999999845827420998,
272 1.9999992569016276586, 1.9999779095030014146, 1.9995930479825550411, 1.9953222650189527342,
273 1.9661051464753107271, 1.8427007929497148695, 1.5204998778130465381, 1,
274 0.47950012218695346194, 0.15729920705028513051, 0.033894853524689272893, 0.0046777349810472658333,
275 0.00040695201744495893941, 2.2090496998585441366E-05, 7.4309837234141274516E-07, 1.5417257900280018858E-08,
276 1.966160441542887477E-10, 1.5374597944280348501E-12, 7.3578479179743980661E-15, 2.1519736712498913103E-17,
277 3.8421483271206474691E-20, 4.1838256077794144006E-23, 2.7766493860305691016E-26, 1.1224297172982927079E-29,
278 2.7623240713337714448E-33, 4.1370317465138102353E-37, 3.7692144856548799402E-41, 2.0884875837625447567E-45};
279 double x = -10d;
280 for (int i = 0; i < 41; i++) {
281 Assert.assertEquals(gnuValues[i], Erf.erfc(x), tol);
282 x += 0.5d;
283 }
284 }
285
286
287
288
289
290 @Test
291 public void testErfcGnuField() {
292 final double tol = 1E-15;
293 final Binary64[] gnuValues = new Binary64[] { new Binary64(2), new Binary64(2), new Binary64(2), new Binary64(2), new Binary64(2),
294 new Binary64(2), new Binary64(2), new Binary64(2), new Binary64(1.9999999999999999785),
295 new Binary64(1.9999999999999926422), new Binary64(1.9999999999984625402), new Binary64(1.9999999998033839558), new Binary64(1.9999999845827420998),
296 new Binary64(1.9999992569016276586), new Binary64(1.9999779095030014146), new Binary64(1.9995930479825550411), new Binary64(1.9953222650189527342),
297 new Binary64(1.9661051464753107271), new Binary64(1.8427007929497148695), new Binary64(1.5204998778130465381), one,
298 new Binary64(0.47950012218695346194), new Binary64(0.15729920705028513051), new Binary64(0.033894853524689272893), new Binary64(0.0046777349810472658333),
299 new Binary64(0.00040695201744495893941), new Binary64(2.2090496998585441366E-05), new Binary64(7.4309837234141274516E-07), new Binary64(1.5417257900280018858E-08),
300 new Binary64(1.966160441542887477E-10), new Binary64(1.5374597944280348501E-12), new Binary64(7.3578479179743980661E-15), new Binary64(2.1519736712498913103E-17),
301 new Binary64(3.8421483271206474691E-20), new Binary64(4.1838256077794144006E-23), new Binary64(2.7766493860305691016E-26), new Binary64(1.1224297172982927079E-29),
302 new Binary64(2.7623240713337714448E-33), new Binary64(4.1370317465138102353E-37), new Binary64(3.7692144856548799402E-41),new Binary64( 2.0884875837625447567E-45)};
303 Binary64 x = new Binary64(-10d);
304 for (int i = 0; i < 41; i++) {
305 Assert.assertEquals(gnuValues[i].getReal(), Erf.erfc(x).getReal(), tol);
306 x = x.add(0.5d);
307 }
308 }
309
310
311
312
313
314
315 @Test
316 public void testErfcMaple() {
317 double[][] ref = new double[][]
318 {{0.1, 4.60172162722971e-01},
319 {1.2, 1.15069670221708e-01},
320 {2.3, 1.07241100216758e-02},
321 {3.4, 3.36929265676881e-04},
322 {4.5, 3.39767312473006e-06},
323 {5.6, 1.07175902583109e-08},
324 {6.7, 1.04209769879652e-11},
325 {7.8, 3.09535877195870e-15},
326 {8.9, 2.79233437493966e-19},
327 {10.0, 7.61985302416053e-24},
328 {11.1, 6.27219439321703e-29},
329 {12.2, 1.55411978638959e-34},
330 {13.3, 1.15734162836904e-40},
331 {14.4, 2.58717592540226e-47},
332 {15.5, 1.73446079179387e-54},
333 {16.6, 3.48454651995041e-62}
334 };
335 for (int i = 0; i < 15; i++) {
336 final double result = 0.5*Erf.erfc(ref[i][0]/FastMath.sqrt(2));
337 Assert.assertEquals(ref[i][1], result, 1E-15);
338 UnitTestUtils.assertRelativelyEquals(ref[i][1], result, 1E-13);
339 }
340 }
341
342
343
344
345
346
347 @Test
348 public void testErfcMapleField() {
349 Binary64[][] ref = new Binary64[][]
350 {{new Binary64(0.1), new Binary64(4.60172162722971e-01)},
351 {new Binary64(1.2), new Binary64(1.15069670221708e-01)},
352 {new Binary64(2.3), new Binary64(1.07241100216758e-02)},
353 {new Binary64(3.4), new Binary64(3.36929265676881e-04)},
354 {new Binary64(4.5), new Binary64(3.39767312473006e-06)},
355 {new Binary64(5.6), new Binary64(1.07175902583109e-08)},
356 {new Binary64(6.7), new Binary64(1.04209769879652e-11)},
357 {new Binary64(7.8), new Binary64(3.09535877195870e-15)},
358 {new Binary64(8.9), new Binary64(2.79233437493966e-19)},
359 {new Binary64(10.0), new Binary64(7.61985302416053e-24)},
360 {new Binary64(11.1), new Binary64(6.27219439321703e-29)},
361 {new Binary64(12.2), new Binary64(1.55411978638959e-34)},
362 {new Binary64(13.3), new Binary64(1.15734162836904e-40)},
363 {new Binary64(14.4), new Binary64(2.58717592540226e-47)},
364 {new Binary64(15.5), new Binary64(1.73446079179387e-54)},
365 {new Binary64(16.6), new Binary64(3.48454651995041e-62)}
366 };
367 for (int i = 0; i < 15; i++) {
368 final Binary64 result = Erf.erfc(ref[i][0].divide(FastMath.sqrt(2))).multiply(0.5);
369 Assert.assertEquals(ref[i][1].getReal(), result.getReal(), 1E-15);
370 UnitTestUtils.assertRelativelyEquals(ref[i][1].getReal(), result.getReal(), 1E-13);
371 }
372 }
373
374
375
376
377
378 @Test
379 public void testTwoArgumentErf() {
380 double[] xi = new double[]{-2.0, -1.0, -0.9, -0.1, 0.0, 0.1, 0.9, 1.0, 2.0};
381 for(double x1 : xi) {
382 for(double x2 : xi) {
383 double a = Erf.erf(x1, x2);
384 double b = Erf.erf(x2) - Erf.erf(x1);
385 double c = Erf.erfc(x1) - Erf.erfc(x2);
386 Assert.assertEquals(a, b, 1E-15);
387 Assert.assertEquals(a, c, 1E-15);
388 }
389 }
390 }
391
392
393
394
395
396 @Test
397 public void testTwoArgumentErfField() {
398 Binary64[] xi = new Binary64[]{new Binary64(-2.0), new Binary64(-1.0), new Binary64(-0.9), new Binary64(-0.1), new Binary64(0.0), new Binary64(0.1), new Binary64(0.9), new Binary64(1.0), new Binary64(2.0)};
399 for(Binary64 x1 : xi) {
400 for(Binary64 x2 : xi) {
401 Binary64 a = Erf.erf(x1, x2);
402 Binary64 b = Erf.erf(x2).subtract(Erf.erf(x1));
403 Binary64 c = Erf.erfc(x1).subtract(Erf.erfc(x2));
404 Assert.assertEquals(a.getReal(), b.getReal(), 1E-15);
405 Assert.assertEquals(a.getReal(), c.getReal(), 1E-15);
406 }
407 }
408 }
409
410 @Test
411 public void testErfInvNaN() {
412 Assert.assertTrue(Double.isNaN(Erf.erfInv(-1.001)));
413 Assert.assertTrue(Double.isNaN(Erf.erfInv(+1.001)));
414 }
415
416 @Test
417 public void testErfInvNaNField() {
418 Assert.assertTrue((Erf.erfInv(new Binary64(-1.001))).isNaN());
419 Assert.assertTrue(Erf.erfInv(new Binary64(+1.001)).isNaN());
420 }
421
422 @Test
423 public void testErfInvInfinite() {
424 Assert.assertTrue(Double.isInfinite(Erf.erfInv(-1)));
425 Assert.assertTrue(Erf.erfInv(-1) < 0);
426 Assert.assertTrue(Double.isInfinite(Erf.erfInv(+1)));
427 Assert.assertTrue(Erf.erfInv(+1) > 0);
428 }
429
430 @Test
431 public void testErfInvInfiniteField() {
432 Assert.assertTrue(Double.isInfinite(Erf.erfInv(-1)));
433 Assert.assertTrue(Erf.erfInv(-1) < 0);
434 Assert.assertTrue(Double.isInfinite(Erf.erfInv(+1)));
435 Assert.assertTrue(Erf.erfInv(+1) > 0);
436 }
437
438 @Test
439 public void testErfInv() {
440 for (double x = -5.9; x < 5.9; x += 0.01) {
441 final double y = Erf.erf(x);
442 final double dydx = 2 * FastMath.exp(-x * x) / FastMath.sqrt(FastMath.PI);
443 Assert.assertEquals(x, Erf.erfInv(y), 1.0e-15 / dydx);
444 }
445 }
446
447 @Test
448 public void testErfInvField() {
449 for (Binary64 x = new Binary64(-5.9); x.getReal() < 5.9; x = x.add(0.01)) {
450 final Binary64 y = Erf.erf(x);
451 final Binary64 dydx = x.square().negate().exp().multiply(2/FastMath.sqrt(FastMath.PI));
452 Assert.assertEquals(x.getReal(), Erf.erfInv(y).getReal(), 1.0e-15 / dydx.getReal());
453 }
454 }
455
456 @Test
457 public void testErfcInvNaN() {
458 Assert.assertTrue(Double.isNaN(Erf.erfcInv(-0.001)));
459 Assert.assertTrue(Double.isNaN(Erf.erfcInv(+2.001)));
460 }
461
462 @Test
463 public void testErfcInvNaNField() {
464 Assert.assertTrue(Erf.erfcInv(new Binary64(-0.001)).isNaN());
465 Assert.assertTrue(Erf.erfcInv(new Binary64(+2.001)).isNaN());
466 }
467
468 @Test
469 public void testErfcInvInfinite() {
470 Assert.assertTrue(Double.isInfinite(Erf.erfcInv(-0)));
471 Assert.assertTrue(Erf.erfcInv( 0) > 0);
472 Assert.assertTrue(Double.isInfinite(Erf.erfcInv(+2)));
473 Assert.assertTrue(Erf.erfcInv(+2) < 0);
474 }
475
476 @Test
477 public void testErfcInvInfiniteField() {
478 Assert.assertTrue(Erf.erfcInv(new Binary64(-0)).isInfinite());
479 Assert.assertTrue(Erf.erfcInv( zero).getReal() > 0);
480 Assert.assertTrue(Erf.erfcInv(new Binary64(+2)).isInfinite());
481 Assert.assertTrue(Erf.erfcInv(new Binary64(+2)).getReal() < 0);
482 }
483
484 @Test
485 public void testErfcInv() {
486 for (double x = -5.85; x < 5.9; x += 0.01) {
487 final double y = Erf.erfc(x);
488 final double dydxAbs = 2 * FastMath.exp(-x * x) / FastMath.sqrt(FastMath.PI);
489 Assert.assertEquals(x, Erf.erfcInv(y), 1.0e-15 / dydxAbs);
490 }
491 }
492
493 @Test
494 public void testErfcInvField() {
495 for (Binary64 x = new Binary64(-5.85); x.getReal() < 5.9; x = x.add(0.01)) {
496 final Binary64 y = Erf.erfc(x);
497 final Binary64 dydxAbs = x.square().negate().exp().multiply(2/FastMath.sqrt(FastMath.PI));
498 Assert.assertEquals(x.getReal(), Erf.erfcInv(y).getReal(), 1.0e-15 / dydxAbs.getReal());
499 }
500 }
501 }