@@ -115,66 +115,37 @@ namespace alfi::spline {
115115 coeffs = util::spline::simple_spline<Number,Container>(X, Y, 3 );
116116 return ;
117117 }
118-
119- const Container<Number> dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
120-
121- Container<Number> B (n);
122-
118+ const auto dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
123119 Container<Number> diag (n - 2 ), right (n - 2 );
124- diag[0 ] = ((dX[0 ] + dX[1 ]) * (dX[0 ] + 2 * dX[1 ])) / dX[1 ];
125- for (SizeT i = 1 ; i < n - 3 ; ++i) {
126- diag[i] = 2 * (dX[i] + dX[i+1 ]);
127- }
128- diag[n-3 ] = ((dX[n-2 ] + dX[n-3 ]) * (dX[n-2 ] + 2 * dX[n-3 ])) / dX[n-3 ];
129120 for (SizeT i = 0 ; i < n - 2 ; ++i) {
121+ diag[i] = 2 * (dX[i] + dX[i+1 ]);
130122 right[i] = 3 * (dY[i+1 ]/dX[i+1 ] - dY[i]/dX[i]);
131123 }
132-
133- const auto m_1 = dX[1 ] / diag[0 ];
134- diag[1 ] -= m_1 * (dX[1 ] - dX[0 ]*dX[0 ]/dX[1 ]);
135- right[1 ] -= m_1 * right[0 ];
136- for (SizeT i = 2 ; i < n - 3 ; ++i) {
137- const auto m = dX[i] / diag[i-1 ];
138- diag[i] -= m * dX[i];
139- right[i] -= m * right[i-1 ];
124+ const auto C = util::linalg::tridiag_solve (
125+ dX[0 ] - dX[1 ], 2 *dX[0 ] + dX[1 ], dX[0 ] / (dX[0 ]+dX[1 ]) * right[0 ],
126+ 2 *dX[n-2 ] + dX[n-3 ], dX[n-2 ] - dX[n-3 ], dX[n-2 ] / (dX[n-2 ]+dX[n-3 ]) * right[n-3 ],
127+ dX.begin (), diag.begin (), dX.begin () + 1 , right.begin (), n
128+ );
129+ for (SizeT i = 0 , index = 0 ; i < n - 1 ; ++i) {
130+ coeffs[index++] = (C[i+1 ] - C[i]) / (3 *dX[i]);
131+ coeffs[index++] = C[i];
132+ coeffs[index++] = dY[i]/dX[i] - dX[i] * ((2 *C[i] + C[i+1 ]) / 3 );
133+ coeffs[index++] = Y[i];
140134 }
141- const auto m_n_3 = (dX[n-3 ] - dX[n-2 ]*dX[n-2 ]/dX[n-3 ]) / diag[n-4 ];
142- diag[n-3 ] -= m_n_3 * dX[n-3 ];
143- right[n-3 ] -= m_n_3 * right[n-4 ];
144-
145- B[n-2 ] = right[n-3 ] / diag[n-3 ];
146- for (SizeT i = n - 3 ; i >= 2 ; --i) {
147- B[i] = (right[i-1 ] - dX[i] * B[i+1 ]) / diag[i-1 ];
148- }
149- B[1 ] = (right[0 ] - (dX[1 ] - dX[0 ]*dX[0 ]/dX[1 ]) * B[2 ]) / diag[0 ];
150- B[0 ] = B[1 ] + dX[0 ]/dX[1 ] * (B[1 ] - B[2 ]);
151- B[n-1 ] = B[n-2 ] + dX[n-2 ]/dX[n-3 ] * (B[n-2 ] - B[n-3 ]);
152-
153- Container<Number> A (n - 1 );
154- for (SizeT i = 1 ; i < A.size () - 1 ; ++i) {
155- A[i] = (B[i+1 ] - B[i]) / (3 *dX[i]);
156- }
157- A[0 ] = A[1 ];
158- A[n-2 ] = A[n-3 ];
159- Container<Number> C (n - 1 );
160- for (SizeT i = 0 ; i < C.size (); ++i) {
161- C[i] = dY[i]/dX[i] - dX[i] * ((2 *B[i] + B[i+1 ]) / 3 );
162- }
163- util::spline::merge_coeffs (coeffs, {A, B, C, Y});
164135 },
165136 [&](const typename Types::Periodic&) {
166137 if (n <= 2 ) {
167138 coeffs = util::spline::simple_spline<Number,Container>(X, Y, 3 );
168139 return ;
169140 }
170141
171- const Container<Number> dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
142+ const auto dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
172143
173- Container<Number> B (n);
144+ Container<Number> C (n);
174145 if (n == 3 ) {
175- B [0 ] = 3 * (dY[0 ]/dX[0 ] - dY[1 ]/dX[1 ]) / (dX[0 ] + dX[1 ]);
176- B [1 ] = -B [0 ];
177- B [2 ] = B [0 ];
146+ C [0 ] = 3 * (dY[0 ]/dX[0 ] - dY[1 ]/dX[1 ]) / (dX[0 ] + dX[1 ]);
147+ C [1 ] = -C [0 ];
148+ C [2 ] = C [0 ];
178149 } else {
179150 Container<Number> diag (n - 1 ), right (n - 1 );
180151 for (SizeT i = 0 ; i < n - 2 ; ++i) {
@@ -204,38 +175,35 @@ namespace alfi::spline {
204175 diag[n-2 ] -= last_row[n-3 ] / diag[n-3 ] * last_col[n-3 ];
205176 right[n-2 ] -= last_row[n-3 ] / diag[n-3 ] * right[n-3 ];
206177
207- B [n-1 ] = right[n-2 ] / diag[n-2 ];
208- B [n-2 ] = (right[n-3 ] - last_col[n-3 ] * B [n-1 ]) / diag[n-3 ];
178+ C [n-1 ] = right[n-2 ] / diag[n-2 ];
179+ C [n-2 ] = (right[n-3 ] - last_col[n-3 ] * C [n-1 ]) / diag[n-3 ];
209180 for (SizeT i = n - 3 ; i >= 1 ; --i) {
210- B [i] = (right[i-1 ] - dX[i]*B [i+1 ] - last_col[i-1 ]*B [n-1 ]) / diag[i-1 ];
181+ C [i] = (right[i-1 ] - dX[i]*C [i+1 ] - last_col[i-1 ]*C [n-1 ]) / diag[i-1 ];
211182 }
212- B [0 ] = B [n-1 ];
183+ C [0 ] = C [n-1 ];
213184 }
214185
215- Container<Number> A (n - 1 );
216- for (SizeT i = 0 ; i < A.size (); ++i) {
217- A[i] = (B[i+1 ] - B[i]) / (3 *dX[i]);
186+ for (SizeT i = 0 , index = 0 ; i < n - 1 ; ++i) {
187+ coeffs[index++] = (C[i+1 ] - C[i]) / (3 *dX[i]);
188+ coeffs[index++] = C[i];
189+ coeffs[index++] = dY[i]/dX[i] - dX[i] * ((2 *C[i] + C[i+1 ]) / 3 );
190+ coeffs[index++] = Y[i];
218191 }
219- Container<Number> C (n - 1 );
220- for (SizeT i = 0 ; i < C.size (); ++i) {
221- C[i] = dY[i]/dX[i] - dX[i] * ((2 *B[i] + B[i+1 ]) / 3 );
222- }
223- util::spline::merge_coeffs (coeffs, {A, B, C, Y});
224192 },
225193 [&](const typename Types::ParabolicEnds&) {
226194 coeffs = compute_coeffs (X, Y, typename Types::FixedThird{0 , 0 });
227195 },
228196 [&](const typename Types::Clamped& c) {
229- const Container<Number> dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
197+ const auto dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
230198
231- Container<Number> B (n);
199+ Container<Number> C (n);
232200 if (n == 2 ) {
233- B [0 ] = (3 *dY[0 ]/dX[0 ] - c.df_n - 2 *c.df_1 ) / dX[0 ];
234- B [1 ] = (c.df_1 + 2 *c.df_n - 3 *dY[0 ]/dX[0 ]) / dX[0 ];
201+ C [0 ] = (3 *dY[0 ]/dX[0 ] - c.df_n - 2 *c.df_1 ) / dX[0 ];
202+ C [1 ] = (c.df_1 + 2 *c.df_n - 3 *dY[0 ]/dX[0 ]) / dX[0 ];
235203 } else if (n == 3 ) {
236- B [1 ] = (3 *(dY[1 ]/dX[1 ] - dY[0 ]/dX[0 ]) + (c.df_1 - c.df_n )) / (dX[0 ] + dX[1 ]);
237- B [0 ] = (3 *(dY[0 ]/dX[0 ] - c.df_1 )/dX[0 ] - B [1 ]) / 2 ;
238- B [2 ] = (3 *(c.df_n - dY[1 ]/dX[1 ])/dX[1 ] - B [1 ]) / 2 ;
204+ C [1 ] = (3 *(dY[1 ]/dX[1 ] - dY[0 ]/dX[0 ]) + (c.df_1 - c.df_n )) / (dX[0 ] + dX[1 ]);
205+ C [0 ] = (3 *(dY[0 ]/dX[0 ] - c.df_1 )/dX[0 ] - C [1 ]) / 2 ;
206+ C [2 ] = (3 *(c.df_n - dY[1 ]/dX[1 ])/dX[1 ] - C [1 ]) / 2 ;
239207 } else {
240208 Container<Number> diag (n - 2 ), right (n - 2 );
241209 diag[0 ] = 1.5 *dX[0 ] + 2 *dX[1 ];
@@ -253,66 +221,60 @@ namespace alfi::spline {
253221 right[i] -= m * right[i-1 ];
254222 }
255223
256- B [n-2 ] = right[n-3 ] / diag[n-3 ];
224+ C [n-2 ] = right[n-3 ] / diag[n-3 ];
257225 for (SizeT i = n - 3 ; i >= 1 ; --i) {
258- B [i] = (right[i-1 ] - dX[i] * B [i+1 ]) / diag[i-1 ];
226+ C [i] = (right[i-1 ] - dX[i] * C [i+1 ]) / diag[i-1 ];
259227 }
260- B [n-1 ] = 1.5 *(c.df_n /dX[n-2 ] - dY[n-2 ]/dX[n-2 ]/dX[n-2 ]) - 0.5 *B [n-2 ];
261- B [0 ] = 1.5 *(dY[0 ]/dX[0 ]/dX[0 ] - c.df_1 /dX[0 ]) - 0.5 *B [1 ];
228+ C [n-1 ] = 1.5 *(c.df_n /dX[n-2 ] - dY[n-2 ]/dX[n-2 ]/dX[n-2 ]) - 0.5 *C [n-2 ];
229+ C [0 ] = 1.5 *(dY[0 ]/dX[0 ]/dX[0 ] - c.df_1 /dX[0 ]) - 0.5 *C [1 ];
262230 }
263231
264- Container<Number> A (n - 1 );
265- for (SizeT i = 0 ; i < A.size (); ++i) {
266- A[i] = (B[i+1 ] - B[i]) / (3 *dX[i]);
267- }
268- Container<Number> C (n - 1 );
269- for (SizeT i = 0 ; i < C.size (); ++i) {
270- C[i] = dY[i]/dX[i] - dX[i] * ((2 *B[i] + B[i+1 ]) / 3 );
232+ for (SizeT i = 0 , index = 0 ; i < n - 1 ; ++i) {
233+ coeffs[index++] = (C[i+1 ] - C[i]) / (3 *dX[i]);
234+ coeffs[index++] = C[i];
235+ coeffs[index++] = dY[i]/dX[i] - dX[i] * ((2 *C[i] + C[i+1 ]) / 3 );
236+ coeffs[index++] = Y[i];
271237 }
272- util::spline::merge_coeffs (coeffs, {A, B, C, Y});
273238 },
274239 [&](const typename Types::FixedSecond& s) {
275- const Container<Number> dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
240+ const auto dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
276241
277- Container<Number> B (n);
278- B [0 ] = s.d2f_1 / 2 ;
279- B [n-1 ] = s.d2f_n / 2 ;
242+ Container<Number> C (n);
243+ C [0 ] = s.d2f_1 / 2 ;
244+ C [n-1 ] = s.d2f_n / 2 ;
280245 if (n > 2 ) {
281246 Container<Number> diag (n - 2 ), right (n - 2 );
282247 for (SizeT i = 0 ; i < n - 2 ; ++i) {
283248 diag[i] = 2 * (dX[i] + dX[i+1 ]);
284249 right[i] = 3 * (dY[i+1 ]/dX[i+1 ] - dY[i]/dX[i]);
285250 }
286- right[0 ] -= B [0 ] * dX[0 ];
287- right[n-3 ] -= B [n-1 ] * dX[n-2 ];
251+ right[0 ] -= C [0 ] * dX[0 ];
252+ right[n-3 ] -= C [n-1 ] * dX[n-2 ];
288253 for (SizeT i = 1 ; i < n - 2 ; ++i) {
289254 const auto m = dX[i] / diag[i-1 ];
290255 diag[i] -= m * dX[i];
291256 right[i] -= m * right[i-1 ];
292257 }
293- B [n-2 ] = right[n-3 ] / diag[n-3 ];
258+ C [n-2 ] = right[n-3 ] / diag[n-3 ];
294259 for (SizeT i = n - 3 ; i >= 1 ; --i) {
295- B [i] = (right[i-1 ] - dX[i] * B [i+1 ]) / diag[i-1 ];
260+ C [i] = (right[i-1 ] - dX[i] * C [i+1 ]) / diag[i-1 ];
296261 }
297262 }
298263
299- Container<Number> A (n - 1 );
300- for (SizeT i = 0 ; i < A.size (); ++i) {
301- A[i] = (B[i+1 ] - B[i]) / (3 *dX[i]);
302- }
303- Container<Number> C (n - 1 );
304- for (SizeT i = 0 ; i < C.size (); ++i) {
305- C[i] = dY[i]/dX[i] - dX[i] * ((2 *B[i] + B[i+1 ]) / 3 );
264+ for (SizeT i = 0 , index = 0 ; i < n - 1 ; ++i) {
265+ coeffs[index++] = (C[i+1 ] - C[i]) / (3 *dX[i]);
266+ coeffs[index++] = C[i];
267+ coeffs[index++] = dY[i]/dX[i] - dX[i] * ((2 *C[i] + C[i+1 ]) / 3 );
268+ coeffs[index++] = Y[i];
306269 }
307- util::spline::merge_coeffs (coeffs, {A, B, C, Y});
308270 },
309271 [&](const typename Types::FixedThird& t) {
310- const Container<Number> dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
272+ const auto dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
311273
312- Container<Number> B (n);
274+ Container<Number> C (n);
313275 if (n == 2 ) {
314- B [0 ] = -dX[0 ] * (t.d3f_1 + t.d3f_n ) / 8 ;
315- B [1 ] = -B [0 ];
276+ C [0 ] = -dX[0 ] * (t.d3f_1 + t.d3f_n ) / 8 ;
277+ C [1 ] = -C [0 ];
316278 } else {
317279 Container<Number> diag (n), right (n);
318280 diag[0 ] = 1 ;
@@ -338,36 +300,37 @@ namespace alfi::spline {
338300 diag[n-1 ] -= m_n_1 * dX[n-2 ];
339301 right[n-1 ] -= m_n_1 * right[n-2 ];
340302
341- B [n-1 ] = right[n-1 ] / diag[n-1 ];
303+ C [n-1 ] = right[n-1 ] / diag[n-1 ];
342304 for (SizeT i = n - 2 ; i >= 1 ; --i) {
343- B [i] = (right[i] - dX[i] * B [i+1 ]) / diag[i];
305+ C [i] = (right[i] - dX[i] * C [i+1 ]) / diag[i];
344306 }
345- B [0 ] = right[0 ] + B [1 ];
307+ C [0 ] = right[0 ] + C [1 ];
346308 }
347309
348- Container<Number> A (n - 1 );
349- for (SizeT i = 1 ; i < A .size () - 1 ; ++i) {
350- A [i] = (B [i+1 ] - B [i]) / (3 *dX[i]);
310+ Container<Number> D (n - 1 );
311+ for (SizeT i = 1 ; i < D .size () - 1 ; ++i) {
312+ D [i] = (C [i+1 ] - C [i]) / (3 *dX[i]);
351313 }
352314 if (n == 2 ) {
353- A [0 ] = (t.d3f_1 + t.d3f_n ) / 12 ;
315+ D [0 ] = (t.d3f_1 + t.d3f_n ) / 12 ;
354316 } else {
355- A [0 ] = t.d3f_1 / 6 ;
356- A [n-2 ] = t.d3f_n / 6 ;
317+ D [0 ] = t.d3f_1 / 6 ;
318+ D [n-2 ] = t.d3f_n / 6 ;
357319 }
358- Container<Number> C (n - 1 );
359- for (SizeT i = 0 ; i < C.size (); ++i) {
360- C[i] = dY[i]/dX[i] - dX[i] * ((2 *B[i] + B[i+1 ]) / 3 );
320+ for (SizeT i = 0 , index = 0 ; i < n - 1 ; ++i) {
321+ coeffs[index++] = D[i];
322+ coeffs[index++] = C[i];
323+ coeffs[index++] = dY[i]/dX[i] - dX[i] * ((2 *C[i] + C[i+1 ]) / 3 );
324+ coeffs[index++] = Y[i];
361325 }
362- util::spline::merge_coeffs (coeffs, {A, B, C, Y});
363326 },
364327 [&](const typename Types::NotAKnotStart&) {
365328 if (n <= 4 ) {
366329 coeffs = util::spline::simple_spline<Number,Container>(X, Y, 3 );
367330 return ;
368331 }
369332
370- const Container<Number> dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
333+ const auto dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
371334
372335 { // first four points
373336 const auto h1 = dX[0 ], h2 = dX[1 ];
@@ -414,7 +377,7 @@ namespace alfi::spline {
414377 return ;
415378 }
416379
417- const Container<Number> dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
380+ const auto dX = util::arrays::diff (X), dY = util::arrays::diff (Y);
418381
419382 { // last four points
420383 const auto h1 = dX[n-4 ], h2 = dX[n-3 ];
0 commit comments