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