|
7 | 7 | namespace ErrorFunctionApproximation { |
8 | 8 | class Program { |
9 | 9 | static void Main(string[] args) { |
10 | | - MultiPrecision<Pow2.N32> dx = 1d / 1024; |
| 10 | + MultiPrecision<Pow2.N32>[] xs = new MultiPrecision<Pow2.N32>[]{ |
| 11 | + 1, 2, 4, 8, 16, 32 |
| 12 | + }; |
11 | 13 |
|
12 | | - using StreamWriter sw = new("../../../../results/pade_erf_e32.txt"); |
13 | | - sw.WriteLine("pade approximant f(x^2) f(x):=erf(x)/x"); |
| 14 | + static MultiPrecision<Pow2.N32> f32(MultiPrecision<Pow2.N32> x) { |
| 15 | + return MultiPrecision<Pow2.N32>.InverseErfc(MultiPrecision<Pow2.N32>.Pow2(-x * x)); |
| 16 | + }; |
14 | 17 |
|
15 | | - MultiPrecision<Pow2.N32> x0 = 0, x1 = 0.5; |
| 18 | + static MultiPrecision<Pow2.N64> f64(MultiPrecision<Pow2.N64> x) { |
| 19 | + return MultiPrecision<Pow2.N64>.InverseErfc(MultiPrecision<Pow2.N64>.Pow2(-x * x)); |
| 20 | + }; |
16 | 21 |
|
17 | | - sw.WriteLine($"\nrange x in [{x0}, {x1}]"); |
| 22 | + using StreamWriter sw = new("../../../../results/pade_inverfc_e16.txt"); |
| 23 | + sw.WriteLine("pade approximant inverse_erfc(2^(-x^2))"); |
18 | 24 |
|
19 | | - MultiPrecision<Pow2.N32> c = 2 / MultiPrecision<Pow2.N32>.Sqrt(MultiPrecision<Pow2.N32>.PI); |
| 25 | + for (int j = 0; j < xs.Length - 1; j++) { |
| 26 | + MultiPrecision<Pow2.N32> x0 = xs[j], x1 = xs[j + 1]; |
| 27 | + MultiPrecision<Pow2.N32> dx = (x1 - x0) / 2048; |
20 | 28 |
|
21 | | - sw.WriteLine("expected"); |
22 | | - List<MultiPrecision<Pow2.N32>> expecteds = new(); |
23 | | - for (MultiPrecision<Pow2.N32> x = x0; x <= x1; x += dx) { |
24 | | - MultiPrecision<Pow2.N32> y = (x > 0) ? MultiPrecision<Pow2.N32>.Erf(x) / (x * c) : 1; |
25 | | - |
26 | | - expecteds.Add(y); |
27 | | - |
28 | | - //sw.WriteLine($"{x},{y:e40}"); |
29 | | - } |
| 29 | + sw.WriteLine($"\nrange x in [{x0}, {x1}]"); |
| 30 | + |
| 31 | + //sw.WriteLine("expected"); |
| 32 | + List<MultiPrecision<Pow2.N32>> expecteds = new(); |
| 33 | + for (MultiPrecision<Pow2.N32> x = x0; x <= x1; x += dx) { |
| 34 | + MultiPrecision<Pow2.N32> y = f32(x); |
30 | 35 |
|
31 | | - sw.WriteLine($"diffs x = {x0}"); |
32 | | - List<MultiPrecision<Pow2.N32>> diffs = new(); |
33 | | - for (int d = 0; d <= 128; d++) { |
34 | | - MultiPrecision<Pow2.N32> dy = 1 / ErfTaylorSeries.Coef<Pow2.N32>(d); |
35 | | - diffs.Add(dy); |
| 36 | + expecteds.Add(y); |
| 37 | + |
| 38 | + if ((x % 0.125) == 0) { |
| 39 | + Console.Write("."); |
| 40 | + } |
36 | 41 |
|
37 | | - //sw.WriteLine($"{d},{dy:e40}"); |
38 | | - } |
39 | | - sw.Flush(); |
| 42 | + //sw.WriteLine($"{x},{y:e40}"); |
| 43 | + } |
40 | 44 |
|
41 | | - sw.WriteLine("pade results"); |
42 | | - bool is_finished = false; |
| 45 | + Console.Write("\n"); |
| 46 | + |
| 47 | + sw.WriteLine($"diffs x = {x0}"); |
| 48 | + MultiPrecision<Pow2.N64>[] diffs = FiniteDifference<Pow2.N64>.Diff(x0.Convert<Pow2.N64>(), f64, Math.ScaleB(1, -20)); |
| 49 | + for (int i = 0; i < diffs.Length; i++) { |
| 50 | + sw.WriteLine($"{i},{diffs[i]:e40}"); |
| 51 | + } |
| 52 | + sw.Flush(); |
43 | 53 |
|
44 | | - for (int m = 4; m <= 64 && !is_finished; m++) { |
45 | | - for (int n = m - 1; n <= m + 1 && m + n < 128 && !is_finished; n++) { |
46 | | - (MultiPrecision<Pow2.N32>[] ms, MultiPrecision<Pow2.N32>[] ns) = |
47 | | - PadeSolver<Pow2.N32>.Solve(diffs.Take(m + n + 1).ToArray(), m, n); |
| 54 | + MultiPrecision<Pow2.N32>[] cs = new MultiPrecision<Pow2.N32>[diffs.Length + 1]; |
| 55 | + cs[0] = f32(x0); |
| 56 | + for (int i = 0; i < diffs.Length; i++) { |
| 57 | + cs[i + 1] = diffs[i].Convert<Pow2.N32>() * MultiPrecision<Pow2.N32>.TaylorSequence[i + 1]; |
| 58 | + } |
48 | 59 |
|
49 | | - MultiPrecision<Pow2.N32> err = 0; |
50 | | - for ((int i, MultiPrecision<Pow2.N32> x) = (0, x0); i < expecteds.Count; i++, x += dx) { |
51 | | - MultiPrecision<Pow2.N32> expected = expecteds[i]; |
52 | | - MultiPrecision<Pow2.N32> actual = PadeSolver<Pow2.N32>.Approx(MultiPrecision<Pow2.N32>.Square(x - x0), ms, ns); |
| 60 | + sw.WriteLine("pade results"); |
| 61 | + bool is_finished = false; |
53 | 62 |
|
54 | | - err = MultiPrecision<Pow2.N32>.Max(err, MultiPrecision<Pow2.N32>.Abs(expected / actual - 1)); |
55 | | - } |
| 63 | + for (int m = 4; m < diffs.Length && !is_finished; m++) { |
| 64 | + for (int n = m - 1; n <= m + 1 && m + n < diffs.Length; n++) { |
| 65 | + (MultiPrecision<Pow2.N32>[] ms, MultiPrecision<Pow2.N32>[] ns) = |
| 66 | + PadeSolver<Pow2.N32>.Solve(cs.Take(m + n + 1).ToArray(), m, n); |
56 | 67 |
|
57 | | - Console.WriteLine($"m={m},n={n}"); |
58 | | - Console.WriteLine($"{err:e20}"); |
| 68 | + MultiPrecision<Pow2.N32> err = 0; |
| 69 | + for ((int i, MultiPrecision<Pow2.N32> x) = (0, x0); i < expecteds.Count; i++, x += dx) { |
| 70 | + MultiPrecision<Pow2.N32> expected = expecteds[i]; |
| 71 | + MultiPrecision<Pow2.N32> actual = PadeSolver<Pow2.N32>.Approx(x - x0, ms, ns); |
59 | 72 |
|
60 | | - if (err < 1e-32 && ms.All((v) => v > 0) && ns.All((v) => v > 0)) { |
61 | | - sw.WriteLine($"m={m},n={n}"); |
62 | | - sw.WriteLine("ms"); |
63 | | - for (int i = 0; i < ms.Length; i++) { |
64 | | - sw.WriteLine($"{(ms[i] * c):e40}"); |
65 | | - } |
66 | | - sw.WriteLine("ns"); |
67 | | - for (int i = 0; i < ns.Length; i++) { |
68 | | - sw.WriteLine($"{ns[i]:e40}"); |
| 73 | + err = MultiPrecision<Pow2.N32>.Max(err, MultiPrecision<Pow2.N32>.Abs(expected / actual - 1)); |
69 | 74 | } |
70 | | - sw.WriteLine("relative err"); |
71 | | - sw.WriteLine($"{err:e20}"); |
72 | | - sw.Flush(); |
73 | 75 |
|
74 | | - is_finished = true; |
75 | | - break; |
| 76 | + Console.WriteLine($"m={m},n={n}"); |
| 77 | + Console.WriteLine($"{err:e20}"); |
| 78 | + |
| 79 | + if (err < 1e-16) { |
| 80 | + sw.WriteLine($"m={m},n={n}"); |
| 81 | + sw.WriteLine("ms"); |
| 82 | + for (int i = 0; i < ms.Length; i++) { |
| 83 | + sw.WriteLine($"{ms[i]:e20}"); |
| 84 | + } |
| 85 | + sw.WriteLine("ns"); |
| 86 | + for (int i = 0; i < ns.Length; i++) { |
| 87 | + sw.WriteLine($"{ns[i]:e20}"); |
| 88 | + } |
| 89 | + sw.WriteLine("relative err"); |
| 90 | + sw.WriteLine($"{err:e20}"); |
| 91 | + sw.Flush(); |
| 92 | + |
| 93 | + if (ms.All((v) => v > 0) && ns.All((v) => v > 0)) { |
| 94 | + is_finished = true; |
| 95 | + } |
| 96 | + } |
76 | 97 | } |
77 | 98 | } |
| 99 | + |
| 100 | + if (!is_finished) { |
| 101 | + Console.WriteLine("not convergence"); |
| 102 | + } |
78 | 103 | } |
79 | 104 |
|
| 105 | + |
80 | 106 | Console.WriteLine("END"); |
81 | 107 | Console.Read(); |
82 | 108 | } |
|
0 commit comments