1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.analysis.interpolation;
23
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.hipparchus.FieldElement;
28 import org.hipparchus.exception.LocalizedCoreFormats;
29 import org.hipparchus.exception.MathIllegalArgumentException;
30 import org.hipparchus.exception.MathRuntimeException;
31 import org.hipparchus.exception.NullArgumentException;
32 import org.hipparchus.util.MathArrays;
33 import org.hipparchus.util.MathUtils;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class FieldHermiteInterpolator<T extends FieldElement<T>> {
53
54
55 private final List<T> abscissae;
56
57
58 private final List<T[]> topDiagonal;
59
60
61 private final List<T[]> bottomDiagonal;
62
63
64
65 public FieldHermiteInterpolator() {
66 this.abscissae = new ArrayList<>();
67 this.topDiagonal = new ArrayList<>();
68 this.bottomDiagonal = new ArrayList<>();
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 @SafeVarargs
93 public final void addSamplePoint(final T x, final T[] ... value)
94 throws MathIllegalArgumentException, MathRuntimeException,
95 NullArgumentException {
96
97 MathUtils.checkNotNull(x);
98 T factorial = x.getField().getOne();
99 for (int i = 0; i < value.length; ++i) {
100
101 final T[] y = value[i].clone();
102 if (i > 1) {
103 factorial = factorial.multiply(i);
104 final T inv = factorial.reciprocal();
105 for (int j = 0; j < y.length; ++j) {
106 y[j] = y[j].multiply(inv);
107 }
108 }
109
110
111 final int n = abscissae.size();
112 bottomDiagonal.add(n - i, y);
113 T[] bottom0 = y;
114 for (int j = i; j < n; ++j) {
115 final T[] bottom1 = bottomDiagonal.get(n - (j + 1));
116 if (x.equals(abscissae.get(n - (j + 1)))) {
117 throw new MathIllegalArgumentException(LocalizedCoreFormats.DUPLICATED_ABSCISSA_DIVISION_BY_ZERO, x);
118 }
119 final T inv = x.subtract(abscissae.get(n - (j + 1))).reciprocal();
120 for (int k = 0; k < y.length; ++k) {
121 bottom1[k] = inv.multiply(bottom0[k].subtract(bottom1[k]));
122 }
123 bottom0 = bottom1;
124 }
125
126
127 topDiagonal.add(bottom0.clone());
128
129
130 abscissae.add(x);
131
132 }
133
134 }
135
136
137
138
139
140
141
142 public T[] value(T x) throws MathIllegalArgumentException, NullArgumentException {
143
144
145 MathUtils.checkNotNull(x);
146 if (abscissae.isEmpty()) {
147 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_INTERPOLATION_SAMPLE);
148 }
149
150 final T[] value = MathArrays.buildArray(x.getField(), topDiagonal.get(0).length);
151 T valueCoeff = x.getField().getOne();
152 for (int i = 0; i < topDiagonal.size(); ++i) {
153 T[] dividedDifference = topDiagonal.get(i);
154 for (int k = 0; k < value.length; ++k) {
155 value[k] = value[k].add(dividedDifference[k].multiply(valueCoeff));
156 }
157 final T deltaX = x.subtract(abscissae.get(i));
158 valueCoeff = valueCoeff.multiply(deltaX);
159 }
160
161 return value;
162
163 }
164
165
166
167
168
169
170
171
172
173 public T[][] derivatives(T x, int order) throws MathIllegalArgumentException, NullArgumentException {
174
175
176 MathUtils.checkNotNull(x);
177 if (abscissae.isEmpty()) {
178 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_INTERPOLATION_SAMPLE);
179 }
180
181 final T zero = x.getField().getZero();
182 final T one = x.getField().getOne();
183 final T[] tj = MathArrays.buildArray(x.getField(), order + 1);
184 tj[0] = zero;
185 for (int i = 0; i < order; ++i) {
186 tj[i + 1] = tj[i].add(one);
187 }
188
189 final T[][] derivatives =
190 MathArrays.buildArray(x.getField(), order + 1, topDiagonal.get(0).length);
191 final T[] valueCoeff = MathArrays.buildArray(x.getField(), order + 1);
192 valueCoeff[0] = x.getField().getOne();
193 for (int i = 0; i < topDiagonal.size(); ++i) {
194 T[] dividedDifference = topDiagonal.get(i);
195 final T deltaX = x.subtract(abscissae.get(i));
196 for (int j = order; j >= 0; --j) {
197 for (int k = 0; k < derivatives[j].length; ++k) {
198 derivatives[j][k] =
199 derivatives[j][k].add(dividedDifference[k].multiply(valueCoeff[j]));
200 }
201 valueCoeff[j] = valueCoeff[j].multiply(deltaX);
202 if (j > 0) {
203 valueCoeff[j] = valueCoeff[j].add(tj[j].multiply(valueCoeff[j - 1]));
204 }
205 }
206 }
207
208 return derivatives;
209
210 }
211
212 }