Line data Source code
1 : /*************************************************************************
2 : ALGLIB 3.17.0 (source code generated 2020-12-27)
3 : Copyright (c) Sergey Bochkanov (ALGLIB project).
4 :
5 : >>> SOURCE LICENSE >>>
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation (www.fsf.org); either version 2 of the
9 : License, or (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : A copy of the GNU General Public License is available at
17 : http://www.fsf.org/licensing/licenses
18 : >>> END OF LICENSE >>>
19 : *************************************************************************/
20 : #ifdef _MSC_VER
21 : #define _CRT_SECURE_NO_WARNINGS
22 : #endif
23 : #include "stdafx.h"
24 : #include "interpolation.h"
25 :
26 : // disable some irrelevant warnings
27 : #if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS)
28 : #pragma warning(disable:4100)
29 : #pragma warning(disable:4127)
30 : #pragma warning(disable:4611)
31 : #pragma warning(disable:4702)
32 : #pragma warning(disable:4996)
33 : #endif
34 :
35 : /////////////////////////////////////////////////////////////////////////
36 : //
37 : // THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
38 : //
39 : /////////////////////////////////////////////////////////////////////////
40 : namespace alglib
41 : {
42 :
43 : #if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD)
44 :
45 : #endif
46 :
47 : #if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD)
48 :
49 : #endif
50 :
51 : #if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD)
52 :
53 : #endif
54 :
55 : #if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD)
56 :
57 : #endif
58 :
59 : #if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD)
60 :
61 : #endif
62 :
63 : #if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD)
64 :
65 : #endif
66 :
67 : #if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD)
68 :
69 : #endif
70 :
71 : #if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD)
72 :
73 : #endif
74 :
75 : #if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD)
76 :
77 : #endif
78 :
79 : #if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD)
80 :
81 : #endif
82 :
83 : #if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD)
84 :
85 : #endif
86 :
87 : #if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD)
88 :
89 : #endif
90 :
91 : #if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD)
92 :
93 : #endif
94 :
95 : #if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD)
96 :
97 : #endif
98 :
99 : #if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD)
100 : /*************************************************************************
101 : Buffer object which is used to perform evaluation requests in the
102 : multithreaded mode (multiple threads working with same IDW object).
103 :
104 : This object should be created with idwcreatecalcbuffer().
105 : *************************************************************************/
106 0 : _idwcalcbuffer_owner::_idwcalcbuffer_owner()
107 : {
108 : jmp_buf _break_jump;
109 : alglib_impl::ae_state _state;
110 :
111 0 : alglib_impl::ae_state_init(&_state);
112 0 : if( setjmp(_break_jump) )
113 : {
114 0 : if( p_struct!=NULL )
115 : {
116 0 : alglib_impl::_idwcalcbuffer_destroy(p_struct);
117 0 : alglib_impl::ae_free(p_struct);
118 : }
119 0 : p_struct = NULL;
120 : #if !defined(AE_NO_EXCEPTIONS)
121 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
122 : #else
123 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
124 : return;
125 : #endif
126 : }
127 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
128 0 : p_struct = NULL;
129 0 : p_struct = (alglib_impl::idwcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwcalcbuffer), &_state);
130 0 : memset(p_struct, 0, sizeof(alglib_impl::idwcalcbuffer));
131 0 : alglib_impl::_idwcalcbuffer_init(p_struct, &_state, ae_false);
132 0 : ae_state_clear(&_state);
133 0 : }
134 :
135 0 : _idwcalcbuffer_owner::_idwcalcbuffer_owner(const _idwcalcbuffer_owner &rhs)
136 : {
137 : jmp_buf _break_jump;
138 : alglib_impl::ae_state _state;
139 :
140 0 : alglib_impl::ae_state_init(&_state);
141 0 : if( setjmp(_break_jump) )
142 : {
143 0 : if( p_struct!=NULL )
144 : {
145 0 : alglib_impl::_idwcalcbuffer_destroy(p_struct);
146 0 : alglib_impl::ae_free(p_struct);
147 : }
148 0 : p_struct = NULL;
149 : #if !defined(AE_NO_EXCEPTIONS)
150 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
151 : #else
152 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
153 : return;
154 : #endif
155 : }
156 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
157 0 : p_struct = NULL;
158 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwcalcbuffer copy constructor failure (source is not initialized)", &_state);
159 0 : p_struct = (alglib_impl::idwcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwcalcbuffer), &_state);
160 0 : memset(p_struct, 0, sizeof(alglib_impl::idwcalcbuffer));
161 0 : alglib_impl::_idwcalcbuffer_init_copy(p_struct, const_cast<alglib_impl::idwcalcbuffer*>(rhs.p_struct), &_state, ae_false);
162 0 : ae_state_clear(&_state);
163 0 : }
164 :
165 0 : _idwcalcbuffer_owner& _idwcalcbuffer_owner::operator=(const _idwcalcbuffer_owner &rhs)
166 : {
167 0 : if( this==&rhs )
168 0 : return *this;
169 : jmp_buf _break_jump;
170 : alglib_impl::ae_state _state;
171 :
172 0 : alglib_impl::ae_state_init(&_state);
173 0 : if( setjmp(_break_jump) )
174 : {
175 : #if !defined(AE_NO_EXCEPTIONS)
176 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
177 : #else
178 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
179 : return *this;
180 : #endif
181 : }
182 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
183 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwcalcbuffer assignment constructor failure (destination is not initialized)", &_state);
184 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwcalcbuffer assignment constructor failure (source is not initialized)", &_state);
185 0 : alglib_impl::_idwcalcbuffer_destroy(p_struct);
186 0 : memset(p_struct, 0, sizeof(alglib_impl::idwcalcbuffer));
187 0 : alglib_impl::_idwcalcbuffer_init_copy(p_struct, const_cast<alglib_impl::idwcalcbuffer*>(rhs.p_struct), &_state, ae_false);
188 0 : ae_state_clear(&_state);
189 0 : return *this;
190 : }
191 :
192 0 : _idwcalcbuffer_owner::~_idwcalcbuffer_owner()
193 : {
194 0 : if( p_struct!=NULL )
195 : {
196 0 : alglib_impl::_idwcalcbuffer_destroy(p_struct);
197 0 : ae_free(p_struct);
198 : }
199 0 : }
200 :
201 0 : alglib_impl::idwcalcbuffer* _idwcalcbuffer_owner::c_ptr()
202 : {
203 0 : return p_struct;
204 : }
205 :
206 0 : alglib_impl::idwcalcbuffer* _idwcalcbuffer_owner::c_ptr() const
207 : {
208 0 : return const_cast<alglib_impl::idwcalcbuffer*>(p_struct);
209 : }
210 0 : idwcalcbuffer::idwcalcbuffer() : _idwcalcbuffer_owner()
211 : {
212 0 : }
213 :
214 0 : idwcalcbuffer::idwcalcbuffer(const idwcalcbuffer &rhs):_idwcalcbuffer_owner(rhs)
215 : {
216 0 : }
217 :
218 0 : idwcalcbuffer& idwcalcbuffer::operator=(const idwcalcbuffer &rhs)
219 : {
220 0 : if( this==&rhs )
221 0 : return *this;
222 0 : _idwcalcbuffer_owner::operator=(rhs);
223 0 : return *this;
224 : }
225 :
226 0 : idwcalcbuffer::~idwcalcbuffer()
227 : {
228 0 : }
229 :
230 :
231 : /*************************************************************************
232 : IDW (Inverse Distance Weighting) model object.
233 : *************************************************************************/
234 0 : _idwmodel_owner::_idwmodel_owner()
235 : {
236 : jmp_buf _break_jump;
237 : alglib_impl::ae_state _state;
238 :
239 0 : alglib_impl::ae_state_init(&_state);
240 0 : if( setjmp(_break_jump) )
241 : {
242 0 : if( p_struct!=NULL )
243 : {
244 0 : alglib_impl::_idwmodel_destroy(p_struct);
245 0 : alglib_impl::ae_free(p_struct);
246 : }
247 0 : p_struct = NULL;
248 : #if !defined(AE_NO_EXCEPTIONS)
249 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
250 : #else
251 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
252 : return;
253 : #endif
254 : }
255 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
256 0 : p_struct = NULL;
257 0 : p_struct = (alglib_impl::idwmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwmodel), &_state);
258 0 : memset(p_struct, 0, sizeof(alglib_impl::idwmodel));
259 0 : alglib_impl::_idwmodel_init(p_struct, &_state, ae_false);
260 0 : ae_state_clear(&_state);
261 0 : }
262 :
263 0 : _idwmodel_owner::_idwmodel_owner(const _idwmodel_owner &rhs)
264 : {
265 : jmp_buf _break_jump;
266 : alglib_impl::ae_state _state;
267 :
268 0 : alglib_impl::ae_state_init(&_state);
269 0 : if( setjmp(_break_jump) )
270 : {
271 0 : if( p_struct!=NULL )
272 : {
273 0 : alglib_impl::_idwmodel_destroy(p_struct);
274 0 : alglib_impl::ae_free(p_struct);
275 : }
276 0 : p_struct = NULL;
277 : #if !defined(AE_NO_EXCEPTIONS)
278 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
279 : #else
280 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
281 : return;
282 : #endif
283 : }
284 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
285 0 : p_struct = NULL;
286 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwmodel copy constructor failure (source is not initialized)", &_state);
287 0 : p_struct = (alglib_impl::idwmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwmodel), &_state);
288 0 : memset(p_struct, 0, sizeof(alglib_impl::idwmodel));
289 0 : alglib_impl::_idwmodel_init_copy(p_struct, const_cast<alglib_impl::idwmodel*>(rhs.p_struct), &_state, ae_false);
290 0 : ae_state_clear(&_state);
291 0 : }
292 :
293 0 : _idwmodel_owner& _idwmodel_owner::operator=(const _idwmodel_owner &rhs)
294 : {
295 0 : if( this==&rhs )
296 0 : return *this;
297 : jmp_buf _break_jump;
298 : alglib_impl::ae_state _state;
299 :
300 0 : alglib_impl::ae_state_init(&_state);
301 0 : if( setjmp(_break_jump) )
302 : {
303 : #if !defined(AE_NO_EXCEPTIONS)
304 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
305 : #else
306 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
307 : return *this;
308 : #endif
309 : }
310 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
311 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwmodel assignment constructor failure (destination is not initialized)", &_state);
312 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwmodel assignment constructor failure (source is not initialized)", &_state);
313 0 : alglib_impl::_idwmodel_destroy(p_struct);
314 0 : memset(p_struct, 0, sizeof(alglib_impl::idwmodel));
315 0 : alglib_impl::_idwmodel_init_copy(p_struct, const_cast<alglib_impl::idwmodel*>(rhs.p_struct), &_state, ae_false);
316 0 : ae_state_clear(&_state);
317 0 : return *this;
318 : }
319 :
320 0 : _idwmodel_owner::~_idwmodel_owner()
321 : {
322 0 : if( p_struct!=NULL )
323 : {
324 0 : alglib_impl::_idwmodel_destroy(p_struct);
325 0 : ae_free(p_struct);
326 : }
327 0 : }
328 :
329 0 : alglib_impl::idwmodel* _idwmodel_owner::c_ptr()
330 : {
331 0 : return p_struct;
332 : }
333 :
334 0 : alglib_impl::idwmodel* _idwmodel_owner::c_ptr() const
335 : {
336 0 : return const_cast<alglib_impl::idwmodel*>(p_struct);
337 : }
338 0 : idwmodel::idwmodel() : _idwmodel_owner()
339 : {
340 0 : }
341 :
342 0 : idwmodel::idwmodel(const idwmodel &rhs):_idwmodel_owner(rhs)
343 : {
344 0 : }
345 :
346 0 : idwmodel& idwmodel::operator=(const idwmodel &rhs)
347 : {
348 0 : if( this==&rhs )
349 0 : return *this;
350 0 : _idwmodel_owner::operator=(rhs);
351 0 : return *this;
352 : }
353 :
354 0 : idwmodel::~idwmodel()
355 : {
356 0 : }
357 :
358 :
359 : /*************************************************************************
360 : Builder object used to generate IDW (Inverse Distance Weighting) model.
361 : *************************************************************************/
362 0 : _idwbuilder_owner::_idwbuilder_owner()
363 : {
364 : jmp_buf _break_jump;
365 : alglib_impl::ae_state _state;
366 :
367 0 : alglib_impl::ae_state_init(&_state);
368 0 : if( setjmp(_break_jump) )
369 : {
370 0 : if( p_struct!=NULL )
371 : {
372 0 : alglib_impl::_idwbuilder_destroy(p_struct);
373 0 : alglib_impl::ae_free(p_struct);
374 : }
375 0 : p_struct = NULL;
376 : #if !defined(AE_NO_EXCEPTIONS)
377 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
378 : #else
379 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
380 : return;
381 : #endif
382 : }
383 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
384 0 : p_struct = NULL;
385 0 : p_struct = (alglib_impl::idwbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwbuilder), &_state);
386 0 : memset(p_struct, 0, sizeof(alglib_impl::idwbuilder));
387 0 : alglib_impl::_idwbuilder_init(p_struct, &_state, ae_false);
388 0 : ae_state_clear(&_state);
389 0 : }
390 :
391 0 : _idwbuilder_owner::_idwbuilder_owner(const _idwbuilder_owner &rhs)
392 : {
393 : jmp_buf _break_jump;
394 : alglib_impl::ae_state _state;
395 :
396 0 : alglib_impl::ae_state_init(&_state);
397 0 : if( setjmp(_break_jump) )
398 : {
399 0 : if( p_struct!=NULL )
400 : {
401 0 : alglib_impl::_idwbuilder_destroy(p_struct);
402 0 : alglib_impl::ae_free(p_struct);
403 : }
404 0 : p_struct = NULL;
405 : #if !defined(AE_NO_EXCEPTIONS)
406 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
407 : #else
408 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
409 : return;
410 : #endif
411 : }
412 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
413 0 : p_struct = NULL;
414 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwbuilder copy constructor failure (source is not initialized)", &_state);
415 0 : p_struct = (alglib_impl::idwbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwbuilder), &_state);
416 0 : memset(p_struct, 0, sizeof(alglib_impl::idwbuilder));
417 0 : alglib_impl::_idwbuilder_init_copy(p_struct, const_cast<alglib_impl::idwbuilder*>(rhs.p_struct), &_state, ae_false);
418 0 : ae_state_clear(&_state);
419 0 : }
420 :
421 0 : _idwbuilder_owner& _idwbuilder_owner::operator=(const _idwbuilder_owner &rhs)
422 : {
423 0 : if( this==&rhs )
424 0 : return *this;
425 : jmp_buf _break_jump;
426 : alglib_impl::ae_state _state;
427 :
428 0 : alglib_impl::ae_state_init(&_state);
429 0 : if( setjmp(_break_jump) )
430 : {
431 : #if !defined(AE_NO_EXCEPTIONS)
432 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
433 : #else
434 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
435 : return *this;
436 : #endif
437 : }
438 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
439 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwbuilder assignment constructor failure (destination is not initialized)", &_state);
440 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwbuilder assignment constructor failure (source is not initialized)", &_state);
441 0 : alglib_impl::_idwbuilder_destroy(p_struct);
442 0 : memset(p_struct, 0, sizeof(alglib_impl::idwbuilder));
443 0 : alglib_impl::_idwbuilder_init_copy(p_struct, const_cast<alglib_impl::idwbuilder*>(rhs.p_struct), &_state, ae_false);
444 0 : ae_state_clear(&_state);
445 0 : return *this;
446 : }
447 :
448 0 : _idwbuilder_owner::~_idwbuilder_owner()
449 : {
450 0 : if( p_struct!=NULL )
451 : {
452 0 : alglib_impl::_idwbuilder_destroy(p_struct);
453 0 : ae_free(p_struct);
454 : }
455 0 : }
456 :
457 0 : alglib_impl::idwbuilder* _idwbuilder_owner::c_ptr()
458 : {
459 0 : return p_struct;
460 : }
461 :
462 0 : alglib_impl::idwbuilder* _idwbuilder_owner::c_ptr() const
463 : {
464 0 : return const_cast<alglib_impl::idwbuilder*>(p_struct);
465 : }
466 0 : idwbuilder::idwbuilder() : _idwbuilder_owner()
467 : {
468 0 : }
469 :
470 0 : idwbuilder::idwbuilder(const idwbuilder &rhs):_idwbuilder_owner(rhs)
471 : {
472 0 : }
473 :
474 0 : idwbuilder& idwbuilder::operator=(const idwbuilder &rhs)
475 : {
476 0 : if( this==&rhs )
477 0 : return *this;
478 0 : _idwbuilder_owner::operator=(rhs);
479 0 : return *this;
480 : }
481 :
482 0 : idwbuilder::~idwbuilder()
483 : {
484 0 : }
485 :
486 :
487 : /*************************************************************************
488 : IDW fitting report:
489 : rmserror RMS error
490 : avgerror average error
491 : maxerror maximum error
492 : r2 coefficient of determination, R-squared, 1-RSS/TSS
493 : *************************************************************************/
494 0 : _idwreport_owner::_idwreport_owner()
495 : {
496 : jmp_buf _break_jump;
497 : alglib_impl::ae_state _state;
498 :
499 0 : alglib_impl::ae_state_init(&_state);
500 0 : if( setjmp(_break_jump) )
501 : {
502 0 : if( p_struct!=NULL )
503 : {
504 0 : alglib_impl::_idwreport_destroy(p_struct);
505 0 : alglib_impl::ae_free(p_struct);
506 : }
507 0 : p_struct = NULL;
508 : #if !defined(AE_NO_EXCEPTIONS)
509 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
510 : #else
511 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
512 : return;
513 : #endif
514 : }
515 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
516 0 : p_struct = NULL;
517 0 : p_struct = (alglib_impl::idwreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwreport), &_state);
518 0 : memset(p_struct, 0, sizeof(alglib_impl::idwreport));
519 0 : alglib_impl::_idwreport_init(p_struct, &_state, ae_false);
520 0 : ae_state_clear(&_state);
521 0 : }
522 :
523 0 : _idwreport_owner::_idwreport_owner(const _idwreport_owner &rhs)
524 : {
525 : jmp_buf _break_jump;
526 : alglib_impl::ae_state _state;
527 :
528 0 : alglib_impl::ae_state_init(&_state);
529 0 : if( setjmp(_break_jump) )
530 : {
531 0 : if( p_struct!=NULL )
532 : {
533 0 : alglib_impl::_idwreport_destroy(p_struct);
534 0 : alglib_impl::ae_free(p_struct);
535 : }
536 0 : p_struct = NULL;
537 : #if !defined(AE_NO_EXCEPTIONS)
538 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
539 : #else
540 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
541 : return;
542 : #endif
543 : }
544 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
545 0 : p_struct = NULL;
546 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwreport copy constructor failure (source is not initialized)", &_state);
547 0 : p_struct = (alglib_impl::idwreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::idwreport), &_state);
548 0 : memset(p_struct, 0, sizeof(alglib_impl::idwreport));
549 0 : alglib_impl::_idwreport_init_copy(p_struct, const_cast<alglib_impl::idwreport*>(rhs.p_struct), &_state, ae_false);
550 0 : ae_state_clear(&_state);
551 0 : }
552 :
553 0 : _idwreport_owner& _idwreport_owner::operator=(const _idwreport_owner &rhs)
554 : {
555 0 : if( this==&rhs )
556 0 : return *this;
557 : jmp_buf _break_jump;
558 : alglib_impl::ae_state _state;
559 :
560 0 : alglib_impl::ae_state_init(&_state);
561 0 : if( setjmp(_break_jump) )
562 : {
563 : #if !defined(AE_NO_EXCEPTIONS)
564 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
565 : #else
566 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
567 : return *this;
568 : #endif
569 : }
570 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
571 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: idwreport assignment constructor failure (destination is not initialized)", &_state);
572 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: idwreport assignment constructor failure (source is not initialized)", &_state);
573 0 : alglib_impl::_idwreport_destroy(p_struct);
574 0 : memset(p_struct, 0, sizeof(alglib_impl::idwreport));
575 0 : alglib_impl::_idwreport_init_copy(p_struct, const_cast<alglib_impl::idwreport*>(rhs.p_struct), &_state, ae_false);
576 0 : ae_state_clear(&_state);
577 0 : return *this;
578 : }
579 :
580 0 : _idwreport_owner::~_idwreport_owner()
581 : {
582 0 : if( p_struct!=NULL )
583 : {
584 0 : alglib_impl::_idwreport_destroy(p_struct);
585 0 : ae_free(p_struct);
586 : }
587 0 : }
588 :
589 0 : alglib_impl::idwreport* _idwreport_owner::c_ptr()
590 : {
591 0 : return p_struct;
592 : }
593 :
594 0 : alglib_impl::idwreport* _idwreport_owner::c_ptr() const
595 : {
596 0 : return const_cast<alglib_impl::idwreport*>(p_struct);
597 : }
598 0 : idwreport::idwreport() : _idwreport_owner() ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2)
599 : {
600 0 : }
601 :
602 0 : idwreport::idwreport(const idwreport &rhs):_idwreport_owner(rhs) ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2)
603 : {
604 0 : }
605 :
606 0 : idwreport& idwreport::operator=(const idwreport &rhs)
607 : {
608 0 : if( this==&rhs )
609 0 : return *this;
610 0 : _idwreport_owner::operator=(rhs);
611 0 : return *this;
612 : }
613 :
614 0 : idwreport::~idwreport()
615 : {
616 0 : }
617 :
618 :
619 : /*************************************************************************
620 : This function serializes data structure to string.
621 :
622 : Important properties of s_out:
623 : * it contains alphanumeric characters, dots, underscores, minus signs
624 : * these symbols are grouped into words, which are separated by spaces
625 : and Windows-style (CR+LF) newlines
626 : * although serializer uses spaces and CR+LF as separators, you can
627 : replace any separator character by arbitrary combination of spaces,
628 : tabs, Windows or Unix newlines. It allows flexible reformatting of
629 : the string in case you want to include it into text or XML file.
630 : But you should not insert separators into the middle of the "words"
631 : nor you should change case of letters.
632 : * s_out can be freely moved between 32-bit and 64-bit systems, little
633 : and big endian machines, and so on. You can serialize structure on
634 : 32-bit machine and unserialize it on 64-bit one (or vice versa), or
635 : serialize it on SPARC and unserialize on x86. You can also
636 : serialize it in C++ version of ALGLIB and unserialize in C# one,
637 : and vice versa.
638 : *************************************************************************/
639 0 : void idwserialize(idwmodel &obj, std::string &s_out)
640 : {
641 : jmp_buf _break_jump;
642 : alglib_impl::ae_state state;
643 : alglib_impl::ae_serializer serializer;
644 : alglib_impl::ae_int_t ssize;
645 :
646 0 : alglib_impl::ae_state_init(&state);
647 0 : if( setjmp(_break_jump) )
648 : {
649 : #if !defined(AE_NO_EXCEPTIONS)
650 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
651 : #else
652 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
653 : return;
654 : #endif
655 : }
656 0 : ae_state_set_break_jump(&state, &_break_jump);
657 0 : alglib_impl::ae_serializer_init(&serializer);
658 0 : alglib_impl::ae_serializer_alloc_start(&serializer);
659 0 : alglib_impl::idwalloc(&serializer, obj.c_ptr(), &state);
660 0 : ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer);
661 0 : s_out.clear();
662 0 : s_out.reserve((size_t)(ssize+1));
663 0 : alglib_impl::ae_serializer_sstart_str(&serializer, &s_out);
664 0 : alglib_impl::idwserialize(&serializer, obj.c_ptr(), &state);
665 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
666 0 : alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state);
667 0 : alglib_impl::ae_serializer_clear(&serializer);
668 0 : alglib_impl::ae_state_clear(&state);
669 0 : }
670 : /*************************************************************************
671 : This function unserializes data structure from string.
672 : *************************************************************************/
673 0 : void idwunserialize(const std::string &s_in, idwmodel &obj)
674 : {
675 : jmp_buf _break_jump;
676 : alglib_impl::ae_state state;
677 : alglib_impl::ae_serializer serializer;
678 :
679 0 : alglib_impl::ae_state_init(&state);
680 0 : if( setjmp(_break_jump) )
681 : {
682 : #if !defined(AE_NO_EXCEPTIONS)
683 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
684 : #else
685 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
686 : return;
687 : #endif
688 : }
689 0 : ae_state_set_break_jump(&state, &_break_jump);
690 0 : alglib_impl::ae_serializer_init(&serializer);
691 0 : alglib_impl::ae_serializer_ustart_str(&serializer, &s_in);
692 0 : alglib_impl::idwunserialize(&serializer, obj.c_ptr(), &state);
693 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
694 0 : alglib_impl::ae_serializer_clear(&serializer);
695 0 : alglib_impl::ae_state_clear(&state);
696 0 : }
697 :
698 :
699 : /*************************************************************************
700 : This function serializes data structure to C++ stream.
701 :
702 : Data stream generated by this function is same as string representation
703 : generated by string version of serializer - alphanumeric characters,
704 : dots, underscores, minus signs, which are grouped into words separated by
705 : spaces and CR+LF.
706 :
707 : We recommend you to read comments on string version of serializer to find
708 : out more about serialization of AlGLIB objects.
709 : *************************************************************************/
710 0 : void idwserialize(idwmodel &obj, std::ostream &s_out)
711 : {
712 : jmp_buf _break_jump;
713 : alglib_impl::ae_state state;
714 : alglib_impl::ae_serializer serializer;
715 :
716 0 : alglib_impl::ae_state_init(&state);
717 0 : if( setjmp(_break_jump) )
718 : {
719 : #if !defined(AE_NO_EXCEPTIONS)
720 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
721 : #else
722 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
723 : return;
724 : #endif
725 : }
726 0 : ae_state_set_break_jump(&state, &_break_jump);
727 0 : alglib_impl::ae_serializer_init(&serializer);
728 0 : alglib_impl::ae_serializer_alloc_start(&serializer);
729 0 : alglib_impl::idwalloc(&serializer, obj.c_ptr(), &state);
730 0 : alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask
731 0 : alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out);
732 0 : alglib_impl::idwserialize(&serializer, obj.c_ptr(), &state);
733 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
734 0 : alglib_impl::ae_serializer_clear(&serializer);
735 0 : alglib_impl::ae_state_clear(&state);
736 0 : }
737 : /*************************************************************************
738 : This function unserializes data structure from stream.
739 : *************************************************************************/
740 0 : void idwunserialize(const std::istream &s_in, idwmodel &obj)
741 : {
742 : jmp_buf _break_jump;
743 : alglib_impl::ae_state state;
744 : alglib_impl::ae_serializer serializer;
745 :
746 0 : alglib_impl::ae_state_init(&state);
747 0 : if( setjmp(_break_jump) )
748 : {
749 : #if !defined(AE_NO_EXCEPTIONS)
750 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
751 : #else
752 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
753 : return;
754 : #endif
755 : }
756 0 : ae_state_set_break_jump(&state, &_break_jump);
757 0 : alglib_impl::ae_serializer_init(&serializer);
758 0 : alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in);
759 0 : alglib_impl::idwunserialize(&serializer, obj.c_ptr(), &state);
760 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
761 0 : alglib_impl::ae_serializer_clear(&serializer);
762 0 : alglib_impl::ae_state_clear(&state);
763 0 : }
764 :
765 : /*************************************************************************
766 : This function creates buffer structure which can be used to perform
767 : parallel IDW model evaluations (with one IDW model instance being
768 : used from multiple threads, as long as different threads use different
769 : instances of buffer).
770 :
771 : This buffer object can be used with idwtscalcbuf() function (here "ts"
772 : stands for "thread-safe", "buf" is a suffix which denotes function which
773 : reuses previously allocated output space).
774 :
775 : How to use it:
776 : * create IDW model structure or load it from file
777 : * call idwcreatecalcbuffer(), once per thread working with IDW model (you
778 : should call this function only AFTER model initialization, see below for
779 : more information)
780 : * call idwtscalcbuf() from different threads, with each thread working
781 : with its own copy of buffer object.
782 :
783 : INPUT PARAMETERS
784 : S - IDW model
785 :
786 : OUTPUT PARAMETERS
787 : Buf - external buffer.
788 :
789 :
790 : IMPORTANT: buffer object should be used only with IDW model object which
791 : was used to initialize buffer. Any attempt to use buffer with
792 : different object is dangerous - you may get memory violation
793 : error because sizes of internal arrays do not fit to dimensions
794 : of the IDW structure.
795 :
796 : IMPORTANT: you should call this function only for model which was built
797 : with model builder (or unserialized from file). Sizes of some
798 : internal structures are determined only after model is built,
799 : so buffer object created before model construction stage will
800 : be useless (and any attempt to use it will result in exception).
801 :
802 : -- ALGLIB --
803 : Copyright 22.10.2018 by Sergey Bochkanov
804 : *************************************************************************/
805 0 : void idwcreatecalcbuffer(const idwmodel &s, idwcalcbuffer &buf, const xparams _xparams)
806 : {
807 : jmp_buf _break_jump;
808 : alglib_impl::ae_state _alglib_env_state;
809 0 : alglib_impl::ae_state_init(&_alglib_env_state);
810 0 : if( setjmp(_break_jump) )
811 : {
812 : #if !defined(AE_NO_EXCEPTIONS)
813 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
814 : #else
815 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
816 : return;
817 : #endif
818 : }
819 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
820 0 : if( _xparams.flags!=0x0 )
821 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
822 0 : alglib_impl::idwcreatecalcbuffer(const_cast<alglib_impl::idwmodel*>(s.c_ptr()), const_cast<alglib_impl::idwcalcbuffer*>(buf.c_ptr()), &_alglib_env_state);
823 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
824 0 : return;
825 : }
826 :
827 : /*************************************************************************
828 : This subroutine creates builder object used to generate IDW model from
829 : irregularly sampled (scattered) dataset. Multidimensional scalar/vector-
830 : -valued are supported.
831 :
832 : Builder object is used to fit model to data as follows:
833 : * builder object is created with idwbuildercreate() function
834 : * dataset is added with idwbuildersetpoints() function
835 : * one of the modern IDW algorithms is chosen with either:
836 : * idwbuildersetalgomstab() - Multilayer STABilized algorithm (interpolation)
837 : Alternatively, one of the textbook algorithms can be chosen (not recommended):
838 : * idwbuildersetalgotextbookshepard() - textbook Shepard algorithm
839 : * idwbuildersetalgotextbookmodshepard()-textbook modified Shepard algorithm
840 : * finally, model construction is performed with idwfit() function.
841 :
842 : ! COMMERCIAL EDITION OF ALGLIB:
843 : !
844 : ! Commercial Edition of ALGLIB includes following important improvements
845 : ! of this function:
846 : ! * high-performance native backend with same C# interface (C# version)
847 : ! * multithreading support (C++ and C# versions)
848 : !
849 : ! We recommend you to read 'Working with commercial version' section of
850 : ! ALGLIB Reference Manual in order to find out how to use performance-
851 : ! related features provided by commercial edition of ALGLIB.
852 :
853 : INPUT PARAMETERS:
854 : NX - dimensionality of the argument, NX>=1
855 : NY - dimensionality of the function being modeled, NY>=1;
856 : NY=1 corresponds to classic scalar function, NY>=1 corresponds
857 : to vector-valued function.
858 :
859 : OUTPUT PARAMETERS:
860 : State- builder object
861 :
862 : -- ALGLIB PROJECT --
863 : Copyright 22.10.2018 by Bochkanov Sergey
864 : *************************************************************************/
865 0 : void idwbuildercreate(const ae_int_t nx, const ae_int_t ny, idwbuilder &state, const xparams _xparams)
866 : {
867 : jmp_buf _break_jump;
868 : alglib_impl::ae_state _alglib_env_state;
869 0 : alglib_impl::ae_state_init(&_alglib_env_state);
870 0 : if( setjmp(_break_jump) )
871 : {
872 : #if !defined(AE_NO_EXCEPTIONS)
873 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
874 : #else
875 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
876 : return;
877 : #endif
878 : }
879 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
880 0 : if( _xparams.flags!=0x0 )
881 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
882 0 : alglib_impl::idwbuildercreate(nx, ny, const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), &_alglib_env_state);
883 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
884 0 : return;
885 : }
886 :
887 : /*************************************************************************
888 : This function changes number of layers used by IDW-MSTAB algorithm.
889 :
890 : The more layers you have, the finer details can be reproduced with IDW
891 : model. The less layers you have, the less memory and CPU time is consumed
892 : by the model.
893 :
894 : Memory consumption grows linearly with layers count, running time grows
895 : sub-linearly.
896 :
897 : The default number of layers is 16, which allows you to reproduce details
898 : at distance down to SRad/65536. You will rarely need to change it.
899 :
900 : INPUT PARAMETERS:
901 : State - builder object
902 : NLayers - NLayers>=1, the number of layers used by the model.
903 :
904 : -- ALGLIB --
905 : Copyright 22.10.2018 by Bochkanov Sergey
906 : *************************************************************************/
907 0 : void idwbuildersetnlayers(const idwbuilder &state, const ae_int_t nlayers, const xparams _xparams)
908 : {
909 : jmp_buf _break_jump;
910 : alglib_impl::ae_state _alglib_env_state;
911 0 : alglib_impl::ae_state_init(&_alglib_env_state);
912 0 : if( setjmp(_break_jump) )
913 : {
914 : #if !defined(AE_NO_EXCEPTIONS)
915 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
916 : #else
917 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
918 : return;
919 : #endif
920 : }
921 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
922 0 : if( _xparams.flags!=0x0 )
923 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
924 0 : alglib_impl::idwbuildersetnlayers(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), nlayers, &_alglib_env_state);
925 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
926 0 : return;
927 : }
928 :
929 : /*************************************************************************
930 : This function adds dataset to the builder object.
931 :
932 : This function overrides results of the previous calls, i.e. multiple calls
933 : of this function will result in only the last set being added.
934 :
935 : INPUT PARAMETERS:
936 : State - builder object
937 : XY - points, array[N,NX+NY]. One row corresponds to one point
938 : in the dataset. First NX elements are coordinates, next
939 : NY elements are function values. Array may be larger than
940 : specified, in this case only leading [N,NX+NY] elements
941 : will be used.
942 : N - number of points in the dataset, N>=0.
943 :
944 : -- ALGLIB --
945 : Copyright 22.10.2018 by Bochkanov Sergey
946 : *************************************************************************/
947 0 : void idwbuildersetpoints(const idwbuilder &state, const real_2d_array &xy, const ae_int_t n, const xparams _xparams)
948 : {
949 : jmp_buf _break_jump;
950 : alglib_impl::ae_state _alglib_env_state;
951 0 : alglib_impl::ae_state_init(&_alglib_env_state);
952 0 : if( setjmp(_break_jump) )
953 : {
954 : #if !defined(AE_NO_EXCEPTIONS)
955 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
956 : #else
957 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
958 : return;
959 : #endif
960 : }
961 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
962 0 : if( _xparams.flags!=0x0 )
963 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
964 0 : alglib_impl::idwbuildersetpoints(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, &_alglib_env_state);
965 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
966 0 : return;
967 : }
968 :
969 : /*************************************************************************
970 : This function adds dataset to the builder object.
971 :
972 : This function overrides results of the previous calls, i.e. multiple calls
973 : of this function will result in only the last set being added.
974 :
975 : INPUT PARAMETERS:
976 : State - builder object
977 : XY - points, array[N,NX+NY]. One row corresponds to one point
978 : in the dataset. First NX elements are coordinates, next
979 : NY elements are function values. Array may be larger than
980 : specified, in this case only leading [N,NX+NY] elements
981 : will be used.
982 : N - number of points in the dataset, N>=0.
983 :
984 : -- ALGLIB --
985 : Copyright 22.10.2018 by Bochkanov Sergey
986 : *************************************************************************/
987 : #if !defined(AE_NO_EXCEPTIONS)
988 0 : void idwbuildersetpoints(const idwbuilder &state, const real_2d_array &xy, const xparams _xparams)
989 : {
990 : jmp_buf _break_jump;
991 : alglib_impl::ae_state _alglib_env_state;
992 : ae_int_t n;
993 :
994 0 : n = xy.rows();
995 0 : alglib_impl::ae_state_init(&_alglib_env_state);
996 0 : if( setjmp(_break_jump) )
997 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
998 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
999 0 : if( _xparams.flags!=0x0 )
1000 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1001 0 : alglib_impl::idwbuildersetpoints(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, &_alglib_env_state);
1002 :
1003 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1004 0 : return;
1005 : }
1006 : #endif
1007 :
1008 : /*************************************************************************
1009 : This function sets IDW model construction algorithm to the Multilayer
1010 : Stabilized IDW method (IDW-MSTAB), a latest incarnation of the inverse
1011 : distance weighting interpolation which fixes shortcomings of the original
1012 : and modified Shepard's variants.
1013 :
1014 : The distinctive features of IDW-MSTAB are:
1015 : 1) exact interpolation is pursued (as opposed to fitting and noise
1016 : suppression)
1017 : 2) improved robustness when compared with that of other algorithms:
1018 : * MSTAB shows almost no strange fitting artifacts like ripples and
1019 : sharp spikes (unlike N-dimensional splines and HRBFs)
1020 : * MSTAB does not return function values far from the interval spanned
1021 : by the dataset; say, if all your points have |f|<=1, you can be sure
1022 : that model value won't deviate too much from [-1,+1]
1023 : 3) good model construction time competing with that of HRBFs and bicubic
1024 : splines
1025 : 4) ability to work with any number of dimensions, starting from NX=1
1026 :
1027 : The drawbacks of IDW-MSTAB (and all IDW algorithms in general) are:
1028 : 1) dependence of the model evaluation time on the search radius
1029 : 2) bad extrapolation properties, models built by this method are usually
1030 : conservative in their predictions
1031 :
1032 : Thus, IDW-MSTAB is a good "default" option if you want to perform
1033 : scattered multidimensional interpolation. Although it has its drawbacks,
1034 : it is easy to use and robust, which makes it a good first step.
1035 :
1036 :
1037 : INPUT PARAMETERS:
1038 : State - builder object
1039 : SRad - initial search radius, SRad>0 is required. A model value
1040 : is obtained by "smart" averaging of the dataset points
1041 : within search radius.
1042 :
1043 : NOTE 1: IDW interpolation can correctly handle ANY dataset, including
1044 : datasets with non-distinct points. In case non-distinct points are
1045 : found, an average value for this point will be calculated.
1046 :
1047 : NOTE 2: the memory requirements for model storage are O(NPoints*NLayers).
1048 : The model construction needs twice as much memory as model storage.
1049 :
1050 : NOTE 3: by default 16 IDW layers are built which is enough for most cases.
1051 : You can change this parameter with idwbuildersetnlayers() method.
1052 : Larger values may be necessary if you need to reproduce extrafine
1053 : details at distances smaller than SRad/65536. Smaller value may
1054 : be necessary if you have to save memory and computing time, and
1055 : ready to sacrifice some model quality.
1056 :
1057 :
1058 : ALGORITHM DESCRIPTION
1059 :
1060 : ALGLIB implementation of IDW is somewhat similar to the modified Shepard's
1061 : method (one with search radius R) but overcomes several of its drawbacks,
1062 : namely:
1063 : 1) a tendency to show stepwise behavior for uniform datasets
1064 : 2) a tendency to show terrible interpolation properties for highly
1065 : nonuniform datasets which often arise in geospatial tasks
1066 : (function values are densely sampled across multiple separated
1067 : "tracks")
1068 :
1069 : IDW-MSTAB method performs several passes over dataset and builds a sequence
1070 : of progressively refined IDW models (layers), which starts from one with
1071 : largest search radius SRad and continues to smaller search radii until
1072 : required number of layers is built. Highest layers reproduce global
1073 : behavior of the target function at larger distances whilst lower layers
1074 : reproduce fine details at smaller distances.
1075 :
1076 : Each layer is an IDW model built with following modifications:
1077 : * weights go to zero when distance approach to the current search radius
1078 : * an additional regularizing term is added to the distance: w=1/(d^2+lambda)
1079 : * an additional fictional term with unit weight and zero function value is
1080 : added in order to promote continuity properties at the isolated and
1081 : boundary points
1082 :
1083 : By default, 16 layers is built, which is enough for most cases. You can
1084 : change this parameter with idwbuildersetnlayers() method.
1085 :
1086 : -- ALGLIB --
1087 : Copyright 22.10.2018 by Bochkanov Sergey
1088 : *************************************************************************/
1089 0 : void idwbuildersetalgomstab(const idwbuilder &state, const double srad, const xparams _xparams)
1090 : {
1091 : jmp_buf _break_jump;
1092 : alglib_impl::ae_state _alglib_env_state;
1093 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1094 0 : if( setjmp(_break_jump) )
1095 : {
1096 : #if !defined(AE_NO_EXCEPTIONS)
1097 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1098 : #else
1099 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1100 : return;
1101 : #endif
1102 : }
1103 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1104 0 : if( _xparams.flags!=0x0 )
1105 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1106 0 : alglib_impl::idwbuildersetalgomstab(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), srad, &_alglib_env_state);
1107 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1108 0 : return;
1109 : }
1110 :
1111 : /*************************************************************************
1112 : This function sets IDW model construction algorithm to the textbook
1113 : Shepard's algorithm with custom (user-specified) power parameter.
1114 :
1115 : IMPORTANT: we do NOT recommend using textbook IDW algorithms because they
1116 : have terrible interpolation properties. Use MSTAB in all cases.
1117 :
1118 : INPUT PARAMETERS:
1119 : State - builder object
1120 : P - power parameter, P>0; good value to start with is 2.0
1121 :
1122 : NOTE 1: IDW interpolation can correctly handle ANY dataset, including
1123 : datasets with non-distinct points. In case non-distinct points are
1124 : found, an average value for this point will be calculated.
1125 :
1126 : -- ALGLIB --
1127 : Copyright 22.10.2018 by Bochkanov Sergey
1128 : *************************************************************************/
1129 0 : void idwbuildersetalgotextbookshepard(const idwbuilder &state, const double p, const xparams _xparams)
1130 : {
1131 : jmp_buf _break_jump;
1132 : alglib_impl::ae_state _alglib_env_state;
1133 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1134 0 : if( setjmp(_break_jump) )
1135 : {
1136 : #if !defined(AE_NO_EXCEPTIONS)
1137 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1138 : #else
1139 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1140 : return;
1141 : #endif
1142 : }
1143 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1144 0 : if( _xparams.flags!=0x0 )
1145 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1146 0 : alglib_impl::idwbuildersetalgotextbookshepard(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), p, &_alglib_env_state);
1147 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1148 0 : return;
1149 : }
1150 :
1151 : /*************************************************************************
1152 : This function sets IDW model construction algorithm to the 'textbook'
1153 : modified Shepard's algorithm with user-specified search radius.
1154 :
1155 : IMPORTANT: we do NOT recommend using textbook IDW algorithms because they
1156 : have terrible interpolation properties. Use MSTAB in all cases.
1157 :
1158 : INPUT PARAMETERS:
1159 : State - builder object
1160 : R - search radius
1161 :
1162 : NOTE 1: IDW interpolation can correctly handle ANY dataset, including
1163 : datasets with non-distinct points. In case non-distinct points are
1164 : found, an average value for this point will be calculated.
1165 :
1166 : -- ALGLIB --
1167 : Copyright 22.10.2018 by Bochkanov Sergey
1168 : *************************************************************************/
1169 0 : void idwbuildersetalgotextbookmodshepard(const idwbuilder &state, const double r, const xparams _xparams)
1170 : {
1171 : jmp_buf _break_jump;
1172 : alglib_impl::ae_state _alglib_env_state;
1173 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1174 0 : if( setjmp(_break_jump) )
1175 : {
1176 : #if !defined(AE_NO_EXCEPTIONS)
1177 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1178 : #else
1179 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1180 : return;
1181 : #endif
1182 : }
1183 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1184 0 : if( _xparams.flags!=0x0 )
1185 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1186 0 : alglib_impl::idwbuildersetalgotextbookmodshepard(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), r, &_alglib_env_state);
1187 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1188 0 : return;
1189 : }
1190 :
1191 : /*************************************************************************
1192 : This function sets prior term (model value at infinity) as user-specified
1193 : value.
1194 :
1195 : INPUT PARAMETERS:
1196 : S - spline builder
1197 : V - value for user-defined prior
1198 :
1199 : NOTE: for vector-valued models all components of the prior are set to same
1200 : user-specified value
1201 :
1202 : -- ALGLIB --
1203 : Copyright 29.10.2018 by Bochkanov Sergey
1204 : *************************************************************************/
1205 0 : void idwbuildersetuserterm(const idwbuilder &state, const double v, const xparams _xparams)
1206 : {
1207 : jmp_buf _break_jump;
1208 : alglib_impl::ae_state _alglib_env_state;
1209 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1210 0 : if( setjmp(_break_jump) )
1211 : {
1212 : #if !defined(AE_NO_EXCEPTIONS)
1213 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1214 : #else
1215 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1216 : return;
1217 : #endif
1218 : }
1219 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1220 0 : if( _xparams.flags!=0x0 )
1221 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1222 0 : alglib_impl::idwbuildersetuserterm(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), v, &_alglib_env_state);
1223 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1224 0 : return;
1225 : }
1226 :
1227 : /*************************************************************************
1228 : This function sets constant prior term (model value at infinity).
1229 :
1230 : Constant prior term is determined as mean value over dataset.
1231 :
1232 : INPUT PARAMETERS:
1233 : S - spline builder
1234 :
1235 : -- ALGLIB --
1236 : Copyright 29.10.2018 by Bochkanov Sergey
1237 : *************************************************************************/
1238 0 : void idwbuildersetconstterm(const idwbuilder &state, const xparams _xparams)
1239 : {
1240 : jmp_buf _break_jump;
1241 : alglib_impl::ae_state _alglib_env_state;
1242 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1243 0 : if( setjmp(_break_jump) )
1244 : {
1245 : #if !defined(AE_NO_EXCEPTIONS)
1246 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1247 : #else
1248 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1249 : return;
1250 : #endif
1251 : }
1252 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1253 0 : if( _xparams.flags!=0x0 )
1254 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1255 0 : alglib_impl::idwbuildersetconstterm(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), &_alglib_env_state);
1256 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1257 0 : return;
1258 : }
1259 :
1260 : /*************************************************************************
1261 : This function sets zero prior term (model value at infinity).
1262 :
1263 : INPUT PARAMETERS:
1264 : S - spline builder
1265 :
1266 : -- ALGLIB --
1267 : Copyright 29.10.2018 by Bochkanov Sergey
1268 : *************************************************************************/
1269 0 : void idwbuildersetzeroterm(const idwbuilder &state, const xparams _xparams)
1270 : {
1271 : jmp_buf _break_jump;
1272 : alglib_impl::ae_state _alglib_env_state;
1273 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1274 0 : if( setjmp(_break_jump) )
1275 : {
1276 : #if !defined(AE_NO_EXCEPTIONS)
1277 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1278 : #else
1279 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1280 : return;
1281 : #endif
1282 : }
1283 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1284 0 : if( _xparams.flags!=0x0 )
1285 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1286 0 : alglib_impl::idwbuildersetzeroterm(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), &_alglib_env_state);
1287 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1288 0 : return;
1289 : }
1290 :
1291 : /*************************************************************************
1292 : IDW interpolation: scalar target, 1-dimensional argument
1293 :
1294 : NOTE: this function modifies internal temporaries of the IDW model, thus
1295 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
1296 : evaluation from the multiple threads, use idwtscalcbuf() with per-
1297 : thread buffer object.
1298 :
1299 : INPUT PARAMETERS:
1300 : S - IDW interpolant built with IDW builder
1301 : X0 - argument value
1302 :
1303 : Result:
1304 : IDW interpolant S(X0)
1305 :
1306 : -- ALGLIB --
1307 : Copyright 22.10.2018 by Bochkanov Sergey
1308 : *************************************************************************/
1309 0 : double idwcalc1(const idwmodel &s, const double x0, const xparams _xparams)
1310 : {
1311 : jmp_buf _break_jump;
1312 : alglib_impl::ae_state _alglib_env_state;
1313 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1314 0 : if( setjmp(_break_jump) )
1315 : {
1316 : #if !defined(AE_NO_EXCEPTIONS)
1317 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1318 : #else
1319 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1320 : return 0;
1321 : #endif
1322 : }
1323 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1324 0 : if( _xparams.flags!=0x0 )
1325 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1326 0 : double result = alglib_impl::idwcalc1(const_cast<alglib_impl::idwmodel*>(s.c_ptr()), x0, &_alglib_env_state);
1327 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1328 0 : return *(reinterpret_cast<double*>(&result));
1329 : }
1330 :
1331 : /*************************************************************************
1332 : IDW interpolation: scalar target, 2-dimensional argument
1333 :
1334 : NOTE: this function modifies internal temporaries of the IDW model, thus
1335 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
1336 : evaluation from the multiple threads, use idwtscalcbuf() with per-
1337 : thread buffer object.
1338 :
1339 : INPUT PARAMETERS:
1340 : S - IDW interpolant built with IDW builder
1341 : X0, X1 - argument value
1342 :
1343 : Result:
1344 : IDW interpolant S(X0,X1)
1345 :
1346 : -- ALGLIB --
1347 : Copyright 22.10.2018 by Bochkanov Sergey
1348 : *************************************************************************/
1349 0 : double idwcalc2(const idwmodel &s, const double x0, const double x1, const xparams _xparams)
1350 : {
1351 : jmp_buf _break_jump;
1352 : alglib_impl::ae_state _alglib_env_state;
1353 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1354 0 : if( setjmp(_break_jump) )
1355 : {
1356 : #if !defined(AE_NO_EXCEPTIONS)
1357 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1358 : #else
1359 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1360 : return 0;
1361 : #endif
1362 : }
1363 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1364 0 : if( _xparams.flags!=0x0 )
1365 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1366 0 : double result = alglib_impl::idwcalc2(const_cast<alglib_impl::idwmodel*>(s.c_ptr()), x0, x1, &_alglib_env_state);
1367 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1368 0 : return *(reinterpret_cast<double*>(&result));
1369 : }
1370 :
1371 : /*************************************************************************
1372 : IDW interpolation: scalar target, 3-dimensional argument
1373 :
1374 : NOTE: this function modifies internal temporaries of the IDW model, thus
1375 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
1376 : evaluation from the multiple threads, use idwtscalcbuf() with per-
1377 : thread buffer object.
1378 :
1379 : INPUT PARAMETERS:
1380 : S - IDW interpolant built with IDW builder
1381 : X0,X1,X2- argument value
1382 :
1383 : Result:
1384 : IDW interpolant S(X0,X1,X2)
1385 :
1386 : -- ALGLIB --
1387 : Copyright 22.10.2018 by Bochkanov Sergey
1388 : *************************************************************************/
1389 0 : double idwcalc3(const idwmodel &s, const double x0, const double x1, const double x2, const xparams _xparams)
1390 : {
1391 : jmp_buf _break_jump;
1392 : alglib_impl::ae_state _alglib_env_state;
1393 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1394 0 : if( setjmp(_break_jump) )
1395 : {
1396 : #if !defined(AE_NO_EXCEPTIONS)
1397 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1398 : #else
1399 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1400 : return 0;
1401 : #endif
1402 : }
1403 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1404 0 : if( _xparams.flags!=0x0 )
1405 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1406 0 : double result = alglib_impl::idwcalc3(const_cast<alglib_impl::idwmodel*>(s.c_ptr()), x0, x1, x2, &_alglib_env_state);
1407 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1408 0 : return *(reinterpret_cast<double*>(&result));
1409 : }
1410 :
1411 : /*************************************************************************
1412 : This function calculates values of the IDW model at the given point.
1413 :
1414 : This is general function which can be used for arbitrary NX (dimension of
1415 : the space of arguments) and NY (dimension of the function itself). However
1416 : when you have NY=1 you may find more convenient to use idwcalc1(),
1417 : idwcalc2() or idwcalc3().
1418 :
1419 : NOTE: this function modifies internal temporaries of the IDW model, thus
1420 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
1421 : evaluation from the multiple threads, use idwtscalcbuf() with per-
1422 : thread buffer object.
1423 :
1424 : INPUT PARAMETERS:
1425 : S - IDW model
1426 : X - coordinates, array[NX]. X may have more than NX elements,
1427 : in this case only leading NX will be used.
1428 :
1429 : OUTPUT PARAMETERS:
1430 : Y - function value, array[NY]. Y is out-parameter and will be
1431 : reallocated after call to this function. In case you want
1432 : to reuse previously allocated Y, you may use idwcalcbuf(),
1433 : which reallocates Y only when it is too small.
1434 :
1435 : -- ALGLIB --
1436 : Copyright 22.10.2018 by Bochkanov Sergey
1437 : *************************************************************************/
1438 0 : void idwcalc(const idwmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
1439 : {
1440 : jmp_buf _break_jump;
1441 : alglib_impl::ae_state _alglib_env_state;
1442 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1443 0 : if( setjmp(_break_jump) )
1444 : {
1445 : #if !defined(AE_NO_EXCEPTIONS)
1446 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1447 : #else
1448 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1449 : return;
1450 : #endif
1451 : }
1452 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1453 0 : if( _xparams.flags!=0x0 )
1454 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1455 0 : alglib_impl::idwcalc(const_cast<alglib_impl::idwmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1456 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1457 0 : return;
1458 : }
1459 :
1460 : /*************************************************************************
1461 : This function calculates values of the IDW model at the given point.
1462 :
1463 : Same as idwcalc(), but does not reallocate Y when in is large enough to
1464 : store function values.
1465 :
1466 : NOTE: this function modifies internal temporaries of the IDW model, thus
1467 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
1468 : evaluation from the multiple threads, use idwtscalcbuf() with per-
1469 : thread buffer object.
1470 :
1471 : INPUT PARAMETERS:
1472 : S - IDW model
1473 : X - coordinates, array[NX]. X may have more than NX elements,
1474 : in this case only leading NX will be used.
1475 : Y - possibly preallocated array
1476 :
1477 : OUTPUT PARAMETERS:
1478 : Y - function value, array[NY]. Y is not reallocated when it
1479 : is larger than NY.
1480 :
1481 : -- ALGLIB --
1482 : Copyright 22.10.2018 by Bochkanov Sergey
1483 : *************************************************************************/
1484 0 : void idwcalcbuf(const idwmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
1485 : {
1486 : jmp_buf _break_jump;
1487 : alglib_impl::ae_state _alglib_env_state;
1488 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1489 0 : if( setjmp(_break_jump) )
1490 : {
1491 : #if !defined(AE_NO_EXCEPTIONS)
1492 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1493 : #else
1494 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1495 : return;
1496 : #endif
1497 : }
1498 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1499 0 : if( _xparams.flags!=0x0 )
1500 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1501 0 : alglib_impl::idwcalcbuf(const_cast<alglib_impl::idwmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1502 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1503 0 : return;
1504 : }
1505 :
1506 : /*************************************************************************
1507 : This function calculates values of the IDW model at the given point, using
1508 : external buffer object (internal temporaries of IDW model are not
1509 : modified).
1510 :
1511 : This function allows to use same IDW model object in different threads,
1512 : assuming that different threads use different instances of the buffer
1513 : structure.
1514 :
1515 : INPUT PARAMETERS:
1516 : S - IDW model, may be shared between different threads
1517 : Buf - buffer object created for this particular instance of IDW
1518 : model with idwcreatecalcbuffer().
1519 : X - coordinates, array[NX]. X may have more than NX elements,
1520 : in this case only leading NX will be used.
1521 : Y - possibly preallocated array
1522 :
1523 : OUTPUT PARAMETERS:
1524 : Y - function value, array[NY]. Y is not reallocated when it
1525 : is larger than NY.
1526 :
1527 : -- ALGLIB --
1528 : Copyright 13.12.2011 by Bochkanov Sergey
1529 : *************************************************************************/
1530 0 : void idwtscalcbuf(const idwmodel &s, const idwcalcbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
1531 : {
1532 : jmp_buf _break_jump;
1533 : alglib_impl::ae_state _alglib_env_state;
1534 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1535 0 : if( setjmp(_break_jump) )
1536 : {
1537 : #if !defined(AE_NO_EXCEPTIONS)
1538 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1539 : #else
1540 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1541 : return;
1542 : #endif
1543 : }
1544 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1545 0 : if( _xparams.flags!=0x0 )
1546 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1547 0 : alglib_impl::idwtscalcbuf(const_cast<alglib_impl::idwmodel*>(s.c_ptr()), const_cast<alglib_impl::idwcalcbuffer*>(buf.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1548 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1549 0 : return;
1550 : }
1551 :
1552 : /*************************************************************************
1553 : This function fits IDW model to the dataset using current IDW construction
1554 : algorithm. A model being built and fitting report are returned.
1555 :
1556 : INPUT PARAMETERS:
1557 : State - builder object
1558 :
1559 : OUTPUT PARAMETERS:
1560 : Model - an IDW model built with current algorithm
1561 : Rep - model fitting report, fields of this structure contain
1562 : information about average fitting errors.
1563 :
1564 : NOTE: although IDW-MSTAB algorithm is an interpolation method, i.e. it
1565 : tries to fit the model exactly, it can handle datasets with non-
1566 : distinct points which can not be fit exactly; in such cases least-
1567 : squares fitting is performed.
1568 :
1569 : -- ALGLIB --
1570 : Copyright 22.10.2018 by Bochkanov Sergey
1571 : *************************************************************************/
1572 0 : void idwfit(const idwbuilder &state, idwmodel &model, idwreport &rep, const xparams _xparams)
1573 : {
1574 : jmp_buf _break_jump;
1575 : alglib_impl::ae_state _alglib_env_state;
1576 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1577 0 : if( setjmp(_break_jump) )
1578 : {
1579 : #if !defined(AE_NO_EXCEPTIONS)
1580 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1581 : #else
1582 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1583 : return;
1584 : #endif
1585 : }
1586 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1587 0 : if( _xparams.flags!=0x0 )
1588 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1589 0 : alglib_impl::idwfit(const_cast<alglib_impl::idwbuilder*>(state.c_ptr()), const_cast<alglib_impl::idwmodel*>(model.c_ptr()), const_cast<alglib_impl::idwreport*>(rep.c_ptr()), &_alglib_env_state);
1590 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1591 0 : return;
1592 : }
1593 : #endif
1594 :
1595 : #if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD)
1596 : /*************************************************************************
1597 : Barycentric interpolant.
1598 : *************************************************************************/
1599 0 : _barycentricinterpolant_owner::_barycentricinterpolant_owner()
1600 : {
1601 : jmp_buf _break_jump;
1602 : alglib_impl::ae_state _state;
1603 :
1604 0 : alglib_impl::ae_state_init(&_state);
1605 0 : if( setjmp(_break_jump) )
1606 : {
1607 0 : if( p_struct!=NULL )
1608 : {
1609 0 : alglib_impl::_barycentricinterpolant_destroy(p_struct);
1610 0 : alglib_impl::ae_free(p_struct);
1611 : }
1612 0 : p_struct = NULL;
1613 : #if !defined(AE_NO_EXCEPTIONS)
1614 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
1615 : #else
1616 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
1617 : return;
1618 : #endif
1619 : }
1620 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
1621 0 : p_struct = NULL;
1622 0 : p_struct = (alglib_impl::barycentricinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricinterpolant), &_state);
1623 0 : memset(p_struct, 0, sizeof(alglib_impl::barycentricinterpolant));
1624 0 : alglib_impl::_barycentricinterpolant_init(p_struct, &_state, ae_false);
1625 0 : ae_state_clear(&_state);
1626 0 : }
1627 :
1628 0 : _barycentricinterpolant_owner::_barycentricinterpolant_owner(const _barycentricinterpolant_owner &rhs)
1629 : {
1630 : jmp_buf _break_jump;
1631 : alglib_impl::ae_state _state;
1632 :
1633 0 : alglib_impl::ae_state_init(&_state);
1634 0 : if( setjmp(_break_jump) )
1635 : {
1636 0 : if( p_struct!=NULL )
1637 : {
1638 0 : alglib_impl::_barycentricinterpolant_destroy(p_struct);
1639 0 : alglib_impl::ae_free(p_struct);
1640 : }
1641 0 : p_struct = NULL;
1642 : #if !defined(AE_NO_EXCEPTIONS)
1643 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
1644 : #else
1645 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
1646 : return;
1647 : #endif
1648 : }
1649 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
1650 0 : p_struct = NULL;
1651 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricinterpolant copy constructor failure (source is not initialized)", &_state);
1652 0 : p_struct = (alglib_impl::barycentricinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricinterpolant), &_state);
1653 0 : memset(p_struct, 0, sizeof(alglib_impl::barycentricinterpolant));
1654 0 : alglib_impl::_barycentricinterpolant_init_copy(p_struct, const_cast<alglib_impl::barycentricinterpolant*>(rhs.p_struct), &_state, ae_false);
1655 0 : ae_state_clear(&_state);
1656 0 : }
1657 :
1658 0 : _barycentricinterpolant_owner& _barycentricinterpolant_owner::operator=(const _barycentricinterpolant_owner &rhs)
1659 : {
1660 0 : if( this==&rhs )
1661 0 : return *this;
1662 : jmp_buf _break_jump;
1663 : alglib_impl::ae_state _state;
1664 :
1665 0 : alglib_impl::ae_state_init(&_state);
1666 0 : if( setjmp(_break_jump) )
1667 : {
1668 : #if !defined(AE_NO_EXCEPTIONS)
1669 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
1670 : #else
1671 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
1672 : return *this;
1673 : #endif
1674 : }
1675 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
1676 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: barycentricinterpolant assignment constructor failure (destination is not initialized)", &_state);
1677 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricinterpolant assignment constructor failure (source is not initialized)", &_state);
1678 0 : alglib_impl::_barycentricinterpolant_destroy(p_struct);
1679 0 : memset(p_struct, 0, sizeof(alglib_impl::barycentricinterpolant));
1680 0 : alglib_impl::_barycentricinterpolant_init_copy(p_struct, const_cast<alglib_impl::barycentricinterpolant*>(rhs.p_struct), &_state, ae_false);
1681 0 : ae_state_clear(&_state);
1682 0 : return *this;
1683 : }
1684 :
1685 0 : _barycentricinterpolant_owner::~_barycentricinterpolant_owner()
1686 : {
1687 0 : if( p_struct!=NULL )
1688 : {
1689 0 : alglib_impl::_barycentricinterpolant_destroy(p_struct);
1690 0 : ae_free(p_struct);
1691 : }
1692 0 : }
1693 :
1694 0 : alglib_impl::barycentricinterpolant* _barycentricinterpolant_owner::c_ptr()
1695 : {
1696 0 : return p_struct;
1697 : }
1698 :
1699 0 : alglib_impl::barycentricinterpolant* _barycentricinterpolant_owner::c_ptr() const
1700 : {
1701 0 : return const_cast<alglib_impl::barycentricinterpolant*>(p_struct);
1702 : }
1703 0 : barycentricinterpolant::barycentricinterpolant() : _barycentricinterpolant_owner()
1704 : {
1705 0 : }
1706 :
1707 0 : barycentricinterpolant::barycentricinterpolant(const barycentricinterpolant &rhs):_barycentricinterpolant_owner(rhs)
1708 : {
1709 0 : }
1710 :
1711 0 : barycentricinterpolant& barycentricinterpolant::operator=(const barycentricinterpolant &rhs)
1712 : {
1713 0 : if( this==&rhs )
1714 0 : return *this;
1715 0 : _barycentricinterpolant_owner::operator=(rhs);
1716 0 : return *this;
1717 : }
1718 :
1719 0 : barycentricinterpolant::~barycentricinterpolant()
1720 : {
1721 0 : }
1722 :
1723 : /*************************************************************************
1724 : Rational interpolation using barycentric formula
1725 :
1726 : F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
1727 :
1728 : Input parameters:
1729 : B - barycentric interpolant built with one of model building
1730 : subroutines.
1731 : T - interpolation point
1732 :
1733 : Result:
1734 : barycentric interpolant F(t)
1735 :
1736 : -- ALGLIB --
1737 : Copyright 17.08.2009 by Bochkanov Sergey
1738 : *************************************************************************/
1739 0 : double barycentriccalc(const barycentricinterpolant &b, const double t, const xparams _xparams)
1740 : {
1741 : jmp_buf _break_jump;
1742 : alglib_impl::ae_state _alglib_env_state;
1743 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1744 0 : if( setjmp(_break_jump) )
1745 : {
1746 : #if !defined(AE_NO_EXCEPTIONS)
1747 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1748 : #else
1749 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1750 : return 0;
1751 : #endif
1752 : }
1753 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1754 0 : if( _xparams.flags!=0x0 )
1755 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1756 0 : double result = alglib_impl::barycentriccalc(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), t, &_alglib_env_state);
1757 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1758 0 : return *(reinterpret_cast<double*>(&result));
1759 : }
1760 :
1761 : /*************************************************************************
1762 : Differentiation of barycentric interpolant: first derivative.
1763 :
1764 : Algorithm used in this subroutine is very robust and should not fail until
1765 : provided with values too close to MaxRealNumber (usually MaxRealNumber/N
1766 : or greater will overflow).
1767 :
1768 : INPUT PARAMETERS:
1769 : B - barycentric interpolant built with one of model building
1770 : subroutines.
1771 : T - interpolation point
1772 :
1773 : OUTPUT PARAMETERS:
1774 : F - barycentric interpolant at T
1775 : DF - first derivative
1776 :
1777 : NOTE
1778 :
1779 :
1780 : -- ALGLIB --
1781 : Copyright 17.08.2009 by Bochkanov Sergey
1782 : *************************************************************************/
1783 0 : void barycentricdiff1(const barycentricinterpolant &b, const double t, double &f, double &df, const xparams _xparams)
1784 : {
1785 : jmp_buf _break_jump;
1786 : alglib_impl::ae_state _alglib_env_state;
1787 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1788 0 : if( setjmp(_break_jump) )
1789 : {
1790 : #if !defined(AE_NO_EXCEPTIONS)
1791 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1792 : #else
1793 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1794 : return;
1795 : #endif
1796 : }
1797 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1798 0 : if( _xparams.flags!=0x0 )
1799 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1800 0 : alglib_impl::barycentricdiff1(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), t, &f, &df, &_alglib_env_state);
1801 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1802 0 : return;
1803 : }
1804 :
1805 : /*************************************************************************
1806 : Differentiation of barycentric interpolant: first/second derivatives.
1807 :
1808 : INPUT PARAMETERS:
1809 : B - barycentric interpolant built with one of model building
1810 : subroutines.
1811 : T - interpolation point
1812 :
1813 : OUTPUT PARAMETERS:
1814 : F - barycentric interpolant at T
1815 : DF - first derivative
1816 : D2F - second derivative
1817 :
1818 : NOTE: this algorithm may fail due to overflow/underflor if used on data
1819 : whose values are close to MaxRealNumber or MinRealNumber. Use more robust
1820 : BarycentricDiff1() subroutine in such cases.
1821 :
1822 :
1823 : -- ALGLIB --
1824 : Copyright 17.08.2009 by Bochkanov Sergey
1825 : *************************************************************************/
1826 0 : void barycentricdiff2(const barycentricinterpolant &b, const double t, double &f, double &df, double &d2f, const xparams _xparams)
1827 : {
1828 : jmp_buf _break_jump;
1829 : alglib_impl::ae_state _alglib_env_state;
1830 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1831 0 : if( setjmp(_break_jump) )
1832 : {
1833 : #if !defined(AE_NO_EXCEPTIONS)
1834 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1835 : #else
1836 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1837 : return;
1838 : #endif
1839 : }
1840 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1841 0 : if( _xparams.flags!=0x0 )
1842 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1843 0 : alglib_impl::barycentricdiff2(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), t, &f, &df, &d2f, &_alglib_env_state);
1844 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1845 0 : return;
1846 : }
1847 :
1848 : /*************************************************************************
1849 : This subroutine performs linear transformation of the argument.
1850 :
1851 : INPUT PARAMETERS:
1852 : B - rational interpolant in barycentric form
1853 : CA, CB - transformation coefficients: x = CA*t + CB
1854 :
1855 : OUTPUT PARAMETERS:
1856 : B - transformed interpolant with X replaced by T
1857 :
1858 : -- ALGLIB PROJECT --
1859 : Copyright 19.08.2009 by Bochkanov Sergey
1860 : *************************************************************************/
1861 0 : void barycentriclintransx(const barycentricinterpolant &b, const double ca, const double cb, const xparams _xparams)
1862 : {
1863 : jmp_buf _break_jump;
1864 : alglib_impl::ae_state _alglib_env_state;
1865 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1866 0 : if( setjmp(_break_jump) )
1867 : {
1868 : #if !defined(AE_NO_EXCEPTIONS)
1869 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1870 : #else
1871 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1872 : return;
1873 : #endif
1874 : }
1875 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1876 0 : if( _xparams.flags!=0x0 )
1877 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1878 0 : alglib_impl::barycentriclintransx(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), ca, cb, &_alglib_env_state);
1879 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1880 0 : return;
1881 : }
1882 :
1883 : /*************************************************************************
1884 : This subroutine performs linear transformation of the barycentric
1885 : interpolant.
1886 :
1887 : INPUT PARAMETERS:
1888 : B - rational interpolant in barycentric form
1889 : CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB
1890 :
1891 : OUTPUT PARAMETERS:
1892 : B - transformed interpolant
1893 :
1894 : -- ALGLIB PROJECT --
1895 : Copyright 19.08.2009 by Bochkanov Sergey
1896 : *************************************************************************/
1897 0 : void barycentriclintransy(const barycentricinterpolant &b, const double ca, const double cb, const xparams _xparams)
1898 : {
1899 : jmp_buf _break_jump;
1900 : alglib_impl::ae_state _alglib_env_state;
1901 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1902 0 : if( setjmp(_break_jump) )
1903 : {
1904 : #if !defined(AE_NO_EXCEPTIONS)
1905 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1906 : #else
1907 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1908 : return;
1909 : #endif
1910 : }
1911 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1912 0 : if( _xparams.flags!=0x0 )
1913 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1914 0 : alglib_impl::barycentriclintransy(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), ca, cb, &_alglib_env_state);
1915 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1916 0 : return;
1917 : }
1918 :
1919 : /*************************************************************************
1920 : Extracts X/Y/W arrays from rational interpolant
1921 :
1922 : INPUT PARAMETERS:
1923 : B - barycentric interpolant
1924 :
1925 : OUTPUT PARAMETERS:
1926 : N - nodes count, N>0
1927 : X - interpolation nodes, array[0..N-1]
1928 : F - function values, array[0..N-1]
1929 : W - barycentric weights, array[0..N-1]
1930 :
1931 : -- ALGLIB --
1932 : Copyright 17.08.2009 by Bochkanov Sergey
1933 : *************************************************************************/
1934 0 : void barycentricunpack(const barycentricinterpolant &b, ae_int_t &n, real_1d_array &x, real_1d_array &y, real_1d_array &w, const xparams _xparams)
1935 : {
1936 : jmp_buf _break_jump;
1937 : alglib_impl::ae_state _alglib_env_state;
1938 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1939 0 : if( setjmp(_break_jump) )
1940 : {
1941 : #if !defined(AE_NO_EXCEPTIONS)
1942 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1943 : #else
1944 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1945 : return;
1946 : #endif
1947 : }
1948 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1949 0 : if( _xparams.flags!=0x0 )
1950 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1951 0 : alglib_impl::barycentricunpack(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), &n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), &_alglib_env_state);
1952 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1953 0 : return;
1954 : }
1955 :
1956 : /*************************************************************************
1957 : Rational interpolant from X/Y/W arrays
1958 :
1959 : F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
1960 :
1961 : INPUT PARAMETERS:
1962 : X - interpolation nodes, array[0..N-1]
1963 : F - function values, array[0..N-1]
1964 : W - barycentric weights, array[0..N-1]
1965 : N - nodes count, N>0
1966 :
1967 : OUTPUT PARAMETERS:
1968 : B - barycentric interpolant built from (X, Y, W)
1969 :
1970 : -- ALGLIB --
1971 : Copyright 17.08.2009 by Bochkanov Sergey
1972 : *************************************************************************/
1973 0 : void barycentricbuildxyw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, barycentricinterpolant &b, const xparams _xparams)
1974 : {
1975 : jmp_buf _break_jump;
1976 : alglib_impl::ae_state _alglib_env_state;
1977 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1978 0 : if( setjmp(_break_jump) )
1979 : {
1980 : #if !defined(AE_NO_EXCEPTIONS)
1981 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1982 : #else
1983 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1984 : return;
1985 : #endif
1986 : }
1987 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1988 0 : if( _xparams.flags!=0x0 )
1989 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1990 0 : alglib_impl::barycentricbuildxyw(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), &_alglib_env_state);
1991 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1992 0 : return;
1993 : }
1994 :
1995 : /*************************************************************************
1996 : Rational interpolant without poles
1997 :
1998 : The subroutine constructs the rational interpolating function without real
1999 : poles (see 'Barycentric rational interpolation with no poles and high
2000 : rates of approximation', Michael S. Floater. and Kai Hormann, for more
2001 : information on this subject).
2002 :
2003 : Input parameters:
2004 : X - interpolation nodes, array[0..N-1].
2005 : Y - function values, array[0..N-1].
2006 : N - number of nodes, N>0.
2007 : D - order of the interpolation scheme, 0 <= D <= N-1.
2008 : D<0 will cause an error.
2009 : D>=N it will be replaced with D=N-1.
2010 : if you don't know what D to choose, use small value about 3-5.
2011 :
2012 : Output parameters:
2013 : B - barycentric interpolant.
2014 :
2015 : Note:
2016 : this algorithm always succeeds and calculates the weights with close
2017 : to machine precision.
2018 :
2019 : -- ALGLIB PROJECT --
2020 : Copyright 17.06.2007 by Bochkanov Sergey
2021 : *************************************************************************/
2022 0 : void barycentricbuildfloaterhormann(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t d, barycentricinterpolant &b, const xparams _xparams)
2023 : {
2024 : jmp_buf _break_jump;
2025 : alglib_impl::ae_state _alglib_env_state;
2026 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2027 0 : if( setjmp(_break_jump) )
2028 : {
2029 : #if !defined(AE_NO_EXCEPTIONS)
2030 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2031 : #else
2032 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2033 : return;
2034 : #endif
2035 : }
2036 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2037 0 : if( _xparams.flags!=0x0 )
2038 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2039 0 : alglib_impl::barycentricbuildfloaterhormann(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, d, const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), &_alglib_env_state);
2040 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2041 0 : return;
2042 : }
2043 : #endif
2044 :
2045 : #if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD)
2046 : /*************************************************************************
2047 : Fits least squares (LS) circle (or NX-dimensional sphere) to data (a set
2048 : of points in NX-dimensional space).
2049 :
2050 : Least squares circle minimizes sum of squared deviations between distances
2051 : from points to the center and some "candidate" radius, which is also
2052 : fitted to the data.
2053 :
2054 : INPUT PARAMETERS:
2055 : XY - array[NPoints,NX] (or larger), contains dataset.
2056 : One row = one point in NX-dimensional space.
2057 : NPoints - dataset size, NPoints>0
2058 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
2059 :
2060 : OUTPUT PARAMETERS:
2061 : CX - central point for a sphere
2062 : R - radius
2063 :
2064 : -- ALGLIB --
2065 : Copyright 07.05.2018 by Bochkanov Sergey
2066 : *************************************************************************/
2067 0 : void fitspherels(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &r, const xparams _xparams)
2068 : {
2069 : jmp_buf _break_jump;
2070 : alglib_impl::ae_state _alglib_env_state;
2071 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2072 0 : if( setjmp(_break_jump) )
2073 : {
2074 : #if !defined(AE_NO_EXCEPTIONS)
2075 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2076 : #else
2077 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2078 : return;
2079 : #endif
2080 : }
2081 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2082 0 : if( _xparams.flags!=0x0 )
2083 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2084 0 : alglib_impl::fitspherels(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &r, &_alglib_env_state);
2085 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2086 0 : return;
2087 : }
2088 :
2089 : /*************************************************************************
2090 : Fits minimum circumscribed (MC) circle (or NX-dimensional sphere) to data
2091 : (a set of points in NX-dimensional space).
2092 :
2093 : INPUT PARAMETERS:
2094 : XY - array[NPoints,NX] (or larger), contains dataset.
2095 : One row = one point in NX-dimensional space.
2096 : NPoints - dataset size, NPoints>0
2097 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
2098 :
2099 : OUTPUT PARAMETERS:
2100 : CX - central point for a sphere
2101 : RHi - radius
2102 :
2103 : NOTE: this function is an easy-to-use wrapper around more powerful "expert"
2104 : function fitspherex().
2105 :
2106 : This wrapper is optimized for ease of use and stability - at the
2107 : cost of somewhat lower performance (we have to use very tight
2108 : stopping criteria for inner optimizer because we want to make sure
2109 : that it will converge on any dataset).
2110 :
2111 : If you are ready to experiment with settings of "expert" function,
2112 : you can achieve ~2-4x speedup over standard "bulletproof" settings.
2113 :
2114 :
2115 : -- ALGLIB --
2116 : Copyright 14.04.2017 by Bochkanov Sergey
2117 : *************************************************************************/
2118 0 : void fitspheremc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rhi, const xparams _xparams)
2119 : {
2120 : jmp_buf _break_jump;
2121 : alglib_impl::ae_state _alglib_env_state;
2122 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2123 0 : if( setjmp(_break_jump) )
2124 : {
2125 : #if !defined(AE_NO_EXCEPTIONS)
2126 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2127 : #else
2128 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2129 : return;
2130 : #endif
2131 : }
2132 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2133 0 : if( _xparams.flags!=0x0 )
2134 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2135 0 : alglib_impl::fitspheremc(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rhi, &_alglib_env_state);
2136 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2137 0 : return;
2138 : }
2139 :
2140 : /*************************************************************************
2141 : Fits maximum inscribed circle (or NX-dimensional sphere) to data (a set of
2142 : points in NX-dimensional space).
2143 :
2144 : INPUT PARAMETERS:
2145 : XY - array[NPoints,NX] (or larger), contains dataset.
2146 : One row = one point in NX-dimensional space.
2147 : NPoints - dataset size, NPoints>0
2148 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
2149 :
2150 : OUTPUT PARAMETERS:
2151 : CX - central point for a sphere
2152 : RLo - radius
2153 :
2154 : NOTE: this function is an easy-to-use wrapper around more powerful "expert"
2155 : function fitspherex().
2156 :
2157 : This wrapper is optimized for ease of use and stability - at the
2158 : cost of somewhat lower performance (we have to use very tight
2159 : stopping criteria for inner optimizer because we want to make sure
2160 : that it will converge on any dataset).
2161 :
2162 : If you are ready to experiment with settings of "expert" function,
2163 : you can achieve ~2-4x speedup over standard "bulletproof" settings.
2164 :
2165 :
2166 : -- ALGLIB --
2167 : Copyright 14.04.2017 by Bochkanov Sergey
2168 : *************************************************************************/
2169 0 : void fitspheremi(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, const xparams _xparams)
2170 : {
2171 : jmp_buf _break_jump;
2172 : alglib_impl::ae_state _alglib_env_state;
2173 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2174 0 : if( setjmp(_break_jump) )
2175 : {
2176 : #if !defined(AE_NO_EXCEPTIONS)
2177 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2178 : #else
2179 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2180 : return;
2181 : #endif
2182 : }
2183 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2184 0 : if( _xparams.flags!=0x0 )
2185 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2186 0 : alglib_impl::fitspheremi(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rlo, &_alglib_env_state);
2187 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2188 0 : return;
2189 : }
2190 :
2191 : /*************************************************************************
2192 : Fits minimum zone circle (or NX-dimensional sphere) to data (a set of
2193 : points in NX-dimensional space).
2194 :
2195 : INPUT PARAMETERS:
2196 : XY - array[NPoints,NX] (or larger), contains dataset.
2197 : One row = one point in NX-dimensional space.
2198 : NPoints - dataset size, NPoints>0
2199 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
2200 :
2201 : OUTPUT PARAMETERS:
2202 : CX - central point for a sphere
2203 : RLo - radius of inscribed circle
2204 : RHo - radius of circumscribed circle
2205 :
2206 : NOTE: this function is an easy-to-use wrapper around more powerful "expert"
2207 : function fitspherex().
2208 :
2209 : This wrapper is optimized for ease of use and stability - at the
2210 : cost of somewhat lower performance (we have to use very tight
2211 : stopping criteria for inner optimizer because we want to make sure
2212 : that it will converge on any dataset).
2213 :
2214 : If you are ready to experiment with settings of "expert" function,
2215 : you can achieve ~2-4x speedup over standard "bulletproof" settings.
2216 :
2217 :
2218 : -- ALGLIB --
2219 : Copyright 14.04.2017 by Bochkanov Sergey
2220 : *************************************************************************/
2221 0 : void fitspheremz(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams)
2222 : {
2223 : jmp_buf _break_jump;
2224 : alglib_impl::ae_state _alglib_env_state;
2225 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2226 0 : if( setjmp(_break_jump) )
2227 : {
2228 : #if !defined(AE_NO_EXCEPTIONS)
2229 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2230 : #else
2231 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2232 : return;
2233 : #endif
2234 : }
2235 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2236 0 : if( _xparams.flags!=0x0 )
2237 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2238 0 : alglib_impl::fitspheremz(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state);
2239 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2240 0 : return;
2241 : }
2242 :
2243 : /*************************************************************************
2244 : Fitting minimum circumscribed, maximum inscribed or minimum zone circles
2245 : (or NX-dimensional spheres) to data (a set of points in NX-dimensional
2246 : space).
2247 :
2248 : This is expert function which allows to tweak many parameters of
2249 : underlying nonlinear solver:
2250 : * stopping criteria for inner iterations
2251 : * number of outer iterations
2252 : * penalty coefficient used to handle nonlinear constraints (we convert
2253 : unconstrained nonsmooth optimization problem ivolving max() and/or min()
2254 : operations to quadratically constrained smooth one).
2255 :
2256 : You may tweak all these parameters or only some of them, leaving other
2257 : ones at their default state - just specify zero value, and solver will
2258 : fill it with appropriate default one.
2259 :
2260 : These comments also include some discussion of approach used to handle
2261 : such unusual fitting problem, its stability, drawbacks of alternative
2262 : methods, and convergence properties.
2263 :
2264 : INPUT PARAMETERS:
2265 : XY - array[NPoints,NX] (or larger), contains dataset.
2266 : One row = one point in NX-dimensional space.
2267 : NPoints - dataset size, NPoints>0
2268 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
2269 : ProblemType-used to encode problem type:
2270 : * 0 for least squares circle
2271 : * 1 for minimum circumscribed circle/sphere fitting (MC)
2272 : * 2 for maximum inscribed circle/sphere fitting (MI)
2273 : * 3 for minimum zone circle fitting (difference between
2274 : Rhi and Rlo is minimized), denoted as MZ
2275 : EpsX - stopping condition for NLC optimizer:
2276 : * must be non-negative
2277 : * use 0 to choose default value (1.0E-12 is used by default)
2278 : * you may specify larger values, up to 1.0E-6, if you want
2279 : to speed-up solver; NLC solver performs several
2280 : preconditioned outer iterations, so final result
2281 : typically has precision much better than EpsX.
2282 : AULIts - number of outer iterations performed by NLC optimizer:
2283 : * must be non-negative
2284 : * use 0 to choose default value (20 is used by default)
2285 : * you may specify values smaller than 20 if you want to
2286 : speed up solver; 10 often results in good combination of
2287 : precision and speed; sometimes you may get good results
2288 : with just 6 outer iterations.
2289 : Ignored for ProblemType=0.
2290 : Penalty - penalty coefficient for NLC optimizer:
2291 : * must be non-negative
2292 : * use 0 to choose default value (1.0E6 in current version)
2293 : * it should be really large, 1.0E6...1.0E7 is a good value
2294 : to start from;
2295 : * generally, default value is good enough
2296 : Ignored for ProblemType=0.
2297 :
2298 : OUTPUT PARAMETERS:
2299 : CX - central point for a sphere
2300 : RLo - radius:
2301 : * for ProblemType=2,3, radius of the inscribed sphere
2302 : * for ProblemType=0 - radius of the least squares sphere
2303 : * for ProblemType=1 - zero
2304 : RHo - radius:
2305 : * for ProblemType=1,3, radius of the circumscribed sphere
2306 : * for ProblemType=0 - radius of the least squares sphere
2307 : * for ProblemType=2 - zero
2308 :
2309 : NOTE: ON THE UNIQUENESS OF SOLUTIONS
2310 :
2311 : ALGLIB provides solution to several related circle fitting problems: MC
2312 : (minimum circumscribed), MI (maximum inscribed) and MZ (minimum zone)
2313 : fitting, LS (least squares) fitting.
2314 :
2315 : It is important to note that among these problems only MC and LS are
2316 : convex and have unique solution independently from starting point.
2317 :
2318 : As for MI, it may (or may not, depending on dataset properties) have
2319 : multiple solutions, and it always has one degenerate solution C=infinity
2320 : which corresponds to infinitely large radius. Thus, there are no guarantees
2321 : that solution to MI returned by this solver will be the best one (and no
2322 : one can provide you with such guarantee because problem is NP-hard). The
2323 : only guarantee you have is that this solution is locally optimal, i.e. it
2324 : can not be improved by infinitesimally small tweaks in the parameters.
2325 :
2326 : It is also possible to "run away" to infinity when started from bad
2327 : initial point located outside of point cloud (or when point cloud does not
2328 : span entire circumference/surface of the sphere).
2329 :
2330 : Finally, MZ (minimum zone circle) stands somewhere between MC and MI in
2331 : stability. It is somewhat regularized by "circumscribed" term of the merit
2332 : function; however, solutions to MZ may be non-unique, and in some unlucky
2333 : cases it is also possible to "run away to infinity".
2334 :
2335 :
2336 : NOTE: ON THE NONLINEARLY CONSTRAINED PROGRAMMING APPROACH
2337 :
2338 : The problem formulation for MC (minimum circumscribed circle; for the
2339 : sake of simplicity we omit MZ and MI here) is:
2340 :
2341 : [ [ ]2 ]
2342 : min [ max [ XY[i]-C ] ]
2343 : C [ i [ ] ]
2344 :
2345 : i.e. it is unconstrained nonsmooth optimization problem of finding "best"
2346 : central point, with radius R being unambiguously determined from C. In
2347 : order to move away from non-smoothness we use following reformulation:
2348 :
2349 : [ ] [ ]2
2350 : min [ R ] subject to R>=0, [ XY[i]-C ] <= R^2
2351 : C,R [ ] [ ]
2352 :
2353 : i.e. it becomes smooth quadratically constrained optimization problem with
2354 : linear target function. Such problem statement is 100% equivalent to the
2355 : original nonsmooth one, but much easier to approach. We solve it with
2356 : MinNLC solver provided by ALGLIB.
2357 :
2358 :
2359 : NOTE: ON INSTABILITY OF SEQUENTIAL LINEARIZATION APPROACH
2360 :
2361 : ALGLIB has nonlinearly constrained solver which proved to be stable on
2362 : such problems. However, some authors proposed to linearize constraints in
2363 : the vicinity of current approximation (Ci,Ri) and to get next approximate
2364 : solution (Ci+1,Ri+1) as solution to linear programming problem. Obviously,
2365 : LP problems are easier than nonlinearly constrained ones.
2366 :
2367 : Indeed, such approach to MC/MI/MZ resulted in ~10-20x increase in
2368 : performance (when compared with NLC solver). However, it turned out that
2369 : in some cases linearized model fails to predict correct direction for next
2370 : step and tells us that we converged to solution even when we are still 2-4
2371 : digits of precision away from it.
2372 :
2373 : It is important that it is not failure of LP solver - it is failure of the
2374 : linear model; even when solved exactly, it fails to handle subtle
2375 : nonlinearities which arise near the solution. We validated it by comparing
2376 : results returned by ALGLIB linear solver with that of MATLAB.
2377 :
2378 : In our experiments with linearization:
2379 : * MC failed most often, at both realistic and synthetic datasets
2380 : * MI sometimes failed, but sometimes succeeded
2381 : * MZ often succeeded; our guess is that presence of two independent sets
2382 : of constraints (one set for Rlo and another one for Rhi) and two terms
2383 : in the target function (Rlo and Rhi) regularizes task, so when linear
2384 : model fails to handle nonlinearities from Rlo, it uses Rhi as a hint
2385 : (and vice versa).
2386 :
2387 : Because linearization approach failed to achieve stable results, we do not
2388 : include it in ALGLIB.
2389 :
2390 :
2391 : -- ALGLIB --
2392 : Copyright 14.04.2017 by Bochkanov Sergey
2393 : *************************************************************************/
2394 0 : void fitspherex(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, const ae_int_t problemtype, const double epsx, const ae_int_t aulits, const double penalty, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams)
2395 : {
2396 : jmp_buf _break_jump;
2397 : alglib_impl::ae_state _alglib_env_state;
2398 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2399 0 : if( setjmp(_break_jump) )
2400 : {
2401 : #if !defined(AE_NO_EXCEPTIONS)
2402 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2403 : #else
2404 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2405 : return;
2406 : #endif
2407 : }
2408 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2409 0 : if( _xparams.flags!=0x0 )
2410 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2411 0 : alglib_impl::fitspherex(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, problemtype, epsx, aulits, penalty, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state);
2412 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2413 0 : return;
2414 : }
2415 : #endif
2416 :
2417 : #if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD)
2418 :
2419 : #endif
2420 :
2421 : #if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD)
2422 : /*************************************************************************
2423 : 1-dimensional spline interpolant
2424 : *************************************************************************/
2425 0 : _spline1dinterpolant_owner::_spline1dinterpolant_owner()
2426 : {
2427 : jmp_buf _break_jump;
2428 : alglib_impl::ae_state _state;
2429 :
2430 0 : alglib_impl::ae_state_init(&_state);
2431 0 : if( setjmp(_break_jump) )
2432 : {
2433 0 : if( p_struct!=NULL )
2434 : {
2435 0 : alglib_impl::_spline1dinterpolant_destroy(p_struct);
2436 0 : alglib_impl::ae_free(p_struct);
2437 : }
2438 0 : p_struct = NULL;
2439 : #if !defined(AE_NO_EXCEPTIONS)
2440 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2441 : #else
2442 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2443 : return;
2444 : #endif
2445 : }
2446 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2447 0 : p_struct = NULL;
2448 0 : p_struct = (alglib_impl::spline1dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dinterpolant), &_state);
2449 0 : memset(p_struct, 0, sizeof(alglib_impl::spline1dinterpolant));
2450 0 : alglib_impl::_spline1dinterpolant_init(p_struct, &_state, ae_false);
2451 0 : ae_state_clear(&_state);
2452 0 : }
2453 :
2454 0 : _spline1dinterpolant_owner::_spline1dinterpolant_owner(const _spline1dinterpolant_owner &rhs)
2455 : {
2456 : jmp_buf _break_jump;
2457 : alglib_impl::ae_state _state;
2458 :
2459 0 : alglib_impl::ae_state_init(&_state);
2460 0 : if( setjmp(_break_jump) )
2461 : {
2462 0 : if( p_struct!=NULL )
2463 : {
2464 0 : alglib_impl::_spline1dinterpolant_destroy(p_struct);
2465 0 : alglib_impl::ae_free(p_struct);
2466 : }
2467 0 : p_struct = NULL;
2468 : #if !defined(AE_NO_EXCEPTIONS)
2469 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2470 : #else
2471 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2472 : return;
2473 : #endif
2474 : }
2475 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2476 0 : p_struct = NULL;
2477 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dinterpolant copy constructor failure (source is not initialized)", &_state);
2478 0 : p_struct = (alglib_impl::spline1dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dinterpolant), &_state);
2479 0 : memset(p_struct, 0, sizeof(alglib_impl::spline1dinterpolant));
2480 0 : alglib_impl::_spline1dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline1dinterpolant*>(rhs.p_struct), &_state, ae_false);
2481 0 : ae_state_clear(&_state);
2482 0 : }
2483 :
2484 0 : _spline1dinterpolant_owner& _spline1dinterpolant_owner::operator=(const _spline1dinterpolant_owner &rhs)
2485 : {
2486 0 : if( this==&rhs )
2487 0 : return *this;
2488 : jmp_buf _break_jump;
2489 : alglib_impl::ae_state _state;
2490 :
2491 0 : alglib_impl::ae_state_init(&_state);
2492 0 : if( setjmp(_break_jump) )
2493 : {
2494 : #if !defined(AE_NO_EXCEPTIONS)
2495 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2496 : #else
2497 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2498 : return *this;
2499 : #endif
2500 : }
2501 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2502 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline1dinterpolant assignment constructor failure (destination is not initialized)", &_state);
2503 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dinterpolant assignment constructor failure (source is not initialized)", &_state);
2504 0 : alglib_impl::_spline1dinterpolant_destroy(p_struct);
2505 0 : memset(p_struct, 0, sizeof(alglib_impl::spline1dinterpolant));
2506 0 : alglib_impl::_spline1dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline1dinterpolant*>(rhs.p_struct), &_state, ae_false);
2507 0 : ae_state_clear(&_state);
2508 0 : return *this;
2509 : }
2510 :
2511 0 : _spline1dinterpolant_owner::~_spline1dinterpolant_owner()
2512 : {
2513 0 : if( p_struct!=NULL )
2514 : {
2515 0 : alglib_impl::_spline1dinterpolant_destroy(p_struct);
2516 0 : ae_free(p_struct);
2517 : }
2518 0 : }
2519 :
2520 0 : alglib_impl::spline1dinterpolant* _spline1dinterpolant_owner::c_ptr()
2521 : {
2522 0 : return p_struct;
2523 : }
2524 :
2525 0 : alglib_impl::spline1dinterpolant* _spline1dinterpolant_owner::c_ptr() const
2526 : {
2527 0 : return const_cast<alglib_impl::spline1dinterpolant*>(p_struct);
2528 : }
2529 0 : spline1dinterpolant::spline1dinterpolant() : _spline1dinterpolant_owner()
2530 : {
2531 0 : }
2532 :
2533 0 : spline1dinterpolant::spline1dinterpolant(const spline1dinterpolant &rhs):_spline1dinterpolant_owner(rhs)
2534 : {
2535 0 : }
2536 :
2537 0 : spline1dinterpolant& spline1dinterpolant::operator=(const spline1dinterpolant &rhs)
2538 : {
2539 0 : if( this==&rhs )
2540 0 : return *this;
2541 0 : _spline1dinterpolant_owner::operator=(rhs);
2542 0 : return *this;
2543 : }
2544 :
2545 0 : spline1dinterpolant::~spline1dinterpolant()
2546 : {
2547 0 : }
2548 :
2549 :
2550 : /*************************************************************************
2551 : Spline fitting report:
2552 : RMSError RMS error
2553 : AvgError average error
2554 : AvgRelError average relative error (for non-zero Y[I])
2555 : MaxError maximum error
2556 :
2557 : Fields below are filled by obsolete functions (Spline1DFitCubic,
2558 : Spline1DFitHermite). Modern fitting functions do NOT fill these fields:
2559 : TaskRCond reciprocal of task's condition number
2560 : *************************************************************************/
2561 0 : _spline1dfitreport_owner::_spline1dfitreport_owner()
2562 : {
2563 : jmp_buf _break_jump;
2564 : alglib_impl::ae_state _state;
2565 :
2566 0 : alglib_impl::ae_state_init(&_state);
2567 0 : if( setjmp(_break_jump) )
2568 : {
2569 0 : if( p_struct!=NULL )
2570 : {
2571 0 : alglib_impl::_spline1dfitreport_destroy(p_struct);
2572 0 : alglib_impl::ae_free(p_struct);
2573 : }
2574 0 : p_struct = NULL;
2575 : #if !defined(AE_NO_EXCEPTIONS)
2576 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2577 : #else
2578 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2579 : return;
2580 : #endif
2581 : }
2582 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2583 0 : p_struct = NULL;
2584 0 : p_struct = (alglib_impl::spline1dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dfitreport), &_state);
2585 0 : memset(p_struct, 0, sizeof(alglib_impl::spline1dfitreport));
2586 0 : alglib_impl::_spline1dfitreport_init(p_struct, &_state, ae_false);
2587 0 : ae_state_clear(&_state);
2588 0 : }
2589 :
2590 0 : _spline1dfitreport_owner::_spline1dfitreport_owner(const _spline1dfitreport_owner &rhs)
2591 : {
2592 : jmp_buf _break_jump;
2593 : alglib_impl::ae_state _state;
2594 :
2595 0 : alglib_impl::ae_state_init(&_state);
2596 0 : if( setjmp(_break_jump) )
2597 : {
2598 0 : if( p_struct!=NULL )
2599 : {
2600 0 : alglib_impl::_spline1dfitreport_destroy(p_struct);
2601 0 : alglib_impl::ae_free(p_struct);
2602 : }
2603 0 : p_struct = NULL;
2604 : #if !defined(AE_NO_EXCEPTIONS)
2605 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2606 : #else
2607 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2608 : return;
2609 : #endif
2610 : }
2611 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2612 0 : p_struct = NULL;
2613 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dfitreport copy constructor failure (source is not initialized)", &_state);
2614 0 : p_struct = (alglib_impl::spline1dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline1dfitreport), &_state);
2615 0 : memset(p_struct, 0, sizeof(alglib_impl::spline1dfitreport));
2616 0 : alglib_impl::_spline1dfitreport_init_copy(p_struct, const_cast<alglib_impl::spline1dfitreport*>(rhs.p_struct), &_state, ae_false);
2617 0 : ae_state_clear(&_state);
2618 0 : }
2619 :
2620 0 : _spline1dfitreport_owner& _spline1dfitreport_owner::operator=(const _spline1dfitreport_owner &rhs)
2621 : {
2622 0 : if( this==&rhs )
2623 0 : return *this;
2624 : jmp_buf _break_jump;
2625 : alglib_impl::ae_state _state;
2626 :
2627 0 : alglib_impl::ae_state_init(&_state);
2628 0 : if( setjmp(_break_jump) )
2629 : {
2630 : #if !defined(AE_NO_EXCEPTIONS)
2631 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2632 : #else
2633 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2634 : return *this;
2635 : #endif
2636 : }
2637 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2638 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline1dfitreport assignment constructor failure (destination is not initialized)", &_state);
2639 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline1dfitreport assignment constructor failure (source is not initialized)", &_state);
2640 0 : alglib_impl::_spline1dfitreport_destroy(p_struct);
2641 0 : memset(p_struct, 0, sizeof(alglib_impl::spline1dfitreport));
2642 0 : alglib_impl::_spline1dfitreport_init_copy(p_struct, const_cast<alglib_impl::spline1dfitreport*>(rhs.p_struct), &_state, ae_false);
2643 0 : ae_state_clear(&_state);
2644 0 : return *this;
2645 : }
2646 :
2647 0 : _spline1dfitreport_owner::~_spline1dfitreport_owner()
2648 : {
2649 0 : if( p_struct!=NULL )
2650 : {
2651 0 : alglib_impl::_spline1dfitreport_destroy(p_struct);
2652 0 : ae_free(p_struct);
2653 : }
2654 0 : }
2655 :
2656 0 : alglib_impl::spline1dfitreport* _spline1dfitreport_owner::c_ptr()
2657 : {
2658 0 : return p_struct;
2659 : }
2660 :
2661 0 : alglib_impl::spline1dfitreport* _spline1dfitreport_owner::c_ptr() const
2662 : {
2663 0 : return const_cast<alglib_impl::spline1dfitreport*>(p_struct);
2664 : }
2665 0 : spline1dfitreport::spline1dfitreport() : _spline1dfitreport_owner() ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror)
2666 : {
2667 0 : }
2668 :
2669 0 : spline1dfitreport::spline1dfitreport(const spline1dfitreport &rhs):_spline1dfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror)
2670 : {
2671 0 : }
2672 :
2673 0 : spline1dfitreport& spline1dfitreport::operator=(const spline1dfitreport &rhs)
2674 : {
2675 0 : if( this==&rhs )
2676 0 : return *this;
2677 0 : _spline1dfitreport_owner::operator=(rhs);
2678 0 : return *this;
2679 : }
2680 :
2681 0 : spline1dfitreport::~spline1dfitreport()
2682 : {
2683 0 : }
2684 :
2685 : /*************************************************************************
2686 : This subroutine builds linear spline interpolant
2687 :
2688 : INPUT PARAMETERS:
2689 : X - spline nodes, array[0..N-1]
2690 : Y - function values, array[0..N-1]
2691 : N - points count (optional):
2692 : * N>=2
2693 : * if given, only first N points are used to build spline
2694 : * if not given, automatically detected from X/Y sizes
2695 : (len(X) must be equal to len(Y))
2696 :
2697 : OUTPUT PARAMETERS:
2698 : C - spline interpolant
2699 :
2700 :
2701 : ORDER OF POINTS
2702 :
2703 : Subroutine automatically sorts points, so caller may pass unsorted array.
2704 :
2705 : -- ALGLIB PROJECT --
2706 : Copyright 24.06.2007 by Bochkanov Sergey
2707 : *************************************************************************/
2708 0 : void spline1dbuildlinear(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams)
2709 : {
2710 : jmp_buf _break_jump;
2711 : alglib_impl::ae_state _alglib_env_state;
2712 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2713 0 : if( setjmp(_break_jump) )
2714 : {
2715 : #if !defined(AE_NO_EXCEPTIONS)
2716 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2717 : #else
2718 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2719 : return;
2720 : #endif
2721 : }
2722 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2723 0 : if( _xparams.flags!=0x0 )
2724 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2725 0 : alglib_impl::spline1dbuildlinear(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
2726 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2727 0 : return;
2728 : }
2729 :
2730 : /*************************************************************************
2731 : This subroutine builds linear spline interpolant
2732 :
2733 : INPUT PARAMETERS:
2734 : X - spline nodes, array[0..N-1]
2735 : Y - function values, array[0..N-1]
2736 : N - points count (optional):
2737 : * N>=2
2738 : * if given, only first N points are used to build spline
2739 : * if not given, automatically detected from X/Y sizes
2740 : (len(X) must be equal to len(Y))
2741 :
2742 : OUTPUT PARAMETERS:
2743 : C - spline interpolant
2744 :
2745 :
2746 : ORDER OF POINTS
2747 :
2748 : Subroutine automatically sorts points, so caller may pass unsorted array.
2749 :
2750 : -- ALGLIB PROJECT --
2751 : Copyright 24.06.2007 by Bochkanov Sergey
2752 : *************************************************************************/
2753 : #if !defined(AE_NO_EXCEPTIONS)
2754 0 : void spline1dbuildlinear(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams)
2755 : {
2756 : jmp_buf _break_jump;
2757 : alglib_impl::ae_state _alglib_env_state;
2758 : ae_int_t n;
2759 0 : if( (x.length()!=y.length()))
2760 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildlinear': looks like one of arguments has wrong size");
2761 0 : n = x.length();
2762 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2763 0 : if( setjmp(_break_jump) )
2764 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2765 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2766 0 : if( _xparams.flags!=0x0 )
2767 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2768 0 : alglib_impl::spline1dbuildlinear(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
2769 :
2770 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2771 0 : return;
2772 : }
2773 : #endif
2774 :
2775 : /*************************************************************************
2776 : This subroutine builds cubic spline interpolant.
2777 :
2778 : INPUT PARAMETERS:
2779 : X - spline nodes, array[0..N-1].
2780 : Y - function values, array[0..N-1].
2781 :
2782 : OPTIONAL PARAMETERS:
2783 : N - points count:
2784 : * N>=2
2785 : * if given, only first N points are used to build spline
2786 : * if not given, automatically detected from X/Y sizes
2787 : (len(X) must be equal to len(Y))
2788 : BoundLType - boundary condition type for the left boundary
2789 : BoundL - left boundary condition (first or second derivative,
2790 : depending on the BoundLType)
2791 : BoundRType - boundary condition type for the right boundary
2792 : BoundR - right boundary condition (first or second derivative,
2793 : depending on the BoundRType)
2794 :
2795 : OUTPUT PARAMETERS:
2796 : C - spline interpolant
2797 :
2798 : ORDER OF POINTS
2799 :
2800 : Subroutine automatically sorts points, so caller may pass unsorted array.
2801 :
2802 : SETTING BOUNDARY VALUES:
2803 :
2804 : The BoundLType/BoundRType parameters can have the following values:
2805 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
2806 : In this case:
2807 : * both BoundLType and BoundRType must be equal to -1.
2808 : * BoundL/BoundR are ignored
2809 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
2810 : * 0, which corresponds to the parabolically terminated spline
2811 : (BoundL and/or BoundR are ignored).
2812 : * 1, which corresponds to the first derivative boundary condition
2813 : * 2, which corresponds to the second derivative boundary condition
2814 : * by default, BoundType=0 is used
2815 :
2816 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2817 :
2818 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2819 : However, this subroutine doesn't require you to specify equal values for
2820 : the first and last points - it automatically forces them to be equal by
2821 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2822 : Y[last_point]. However it is recommended to pass consistent values of Y[],
2823 : i.e. to make Y[first_point]=Y[last_point].
2824 :
2825 : -- ALGLIB PROJECT --
2826 : Copyright 23.06.2007 by Bochkanov Sergey
2827 : *************************************************************************/
2828 0 : void spline1dbuildcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, spline1dinterpolant &c, const xparams _xparams)
2829 : {
2830 : jmp_buf _break_jump;
2831 : alglib_impl::ae_state _alglib_env_state;
2832 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2833 0 : if( setjmp(_break_jump) )
2834 : {
2835 : #if !defined(AE_NO_EXCEPTIONS)
2836 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2837 : #else
2838 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2839 : return;
2840 : #endif
2841 : }
2842 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2843 0 : if( _xparams.flags!=0x0 )
2844 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2845 0 : alglib_impl::spline1dbuildcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
2846 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2847 0 : return;
2848 : }
2849 :
2850 : /*************************************************************************
2851 : This subroutine builds cubic spline interpolant.
2852 :
2853 : INPUT PARAMETERS:
2854 : X - spline nodes, array[0..N-1].
2855 : Y - function values, array[0..N-1].
2856 :
2857 : OPTIONAL PARAMETERS:
2858 : N - points count:
2859 : * N>=2
2860 : * if given, only first N points are used to build spline
2861 : * if not given, automatically detected from X/Y sizes
2862 : (len(X) must be equal to len(Y))
2863 : BoundLType - boundary condition type for the left boundary
2864 : BoundL - left boundary condition (first or second derivative,
2865 : depending on the BoundLType)
2866 : BoundRType - boundary condition type for the right boundary
2867 : BoundR - right boundary condition (first or second derivative,
2868 : depending on the BoundRType)
2869 :
2870 : OUTPUT PARAMETERS:
2871 : C - spline interpolant
2872 :
2873 : ORDER OF POINTS
2874 :
2875 : Subroutine automatically sorts points, so caller may pass unsorted array.
2876 :
2877 : SETTING BOUNDARY VALUES:
2878 :
2879 : The BoundLType/BoundRType parameters can have the following values:
2880 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
2881 : In this case:
2882 : * both BoundLType and BoundRType must be equal to -1.
2883 : * BoundL/BoundR are ignored
2884 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
2885 : * 0, which corresponds to the parabolically terminated spline
2886 : (BoundL and/or BoundR are ignored).
2887 : * 1, which corresponds to the first derivative boundary condition
2888 : * 2, which corresponds to the second derivative boundary condition
2889 : * by default, BoundType=0 is used
2890 :
2891 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2892 :
2893 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2894 : However, this subroutine doesn't require you to specify equal values for
2895 : the first and last points - it automatically forces them to be equal by
2896 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2897 : Y[last_point]. However it is recommended to pass consistent values of Y[],
2898 : i.e. to make Y[first_point]=Y[last_point].
2899 :
2900 : -- ALGLIB PROJECT --
2901 : Copyright 23.06.2007 by Bochkanov Sergey
2902 : *************************************************************************/
2903 : #if !defined(AE_NO_EXCEPTIONS)
2904 0 : void spline1dbuildcubic(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams)
2905 : {
2906 : jmp_buf _break_jump;
2907 : alglib_impl::ae_state _alglib_env_state;
2908 : ae_int_t n;
2909 : ae_int_t boundltype;
2910 : double boundl;
2911 : ae_int_t boundrtype;
2912 : double boundr;
2913 0 : if( (x.length()!=y.length()))
2914 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildcubic': looks like one of arguments has wrong size");
2915 0 : n = x.length();
2916 0 : boundltype = 0;
2917 0 : boundl = 0;
2918 0 : boundrtype = 0;
2919 0 : boundr = 0;
2920 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2921 0 : if( setjmp(_break_jump) )
2922 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2923 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2924 0 : if( _xparams.flags!=0x0 )
2925 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2926 0 : alglib_impl::spline1dbuildcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
2927 :
2928 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2929 0 : return;
2930 : }
2931 : #endif
2932 :
2933 : /*************************************************************************
2934 : This function solves following problem: given table y[] of function values
2935 : at nodes x[], it calculates and returns table of function derivatives d[]
2936 : (calculated at the same nodes x[]).
2937 :
2938 : This function yields same result as Spline1DBuildCubic() call followed by
2939 : sequence of Spline1DDiff() calls, but it can be several times faster when
2940 : called for ordered X[] and X2[].
2941 :
2942 : INPUT PARAMETERS:
2943 : X - spline nodes
2944 : Y - function values
2945 :
2946 : OPTIONAL PARAMETERS:
2947 : N - points count:
2948 : * N>=2
2949 : * if given, only first N points are used
2950 : * if not given, automatically detected from X/Y sizes
2951 : (len(X) must be equal to len(Y))
2952 : BoundLType - boundary condition type for the left boundary
2953 : BoundL - left boundary condition (first or second derivative,
2954 : depending on the BoundLType)
2955 : BoundRType - boundary condition type for the right boundary
2956 : BoundR - right boundary condition (first or second derivative,
2957 : depending on the BoundRType)
2958 :
2959 : OUTPUT PARAMETERS:
2960 : D - derivative values at X[]
2961 :
2962 : ORDER OF POINTS
2963 :
2964 : Subroutine automatically sorts points, so caller may pass unsorted array.
2965 : Derivative values are correctly reordered on return, so D[I] is always
2966 : equal to S'(X[I]) independently of points order.
2967 :
2968 : SETTING BOUNDARY VALUES:
2969 :
2970 : The BoundLType/BoundRType parameters can have the following values:
2971 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
2972 : In this case:
2973 : * both BoundLType and BoundRType must be equal to -1.
2974 : * BoundL/BoundR are ignored
2975 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
2976 : * 0, which corresponds to the parabolically terminated spline
2977 : (BoundL and/or BoundR are ignored).
2978 : * 1, which corresponds to the first derivative boundary condition
2979 : * 2, which corresponds to the second derivative boundary condition
2980 : * by default, BoundType=0 is used
2981 :
2982 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2983 :
2984 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2985 : However, this subroutine doesn't require you to specify equal values for
2986 : the first and last points - it automatically forces them to be equal by
2987 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2988 : Y[last_point]. However it is recommended to pass consistent values of Y[],
2989 : i.e. to make Y[first_point]=Y[last_point].
2990 :
2991 : -- ALGLIB PROJECT --
2992 : Copyright 03.09.2010 by Bochkanov Sergey
2993 : *************************************************************************/
2994 0 : void spline1dgriddiffcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, real_1d_array &d, const xparams _xparams)
2995 : {
2996 : jmp_buf _break_jump;
2997 : alglib_impl::ae_state _alglib_env_state;
2998 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2999 0 : if( setjmp(_break_jump) )
3000 : {
3001 : #if !defined(AE_NO_EXCEPTIONS)
3002 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3003 : #else
3004 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3005 : return;
3006 : #endif
3007 : }
3008 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3009 0 : if( _xparams.flags!=0x0 )
3010 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3011 0 : alglib_impl::spline1dgriddiffcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
3012 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3013 0 : return;
3014 : }
3015 :
3016 : /*************************************************************************
3017 : This function solves following problem: given table y[] of function values
3018 : at nodes x[], it calculates and returns table of function derivatives d[]
3019 : (calculated at the same nodes x[]).
3020 :
3021 : This function yields same result as Spline1DBuildCubic() call followed by
3022 : sequence of Spline1DDiff() calls, but it can be several times faster when
3023 : called for ordered X[] and X2[].
3024 :
3025 : INPUT PARAMETERS:
3026 : X - spline nodes
3027 : Y - function values
3028 :
3029 : OPTIONAL PARAMETERS:
3030 : N - points count:
3031 : * N>=2
3032 : * if given, only first N points are used
3033 : * if not given, automatically detected from X/Y sizes
3034 : (len(X) must be equal to len(Y))
3035 : BoundLType - boundary condition type for the left boundary
3036 : BoundL - left boundary condition (first or second derivative,
3037 : depending on the BoundLType)
3038 : BoundRType - boundary condition type for the right boundary
3039 : BoundR - right boundary condition (first or second derivative,
3040 : depending on the BoundRType)
3041 :
3042 : OUTPUT PARAMETERS:
3043 : D - derivative values at X[]
3044 :
3045 : ORDER OF POINTS
3046 :
3047 : Subroutine automatically sorts points, so caller may pass unsorted array.
3048 : Derivative values are correctly reordered on return, so D[I] is always
3049 : equal to S'(X[I]) independently of points order.
3050 :
3051 : SETTING BOUNDARY VALUES:
3052 :
3053 : The BoundLType/BoundRType parameters can have the following values:
3054 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3055 : In this case:
3056 : * both BoundLType and BoundRType must be equal to -1.
3057 : * BoundL/BoundR are ignored
3058 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3059 : * 0, which corresponds to the parabolically terminated spline
3060 : (BoundL and/or BoundR are ignored).
3061 : * 1, which corresponds to the first derivative boundary condition
3062 : * 2, which corresponds to the second derivative boundary condition
3063 : * by default, BoundType=0 is used
3064 :
3065 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3066 :
3067 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3068 : However, this subroutine doesn't require you to specify equal values for
3069 : the first and last points - it automatically forces them to be equal by
3070 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3071 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3072 : i.e. to make Y[first_point]=Y[last_point].
3073 :
3074 : -- ALGLIB PROJECT --
3075 : Copyright 03.09.2010 by Bochkanov Sergey
3076 : *************************************************************************/
3077 : #if !defined(AE_NO_EXCEPTIONS)
3078 0 : void spline1dgriddiffcubic(const real_1d_array &x, const real_1d_array &y, real_1d_array &d, const xparams _xparams)
3079 : {
3080 : jmp_buf _break_jump;
3081 : alglib_impl::ae_state _alglib_env_state;
3082 : ae_int_t n;
3083 : ae_int_t boundltype;
3084 : double boundl;
3085 : ae_int_t boundrtype;
3086 : double boundr;
3087 0 : if( (x.length()!=y.length()))
3088 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dgriddiffcubic': looks like one of arguments has wrong size");
3089 0 : n = x.length();
3090 0 : boundltype = 0;
3091 0 : boundl = 0;
3092 0 : boundrtype = 0;
3093 0 : boundr = 0;
3094 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3095 0 : if( setjmp(_break_jump) )
3096 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3097 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3098 0 : if( _xparams.flags!=0x0 )
3099 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3100 0 : alglib_impl::spline1dgriddiffcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
3101 :
3102 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3103 0 : return;
3104 : }
3105 : #endif
3106 :
3107 : /*************************************************************************
3108 : This function solves following problem: given table y[] of function values
3109 : at nodes x[], it calculates and returns tables of first and second
3110 : function derivatives d1[] and d2[] (calculated at the same nodes x[]).
3111 :
3112 : This function yields same result as Spline1DBuildCubic() call followed by
3113 : sequence of Spline1DDiff() calls, but it can be several times faster when
3114 : called for ordered X[] and X2[].
3115 :
3116 : INPUT PARAMETERS:
3117 : X - spline nodes
3118 : Y - function values
3119 :
3120 : OPTIONAL PARAMETERS:
3121 : N - points count:
3122 : * N>=2
3123 : * if given, only first N points are used
3124 : * if not given, automatically detected from X/Y sizes
3125 : (len(X) must be equal to len(Y))
3126 : BoundLType - boundary condition type for the left boundary
3127 : BoundL - left boundary condition (first or second derivative,
3128 : depending on the BoundLType)
3129 : BoundRType - boundary condition type for the right boundary
3130 : BoundR - right boundary condition (first or second derivative,
3131 : depending on the BoundRType)
3132 :
3133 : OUTPUT PARAMETERS:
3134 : D1 - S' values at X[]
3135 : D2 - S'' values at X[]
3136 :
3137 : ORDER OF POINTS
3138 :
3139 : Subroutine automatically sorts points, so caller may pass unsorted array.
3140 : Derivative values are correctly reordered on return, so D[I] is always
3141 : equal to S'(X[I]) independently of points order.
3142 :
3143 : SETTING BOUNDARY VALUES:
3144 :
3145 : The BoundLType/BoundRType parameters can have the following values:
3146 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3147 : In this case:
3148 : * both BoundLType and BoundRType must be equal to -1.
3149 : * BoundL/BoundR are ignored
3150 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3151 : * 0, which corresponds to the parabolically terminated spline
3152 : (BoundL and/or BoundR are ignored).
3153 : * 1, which corresponds to the first derivative boundary condition
3154 : * 2, which corresponds to the second derivative boundary condition
3155 : * by default, BoundType=0 is used
3156 :
3157 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3158 :
3159 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3160 : However, this subroutine doesn't require you to specify equal values for
3161 : the first and last points - it automatically forces them to be equal by
3162 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3163 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3164 : i.e. to make Y[first_point]=Y[last_point].
3165 :
3166 : -- ALGLIB PROJECT --
3167 : Copyright 03.09.2010 by Bochkanov Sergey
3168 : *************************************************************************/
3169 0 : void spline1dgriddiff2cubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, real_1d_array &d1, real_1d_array &d2, const xparams _xparams)
3170 : {
3171 : jmp_buf _break_jump;
3172 : alglib_impl::ae_state _alglib_env_state;
3173 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3174 0 : if( setjmp(_break_jump) )
3175 : {
3176 : #if !defined(AE_NO_EXCEPTIONS)
3177 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3178 : #else
3179 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3180 : return;
3181 : #endif
3182 : }
3183 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3184 0 : if( _xparams.flags!=0x0 )
3185 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3186 0 : alglib_impl::spline1dgriddiff2cubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(d1.c_ptr()), const_cast<alglib_impl::ae_vector*>(d2.c_ptr()), &_alglib_env_state);
3187 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3188 0 : return;
3189 : }
3190 :
3191 : /*************************************************************************
3192 : This function solves following problem: given table y[] of function values
3193 : at nodes x[], it calculates and returns tables of first and second
3194 : function derivatives d1[] and d2[] (calculated at the same nodes x[]).
3195 :
3196 : This function yields same result as Spline1DBuildCubic() call followed by
3197 : sequence of Spline1DDiff() calls, but it can be several times faster when
3198 : called for ordered X[] and X2[].
3199 :
3200 : INPUT PARAMETERS:
3201 : X - spline nodes
3202 : Y - function values
3203 :
3204 : OPTIONAL PARAMETERS:
3205 : N - points count:
3206 : * N>=2
3207 : * if given, only first N points are used
3208 : * if not given, automatically detected from X/Y sizes
3209 : (len(X) must be equal to len(Y))
3210 : BoundLType - boundary condition type for the left boundary
3211 : BoundL - left boundary condition (first or second derivative,
3212 : depending on the BoundLType)
3213 : BoundRType - boundary condition type for the right boundary
3214 : BoundR - right boundary condition (first or second derivative,
3215 : depending on the BoundRType)
3216 :
3217 : OUTPUT PARAMETERS:
3218 : D1 - S' values at X[]
3219 : D2 - S'' values at X[]
3220 :
3221 : ORDER OF POINTS
3222 :
3223 : Subroutine automatically sorts points, so caller may pass unsorted array.
3224 : Derivative values are correctly reordered on return, so D[I] is always
3225 : equal to S'(X[I]) independently of points order.
3226 :
3227 : SETTING BOUNDARY VALUES:
3228 :
3229 : The BoundLType/BoundRType parameters can have the following values:
3230 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3231 : In this case:
3232 : * both BoundLType and BoundRType must be equal to -1.
3233 : * BoundL/BoundR are ignored
3234 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3235 : * 0, which corresponds to the parabolically terminated spline
3236 : (BoundL and/or BoundR are ignored).
3237 : * 1, which corresponds to the first derivative boundary condition
3238 : * 2, which corresponds to the second derivative boundary condition
3239 : * by default, BoundType=0 is used
3240 :
3241 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3242 :
3243 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3244 : However, this subroutine doesn't require you to specify equal values for
3245 : the first and last points - it automatically forces them to be equal by
3246 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3247 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3248 : i.e. to make Y[first_point]=Y[last_point].
3249 :
3250 : -- ALGLIB PROJECT --
3251 : Copyright 03.09.2010 by Bochkanov Sergey
3252 : *************************************************************************/
3253 : #if !defined(AE_NO_EXCEPTIONS)
3254 0 : void spline1dgriddiff2cubic(const real_1d_array &x, const real_1d_array &y, real_1d_array &d1, real_1d_array &d2, const xparams _xparams)
3255 : {
3256 : jmp_buf _break_jump;
3257 : alglib_impl::ae_state _alglib_env_state;
3258 : ae_int_t n;
3259 : ae_int_t boundltype;
3260 : double boundl;
3261 : ae_int_t boundrtype;
3262 : double boundr;
3263 0 : if( (x.length()!=y.length()))
3264 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dgriddiff2cubic': looks like one of arguments has wrong size");
3265 0 : n = x.length();
3266 0 : boundltype = 0;
3267 0 : boundl = 0;
3268 0 : boundrtype = 0;
3269 0 : boundr = 0;
3270 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3271 0 : if( setjmp(_break_jump) )
3272 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3273 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3274 0 : if( _xparams.flags!=0x0 )
3275 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3276 0 : alglib_impl::spline1dgriddiff2cubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(d1.c_ptr()), const_cast<alglib_impl::ae_vector*>(d2.c_ptr()), &_alglib_env_state);
3277 :
3278 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3279 0 : return;
3280 : }
3281 : #endif
3282 :
3283 : /*************************************************************************
3284 : This function solves following problem: given table y[] of function values
3285 : at old nodes x[] and new nodes x2[], it calculates and returns table of
3286 : function values y2[] (calculated at x2[]).
3287 :
3288 : This function yields same result as Spline1DBuildCubic() call followed by
3289 : sequence of Spline1DDiff() calls, but it can be several times faster when
3290 : called for ordered X[] and X2[].
3291 :
3292 : INPUT PARAMETERS:
3293 : X - old spline nodes
3294 : Y - function values
3295 : X2 - new spline nodes
3296 :
3297 : OPTIONAL PARAMETERS:
3298 : N - points count:
3299 : * N>=2
3300 : * if given, only first N points from X/Y are used
3301 : * if not given, automatically detected from X/Y sizes
3302 : (len(X) must be equal to len(Y))
3303 : BoundLType - boundary condition type for the left boundary
3304 : BoundL - left boundary condition (first or second derivative,
3305 : depending on the BoundLType)
3306 : BoundRType - boundary condition type for the right boundary
3307 : BoundR - right boundary condition (first or second derivative,
3308 : depending on the BoundRType)
3309 : N2 - new points count:
3310 : * N2>=2
3311 : * if given, only first N2 points from X2 are used
3312 : * if not given, automatically detected from X2 size
3313 :
3314 : OUTPUT PARAMETERS:
3315 : F2 - function values at X2[]
3316 :
3317 : ORDER OF POINTS
3318 :
3319 : Subroutine automatically sorts points, so caller may pass unsorted array.
3320 : Function values are correctly reordered on return, so F2[I] is always
3321 : equal to S(X2[I]) independently of points order.
3322 :
3323 : SETTING BOUNDARY VALUES:
3324 :
3325 : The BoundLType/BoundRType parameters can have the following values:
3326 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3327 : In this case:
3328 : * both BoundLType and BoundRType must be equal to -1.
3329 : * BoundL/BoundR are ignored
3330 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3331 : * 0, which corresponds to the parabolically terminated spline
3332 : (BoundL and/or BoundR are ignored).
3333 : * 1, which corresponds to the first derivative boundary condition
3334 : * 2, which corresponds to the second derivative boundary condition
3335 : * by default, BoundType=0 is used
3336 :
3337 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3338 :
3339 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3340 : However, this subroutine doesn't require you to specify equal values for
3341 : the first and last points - it automatically forces them to be equal by
3342 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3343 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3344 : i.e. to make Y[first_point]=Y[last_point].
3345 :
3346 : -- ALGLIB PROJECT --
3347 : Copyright 03.09.2010 by Bochkanov Sergey
3348 : *************************************************************************/
3349 0 : void spline1dconvcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, const xparams _xparams)
3350 : {
3351 : jmp_buf _break_jump;
3352 : alglib_impl::ae_state _alglib_env_state;
3353 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3354 0 : if( setjmp(_break_jump) )
3355 : {
3356 : #if !defined(AE_NO_EXCEPTIONS)
3357 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3358 : #else
3359 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3360 : return;
3361 : #endif
3362 : }
3363 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3364 0 : if( _xparams.flags!=0x0 )
3365 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3366 0 : alglib_impl::spline1dconvcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), &_alglib_env_state);
3367 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3368 0 : return;
3369 : }
3370 :
3371 : /*************************************************************************
3372 : This function solves following problem: given table y[] of function values
3373 : at old nodes x[] and new nodes x2[], it calculates and returns table of
3374 : function values y2[] (calculated at x2[]).
3375 :
3376 : This function yields same result as Spline1DBuildCubic() call followed by
3377 : sequence of Spline1DDiff() calls, but it can be several times faster when
3378 : called for ordered X[] and X2[].
3379 :
3380 : INPUT PARAMETERS:
3381 : X - old spline nodes
3382 : Y - function values
3383 : X2 - new spline nodes
3384 :
3385 : OPTIONAL PARAMETERS:
3386 : N - points count:
3387 : * N>=2
3388 : * if given, only first N points from X/Y are used
3389 : * if not given, automatically detected from X/Y sizes
3390 : (len(X) must be equal to len(Y))
3391 : BoundLType - boundary condition type for the left boundary
3392 : BoundL - left boundary condition (first or second derivative,
3393 : depending on the BoundLType)
3394 : BoundRType - boundary condition type for the right boundary
3395 : BoundR - right boundary condition (first or second derivative,
3396 : depending on the BoundRType)
3397 : N2 - new points count:
3398 : * N2>=2
3399 : * if given, only first N2 points from X2 are used
3400 : * if not given, automatically detected from X2 size
3401 :
3402 : OUTPUT PARAMETERS:
3403 : F2 - function values at X2[]
3404 :
3405 : ORDER OF POINTS
3406 :
3407 : Subroutine automatically sorts points, so caller may pass unsorted array.
3408 : Function values are correctly reordered on return, so F2[I] is always
3409 : equal to S(X2[I]) independently of points order.
3410 :
3411 : SETTING BOUNDARY VALUES:
3412 :
3413 : The BoundLType/BoundRType parameters can have the following values:
3414 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3415 : In this case:
3416 : * both BoundLType and BoundRType must be equal to -1.
3417 : * BoundL/BoundR are ignored
3418 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3419 : * 0, which corresponds to the parabolically terminated spline
3420 : (BoundL and/or BoundR are ignored).
3421 : * 1, which corresponds to the first derivative boundary condition
3422 : * 2, which corresponds to the second derivative boundary condition
3423 : * by default, BoundType=0 is used
3424 :
3425 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3426 :
3427 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3428 : However, this subroutine doesn't require you to specify equal values for
3429 : the first and last points - it automatically forces them to be equal by
3430 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3431 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3432 : i.e. to make Y[first_point]=Y[last_point].
3433 :
3434 : -- ALGLIB PROJECT --
3435 : Copyright 03.09.2010 by Bochkanov Sergey
3436 : *************************************************************************/
3437 : #if !defined(AE_NO_EXCEPTIONS)
3438 0 : void spline1dconvcubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, const xparams _xparams)
3439 : {
3440 : jmp_buf _break_jump;
3441 : alglib_impl::ae_state _alglib_env_state;
3442 : ae_int_t n;
3443 : ae_int_t boundltype;
3444 : double boundl;
3445 : ae_int_t boundrtype;
3446 : double boundr;
3447 : ae_int_t n2;
3448 0 : if( (x.length()!=y.length()))
3449 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dconvcubic': looks like one of arguments has wrong size");
3450 0 : n = x.length();
3451 0 : boundltype = 0;
3452 0 : boundl = 0;
3453 0 : boundrtype = 0;
3454 0 : boundr = 0;
3455 0 : n2 = x2.length();
3456 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3457 0 : if( setjmp(_break_jump) )
3458 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3459 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3460 0 : if( _xparams.flags!=0x0 )
3461 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3462 0 : alglib_impl::spline1dconvcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), &_alglib_env_state);
3463 :
3464 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3465 0 : return;
3466 : }
3467 : #endif
3468 :
3469 : /*************************************************************************
3470 : This function solves following problem: given table y[] of function values
3471 : at old nodes x[] and new nodes x2[], it calculates and returns table of
3472 : function values y2[] and derivatives d2[] (calculated at x2[]).
3473 :
3474 : This function yields same result as Spline1DBuildCubic() call followed by
3475 : sequence of Spline1DDiff() calls, but it can be several times faster when
3476 : called for ordered X[] and X2[].
3477 :
3478 : INPUT PARAMETERS:
3479 : X - old spline nodes
3480 : Y - function values
3481 : X2 - new spline nodes
3482 :
3483 : OPTIONAL PARAMETERS:
3484 : N - points count:
3485 : * N>=2
3486 : * if given, only first N points from X/Y are used
3487 : * if not given, automatically detected from X/Y sizes
3488 : (len(X) must be equal to len(Y))
3489 : BoundLType - boundary condition type for the left boundary
3490 : BoundL - left boundary condition (first or second derivative,
3491 : depending on the BoundLType)
3492 : BoundRType - boundary condition type for the right boundary
3493 : BoundR - right boundary condition (first or second derivative,
3494 : depending on the BoundRType)
3495 : N2 - new points count:
3496 : * N2>=2
3497 : * if given, only first N2 points from X2 are used
3498 : * if not given, automatically detected from X2 size
3499 :
3500 : OUTPUT PARAMETERS:
3501 : F2 - function values at X2[]
3502 : D2 - first derivatives at X2[]
3503 :
3504 : ORDER OF POINTS
3505 :
3506 : Subroutine automatically sorts points, so caller may pass unsorted array.
3507 : Function values are correctly reordered on return, so F2[I] is always
3508 : equal to S(X2[I]) independently of points order.
3509 :
3510 : SETTING BOUNDARY VALUES:
3511 :
3512 : The BoundLType/BoundRType parameters can have the following values:
3513 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3514 : In this case:
3515 : * both BoundLType and BoundRType must be equal to -1.
3516 : * BoundL/BoundR are ignored
3517 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3518 : * 0, which corresponds to the parabolically terminated spline
3519 : (BoundL and/or BoundR are ignored).
3520 : * 1, which corresponds to the first derivative boundary condition
3521 : * 2, which corresponds to the second derivative boundary condition
3522 : * by default, BoundType=0 is used
3523 :
3524 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3525 :
3526 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3527 : However, this subroutine doesn't require you to specify equal values for
3528 : the first and last points - it automatically forces them to be equal by
3529 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3530 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3531 : i.e. to make Y[first_point]=Y[last_point].
3532 :
3533 : -- ALGLIB PROJECT --
3534 : Copyright 03.09.2010 by Bochkanov Sergey
3535 : *************************************************************************/
3536 0 : void spline1dconvdiffcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, real_1d_array &d2, const xparams _xparams)
3537 : {
3538 : jmp_buf _break_jump;
3539 : alglib_impl::ae_state _alglib_env_state;
3540 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3541 0 : if( setjmp(_break_jump) )
3542 : {
3543 : #if !defined(AE_NO_EXCEPTIONS)
3544 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3545 : #else
3546 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3547 : return;
3548 : #endif
3549 : }
3550 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3551 0 : if( _xparams.flags!=0x0 )
3552 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3553 0 : alglib_impl::spline1dconvdiffcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), const_cast<alglib_impl::ae_vector*>(d2.c_ptr()), &_alglib_env_state);
3554 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3555 0 : return;
3556 : }
3557 :
3558 : /*************************************************************************
3559 : This function solves following problem: given table y[] of function values
3560 : at old nodes x[] and new nodes x2[], it calculates and returns table of
3561 : function values y2[] and derivatives d2[] (calculated at x2[]).
3562 :
3563 : This function yields same result as Spline1DBuildCubic() call followed by
3564 : sequence of Spline1DDiff() calls, but it can be several times faster when
3565 : called for ordered X[] and X2[].
3566 :
3567 : INPUT PARAMETERS:
3568 : X - old spline nodes
3569 : Y - function values
3570 : X2 - new spline nodes
3571 :
3572 : OPTIONAL PARAMETERS:
3573 : N - points count:
3574 : * N>=2
3575 : * if given, only first N points from X/Y are used
3576 : * if not given, automatically detected from X/Y sizes
3577 : (len(X) must be equal to len(Y))
3578 : BoundLType - boundary condition type for the left boundary
3579 : BoundL - left boundary condition (first or second derivative,
3580 : depending on the BoundLType)
3581 : BoundRType - boundary condition type for the right boundary
3582 : BoundR - right boundary condition (first or second derivative,
3583 : depending on the BoundRType)
3584 : N2 - new points count:
3585 : * N2>=2
3586 : * if given, only first N2 points from X2 are used
3587 : * if not given, automatically detected from X2 size
3588 :
3589 : OUTPUT PARAMETERS:
3590 : F2 - function values at X2[]
3591 : D2 - first derivatives at X2[]
3592 :
3593 : ORDER OF POINTS
3594 :
3595 : Subroutine automatically sorts points, so caller may pass unsorted array.
3596 : Function values are correctly reordered on return, so F2[I] is always
3597 : equal to S(X2[I]) independently of points order.
3598 :
3599 : SETTING BOUNDARY VALUES:
3600 :
3601 : The BoundLType/BoundRType parameters can have the following values:
3602 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3603 : In this case:
3604 : * both BoundLType and BoundRType must be equal to -1.
3605 : * BoundL/BoundR are ignored
3606 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3607 : * 0, which corresponds to the parabolically terminated spline
3608 : (BoundL and/or BoundR are ignored).
3609 : * 1, which corresponds to the first derivative boundary condition
3610 : * 2, which corresponds to the second derivative boundary condition
3611 : * by default, BoundType=0 is used
3612 :
3613 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3614 :
3615 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3616 : However, this subroutine doesn't require you to specify equal values for
3617 : the first and last points - it automatically forces them to be equal by
3618 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3619 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3620 : i.e. to make Y[first_point]=Y[last_point].
3621 :
3622 : -- ALGLIB PROJECT --
3623 : Copyright 03.09.2010 by Bochkanov Sergey
3624 : *************************************************************************/
3625 : #if !defined(AE_NO_EXCEPTIONS)
3626 0 : void spline1dconvdiffcubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, real_1d_array &d2, const xparams _xparams)
3627 : {
3628 : jmp_buf _break_jump;
3629 : alglib_impl::ae_state _alglib_env_state;
3630 : ae_int_t n;
3631 : ae_int_t boundltype;
3632 : double boundl;
3633 : ae_int_t boundrtype;
3634 : double boundr;
3635 : ae_int_t n2;
3636 0 : if( (x.length()!=y.length()))
3637 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dconvdiffcubic': looks like one of arguments has wrong size");
3638 0 : n = x.length();
3639 0 : boundltype = 0;
3640 0 : boundl = 0;
3641 0 : boundrtype = 0;
3642 0 : boundr = 0;
3643 0 : n2 = x2.length();
3644 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3645 0 : if( setjmp(_break_jump) )
3646 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3647 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3648 0 : if( _xparams.flags!=0x0 )
3649 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3650 0 : alglib_impl::spline1dconvdiffcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), const_cast<alglib_impl::ae_vector*>(d2.c_ptr()), &_alglib_env_state);
3651 :
3652 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3653 0 : return;
3654 : }
3655 : #endif
3656 :
3657 : /*************************************************************************
3658 : This function solves following problem: given table y[] of function values
3659 : at old nodes x[] and new nodes x2[], it calculates and returns table of
3660 : function values y2[], first and second derivatives d2[] and dd2[]
3661 : (calculated at x2[]).
3662 :
3663 : This function yields same result as Spline1DBuildCubic() call followed by
3664 : sequence of Spline1DDiff() calls, but it can be several times faster when
3665 : called for ordered X[] and X2[].
3666 :
3667 : INPUT PARAMETERS:
3668 : X - old spline nodes
3669 : Y - function values
3670 : X2 - new spline nodes
3671 :
3672 : OPTIONAL PARAMETERS:
3673 : N - points count:
3674 : * N>=2
3675 : * if given, only first N points from X/Y are used
3676 : * if not given, automatically detected from X/Y sizes
3677 : (len(X) must be equal to len(Y))
3678 : BoundLType - boundary condition type for the left boundary
3679 : BoundL - left boundary condition (first or second derivative,
3680 : depending on the BoundLType)
3681 : BoundRType - boundary condition type for the right boundary
3682 : BoundR - right boundary condition (first or second derivative,
3683 : depending on the BoundRType)
3684 : N2 - new points count:
3685 : * N2>=2
3686 : * if given, only first N2 points from X2 are used
3687 : * if not given, automatically detected from X2 size
3688 :
3689 : OUTPUT PARAMETERS:
3690 : F2 - function values at X2[]
3691 : D2 - first derivatives at X2[]
3692 : DD2 - second derivatives at X2[]
3693 :
3694 : ORDER OF POINTS
3695 :
3696 : Subroutine automatically sorts points, so caller may pass unsorted array.
3697 : Function values are correctly reordered on return, so F2[I] is always
3698 : equal to S(X2[I]) independently of points order.
3699 :
3700 : SETTING BOUNDARY VALUES:
3701 :
3702 : The BoundLType/BoundRType parameters can have the following values:
3703 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3704 : In this case:
3705 : * both BoundLType and BoundRType must be equal to -1.
3706 : * BoundL/BoundR are ignored
3707 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3708 : * 0, which corresponds to the parabolically terminated spline
3709 : (BoundL and/or BoundR are ignored).
3710 : * 1, which corresponds to the first derivative boundary condition
3711 : * 2, which corresponds to the second derivative boundary condition
3712 : * by default, BoundType=0 is used
3713 :
3714 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3715 :
3716 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3717 : However, this subroutine doesn't require you to specify equal values for
3718 : the first and last points - it automatically forces them to be equal by
3719 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3720 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3721 : i.e. to make Y[first_point]=Y[last_point].
3722 :
3723 : -- ALGLIB PROJECT --
3724 : Copyright 03.09.2010 by Bochkanov Sergey
3725 : *************************************************************************/
3726 0 : void spline1dconvdiff2cubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundltype, const double boundl, const ae_int_t boundrtype, const double boundr, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y2, real_1d_array &d2, real_1d_array &dd2, const xparams _xparams)
3727 : {
3728 : jmp_buf _break_jump;
3729 : alglib_impl::ae_state _alglib_env_state;
3730 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3731 0 : if( setjmp(_break_jump) )
3732 : {
3733 : #if !defined(AE_NO_EXCEPTIONS)
3734 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3735 : #else
3736 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3737 : return;
3738 : #endif
3739 : }
3740 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3741 0 : if( _xparams.flags!=0x0 )
3742 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3743 0 : alglib_impl::spline1dconvdiff2cubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), const_cast<alglib_impl::ae_vector*>(d2.c_ptr()), const_cast<alglib_impl::ae_vector*>(dd2.c_ptr()), &_alglib_env_state);
3744 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3745 0 : return;
3746 : }
3747 :
3748 : /*************************************************************************
3749 : This function solves following problem: given table y[] of function values
3750 : at old nodes x[] and new nodes x2[], it calculates and returns table of
3751 : function values y2[], first and second derivatives d2[] and dd2[]
3752 : (calculated at x2[]).
3753 :
3754 : This function yields same result as Spline1DBuildCubic() call followed by
3755 : sequence of Spline1DDiff() calls, but it can be several times faster when
3756 : called for ordered X[] and X2[].
3757 :
3758 : INPUT PARAMETERS:
3759 : X - old spline nodes
3760 : Y - function values
3761 : X2 - new spline nodes
3762 :
3763 : OPTIONAL PARAMETERS:
3764 : N - points count:
3765 : * N>=2
3766 : * if given, only first N points from X/Y are used
3767 : * if not given, automatically detected from X/Y sizes
3768 : (len(X) must be equal to len(Y))
3769 : BoundLType - boundary condition type for the left boundary
3770 : BoundL - left boundary condition (first or second derivative,
3771 : depending on the BoundLType)
3772 : BoundRType - boundary condition type for the right boundary
3773 : BoundR - right boundary condition (first or second derivative,
3774 : depending on the BoundRType)
3775 : N2 - new points count:
3776 : * N2>=2
3777 : * if given, only first N2 points from X2 are used
3778 : * if not given, automatically detected from X2 size
3779 :
3780 : OUTPUT PARAMETERS:
3781 : F2 - function values at X2[]
3782 : D2 - first derivatives at X2[]
3783 : DD2 - second derivatives at X2[]
3784 :
3785 : ORDER OF POINTS
3786 :
3787 : Subroutine automatically sorts points, so caller may pass unsorted array.
3788 : Function values are correctly reordered on return, so F2[I] is always
3789 : equal to S(X2[I]) independently of points order.
3790 :
3791 : SETTING BOUNDARY VALUES:
3792 :
3793 : The BoundLType/BoundRType parameters can have the following values:
3794 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
3795 : In this case:
3796 : * both BoundLType and BoundRType must be equal to -1.
3797 : * BoundL/BoundR are ignored
3798 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
3799 : * 0, which corresponds to the parabolically terminated spline
3800 : (BoundL and/or BoundR are ignored).
3801 : * 1, which corresponds to the first derivative boundary condition
3802 : * 2, which corresponds to the second derivative boundary condition
3803 : * by default, BoundType=0 is used
3804 :
3805 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3806 :
3807 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3808 : However, this subroutine doesn't require you to specify equal values for
3809 : the first and last points - it automatically forces them to be equal by
3810 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3811 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3812 : i.e. to make Y[first_point]=Y[last_point].
3813 :
3814 : -- ALGLIB PROJECT --
3815 : Copyright 03.09.2010 by Bochkanov Sergey
3816 : *************************************************************************/
3817 : #if !defined(AE_NO_EXCEPTIONS)
3818 0 : void spline1dconvdiff2cubic(const real_1d_array &x, const real_1d_array &y, const real_1d_array &x2, real_1d_array &y2, real_1d_array &d2, real_1d_array &dd2, const xparams _xparams)
3819 : {
3820 : jmp_buf _break_jump;
3821 : alglib_impl::ae_state _alglib_env_state;
3822 : ae_int_t n;
3823 : ae_int_t boundltype;
3824 : double boundl;
3825 : ae_int_t boundrtype;
3826 : double boundr;
3827 : ae_int_t n2;
3828 0 : if( (x.length()!=y.length()))
3829 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dconvdiff2cubic': looks like one of arguments has wrong size");
3830 0 : n = x.length();
3831 0 : boundltype = 0;
3832 0 : boundl = 0;
3833 0 : boundrtype = 0;
3834 0 : boundr = 0;
3835 0 : n2 = x2.length();
3836 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3837 0 : if( setjmp(_break_jump) )
3838 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3839 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3840 0 : if( _xparams.flags!=0x0 )
3841 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3842 0 : alglib_impl::spline1dconvdiff2cubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundltype, boundl, boundrtype, boundr, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), const_cast<alglib_impl::ae_vector*>(d2.c_ptr()), const_cast<alglib_impl::ae_vector*>(dd2.c_ptr()), &_alglib_env_state);
3843 :
3844 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3845 0 : return;
3846 : }
3847 : #endif
3848 :
3849 : /*************************************************************************
3850 : This subroutine builds Catmull-Rom spline interpolant.
3851 :
3852 : INPUT PARAMETERS:
3853 : X - spline nodes, array[0..N-1].
3854 : Y - function values, array[0..N-1].
3855 :
3856 : OPTIONAL PARAMETERS:
3857 : N - points count:
3858 : * N>=2
3859 : * if given, only first N points are used to build spline
3860 : * if not given, automatically detected from X/Y sizes
3861 : (len(X) must be equal to len(Y))
3862 : BoundType - boundary condition type:
3863 : * -1 for periodic boundary condition
3864 : * 0 for parabolically terminated spline (default)
3865 : Tension - tension parameter:
3866 : * tension=0 corresponds to classic Catmull-Rom spline (default)
3867 : * 0<tension<1 corresponds to more general form - cardinal spline
3868 :
3869 : OUTPUT PARAMETERS:
3870 : C - spline interpolant
3871 :
3872 :
3873 : ORDER OF POINTS
3874 :
3875 : Subroutine automatically sorts points, so caller may pass unsorted array.
3876 :
3877 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3878 :
3879 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3880 : However, this subroutine doesn't require you to specify equal values for
3881 : the first and last points - it automatically forces them to be equal by
3882 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3883 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3884 : i.e. to make Y[first_point]=Y[last_point].
3885 :
3886 : -- ALGLIB PROJECT --
3887 : Copyright 23.06.2007 by Bochkanov Sergey
3888 : *************************************************************************/
3889 0 : void spline1dbuildcatmullrom(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t boundtype, const double tension, spline1dinterpolant &c, const xparams _xparams)
3890 : {
3891 : jmp_buf _break_jump;
3892 : alglib_impl::ae_state _alglib_env_state;
3893 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3894 0 : if( setjmp(_break_jump) )
3895 : {
3896 : #if !defined(AE_NO_EXCEPTIONS)
3897 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3898 : #else
3899 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3900 : return;
3901 : #endif
3902 : }
3903 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3904 0 : if( _xparams.flags!=0x0 )
3905 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3906 0 : alglib_impl::spline1dbuildcatmullrom(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundtype, tension, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
3907 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3908 0 : return;
3909 : }
3910 :
3911 : /*************************************************************************
3912 : This subroutine builds Catmull-Rom spline interpolant.
3913 :
3914 : INPUT PARAMETERS:
3915 : X - spline nodes, array[0..N-1].
3916 : Y - function values, array[0..N-1].
3917 :
3918 : OPTIONAL PARAMETERS:
3919 : N - points count:
3920 : * N>=2
3921 : * if given, only first N points are used to build spline
3922 : * if not given, automatically detected from X/Y sizes
3923 : (len(X) must be equal to len(Y))
3924 : BoundType - boundary condition type:
3925 : * -1 for periodic boundary condition
3926 : * 0 for parabolically terminated spline (default)
3927 : Tension - tension parameter:
3928 : * tension=0 corresponds to classic Catmull-Rom spline (default)
3929 : * 0<tension<1 corresponds to more general form - cardinal spline
3930 :
3931 : OUTPUT PARAMETERS:
3932 : C - spline interpolant
3933 :
3934 :
3935 : ORDER OF POINTS
3936 :
3937 : Subroutine automatically sorts points, so caller may pass unsorted array.
3938 :
3939 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
3940 :
3941 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
3942 : However, this subroutine doesn't require you to specify equal values for
3943 : the first and last points - it automatically forces them to be equal by
3944 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
3945 : Y[last_point]. However it is recommended to pass consistent values of Y[],
3946 : i.e. to make Y[first_point]=Y[last_point].
3947 :
3948 : -- ALGLIB PROJECT --
3949 : Copyright 23.06.2007 by Bochkanov Sergey
3950 : *************************************************************************/
3951 : #if !defined(AE_NO_EXCEPTIONS)
3952 0 : void spline1dbuildcatmullrom(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams)
3953 : {
3954 : jmp_buf _break_jump;
3955 : alglib_impl::ae_state _alglib_env_state;
3956 : ae_int_t n;
3957 : ae_int_t boundtype;
3958 : double tension;
3959 0 : if( (x.length()!=y.length()))
3960 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildcatmullrom': looks like one of arguments has wrong size");
3961 0 : n = x.length();
3962 0 : boundtype = 0;
3963 0 : tension = 0;
3964 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3965 0 : if( setjmp(_break_jump) )
3966 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3967 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3968 0 : if( _xparams.flags!=0x0 )
3969 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3970 0 : alglib_impl::spline1dbuildcatmullrom(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, boundtype, tension, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
3971 :
3972 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3973 0 : return;
3974 : }
3975 : #endif
3976 :
3977 : /*************************************************************************
3978 : This subroutine builds Hermite spline interpolant.
3979 :
3980 : INPUT PARAMETERS:
3981 : X - spline nodes, array[0..N-1]
3982 : Y - function values, array[0..N-1]
3983 : D - derivatives, array[0..N-1]
3984 : N - points count (optional):
3985 : * N>=2
3986 : * if given, only first N points are used to build spline
3987 : * if not given, automatically detected from X/Y sizes
3988 : (len(X) must be equal to len(Y))
3989 :
3990 : OUTPUT PARAMETERS:
3991 : C - spline interpolant.
3992 :
3993 :
3994 : ORDER OF POINTS
3995 :
3996 : Subroutine automatically sorts points, so caller may pass unsorted array.
3997 :
3998 : -- ALGLIB PROJECT --
3999 : Copyright 23.06.2007 by Bochkanov Sergey
4000 : *************************************************************************/
4001 0 : void spline1dbuildhermite(const real_1d_array &x, const real_1d_array &y, const real_1d_array &d, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams)
4002 : {
4003 : jmp_buf _break_jump;
4004 : alglib_impl::ae_state _alglib_env_state;
4005 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4006 0 : if( setjmp(_break_jump) )
4007 : {
4008 : #if !defined(AE_NO_EXCEPTIONS)
4009 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4010 : #else
4011 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4012 : return;
4013 : #endif
4014 : }
4015 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4016 0 : if( _xparams.flags!=0x0 )
4017 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4018 0 : alglib_impl::spline1dbuildhermite(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
4019 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4020 0 : return;
4021 : }
4022 :
4023 : /*************************************************************************
4024 : This subroutine builds Hermite spline interpolant.
4025 :
4026 : INPUT PARAMETERS:
4027 : X - spline nodes, array[0..N-1]
4028 : Y - function values, array[0..N-1]
4029 : D - derivatives, array[0..N-1]
4030 : N - points count (optional):
4031 : * N>=2
4032 : * if given, only first N points are used to build spline
4033 : * if not given, automatically detected from X/Y sizes
4034 : (len(X) must be equal to len(Y))
4035 :
4036 : OUTPUT PARAMETERS:
4037 : C - spline interpolant.
4038 :
4039 :
4040 : ORDER OF POINTS
4041 :
4042 : Subroutine automatically sorts points, so caller may pass unsorted array.
4043 :
4044 : -- ALGLIB PROJECT --
4045 : Copyright 23.06.2007 by Bochkanov Sergey
4046 : *************************************************************************/
4047 : #if !defined(AE_NO_EXCEPTIONS)
4048 0 : void spline1dbuildhermite(const real_1d_array &x, const real_1d_array &y, const real_1d_array &d, spline1dinterpolant &c, const xparams _xparams)
4049 : {
4050 : jmp_buf _break_jump;
4051 : alglib_impl::ae_state _alglib_env_state;
4052 : ae_int_t n;
4053 0 : if( (x.length()!=y.length()) || (x.length()!=d.length()))
4054 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildhermite': looks like one of arguments has wrong size");
4055 0 : n = x.length();
4056 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4057 0 : if( setjmp(_break_jump) )
4058 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4059 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4060 0 : if( _xparams.flags!=0x0 )
4061 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4062 0 : alglib_impl::spline1dbuildhermite(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
4063 :
4064 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4065 0 : return;
4066 : }
4067 : #endif
4068 :
4069 : /*************************************************************************
4070 : This subroutine builds Akima spline interpolant
4071 :
4072 : INPUT PARAMETERS:
4073 : X - spline nodes, array[0..N-1]
4074 : Y - function values, array[0..N-1]
4075 : N - points count (optional):
4076 : * N>=2
4077 : * if given, only first N points are used to build spline
4078 : * if not given, automatically detected from X/Y sizes
4079 : (len(X) must be equal to len(Y))
4080 :
4081 : OUTPUT PARAMETERS:
4082 : C - spline interpolant
4083 :
4084 :
4085 : ORDER OF POINTS
4086 :
4087 : Subroutine automatically sorts points, so caller may pass unsorted array.
4088 :
4089 : -- ALGLIB PROJECT --
4090 : Copyright 24.06.2007 by Bochkanov Sergey
4091 : *************************************************************************/
4092 0 : void spline1dbuildakima(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams)
4093 : {
4094 : jmp_buf _break_jump;
4095 : alglib_impl::ae_state _alglib_env_state;
4096 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4097 0 : if( setjmp(_break_jump) )
4098 : {
4099 : #if !defined(AE_NO_EXCEPTIONS)
4100 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4101 : #else
4102 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4103 : return;
4104 : #endif
4105 : }
4106 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4107 0 : if( _xparams.flags!=0x0 )
4108 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4109 0 : alglib_impl::spline1dbuildakima(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
4110 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4111 0 : return;
4112 : }
4113 :
4114 : /*************************************************************************
4115 : This subroutine builds Akima spline interpolant
4116 :
4117 : INPUT PARAMETERS:
4118 : X - spline nodes, array[0..N-1]
4119 : Y - function values, array[0..N-1]
4120 : N - points count (optional):
4121 : * N>=2
4122 : * if given, only first N points are used to build spline
4123 : * if not given, automatically detected from X/Y sizes
4124 : (len(X) must be equal to len(Y))
4125 :
4126 : OUTPUT PARAMETERS:
4127 : C - spline interpolant
4128 :
4129 :
4130 : ORDER OF POINTS
4131 :
4132 : Subroutine automatically sorts points, so caller may pass unsorted array.
4133 :
4134 : -- ALGLIB PROJECT --
4135 : Copyright 24.06.2007 by Bochkanov Sergey
4136 : *************************************************************************/
4137 : #if !defined(AE_NO_EXCEPTIONS)
4138 0 : void spline1dbuildakima(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams)
4139 : {
4140 : jmp_buf _break_jump;
4141 : alglib_impl::ae_state _alglib_env_state;
4142 : ae_int_t n;
4143 0 : if( (x.length()!=y.length()))
4144 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildakima': looks like one of arguments has wrong size");
4145 0 : n = x.length();
4146 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4147 0 : if( setjmp(_break_jump) )
4148 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4149 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4150 0 : if( _xparams.flags!=0x0 )
4151 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4152 0 : alglib_impl::spline1dbuildakima(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
4153 :
4154 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4155 0 : return;
4156 : }
4157 : #endif
4158 :
4159 : /*************************************************************************
4160 : This subroutine calculates the value of the spline at the given point X.
4161 :
4162 : INPUT PARAMETERS:
4163 : C - spline interpolant
4164 : X - point
4165 :
4166 : Result:
4167 : S(x)
4168 :
4169 : -- ALGLIB PROJECT --
4170 : Copyright 23.06.2007 by Bochkanov Sergey
4171 : *************************************************************************/
4172 0 : double spline1dcalc(const spline1dinterpolant &c, const double x, const xparams _xparams)
4173 : {
4174 : jmp_buf _break_jump;
4175 : alglib_impl::ae_state _alglib_env_state;
4176 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4177 0 : if( setjmp(_break_jump) )
4178 : {
4179 : #if !defined(AE_NO_EXCEPTIONS)
4180 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4181 : #else
4182 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4183 : return 0;
4184 : #endif
4185 : }
4186 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4187 0 : if( _xparams.flags!=0x0 )
4188 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4189 0 : double result = alglib_impl::spline1dcalc(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), x, &_alglib_env_state);
4190 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4191 0 : return *(reinterpret_cast<double*>(&result));
4192 : }
4193 :
4194 : /*************************************************************************
4195 : This subroutine differentiates the spline.
4196 :
4197 : INPUT PARAMETERS:
4198 : C - spline interpolant.
4199 : X - point
4200 :
4201 : Result:
4202 : S - S(x)
4203 : DS - S'(x)
4204 : D2S - S''(x)
4205 :
4206 : -- ALGLIB PROJECT --
4207 : Copyright 24.06.2007 by Bochkanov Sergey
4208 : *************************************************************************/
4209 0 : void spline1ddiff(const spline1dinterpolant &c, const double x, double &s, double &ds, double &d2s, const xparams _xparams)
4210 : {
4211 : jmp_buf _break_jump;
4212 : alglib_impl::ae_state _alglib_env_state;
4213 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4214 0 : if( setjmp(_break_jump) )
4215 : {
4216 : #if !defined(AE_NO_EXCEPTIONS)
4217 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4218 : #else
4219 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4220 : return;
4221 : #endif
4222 : }
4223 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4224 0 : if( _xparams.flags!=0x0 )
4225 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4226 0 : alglib_impl::spline1ddiff(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), x, &s, &ds, &d2s, &_alglib_env_state);
4227 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4228 0 : return;
4229 : }
4230 :
4231 : /*************************************************************************
4232 : This subroutine unpacks the spline into the coefficients table.
4233 :
4234 : INPUT PARAMETERS:
4235 : C - spline interpolant.
4236 : X - point
4237 :
4238 : OUTPUT PARAMETERS:
4239 : Tbl - coefficients table, unpacked format, array[0..N-2, 0..5].
4240 : For I = 0...N-2:
4241 : Tbl[I,0] = X[i]
4242 : Tbl[I,1] = X[i+1]
4243 : Tbl[I,2] = C0
4244 : Tbl[I,3] = C1
4245 : Tbl[I,4] = C2
4246 : Tbl[I,5] = C3
4247 : On [x[i], x[i+1]] spline is equals to:
4248 : S(x) = C0 + C1*t + C2*t^2 + C3*t^3
4249 : t = x-x[i]
4250 :
4251 : NOTE:
4252 : You can rebuild spline with Spline1DBuildHermite() function, which
4253 : accepts as inputs function values and derivatives at nodes, which are
4254 : easy to calculate when you have coefficients.
4255 :
4256 : -- ALGLIB PROJECT --
4257 : Copyright 29.06.2007 by Bochkanov Sergey
4258 : *************************************************************************/
4259 0 : void spline1dunpack(const spline1dinterpolant &c, ae_int_t &n, real_2d_array &tbl, const xparams _xparams)
4260 : {
4261 : jmp_buf _break_jump;
4262 : alglib_impl::ae_state _alglib_env_state;
4263 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4264 0 : if( setjmp(_break_jump) )
4265 : {
4266 : #if !defined(AE_NO_EXCEPTIONS)
4267 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4268 : #else
4269 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4270 : return;
4271 : #endif
4272 : }
4273 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4274 0 : if( _xparams.flags!=0x0 )
4275 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4276 0 : alglib_impl::spline1dunpack(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &n, const_cast<alglib_impl::ae_matrix*>(tbl.c_ptr()), &_alglib_env_state);
4277 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4278 0 : return;
4279 : }
4280 :
4281 : /*************************************************************************
4282 : This subroutine performs linear transformation of the spline argument.
4283 :
4284 : INPUT PARAMETERS:
4285 : C - spline interpolant.
4286 : A, B- transformation coefficients: x = A*t + B
4287 : Result:
4288 : C - transformed spline
4289 :
4290 : -- ALGLIB PROJECT --
4291 : Copyright 30.06.2007 by Bochkanov Sergey
4292 : *************************************************************************/
4293 0 : void spline1dlintransx(const spline1dinterpolant &c, const double a, const double b, const xparams _xparams)
4294 : {
4295 : jmp_buf _break_jump;
4296 : alglib_impl::ae_state _alglib_env_state;
4297 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4298 0 : if( setjmp(_break_jump) )
4299 : {
4300 : #if !defined(AE_NO_EXCEPTIONS)
4301 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4302 : #else
4303 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4304 : return;
4305 : #endif
4306 : }
4307 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4308 0 : if( _xparams.flags!=0x0 )
4309 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4310 0 : alglib_impl::spline1dlintransx(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
4311 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4312 0 : return;
4313 : }
4314 :
4315 : /*************************************************************************
4316 : This subroutine performs linear transformation of the spline.
4317 :
4318 : INPUT PARAMETERS:
4319 : C - spline interpolant.
4320 : A, B- transformation coefficients: S2(x) = A*S(x) + B
4321 : Result:
4322 : C - transformed spline
4323 :
4324 : -- ALGLIB PROJECT --
4325 : Copyright 30.06.2007 by Bochkanov Sergey
4326 : *************************************************************************/
4327 0 : void spline1dlintransy(const spline1dinterpolant &c, const double a, const double b, const xparams _xparams)
4328 : {
4329 : jmp_buf _break_jump;
4330 : alglib_impl::ae_state _alglib_env_state;
4331 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4332 0 : if( setjmp(_break_jump) )
4333 : {
4334 : #if !defined(AE_NO_EXCEPTIONS)
4335 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4336 : #else
4337 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4338 : return;
4339 : #endif
4340 : }
4341 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4342 0 : if( _xparams.flags!=0x0 )
4343 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4344 0 : alglib_impl::spline1dlintransy(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
4345 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4346 0 : return;
4347 : }
4348 :
4349 : /*************************************************************************
4350 : This subroutine integrates the spline.
4351 :
4352 : INPUT PARAMETERS:
4353 : C - spline interpolant.
4354 : X - right bound of the integration interval [a, x],
4355 : here 'a' denotes min(x[])
4356 : Result:
4357 : integral(S(t)dt,a,x)
4358 :
4359 : -- ALGLIB PROJECT --
4360 : Copyright 23.06.2007 by Bochkanov Sergey
4361 : *************************************************************************/
4362 0 : double spline1dintegrate(const spline1dinterpolant &c, const double x, const xparams _xparams)
4363 : {
4364 : jmp_buf _break_jump;
4365 : alglib_impl::ae_state _alglib_env_state;
4366 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4367 0 : if( setjmp(_break_jump) )
4368 : {
4369 : #if !defined(AE_NO_EXCEPTIONS)
4370 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4371 : #else
4372 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4373 : return 0;
4374 : #endif
4375 : }
4376 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4377 0 : if( _xparams.flags!=0x0 )
4378 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4379 0 : double result = alglib_impl::spline1dintegrate(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), x, &_alglib_env_state);
4380 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4381 0 : return *(reinterpret_cast<double*>(&result));
4382 : }
4383 :
4384 : /*************************************************************************
4385 : Fitting by smoothing (penalized) cubic spline.
4386 :
4387 : This function approximates N scattered points (some of X[] may be equal to
4388 : each other) by cubic spline with M nodes at equidistant grid spanning
4389 : interval [min(x,xc),max(x,xc)].
4390 :
4391 : The problem is regularized by adding nonlinearity penalty to usual least
4392 : squares penalty function:
4393 :
4394 : MERIT_FUNC = F_LS + F_NL
4395 :
4396 : where F_LS is a least squares error term, and F_NL is a nonlinearity
4397 : penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }.
4398 : Algorithm applies automatic renormalization of F_NL which makes penalty
4399 : term roughly invariant to scaling of X[] and changes in M.
4400 :
4401 : This function is a new edition of penalized regression spline fitting,
4402 : a fast and compact one which needs much less resources that its previous
4403 : version: just O(maxMN) memory and O(maxMN*log(maxMN)) time.
4404 :
4405 : NOTE: it is OK to run this function with both M<<N and M>>N; say, it is
4406 : possible to process 100 points with 1000-node spline.
4407 :
4408 : INPUT PARAMETERS:
4409 : X - points, array[0..N-1].
4410 : Y - function values, array[0..N-1].
4411 : N - number of points (optional):
4412 : * N>0
4413 : * if given, only first N elements of X/Y are processed
4414 : * if not given, automatically determined from lengths
4415 : M - number of basis functions ( = number_of_nodes), M>=4.
4416 : LambdaNS - LambdaNS>=0, regularization constant passed by user.
4417 : It penalizes nonlinearity in the regression spline.
4418 : Possible values to start from are 0.00001, 0.1, 1
4419 :
4420 : OUTPUT PARAMETERS:
4421 : S - spline interpolant.
4422 : Rep - Following fields are set:
4423 : * RMSError rms error on the (X,Y).
4424 : * AvgError average error on the (X,Y).
4425 : * AvgRelError average relative error on the non-zero Y
4426 : * MaxError maximum error
4427 :
4428 : -- ALGLIB PROJECT --
4429 : Copyright 27.08.2019 by Bochkanov Sergey
4430 : *************************************************************************/
4431 0 : void spline1dfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, const double lambdans, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
4432 : {
4433 : jmp_buf _break_jump;
4434 : alglib_impl::ae_state _alglib_env_state;
4435 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4436 0 : if( setjmp(_break_jump) )
4437 : {
4438 : #if !defined(AE_NO_EXCEPTIONS)
4439 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4440 : #else
4441 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4442 : return;
4443 : #endif
4444 : }
4445 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4446 0 : if( _xparams.flags!=0x0 )
4447 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4448 0 : alglib_impl::spline1dfit(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, lambdans, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
4449 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4450 0 : return;
4451 : }
4452 :
4453 : /*************************************************************************
4454 : Fitting by smoothing (penalized) cubic spline.
4455 :
4456 : This function approximates N scattered points (some of X[] may be equal to
4457 : each other) by cubic spline with M nodes at equidistant grid spanning
4458 : interval [min(x,xc),max(x,xc)].
4459 :
4460 : The problem is regularized by adding nonlinearity penalty to usual least
4461 : squares penalty function:
4462 :
4463 : MERIT_FUNC = F_LS + F_NL
4464 :
4465 : where F_LS is a least squares error term, and F_NL is a nonlinearity
4466 : penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }.
4467 : Algorithm applies automatic renormalization of F_NL which makes penalty
4468 : term roughly invariant to scaling of X[] and changes in M.
4469 :
4470 : This function is a new edition of penalized regression spline fitting,
4471 : a fast and compact one which needs much less resources that its previous
4472 : version: just O(maxMN) memory and O(maxMN*log(maxMN)) time.
4473 :
4474 : NOTE: it is OK to run this function with both M<<N and M>>N; say, it is
4475 : possible to process 100 points with 1000-node spline.
4476 :
4477 : INPUT PARAMETERS:
4478 : X - points, array[0..N-1].
4479 : Y - function values, array[0..N-1].
4480 : N - number of points (optional):
4481 : * N>0
4482 : * if given, only first N elements of X/Y are processed
4483 : * if not given, automatically determined from lengths
4484 : M - number of basis functions ( = number_of_nodes), M>=4.
4485 : LambdaNS - LambdaNS>=0, regularization constant passed by user.
4486 : It penalizes nonlinearity in the regression spline.
4487 : Possible values to start from are 0.00001, 0.1, 1
4488 :
4489 : OUTPUT PARAMETERS:
4490 : S - spline interpolant.
4491 : Rep - Following fields are set:
4492 : * RMSError rms error on the (X,Y).
4493 : * AvgError average error on the (X,Y).
4494 : * AvgRelError average relative error on the non-zero Y
4495 : * MaxError maximum error
4496 :
4497 : -- ALGLIB PROJECT --
4498 : Copyright 27.08.2019 by Bochkanov Sergey
4499 : *************************************************************************/
4500 : #if !defined(AE_NO_EXCEPTIONS)
4501 0 : void spline1dfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, const double lambdans, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
4502 : {
4503 : jmp_buf _break_jump;
4504 : alglib_impl::ae_state _alglib_env_state;
4505 : ae_int_t n;
4506 0 : if( (x.length()!=y.length()))
4507 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfit': looks like one of arguments has wrong size");
4508 0 : n = x.length();
4509 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4510 0 : if( setjmp(_break_jump) )
4511 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4512 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4513 0 : if( _xparams.flags!=0x0 )
4514 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4515 0 : alglib_impl::spline1dfit(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, lambdans, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
4516 :
4517 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4518 0 : return;
4519 : }
4520 : #endif
4521 :
4522 : /*************************************************************************
4523 : This function builds monotone cubic Hermite interpolant. This interpolant
4524 : is monotonic in [x(0),x(n-1)] and is constant outside of this interval.
4525 :
4526 : In case y[] form non-monotonic sequence, interpolant is piecewise
4527 : monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will
4528 : monotonically grow at [0..2] and monotonically decrease at [2..4].
4529 :
4530 : INPUT PARAMETERS:
4531 : X - spline nodes, array[0..N-1]. Subroutine automatically
4532 : sorts points, so caller may pass unsorted array.
4533 : Y - function values, array[0..N-1]
4534 : N - the number of points(N>=2).
4535 :
4536 : OUTPUT PARAMETERS:
4537 : C - spline interpolant.
4538 :
4539 : -- ALGLIB PROJECT --
4540 : Copyright 21.06.2012 by Bochkanov Sergey
4541 : *************************************************************************/
4542 0 : void spline1dbuildmonotone(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c, const xparams _xparams)
4543 : {
4544 : jmp_buf _break_jump;
4545 : alglib_impl::ae_state _alglib_env_state;
4546 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4547 0 : if( setjmp(_break_jump) )
4548 : {
4549 : #if !defined(AE_NO_EXCEPTIONS)
4550 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4551 : #else
4552 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4553 : return;
4554 : #endif
4555 : }
4556 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4557 0 : if( _xparams.flags!=0x0 )
4558 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4559 0 : alglib_impl::spline1dbuildmonotone(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
4560 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4561 0 : return;
4562 : }
4563 :
4564 : /*************************************************************************
4565 : This function builds monotone cubic Hermite interpolant. This interpolant
4566 : is monotonic in [x(0),x(n-1)] and is constant outside of this interval.
4567 :
4568 : In case y[] form non-monotonic sequence, interpolant is piecewise
4569 : monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will
4570 : monotonically grow at [0..2] and monotonically decrease at [2..4].
4571 :
4572 : INPUT PARAMETERS:
4573 : X - spline nodes, array[0..N-1]. Subroutine automatically
4574 : sorts points, so caller may pass unsorted array.
4575 : Y - function values, array[0..N-1]
4576 : N - the number of points(N>=2).
4577 :
4578 : OUTPUT PARAMETERS:
4579 : C - spline interpolant.
4580 :
4581 : -- ALGLIB PROJECT --
4582 : Copyright 21.06.2012 by Bochkanov Sergey
4583 : *************************************************************************/
4584 : #if !defined(AE_NO_EXCEPTIONS)
4585 0 : void spline1dbuildmonotone(const real_1d_array &x, const real_1d_array &y, spline1dinterpolant &c, const xparams _xparams)
4586 : {
4587 : jmp_buf _break_jump;
4588 : alglib_impl::ae_state _alglib_env_state;
4589 : ae_int_t n;
4590 0 : if( (x.length()!=y.length()))
4591 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dbuildmonotone': looks like one of arguments has wrong size");
4592 0 : n = x.length();
4593 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4594 0 : if( setjmp(_break_jump) )
4595 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4596 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4597 0 : if( _xparams.flags!=0x0 )
4598 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4599 0 : alglib_impl::spline1dbuildmonotone(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &_alglib_env_state);
4600 :
4601 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4602 0 : return;
4603 : }
4604 : #endif
4605 : #endif
4606 :
4607 : #if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD)
4608 : /*************************************************************************
4609 : Parametric spline inteprolant: 2-dimensional curve.
4610 :
4611 : You should not try to access its members directly - use PSpline2XXXXXXXX()
4612 : functions instead.
4613 : *************************************************************************/
4614 0 : _pspline2interpolant_owner::_pspline2interpolant_owner()
4615 : {
4616 : jmp_buf _break_jump;
4617 : alglib_impl::ae_state _state;
4618 :
4619 0 : alglib_impl::ae_state_init(&_state);
4620 0 : if( setjmp(_break_jump) )
4621 : {
4622 0 : if( p_struct!=NULL )
4623 : {
4624 0 : alglib_impl::_pspline2interpolant_destroy(p_struct);
4625 0 : alglib_impl::ae_free(p_struct);
4626 : }
4627 0 : p_struct = NULL;
4628 : #if !defined(AE_NO_EXCEPTIONS)
4629 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4630 : #else
4631 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4632 : return;
4633 : #endif
4634 : }
4635 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4636 0 : p_struct = NULL;
4637 0 : p_struct = (alglib_impl::pspline2interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline2interpolant), &_state);
4638 0 : memset(p_struct, 0, sizeof(alglib_impl::pspline2interpolant));
4639 0 : alglib_impl::_pspline2interpolant_init(p_struct, &_state, ae_false);
4640 0 : ae_state_clear(&_state);
4641 0 : }
4642 :
4643 0 : _pspline2interpolant_owner::_pspline2interpolant_owner(const _pspline2interpolant_owner &rhs)
4644 : {
4645 : jmp_buf _break_jump;
4646 : alglib_impl::ae_state _state;
4647 :
4648 0 : alglib_impl::ae_state_init(&_state);
4649 0 : if( setjmp(_break_jump) )
4650 : {
4651 0 : if( p_struct!=NULL )
4652 : {
4653 0 : alglib_impl::_pspline2interpolant_destroy(p_struct);
4654 0 : alglib_impl::ae_free(p_struct);
4655 : }
4656 0 : p_struct = NULL;
4657 : #if !defined(AE_NO_EXCEPTIONS)
4658 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4659 : #else
4660 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4661 : return;
4662 : #endif
4663 : }
4664 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4665 0 : p_struct = NULL;
4666 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline2interpolant copy constructor failure (source is not initialized)", &_state);
4667 0 : p_struct = (alglib_impl::pspline2interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline2interpolant), &_state);
4668 0 : memset(p_struct, 0, sizeof(alglib_impl::pspline2interpolant));
4669 0 : alglib_impl::_pspline2interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline2interpolant*>(rhs.p_struct), &_state, ae_false);
4670 0 : ae_state_clear(&_state);
4671 0 : }
4672 :
4673 0 : _pspline2interpolant_owner& _pspline2interpolant_owner::operator=(const _pspline2interpolant_owner &rhs)
4674 : {
4675 0 : if( this==&rhs )
4676 0 : return *this;
4677 : jmp_buf _break_jump;
4678 : alglib_impl::ae_state _state;
4679 :
4680 0 : alglib_impl::ae_state_init(&_state);
4681 0 : if( setjmp(_break_jump) )
4682 : {
4683 : #if !defined(AE_NO_EXCEPTIONS)
4684 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4685 : #else
4686 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4687 : return *this;
4688 : #endif
4689 : }
4690 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4691 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: pspline2interpolant assignment constructor failure (destination is not initialized)", &_state);
4692 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline2interpolant assignment constructor failure (source is not initialized)", &_state);
4693 0 : alglib_impl::_pspline2interpolant_destroy(p_struct);
4694 0 : memset(p_struct, 0, sizeof(alglib_impl::pspline2interpolant));
4695 0 : alglib_impl::_pspline2interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline2interpolant*>(rhs.p_struct), &_state, ae_false);
4696 0 : ae_state_clear(&_state);
4697 0 : return *this;
4698 : }
4699 :
4700 0 : _pspline2interpolant_owner::~_pspline2interpolant_owner()
4701 : {
4702 0 : if( p_struct!=NULL )
4703 : {
4704 0 : alglib_impl::_pspline2interpolant_destroy(p_struct);
4705 0 : ae_free(p_struct);
4706 : }
4707 0 : }
4708 :
4709 0 : alglib_impl::pspline2interpolant* _pspline2interpolant_owner::c_ptr()
4710 : {
4711 0 : return p_struct;
4712 : }
4713 :
4714 0 : alglib_impl::pspline2interpolant* _pspline2interpolant_owner::c_ptr() const
4715 : {
4716 0 : return const_cast<alglib_impl::pspline2interpolant*>(p_struct);
4717 : }
4718 0 : pspline2interpolant::pspline2interpolant() : _pspline2interpolant_owner()
4719 : {
4720 0 : }
4721 :
4722 0 : pspline2interpolant::pspline2interpolant(const pspline2interpolant &rhs):_pspline2interpolant_owner(rhs)
4723 : {
4724 0 : }
4725 :
4726 0 : pspline2interpolant& pspline2interpolant::operator=(const pspline2interpolant &rhs)
4727 : {
4728 0 : if( this==&rhs )
4729 0 : return *this;
4730 0 : _pspline2interpolant_owner::operator=(rhs);
4731 0 : return *this;
4732 : }
4733 :
4734 0 : pspline2interpolant::~pspline2interpolant()
4735 : {
4736 0 : }
4737 :
4738 :
4739 : /*************************************************************************
4740 : Parametric spline inteprolant: 3-dimensional curve.
4741 :
4742 : You should not try to access its members directly - use PSpline3XXXXXXXX()
4743 : functions instead.
4744 : *************************************************************************/
4745 0 : _pspline3interpolant_owner::_pspline3interpolant_owner()
4746 : {
4747 : jmp_buf _break_jump;
4748 : alglib_impl::ae_state _state;
4749 :
4750 0 : alglib_impl::ae_state_init(&_state);
4751 0 : if( setjmp(_break_jump) )
4752 : {
4753 0 : if( p_struct!=NULL )
4754 : {
4755 0 : alglib_impl::_pspline3interpolant_destroy(p_struct);
4756 0 : alglib_impl::ae_free(p_struct);
4757 : }
4758 0 : p_struct = NULL;
4759 : #if !defined(AE_NO_EXCEPTIONS)
4760 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4761 : #else
4762 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4763 : return;
4764 : #endif
4765 : }
4766 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4767 0 : p_struct = NULL;
4768 0 : p_struct = (alglib_impl::pspline3interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline3interpolant), &_state);
4769 0 : memset(p_struct, 0, sizeof(alglib_impl::pspline3interpolant));
4770 0 : alglib_impl::_pspline3interpolant_init(p_struct, &_state, ae_false);
4771 0 : ae_state_clear(&_state);
4772 0 : }
4773 :
4774 0 : _pspline3interpolant_owner::_pspline3interpolant_owner(const _pspline3interpolant_owner &rhs)
4775 : {
4776 : jmp_buf _break_jump;
4777 : alglib_impl::ae_state _state;
4778 :
4779 0 : alglib_impl::ae_state_init(&_state);
4780 0 : if( setjmp(_break_jump) )
4781 : {
4782 0 : if( p_struct!=NULL )
4783 : {
4784 0 : alglib_impl::_pspline3interpolant_destroy(p_struct);
4785 0 : alglib_impl::ae_free(p_struct);
4786 : }
4787 0 : p_struct = NULL;
4788 : #if !defined(AE_NO_EXCEPTIONS)
4789 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4790 : #else
4791 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4792 : return;
4793 : #endif
4794 : }
4795 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4796 0 : p_struct = NULL;
4797 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline3interpolant copy constructor failure (source is not initialized)", &_state);
4798 0 : p_struct = (alglib_impl::pspline3interpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::pspline3interpolant), &_state);
4799 0 : memset(p_struct, 0, sizeof(alglib_impl::pspline3interpolant));
4800 0 : alglib_impl::_pspline3interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline3interpolant*>(rhs.p_struct), &_state, ae_false);
4801 0 : ae_state_clear(&_state);
4802 0 : }
4803 :
4804 0 : _pspline3interpolant_owner& _pspline3interpolant_owner::operator=(const _pspline3interpolant_owner &rhs)
4805 : {
4806 0 : if( this==&rhs )
4807 0 : return *this;
4808 : jmp_buf _break_jump;
4809 : alglib_impl::ae_state _state;
4810 :
4811 0 : alglib_impl::ae_state_init(&_state);
4812 0 : if( setjmp(_break_jump) )
4813 : {
4814 : #if !defined(AE_NO_EXCEPTIONS)
4815 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4816 : #else
4817 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4818 : return *this;
4819 : #endif
4820 : }
4821 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4822 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: pspline3interpolant assignment constructor failure (destination is not initialized)", &_state);
4823 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: pspline3interpolant assignment constructor failure (source is not initialized)", &_state);
4824 0 : alglib_impl::_pspline3interpolant_destroy(p_struct);
4825 0 : memset(p_struct, 0, sizeof(alglib_impl::pspline3interpolant));
4826 0 : alglib_impl::_pspline3interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline3interpolant*>(rhs.p_struct), &_state, ae_false);
4827 0 : ae_state_clear(&_state);
4828 0 : return *this;
4829 : }
4830 :
4831 0 : _pspline3interpolant_owner::~_pspline3interpolant_owner()
4832 : {
4833 0 : if( p_struct!=NULL )
4834 : {
4835 0 : alglib_impl::_pspline3interpolant_destroy(p_struct);
4836 0 : ae_free(p_struct);
4837 : }
4838 0 : }
4839 :
4840 0 : alglib_impl::pspline3interpolant* _pspline3interpolant_owner::c_ptr()
4841 : {
4842 0 : return p_struct;
4843 : }
4844 :
4845 0 : alglib_impl::pspline3interpolant* _pspline3interpolant_owner::c_ptr() const
4846 : {
4847 0 : return const_cast<alglib_impl::pspline3interpolant*>(p_struct);
4848 : }
4849 0 : pspline3interpolant::pspline3interpolant() : _pspline3interpolant_owner()
4850 : {
4851 0 : }
4852 :
4853 0 : pspline3interpolant::pspline3interpolant(const pspline3interpolant &rhs):_pspline3interpolant_owner(rhs)
4854 : {
4855 0 : }
4856 :
4857 0 : pspline3interpolant& pspline3interpolant::operator=(const pspline3interpolant &rhs)
4858 : {
4859 0 : if( this==&rhs )
4860 0 : return *this;
4861 0 : _pspline3interpolant_owner::operator=(rhs);
4862 0 : return *this;
4863 : }
4864 :
4865 0 : pspline3interpolant::~pspline3interpolant()
4866 : {
4867 0 : }
4868 :
4869 : /*************************************************************************
4870 : This function builds non-periodic 2-dimensional parametric spline which
4871 : starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]).
4872 :
4873 : INPUT PARAMETERS:
4874 : XY - points, array[0..N-1,0..1].
4875 : XY[I,0:1] corresponds to the Ith point.
4876 : Order of points is important!
4877 : N - points count, N>=5 for Akima splines, N>=2 for other types of
4878 : splines.
4879 : ST - spline type:
4880 : * 0 Akima spline
4881 : * 1 parabolically terminated Catmull-Rom spline (Tension=0)
4882 : * 2 parabolically terminated cubic spline
4883 : PT - parameterization type:
4884 : * 0 uniform
4885 : * 1 chord length
4886 : * 2 centripetal
4887 :
4888 : OUTPUT PARAMETERS:
4889 : P - parametric spline interpolant
4890 :
4891 :
4892 : NOTES:
4893 : * this function assumes that there all consequent points are distinct.
4894 : I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
4895 : However, non-consequent points may coincide, i.e. we can have (x0,y0)=
4896 : =(x2,y2).
4897 :
4898 : -- ALGLIB PROJECT --
4899 : Copyright 28.05.2010 by Bochkanov Sergey
4900 : *************************************************************************/
4901 0 : void pspline2build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p, const xparams _xparams)
4902 : {
4903 : jmp_buf _break_jump;
4904 : alglib_impl::ae_state _alglib_env_state;
4905 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4906 0 : if( setjmp(_break_jump) )
4907 : {
4908 : #if !defined(AE_NO_EXCEPTIONS)
4909 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4910 : #else
4911 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4912 : return;
4913 : #endif
4914 : }
4915 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4916 0 : if( _xparams.flags!=0x0 )
4917 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4918 0 : alglib_impl::pspline2build(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, st, pt, const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), &_alglib_env_state);
4919 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4920 0 : return;
4921 : }
4922 :
4923 : /*************************************************************************
4924 : This function builds non-periodic 3-dimensional parametric spline which
4925 : starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]).
4926 :
4927 : Same as PSpline2Build() function, but for 3D, so we won't duplicate its
4928 : description here.
4929 :
4930 : -- ALGLIB PROJECT --
4931 : Copyright 28.05.2010 by Bochkanov Sergey
4932 : *************************************************************************/
4933 0 : void pspline3build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p, const xparams _xparams)
4934 : {
4935 : jmp_buf _break_jump;
4936 : alglib_impl::ae_state _alglib_env_state;
4937 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4938 0 : if( setjmp(_break_jump) )
4939 : {
4940 : #if !defined(AE_NO_EXCEPTIONS)
4941 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4942 : #else
4943 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4944 : return;
4945 : #endif
4946 : }
4947 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4948 0 : if( _xparams.flags!=0x0 )
4949 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4950 0 : alglib_impl::pspline3build(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, st, pt, const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), &_alglib_env_state);
4951 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4952 0 : return;
4953 : }
4954 :
4955 : /*************************************************************************
4956 : This function builds periodic 2-dimensional parametric spline which
4957 : starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then
4958 : back to (X[0],Y[0]).
4959 :
4960 : INPUT PARAMETERS:
4961 : XY - points, array[0..N-1,0..1].
4962 : XY[I,0:1] corresponds to the Ith point.
4963 : XY[N-1,0:1] must be different from XY[0,0:1].
4964 : Order of points is important!
4965 : N - points count, N>=3 for other types of splines.
4966 : ST - spline type:
4967 : * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions
4968 : * 2 cubic spline with cyclic boundary conditions
4969 : PT - parameterization type:
4970 : * 0 uniform
4971 : * 1 chord length
4972 : * 2 centripetal
4973 :
4974 : OUTPUT PARAMETERS:
4975 : P - parametric spline interpolant
4976 :
4977 :
4978 : NOTES:
4979 : * this function assumes that there all consequent points are distinct.
4980 : I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
4981 : However, non-consequent points may coincide, i.e. we can have (x0,y0)=
4982 : =(x2,y2).
4983 : * last point of sequence is NOT equal to the first point. You shouldn't
4984 : make curve "explicitly periodic" by making them equal.
4985 :
4986 : -- ALGLIB PROJECT --
4987 : Copyright 28.05.2010 by Bochkanov Sergey
4988 : *************************************************************************/
4989 0 : void pspline2buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p, const xparams _xparams)
4990 : {
4991 : jmp_buf _break_jump;
4992 : alglib_impl::ae_state _alglib_env_state;
4993 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4994 0 : if( setjmp(_break_jump) )
4995 : {
4996 : #if !defined(AE_NO_EXCEPTIONS)
4997 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4998 : #else
4999 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5000 : return;
5001 : #endif
5002 : }
5003 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5004 0 : if( _xparams.flags!=0x0 )
5005 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5006 0 : alglib_impl::pspline2buildperiodic(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, st, pt, const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), &_alglib_env_state);
5007 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5008 0 : return;
5009 : }
5010 :
5011 : /*************************************************************************
5012 : This function builds periodic 3-dimensional parametric spline which
5013 : starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1])
5014 : and then back to (X[0],Y[0],Z[0]).
5015 :
5016 : Same as PSpline2Build() function, but for 3D, so we won't duplicate its
5017 : description here.
5018 :
5019 : -- ALGLIB PROJECT --
5020 : Copyright 28.05.2010 by Bochkanov Sergey
5021 : *************************************************************************/
5022 0 : void pspline3buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p, const xparams _xparams)
5023 : {
5024 : jmp_buf _break_jump;
5025 : alglib_impl::ae_state _alglib_env_state;
5026 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5027 0 : if( setjmp(_break_jump) )
5028 : {
5029 : #if !defined(AE_NO_EXCEPTIONS)
5030 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5031 : #else
5032 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5033 : return;
5034 : #endif
5035 : }
5036 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5037 0 : if( _xparams.flags!=0x0 )
5038 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5039 0 : alglib_impl::pspline3buildperiodic(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, st, pt, const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), &_alglib_env_state);
5040 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5041 0 : return;
5042 : }
5043 :
5044 : /*************************************************************************
5045 : This function returns vector of parameter values correspoding to points.
5046 :
5047 : I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we
5048 : have
5049 : (X[0],Y[0]) = PSpline2Calc(P,U[0]),
5050 : (X[1],Y[1]) = PSpline2Calc(P,U[1]),
5051 : (X[2],Y[2]) = PSpline2Calc(P,U[2]),
5052 : ...
5053 :
5054 : INPUT PARAMETERS:
5055 : P - parametric spline interpolant
5056 :
5057 : OUTPUT PARAMETERS:
5058 : N - array size
5059 : T - array[0..N-1]
5060 :
5061 :
5062 : NOTES:
5063 : * for non-periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]=1
5064 : * for periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]<1
5065 :
5066 : -- ALGLIB PROJECT --
5067 : Copyright 28.05.2010 by Bochkanov Sergey
5068 : *************************************************************************/
5069 0 : void pspline2parametervalues(const pspline2interpolant &p, ae_int_t &n, real_1d_array &t, const xparams _xparams)
5070 : {
5071 : jmp_buf _break_jump;
5072 : alglib_impl::ae_state _alglib_env_state;
5073 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5074 0 : if( setjmp(_break_jump) )
5075 : {
5076 : #if !defined(AE_NO_EXCEPTIONS)
5077 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5078 : #else
5079 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5080 : return;
5081 : #endif
5082 : }
5083 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5084 0 : if( _xparams.flags!=0x0 )
5085 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5086 0 : alglib_impl::pspline2parametervalues(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), &n, const_cast<alglib_impl::ae_vector*>(t.c_ptr()), &_alglib_env_state);
5087 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5088 0 : return;
5089 : }
5090 :
5091 : /*************************************************************************
5092 : This function returns vector of parameter values correspoding to points.
5093 :
5094 : Same as PSpline2ParameterValues(), but for 3D.
5095 :
5096 : -- ALGLIB PROJECT --
5097 : Copyright 28.05.2010 by Bochkanov Sergey
5098 : *************************************************************************/
5099 0 : void pspline3parametervalues(const pspline3interpolant &p, ae_int_t &n, real_1d_array &t, const xparams _xparams)
5100 : {
5101 : jmp_buf _break_jump;
5102 : alglib_impl::ae_state _alglib_env_state;
5103 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5104 0 : if( setjmp(_break_jump) )
5105 : {
5106 : #if !defined(AE_NO_EXCEPTIONS)
5107 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5108 : #else
5109 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5110 : return;
5111 : #endif
5112 : }
5113 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5114 0 : if( _xparams.flags!=0x0 )
5115 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5116 0 : alglib_impl::pspline3parametervalues(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), &n, const_cast<alglib_impl::ae_vector*>(t.c_ptr()), &_alglib_env_state);
5117 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5118 0 : return;
5119 : }
5120 :
5121 : /*************************************************************************
5122 : This function calculates the value of the parametric spline for a given
5123 : value of parameter T
5124 :
5125 : INPUT PARAMETERS:
5126 : P - parametric spline interpolant
5127 : T - point:
5128 : * T in [0,1] corresponds to interval spanned by points
5129 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5130 : the curve before the first (after the last) point
5131 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5132 : by making T=T-floor(T).
5133 :
5134 : OUTPUT PARAMETERS:
5135 : X - X-position
5136 : Y - Y-position
5137 :
5138 :
5139 : -- ALGLIB PROJECT --
5140 : Copyright 28.05.2010 by Bochkanov Sergey
5141 : *************************************************************************/
5142 0 : void pspline2calc(const pspline2interpolant &p, const double t, double &x, double &y, const xparams _xparams)
5143 : {
5144 : jmp_buf _break_jump;
5145 : alglib_impl::ae_state _alglib_env_state;
5146 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5147 0 : if( setjmp(_break_jump) )
5148 : {
5149 : #if !defined(AE_NO_EXCEPTIONS)
5150 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5151 : #else
5152 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5153 : return;
5154 : #endif
5155 : }
5156 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5157 0 : if( _xparams.flags!=0x0 )
5158 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5159 0 : alglib_impl::pspline2calc(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &y, &_alglib_env_state);
5160 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5161 0 : return;
5162 : }
5163 :
5164 : /*************************************************************************
5165 : This function calculates the value of the parametric spline for a given
5166 : value of parameter T.
5167 :
5168 : INPUT PARAMETERS:
5169 : P - parametric spline interpolant
5170 : T - point:
5171 : * T in [0,1] corresponds to interval spanned by points
5172 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5173 : the curve before the first (after the last) point
5174 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5175 : by making T=T-floor(T).
5176 :
5177 : OUTPUT PARAMETERS:
5178 : X - X-position
5179 : Y - Y-position
5180 : Z - Z-position
5181 :
5182 :
5183 : -- ALGLIB PROJECT --
5184 : Copyright 28.05.2010 by Bochkanov Sergey
5185 : *************************************************************************/
5186 0 : void pspline3calc(const pspline3interpolant &p, const double t, double &x, double &y, double &z, const xparams _xparams)
5187 : {
5188 : jmp_buf _break_jump;
5189 : alglib_impl::ae_state _alglib_env_state;
5190 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5191 0 : if( setjmp(_break_jump) )
5192 : {
5193 : #if !defined(AE_NO_EXCEPTIONS)
5194 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5195 : #else
5196 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5197 : return;
5198 : #endif
5199 : }
5200 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5201 0 : if( _xparams.flags!=0x0 )
5202 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5203 0 : alglib_impl::pspline3calc(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &y, &z, &_alglib_env_state);
5204 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5205 0 : return;
5206 : }
5207 :
5208 : /*************************************************************************
5209 : This function calculates tangent vector for a given value of parameter T
5210 :
5211 : INPUT PARAMETERS:
5212 : P - parametric spline interpolant
5213 : T - point:
5214 : * T in [0,1] corresponds to interval spanned by points
5215 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5216 : the curve before the first (after the last) point
5217 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5218 : by making T=T-floor(T).
5219 :
5220 : OUTPUT PARAMETERS:
5221 : X - X-component of tangent vector (normalized)
5222 : Y - Y-component of tangent vector (normalized)
5223 :
5224 : NOTE:
5225 : X^2+Y^2 is either 1 (for non-zero tangent vector) or 0.
5226 :
5227 :
5228 : -- ALGLIB PROJECT --
5229 : Copyright 28.05.2010 by Bochkanov Sergey
5230 : *************************************************************************/
5231 0 : void pspline2tangent(const pspline2interpolant &p, const double t, double &x, double &y, const xparams _xparams)
5232 : {
5233 : jmp_buf _break_jump;
5234 : alglib_impl::ae_state _alglib_env_state;
5235 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5236 0 : if( setjmp(_break_jump) )
5237 : {
5238 : #if !defined(AE_NO_EXCEPTIONS)
5239 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5240 : #else
5241 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5242 : return;
5243 : #endif
5244 : }
5245 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5246 0 : if( _xparams.flags!=0x0 )
5247 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5248 0 : alglib_impl::pspline2tangent(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &y, &_alglib_env_state);
5249 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5250 0 : return;
5251 : }
5252 :
5253 : /*************************************************************************
5254 : This function calculates tangent vector for a given value of parameter T
5255 :
5256 : INPUT PARAMETERS:
5257 : P - parametric spline interpolant
5258 : T - point:
5259 : * T in [0,1] corresponds to interval spanned by points
5260 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5261 : the curve before the first (after the last) point
5262 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5263 : by making T=T-floor(T).
5264 :
5265 : OUTPUT PARAMETERS:
5266 : X - X-component of tangent vector (normalized)
5267 : Y - Y-component of tangent vector (normalized)
5268 : Z - Z-component of tangent vector (normalized)
5269 :
5270 : NOTE:
5271 : X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0.
5272 :
5273 :
5274 : -- ALGLIB PROJECT --
5275 : Copyright 28.05.2010 by Bochkanov Sergey
5276 : *************************************************************************/
5277 0 : void pspline3tangent(const pspline3interpolant &p, const double t, double &x, double &y, double &z, const xparams _xparams)
5278 : {
5279 : jmp_buf _break_jump;
5280 : alglib_impl::ae_state _alglib_env_state;
5281 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5282 0 : if( setjmp(_break_jump) )
5283 : {
5284 : #if !defined(AE_NO_EXCEPTIONS)
5285 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5286 : #else
5287 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5288 : return;
5289 : #endif
5290 : }
5291 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5292 0 : if( _xparams.flags!=0x0 )
5293 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5294 0 : alglib_impl::pspline3tangent(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &y, &z, &_alglib_env_state);
5295 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5296 0 : return;
5297 : }
5298 :
5299 : /*************************************************************************
5300 : This function calculates derivative, i.e. it returns (dX/dT,dY/dT).
5301 :
5302 : INPUT PARAMETERS:
5303 : P - parametric spline interpolant
5304 : T - point:
5305 : * T in [0,1] corresponds to interval spanned by points
5306 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5307 : the curve before the first (after the last) point
5308 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5309 : by making T=T-floor(T).
5310 :
5311 : OUTPUT PARAMETERS:
5312 : X - X-value
5313 : DX - X-derivative
5314 : Y - Y-value
5315 : DY - Y-derivative
5316 :
5317 :
5318 : -- ALGLIB PROJECT --
5319 : Copyright 28.05.2010 by Bochkanov Sergey
5320 : *************************************************************************/
5321 0 : void pspline2diff(const pspline2interpolant &p, const double t, double &x, double &dx, double &y, double &dy, const xparams _xparams)
5322 : {
5323 : jmp_buf _break_jump;
5324 : alglib_impl::ae_state _alglib_env_state;
5325 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5326 0 : if( setjmp(_break_jump) )
5327 : {
5328 : #if !defined(AE_NO_EXCEPTIONS)
5329 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5330 : #else
5331 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5332 : return;
5333 : #endif
5334 : }
5335 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5336 0 : if( _xparams.flags!=0x0 )
5337 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5338 0 : alglib_impl::pspline2diff(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &dx, &y, &dy, &_alglib_env_state);
5339 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5340 0 : return;
5341 : }
5342 :
5343 : /*************************************************************************
5344 : This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT).
5345 :
5346 : INPUT PARAMETERS:
5347 : P - parametric spline interpolant
5348 : T - point:
5349 : * T in [0,1] corresponds to interval spanned by points
5350 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5351 : the curve before the first (after the last) point
5352 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5353 : by making T=T-floor(T).
5354 :
5355 : OUTPUT PARAMETERS:
5356 : X - X-value
5357 : DX - X-derivative
5358 : Y - Y-value
5359 : DY - Y-derivative
5360 : Z - Z-value
5361 : DZ - Z-derivative
5362 :
5363 :
5364 : -- ALGLIB PROJECT --
5365 : Copyright 28.05.2010 by Bochkanov Sergey
5366 : *************************************************************************/
5367 0 : void pspline3diff(const pspline3interpolant &p, const double t, double &x, double &dx, double &y, double &dy, double &z, double &dz, const xparams _xparams)
5368 : {
5369 : jmp_buf _break_jump;
5370 : alglib_impl::ae_state _alglib_env_state;
5371 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5372 0 : if( setjmp(_break_jump) )
5373 : {
5374 : #if !defined(AE_NO_EXCEPTIONS)
5375 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5376 : #else
5377 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5378 : return;
5379 : #endif
5380 : }
5381 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5382 0 : if( _xparams.flags!=0x0 )
5383 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5384 0 : alglib_impl::pspline3diff(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &dx, &y, &dy, &z, &dz, &_alglib_env_state);
5385 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5386 0 : return;
5387 : }
5388 :
5389 : /*************************************************************************
5390 : This function calculates first and second derivative with respect to T.
5391 :
5392 : INPUT PARAMETERS:
5393 : P - parametric spline interpolant
5394 : T - point:
5395 : * T in [0,1] corresponds to interval spanned by points
5396 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5397 : the curve before the first (after the last) point
5398 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5399 : by making T=T-floor(T).
5400 :
5401 : OUTPUT PARAMETERS:
5402 : X - X-value
5403 : DX - derivative
5404 : D2X - second derivative
5405 : Y - Y-value
5406 : DY - derivative
5407 : D2Y - second derivative
5408 :
5409 :
5410 : -- ALGLIB PROJECT --
5411 : Copyright 28.05.2010 by Bochkanov Sergey
5412 : *************************************************************************/
5413 0 : void pspline2diff2(const pspline2interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y, const xparams _xparams)
5414 : {
5415 : jmp_buf _break_jump;
5416 : alglib_impl::ae_state _alglib_env_state;
5417 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5418 0 : if( setjmp(_break_jump) )
5419 : {
5420 : #if !defined(AE_NO_EXCEPTIONS)
5421 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5422 : #else
5423 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5424 : return;
5425 : #endif
5426 : }
5427 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5428 0 : if( _xparams.flags!=0x0 )
5429 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5430 0 : alglib_impl::pspline2diff2(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &dx, &d2x, &y, &dy, &d2y, &_alglib_env_state);
5431 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5432 0 : return;
5433 : }
5434 :
5435 : /*************************************************************************
5436 : This function calculates first and second derivative with respect to T.
5437 :
5438 : INPUT PARAMETERS:
5439 : P - parametric spline interpolant
5440 : T - point:
5441 : * T in [0,1] corresponds to interval spanned by points
5442 : * for non-periodic splines T<0 (or T>1) correspond to parts of
5443 : the curve before the first (after the last) point
5444 : * for periodic splines T<0 (or T>1) are projected into [0,1]
5445 : by making T=T-floor(T).
5446 :
5447 : OUTPUT PARAMETERS:
5448 : X - X-value
5449 : DX - derivative
5450 : D2X - second derivative
5451 : Y - Y-value
5452 : DY - derivative
5453 : D2Y - second derivative
5454 : Z - Z-value
5455 : DZ - derivative
5456 : D2Z - second derivative
5457 :
5458 :
5459 : -- ALGLIB PROJECT --
5460 : Copyright 28.05.2010 by Bochkanov Sergey
5461 : *************************************************************************/
5462 0 : void pspline3diff2(const pspline3interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y, double &z, double &dz, double &d2z, const xparams _xparams)
5463 : {
5464 : jmp_buf _break_jump;
5465 : alglib_impl::ae_state _alglib_env_state;
5466 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5467 0 : if( setjmp(_break_jump) )
5468 : {
5469 : #if !defined(AE_NO_EXCEPTIONS)
5470 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5471 : #else
5472 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5473 : return;
5474 : #endif
5475 : }
5476 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5477 0 : if( _xparams.flags!=0x0 )
5478 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5479 0 : alglib_impl::pspline3diff2(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &dx, &d2x, &y, &dy, &d2y, &z, &dz, &d2z, &_alglib_env_state);
5480 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5481 0 : return;
5482 : }
5483 :
5484 : /*************************************************************************
5485 : This function calculates arc length, i.e. length of curve between t=a
5486 : and t=b.
5487 :
5488 : INPUT PARAMETERS:
5489 : P - parametric spline interpolant
5490 : A,B - parameter values corresponding to arc ends:
5491 : * B>A will result in positive length returned
5492 : * B<A will result in negative length returned
5493 :
5494 : RESULT:
5495 : length of arc starting at T=A and ending at T=B.
5496 :
5497 :
5498 : -- ALGLIB PROJECT --
5499 : Copyright 30.05.2010 by Bochkanov Sergey
5500 : *************************************************************************/
5501 0 : double pspline2arclength(const pspline2interpolant &p, const double a, const double b, const xparams _xparams)
5502 : {
5503 : jmp_buf _break_jump;
5504 : alglib_impl::ae_state _alglib_env_state;
5505 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5506 0 : if( setjmp(_break_jump) )
5507 : {
5508 : #if !defined(AE_NO_EXCEPTIONS)
5509 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5510 : #else
5511 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5512 : return 0;
5513 : #endif
5514 : }
5515 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5516 0 : if( _xparams.flags!=0x0 )
5517 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5518 0 : double result = alglib_impl::pspline2arclength(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), a, b, &_alglib_env_state);
5519 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5520 0 : return *(reinterpret_cast<double*>(&result));
5521 : }
5522 :
5523 : /*************************************************************************
5524 : This function calculates arc length, i.e. length of curve between t=a
5525 : and t=b.
5526 :
5527 : INPUT PARAMETERS:
5528 : P - parametric spline interpolant
5529 : A,B - parameter values corresponding to arc ends:
5530 : * B>A will result in positive length returned
5531 : * B<A will result in negative length returned
5532 :
5533 : RESULT:
5534 : length of arc starting at T=A and ending at T=B.
5535 :
5536 :
5537 : -- ALGLIB PROJECT --
5538 : Copyright 30.05.2010 by Bochkanov Sergey
5539 : *************************************************************************/
5540 0 : double pspline3arclength(const pspline3interpolant &p, const double a, const double b, const xparams _xparams)
5541 : {
5542 : jmp_buf _break_jump;
5543 : alglib_impl::ae_state _alglib_env_state;
5544 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5545 0 : if( setjmp(_break_jump) )
5546 : {
5547 : #if !defined(AE_NO_EXCEPTIONS)
5548 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5549 : #else
5550 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5551 : return 0;
5552 : #endif
5553 : }
5554 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5555 0 : if( _xparams.flags!=0x0 )
5556 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5557 0 : double result = alglib_impl::pspline3arclength(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), a, b, &_alglib_env_state);
5558 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5559 0 : return *(reinterpret_cast<double*>(&result));
5560 : }
5561 :
5562 : /*************************************************************************
5563 : This subroutine fits piecewise linear curve to points with Ramer-Douglas-
5564 : Peucker algorithm. This function performs PARAMETRIC fit, i.e. it can be
5565 : used to fit curves like circles.
5566 :
5567 : On input it accepts dataset which describes parametric multidimensional
5568 : curve X(t), with X being vector, and t taking values in [0,N), where N is
5569 : a number of points in dataset. As result, it returns reduced dataset X2,
5570 : which can be used to build parametric curve X2(t), which approximates
5571 : X(t) with desired precision (or has specified number of sections).
5572 :
5573 :
5574 : INPUT PARAMETERS:
5575 : X - array of multidimensional points:
5576 : * at least N elements, leading N elements are used if more
5577 : than N elements were specified
5578 : * order of points is IMPORTANT because it is parametric
5579 : fit
5580 : * each row of array is one point which has D coordinates
5581 : N - number of elements in X
5582 : D - number of dimensions (elements per row of X)
5583 : StopM - stopping condition - desired number of sections:
5584 : * at most M sections are generated by this function
5585 : * less than M sections can be generated if we have N<M
5586 : (or some X are non-distinct).
5587 : * zero StopM means that algorithm does not stop after
5588 : achieving some pre-specified section count
5589 : StopEps - stopping condition - desired precision:
5590 : * algorithm stops after error in each section is at most Eps
5591 : * zero Eps means that algorithm does not stop after
5592 : achieving some pre-specified precision
5593 :
5594 : OUTPUT PARAMETERS:
5595 : X2 - array of corner points for piecewise approximation,
5596 : has length NSections+1 or zero (for NSections=0).
5597 : Idx2 - array of indexes (parameter values):
5598 : * has length NSections+1 or zero (for NSections=0).
5599 : * each element of Idx2 corresponds to same-numbered
5600 : element of X2
5601 : * each element of Idx2 is index of corresponding element
5602 : of X2 at original array X, i.e. I-th row of X2 is
5603 : Idx2[I]-th row of X.
5604 : * elements of Idx2 can be treated as parameter values
5605 : which should be used when building new parametric curve
5606 : * Idx2[0]=0, Idx2[NSections]=N-1
5607 : NSections- number of sections found by algorithm, NSections<=M,
5608 : NSections can be zero for degenerate datasets
5609 : (N<=1 or all X[] are non-distinct).
5610 :
5611 : NOTE: algorithm stops after:
5612 : a) dividing curve into StopM sections
5613 : b) achieving required precision StopEps
5614 : c) dividing curve into N-1 sections
5615 : If both StopM and StopEps are non-zero, algorithm is stopped by the
5616 : FIRST criterion which is satisfied. In case both StopM and StopEps
5617 : are zero, algorithm stops because of (c).
5618 :
5619 : -- ALGLIB --
5620 : Copyright 02.10.2014 by Bochkanov Sergey
5621 : *************************************************************************/
5622 0 : void parametricrdpfixed(const real_2d_array &x, const ae_int_t n, const ae_int_t d, const ae_int_t stopm, const double stopeps, real_2d_array &x2, integer_1d_array &idx2, ae_int_t &nsections, const xparams _xparams)
5623 : {
5624 : jmp_buf _break_jump;
5625 : alglib_impl::ae_state _alglib_env_state;
5626 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5627 0 : if( setjmp(_break_jump) )
5628 : {
5629 : #if !defined(AE_NO_EXCEPTIONS)
5630 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5631 : #else
5632 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5633 : return;
5634 : #endif
5635 : }
5636 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5637 0 : if( _xparams.flags!=0x0 )
5638 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5639 0 : alglib_impl::parametricrdpfixed(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), n, d, stopm, stopeps, const_cast<alglib_impl::ae_matrix*>(x2.c_ptr()), const_cast<alglib_impl::ae_vector*>(idx2.c_ptr()), &nsections, &_alglib_env_state);
5640 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5641 0 : return;
5642 : }
5643 : #endif
5644 :
5645 : #if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD)
5646 : /*************************************************************************
5647 : 3-dimensional spline inteprolant
5648 : *************************************************************************/
5649 0 : _spline3dinterpolant_owner::_spline3dinterpolant_owner()
5650 : {
5651 : jmp_buf _break_jump;
5652 : alglib_impl::ae_state _state;
5653 :
5654 0 : alglib_impl::ae_state_init(&_state);
5655 0 : if( setjmp(_break_jump) )
5656 : {
5657 0 : if( p_struct!=NULL )
5658 : {
5659 0 : alglib_impl::_spline3dinterpolant_destroy(p_struct);
5660 0 : alglib_impl::ae_free(p_struct);
5661 : }
5662 0 : p_struct = NULL;
5663 : #if !defined(AE_NO_EXCEPTIONS)
5664 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
5665 : #else
5666 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
5667 : return;
5668 : #endif
5669 : }
5670 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
5671 0 : p_struct = NULL;
5672 0 : p_struct = (alglib_impl::spline3dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline3dinterpolant), &_state);
5673 0 : memset(p_struct, 0, sizeof(alglib_impl::spline3dinterpolant));
5674 0 : alglib_impl::_spline3dinterpolant_init(p_struct, &_state, ae_false);
5675 0 : ae_state_clear(&_state);
5676 0 : }
5677 :
5678 0 : _spline3dinterpolant_owner::_spline3dinterpolant_owner(const _spline3dinterpolant_owner &rhs)
5679 : {
5680 : jmp_buf _break_jump;
5681 : alglib_impl::ae_state _state;
5682 :
5683 0 : alglib_impl::ae_state_init(&_state);
5684 0 : if( setjmp(_break_jump) )
5685 : {
5686 0 : if( p_struct!=NULL )
5687 : {
5688 0 : alglib_impl::_spline3dinterpolant_destroy(p_struct);
5689 0 : alglib_impl::ae_free(p_struct);
5690 : }
5691 0 : p_struct = NULL;
5692 : #if !defined(AE_NO_EXCEPTIONS)
5693 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
5694 : #else
5695 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
5696 : return;
5697 : #endif
5698 : }
5699 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
5700 0 : p_struct = NULL;
5701 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline3dinterpolant copy constructor failure (source is not initialized)", &_state);
5702 0 : p_struct = (alglib_impl::spline3dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline3dinterpolant), &_state);
5703 0 : memset(p_struct, 0, sizeof(alglib_impl::spline3dinterpolant));
5704 0 : alglib_impl::_spline3dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline3dinterpolant*>(rhs.p_struct), &_state, ae_false);
5705 0 : ae_state_clear(&_state);
5706 0 : }
5707 :
5708 0 : _spline3dinterpolant_owner& _spline3dinterpolant_owner::operator=(const _spline3dinterpolant_owner &rhs)
5709 : {
5710 0 : if( this==&rhs )
5711 0 : return *this;
5712 : jmp_buf _break_jump;
5713 : alglib_impl::ae_state _state;
5714 :
5715 0 : alglib_impl::ae_state_init(&_state);
5716 0 : if( setjmp(_break_jump) )
5717 : {
5718 : #if !defined(AE_NO_EXCEPTIONS)
5719 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
5720 : #else
5721 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
5722 : return *this;
5723 : #endif
5724 : }
5725 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
5726 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline3dinterpolant assignment constructor failure (destination is not initialized)", &_state);
5727 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline3dinterpolant assignment constructor failure (source is not initialized)", &_state);
5728 0 : alglib_impl::_spline3dinterpolant_destroy(p_struct);
5729 0 : memset(p_struct, 0, sizeof(alglib_impl::spline3dinterpolant));
5730 0 : alglib_impl::_spline3dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline3dinterpolant*>(rhs.p_struct), &_state, ae_false);
5731 0 : ae_state_clear(&_state);
5732 0 : return *this;
5733 : }
5734 :
5735 0 : _spline3dinterpolant_owner::~_spline3dinterpolant_owner()
5736 : {
5737 0 : if( p_struct!=NULL )
5738 : {
5739 0 : alglib_impl::_spline3dinterpolant_destroy(p_struct);
5740 0 : ae_free(p_struct);
5741 : }
5742 0 : }
5743 :
5744 0 : alglib_impl::spline3dinterpolant* _spline3dinterpolant_owner::c_ptr()
5745 : {
5746 0 : return p_struct;
5747 : }
5748 :
5749 0 : alglib_impl::spline3dinterpolant* _spline3dinterpolant_owner::c_ptr() const
5750 : {
5751 0 : return const_cast<alglib_impl::spline3dinterpolant*>(p_struct);
5752 : }
5753 0 : spline3dinterpolant::spline3dinterpolant() : _spline3dinterpolant_owner()
5754 : {
5755 0 : }
5756 :
5757 0 : spline3dinterpolant::spline3dinterpolant(const spline3dinterpolant &rhs):_spline3dinterpolant_owner(rhs)
5758 : {
5759 0 : }
5760 :
5761 0 : spline3dinterpolant& spline3dinterpolant::operator=(const spline3dinterpolant &rhs)
5762 : {
5763 0 : if( this==&rhs )
5764 0 : return *this;
5765 0 : _spline3dinterpolant_owner::operator=(rhs);
5766 0 : return *this;
5767 : }
5768 :
5769 0 : spline3dinterpolant::~spline3dinterpolant()
5770 : {
5771 0 : }
5772 :
5773 : /*************************************************************************
5774 : This subroutine calculates the value of the trilinear or tricubic spline at
5775 : the given point (X,Y,Z).
5776 :
5777 : INPUT PARAMETERS:
5778 : C - coefficients table.
5779 : Built by BuildBilinearSpline or BuildBicubicSpline.
5780 : X, Y,
5781 : Z - point
5782 :
5783 : Result:
5784 : S(x,y,z)
5785 :
5786 : -- ALGLIB PROJECT --
5787 : Copyright 26.04.2012 by Bochkanov Sergey
5788 : *************************************************************************/
5789 0 : double spline3dcalc(const spline3dinterpolant &c, const double x, const double y, const double z, const xparams _xparams)
5790 : {
5791 : jmp_buf _break_jump;
5792 : alglib_impl::ae_state _alglib_env_state;
5793 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5794 0 : if( setjmp(_break_jump) )
5795 : {
5796 : #if !defined(AE_NO_EXCEPTIONS)
5797 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5798 : #else
5799 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5800 : return 0;
5801 : #endif
5802 : }
5803 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5804 0 : if( _xparams.flags!=0x0 )
5805 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5806 0 : double result = alglib_impl::spline3dcalc(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), x, y, z, &_alglib_env_state);
5807 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5808 0 : return *(reinterpret_cast<double*>(&result));
5809 : }
5810 :
5811 : /*************************************************************************
5812 : This subroutine performs linear transformation of the spline argument.
5813 :
5814 : INPUT PARAMETERS:
5815 : C - spline interpolant
5816 : AX, BX - transformation coefficients: x = A*u + B
5817 : AY, BY - transformation coefficients: y = A*v + B
5818 : AZ, BZ - transformation coefficients: z = A*w + B
5819 :
5820 : OUTPUT PARAMETERS:
5821 : C - transformed spline
5822 :
5823 : -- ALGLIB PROJECT --
5824 : Copyright 26.04.2012 by Bochkanov Sergey
5825 : *************************************************************************/
5826 0 : void spline3dlintransxyz(const spline3dinterpolant &c, const double ax, const double bx, const double ay, const double by, const double az, const double bz, const xparams _xparams)
5827 : {
5828 : jmp_buf _break_jump;
5829 : alglib_impl::ae_state _alglib_env_state;
5830 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5831 0 : if( setjmp(_break_jump) )
5832 : {
5833 : #if !defined(AE_NO_EXCEPTIONS)
5834 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5835 : #else
5836 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5837 : return;
5838 : #endif
5839 : }
5840 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5841 0 : if( _xparams.flags!=0x0 )
5842 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5843 0 : alglib_impl::spline3dlintransxyz(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), ax, bx, ay, by, az, bz, &_alglib_env_state);
5844 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5845 0 : return;
5846 : }
5847 :
5848 : /*************************************************************************
5849 : This subroutine performs linear transformation of the spline.
5850 :
5851 : INPUT PARAMETERS:
5852 : C - spline interpolant.
5853 : A, B- transformation coefficients: S2(x,y) = A*S(x,y,z) + B
5854 :
5855 : OUTPUT PARAMETERS:
5856 : C - transformed spline
5857 :
5858 : -- ALGLIB PROJECT --
5859 : Copyright 26.04.2012 by Bochkanov Sergey
5860 : *************************************************************************/
5861 0 : void spline3dlintransf(const spline3dinterpolant &c, const double a, const double b, const xparams _xparams)
5862 : {
5863 : jmp_buf _break_jump;
5864 : alglib_impl::ae_state _alglib_env_state;
5865 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5866 0 : if( setjmp(_break_jump) )
5867 : {
5868 : #if !defined(AE_NO_EXCEPTIONS)
5869 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5870 : #else
5871 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5872 : return;
5873 : #endif
5874 : }
5875 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5876 0 : if( _xparams.flags!=0x0 )
5877 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5878 0 : alglib_impl::spline3dlintransf(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
5879 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5880 0 : return;
5881 : }
5882 :
5883 : /*************************************************************************
5884 : Trilinear spline resampling
5885 :
5886 : INPUT PARAMETERS:
5887 : A - array[0..OldXCount*OldYCount*OldZCount-1], function
5888 : values at the old grid, :
5889 : A[0] x=0,y=0,z=0
5890 : A[1] x=1,y=0,z=0
5891 : A[..] ...
5892 : A[..] x=oldxcount-1,y=0,z=0
5893 : A[..] x=0,y=1,z=0
5894 : A[..] ...
5895 : ...
5896 : OldZCount - old Z-count, OldZCount>1
5897 : OldYCount - old Y-count, OldYCount>1
5898 : OldXCount - old X-count, OldXCount>1
5899 : NewZCount - new Z-count, NewZCount>1
5900 : NewYCount - new Y-count, NewYCount>1
5901 : NewXCount - new X-count, NewXCount>1
5902 :
5903 : OUTPUT PARAMETERS:
5904 : B - array[0..NewXCount*NewYCount*NewZCount-1], function
5905 : values at the new grid:
5906 : B[0] x=0,y=0,z=0
5907 : B[1] x=1,y=0,z=0
5908 : B[..] ...
5909 : B[..] x=newxcount-1,y=0,z=0
5910 : B[..] x=0,y=1,z=0
5911 : B[..] ...
5912 : ...
5913 :
5914 : -- ALGLIB routine --
5915 : 26.04.2012
5916 : Copyright by Bochkanov Sergey
5917 : *************************************************************************/
5918 0 : void spline3dresampletrilinear(const real_1d_array &a, const ae_int_t oldzcount, const ae_int_t oldycount, const ae_int_t oldxcount, const ae_int_t newzcount, const ae_int_t newycount, const ae_int_t newxcount, real_1d_array &b, const xparams _xparams)
5919 : {
5920 : jmp_buf _break_jump;
5921 : alglib_impl::ae_state _alglib_env_state;
5922 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5923 0 : if( setjmp(_break_jump) )
5924 : {
5925 : #if !defined(AE_NO_EXCEPTIONS)
5926 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5927 : #else
5928 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5929 : return;
5930 : #endif
5931 : }
5932 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5933 0 : if( _xparams.flags!=0x0 )
5934 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5935 0 : alglib_impl::spline3dresampletrilinear(const_cast<alglib_impl::ae_vector*>(a.c_ptr()), oldzcount, oldycount, oldxcount, newzcount, newycount, newxcount, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &_alglib_env_state);
5936 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5937 0 : return;
5938 : }
5939 :
5940 : /*************************************************************************
5941 : This subroutine builds trilinear vector-valued spline.
5942 :
5943 : INPUT PARAMETERS:
5944 : X - spline abscissas, array[0..N-1]
5945 : Y - spline ordinates, array[0..M-1]
5946 : Z - spline applicates, array[0..L-1]
5947 : F - function values, array[0..M*N*L*D-1]:
5948 : * first D elements store D values at (X[0],Y[0],Z[0])
5949 : * next D elements store D values at (X[1],Y[0],Z[0])
5950 : * next D elements store D values at (X[2],Y[0],Z[0])
5951 : * ...
5952 : * next D elements store D values at (X[0],Y[1],Z[0])
5953 : * next D elements store D values at (X[1],Y[1],Z[0])
5954 : * next D elements store D values at (X[2],Y[1],Z[0])
5955 : * ...
5956 : * next D elements store D values at (X[0],Y[0],Z[1])
5957 : * next D elements store D values at (X[1],Y[0],Z[1])
5958 : * next D elements store D values at (X[2],Y[0],Z[1])
5959 : * ...
5960 : * general form - D function values at (X[i],Y[j]) are stored
5961 : at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1].
5962 : M,N,
5963 : L - grid size, M>=2, N>=2, L>=2
5964 : D - vector dimension, D>=1
5965 :
5966 : OUTPUT PARAMETERS:
5967 : C - spline interpolant
5968 :
5969 : -- ALGLIB PROJECT --
5970 : Copyright 26.04.2012 by Bochkanov Sergey
5971 : *************************************************************************/
5972 0 : void spline3dbuildtrilinearv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &z, const ae_int_t l, const real_1d_array &f, const ae_int_t d, spline3dinterpolant &c, const xparams _xparams)
5973 : {
5974 : jmp_buf _break_jump;
5975 : alglib_impl::ae_state _alglib_env_state;
5976 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5977 0 : if( setjmp(_break_jump) )
5978 : {
5979 : #if !defined(AE_NO_EXCEPTIONS)
5980 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5981 : #else
5982 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5983 : return;
5984 : #endif
5985 : }
5986 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5987 0 : if( _xparams.flags!=0x0 )
5988 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5989 0 : alglib_impl::spline3dbuildtrilinearv(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), m, const_cast<alglib_impl::ae_vector*>(z.c_ptr()), l, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), d, const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), &_alglib_env_state);
5990 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5991 0 : return;
5992 : }
5993 :
5994 : /*************************************************************************
5995 : This subroutine calculates bilinear or bicubic vector-valued spline at the
5996 : given point (X,Y,Z).
5997 :
5998 : INPUT PARAMETERS:
5999 : C - spline interpolant.
6000 : X, Y,
6001 : Z - point
6002 : F - output buffer, possibly preallocated array. In case array size
6003 : is large enough to store result, it is not reallocated. Array
6004 : which is too short will be reallocated
6005 :
6006 : OUTPUT PARAMETERS:
6007 : F - array[D] (or larger) which stores function values
6008 :
6009 : -- ALGLIB PROJECT --
6010 : Copyright 26.04.2012 by Bochkanov Sergey
6011 : *************************************************************************/
6012 0 : void spline3dcalcvbuf(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f, const xparams _xparams)
6013 : {
6014 : jmp_buf _break_jump;
6015 : alglib_impl::ae_state _alglib_env_state;
6016 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6017 0 : if( setjmp(_break_jump) )
6018 : {
6019 : #if !defined(AE_NO_EXCEPTIONS)
6020 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6021 : #else
6022 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6023 : return;
6024 : #endif
6025 : }
6026 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6027 0 : if( _xparams.flags!=0x0 )
6028 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6029 0 : alglib_impl::spline3dcalcvbuf(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), x, y, z, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), &_alglib_env_state);
6030 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6031 0 : return;
6032 : }
6033 :
6034 : /*************************************************************************
6035 : This subroutine calculates trilinear or tricubic vector-valued spline at the
6036 : given point (X,Y,Z).
6037 :
6038 : INPUT PARAMETERS:
6039 : C - spline interpolant.
6040 : X, Y,
6041 : Z - point
6042 :
6043 : OUTPUT PARAMETERS:
6044 : F - array[D] which stores function values. F is out-parameter and
6045 : it is reallocated after call to this function. In case you
6046 : want to reuse previously allocated F, you may use
6047 : Spline2DCalcVBuf(), which reallocates F only when it is too
6048 : small.
6049 :
6050 : -- ALGLIB PROJECT --
6051 : Copyright 26.04.2012 by Bochkanov Sergey
6052 : *************************************************************************/
6053 0 : void spline3dcalcv(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f, const xparams _xparams)
6054 : {
6055 : jmp_buf _break_jump;
6056 : alglib_impl::ae_state _alglib_env_state;
6057 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6058 0 : if( setjmp(_break_jump) )
6059 : {
6060 : #if !defined(AE_NO_EXCEPTIONS)
6061 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6062 : #else
6063 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6064 : return;
6065 : #endif
6066 : }
6067 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6068 0 : if( _xparams.flags!=0x0 )
6069 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6070 0 : alglib_impl::spline3dcalcv(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), x, y, z, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), &_alglib_env_state);
6071 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6072 0 : return;
6073 : }
6074 :
6075 : /*************************************************************************
6076 : This subroutine unpacks tri-dimensional spline into the coefficients table
6077 :
6078 : INPUT PARAMETERS:
6079 : C - spline interpolant.
6080 :
6081 : Result:
6082 : N - grid size (X)
6083 : M - grid size (Y)
6084 : L - grid size (Z)
6085 : D - number of components
6086 : SType- spline type. Currently, only one spline type is supported:
6087 : trilinear spline, as indicated by SType=1.
6088 : Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13].
6089 : For T=0..D-1 (component index), I = 0...N-2 (x index),
6090 : J=0..M-2 (y index), K=0..L-2 (z index):
6091 : Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1),
6092 :
6093 : Q-th row stores decomposition for T-th component of the
6094 : vector-valued function
6095 :
6096 : Tbl[Q,0] = X[i]
6097 : Tbl[Q,1] = X[i+1]
6098 : Tbl[Q,2] = Y[j]
6099 : Tbl[Q,3] = Y[j+1]
6100 : Tbl[Q,4] = Z[k]
6101 : Tbl[Q,5] = Z[k+1]
6102 :
6103 : Tbl[Q,6] = C000
6104 : Tbl[Q,7] = C100
6105 : Tbl[Q,8] = C010
6106 : Tbl[Q,9] = C110
6107 : Tbl[Q,10]= C001
6108 : Tbl[Q,11]= C101
6109 : Tbl[Q,12]= C011
6110 : Tbl[Q,13]= C111
6111 : On each grid square spline is equals to:
6112 : S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1)
6113 : t = x-x[j]
6114 : u = y-y[i]
6115 : v = z-z[k]
6116 :
6117 : NOTE: format of Tbl is given for SType=1. Future versions of
6118 : ALGLIB can use different formats for different values of
6119 : SType.
6120 :
6121 : -- ALGLIB PROJECT --
6122 : Copyright 26.04.2012 by Bochkanov Sergey
6123 : *************************************************************************/
6124 0 : void spline3dunpackv(const spline3dinterpolant &c, ae_int_t &n, ae_int_t &m, ae_int_t &l, ae_int_t &d, ae_int_t &stype, real_2d_array &tbl, const xparams _xparams)
6125 : {
6126 : jmp_buf _break_jump;
6127 : alglib_impl::ae_state _alglib_env_state;
6128 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6129 0 : if( setjmp(_break_jump) )
6130 : {
6131 : #if !defined(AE_NO_EXCEPTIONS)
6132 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6133 : #else
6134 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6135 : return;
6136 : #endif
6137 : }
6138 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6139 0 : if( _xparams.flags!=0x0 )
6140 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6141 0 : alglib_impl::spline3dunpackv(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), &n, &m, &l, &d, &stype, const_cast<alglib_impl::ae_matrix*>(tbl.c_ptr()), &_alglib_env_state);
6142 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6143 0 : return;
6144 : }
6145 : #endif
6146 :
6147 : #if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD)
6148 : /*************************************************************************
6149 : Conversion from barycentric representation to Chebyshev basis.
6150 : This function has O(N^2) complexity.
6151 :
6152 : INPUT PARAMETERS:
6153 : P - polynomial in barycentric form
6154 : A,B - base interval for Chebyshev polynomials (see below)
6155 : A<>B
6156 :
6157 : OUTPUT PARAMETERS
6158 : T - coefficients of Chebyshev representation;
6159 : P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 },
6160 : where Ti - I-th Chebyshev polynomial.
6161 :
6162 : NOTES:
6163 : barycentric interpolant passed as P may be either polynomial obtained
6164 : from polynomial interpolation/ fitting or rational function which is
6165 : NOT polynomial. We can't distinguish between these two cases, and this
6166 : algorithm just tries to work assuming that P IS a polynomial. If not,
6167 : algorithm will return results, but they won't have any meaning.
6168 :
6169 : -- ALGLIB --
6170 : Copyright 30.09.2010 by Bochkanov Sergey
6171 : *************************************************************************/
6172 0 : void polynomialbar2cheb(const barycentricinterpolant &p, const double a, const double b, real_1d_array &t, const xparams _xparams)
6173 : {
6174 : jmp_buf _break_jump;
6175 : alglib_impl::ae_state _alglib_env_state;
6176 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6177 0 : if( setjmp(_break_jump) )
6178 : {
6179 : #if !defined(AE_NO_EXCEPTIONS)
6180 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6181 : #else
6182 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6183 : return;
6184 : #endif
6185 : }
6186 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6187 0 : if( _xparams.flags!=0x0 )
6188 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6189 0 : alglib_impl::polynomialbar2cheb(const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), a, b, const_cast<alglib_impl::ae_vector*>(t.c_ptr()), &_alglib_env_state);
6190 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6191 0 : return;
6192 : }
6193 :
6194 : /*************************************************************************
6195 : Conversion from Chebyshev basis to barycentric representation.
6196 : This function has O(N^2) complexity.
6197 :
6198 : INPUT PARAMETERS:
6199 : T - coefficients of Chebyshev representation;
6200 : P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N },
6201 : where Ti - I-th Chebyshev polynomial.
6202 : N - number of coefficients:
6203 : * if given, only leading N elements of T are used
6204 : * if not given, automatically determined from size of T
6205 : A,B - base interval for Chebyshev polynomials (see above)
6206 : A<B
6207 :
6208 : OUTPUT PARAMETERS
6209 : P - polynomial in barycentric form
6210 :
6211 : -- ALGLIB --
6212 : Copyright 30.09.2010 by Bochkanov Sergey
6213 : *************************************************************************/
6214 0 : void polynomialcheb2bar(const real_1d_array &t, const ae_int_t n, const double a, const double b, barycentricinterpolant &p, const xparams _xparams)
6215 : {
6216 : jmp_buf _break_jump;
6217 : alglib_impl::ae_state _alglib_env_state;
6218 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6219 0 : if( setjmp(_break_jump) )
6220 : {
6221 : #if !defined(AE_NO_EXCEPTIONS)
6222 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6223 : #else
6224 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6225 : return;
6226 : #endif
6227 : }
6228 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6229 0 : if( _xparams.flags!=0x0 )
6230 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6231 0 : alglib_impl::polynomialcheb2bar(const_cast<alglib_impl::ae_vector*>(t.c_ptr()), n, a, b, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6232 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6233 0 : return;
6234 : }
6235 :
6236 : /*************************************************************************
6237 : Conversion from Chebyshev basis to barycentric representation.
6238 : This function has O(N^2) complexity.
6239 :
6240 : INPUT PARAMETERS:
6241 : T - coefficients of Chebyshev representation;
6242 : P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N },
6243 : where Ti - I-th Chebyshev polynomial.
6244 : N - number of coefficients:
6245 : * if given, only leading N elements of T are used
6246 : * if not given, automatically determined from size of T
6247 : A,B - base interval for Chebyshev polynomials (see above)
6248 : A<B
6249 :
6250 : OUTPUT PARAMETERS
6251 : P - polynomial in barycentric form
6252 :
6253 : -- ALGLIB --
6254 : Copyright 30.09.2010 by Bochkanov Sergey
6255 : *************************************************************************/
6256 : #if !defined(AE_NO_EXCEPTIONS)
6257 0 : void polynomialcheb2bar(const real_1d_array &t, const double a, const double b, barycentricinterpolant &p, const xparams _xparams)
6258 : {
6259 : jmp_buf _break_jump;
6260 : alglib_impl::ae_state _alglib_env_state;
6261 : ae_int_t n;
6262 :
6263 0 : n = t.length();
6264 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6265 0 : if( setjmp(_break_jump) )
6266 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6267 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6268 0 : if( _xparams.flags!=0x0 )
6269 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6270 0 : alglib_impl::polynomialcheb2bar(const_cast<alglib_impl::ae_vector*>(t.c_ptr()), n, a, b, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6271 :
6272 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6273 0 : return;
6274 : }
6275 : #endif
6276 :
6277 : /*************************************************************************
6278 : Conversion from barycentric representation to power basis.
6279 : This function has O(N^2) complexity.
6280 :
6281 : INPUT PARAMETERS:
6282 : P - polynomial in barycentric form
6283 : C - offset (see below); 0.0 is used as default value.
6284 : S - scale (see below); 1.0 is used as default value. S<>0.
6285 :
6286 : OUTPUT PARAMETERS
6287 : A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
6288 : N - number of coefficients (polynomial degree plus 1)
6289 :
6290 : NOTES:
6291 : 1. this function accepts offset and scale, which can be set to improve
6292 : numerical properties of polynomial. For example, if P was obtained as
6293 : result of interpolation on [-1,+1], you can set C=0 and S=1 and
6294 : represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it
6295 : is exactly what you need.
6296 :
6297 : However, if your interpolation model was built on [999,1001], you will
6298 : see significant growth of numerical errors when using {1, x, x^2, x^3}
6299 : as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
6300 : will be better option. Such representation can be obtained by using
6301 : 1000.0 as offset C and 1.0 as scale S.
6302 :
6303 : 2. power basis is ill-conditioned and tricks described above can't solve
6304 : this problem completely. This function will return coefficients in
6305 : any case, but for N>8 they will become unreliable. However, N's
6306 : less than 5 are pretty safe.
6307 :
6308 : 3. barycentric interpolant passed as P may be either polynomial obtained
6309 : from polynomial interpolation/ fitting or rational function which is
6310 : NOT polynomial. We can't distinguish between these two cases, and this
6311 : algorithm just tries to work assuming that P IS a polynomial. If not,
6312 : algorithm will return results, but they won't have any meaning.
6313 :
6314 : -- ALGLIB --
6315 : Copyright 30.09.2010 by Bochkanov Sergey
6316 : *************************************************************************/
6317 0 : void polynomialbar2pow(const barycentricinterpolant &p, const double c, const double s, real_1d_array &a, const xparams _xparams)
6318 : {
6319 : jmp_buf _break_jump;
6320 : alglib_impl::ae_state _alglib_env_state;
6321 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6322 0 : if( setjmp(_break_jump) )
6323 : {
6324 : #if !defined(AE_NO_EXCEPTIONS)
6325 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6326 : #else
6327 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6328 : return;
6329 : #endif
6330 : }
6331 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6332 0 : if( _xparams.flags!=0x0 )
6333 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6334 0 : alglib_impl::polynomialbar2pow(const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), c, s, const_cast<alglib_impl::ae_vector*>(a.c_ptr()), &_alglib_env_state);
6335 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6336 0 : return;
6337 : }
6338 :
6339 : /*************************************************************************
6340 : Conversion from barycentric representation to power basis.
6341 : This function has O(N^2) complexity.
6342 :
6343 : INPUT PARAMETERS:
6344 : P - polynomial in barycentric form
6345 : C - offset (see below); 0.0 is used as default value.
6346 : S - scale (see below); 1.0 is used as default value. S<>0.
6347 :
6348 : OUTPUT PARAMETERS
6349 : A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
6350 : N - number of coefficients (polynomial degree plus 1)
6351 :
6352 : NOTES:
6353 : 1. this function accepts offset and scale, which can be set to improve
6354 : numerical properties of polynomial. For example, if P was obtained as
6355 : result of interpolation on [-1,+1], you can set C=0 and S=1 and
6356 : represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it
6357 : is exactly what you need.
6358 :
6359 : However, if your interpolation model was built on [999,1001], you will
6360 : see significant growth of numerical errors when using {1, x, x^2, x^3}
6361 : as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
6362 : will be better option. Such representation can be obtained by using
6363 : 1000.0 as offset C and 1.0 as scale S.
6364 :
6365 : 2. power basis is ill-conditioned and tricks described above can't solve
6366 : this problem completely. This function will return coefficients in
6367 : any case, but for N>8 they will become unreliable. However, N's
6368 : less than 5 are pretty safe.
6369 :
6370 : 3. barycentric interpolant passed as P may be either polynomial obtained
6371 : from polynomial interpolation/ fitting or rational function which is
6372 : NOT polynomial. We can't distinguish between these two cases, and this
6373 : algorithm just tries to work assuming that P IS a polynomial. If not,
6374 : algorithm will return results, but they won't have any meaning.
6375 :
6376 : -- ALGLIB --
6377 : Copyright 30.09.2010 by Bochkanov Sergey
6378 : *************************************************************************/
6379 : #if !defined(AE_NO_EXCEPTIONS)
6380 0 : void polynomialbar2pow(const barycentricinterpolant &p, real_1d_array &a, const xparams _xparams)
6381 : {
6382 : jmp_buf _break_jump;
6383 : alglib_impl::ae_state _alglib_env_state;
6384 : double c;
6385 : double s;
6386 :
6387 0 : c = 0;
6388 0 : s = 1;
6389 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6390 0 : if( setjmp(_break_jump) )
6391 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6392 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6393 0 : if( _xparams.flags!=0x0 )
6394 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6395 0 : alglib_impl::polynomialbar2pow(const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), c, s, const_cast<alglib_impl::ae_vector*>(a.c_ptr()), &_alglib_env_state);
6396 :
6397 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6398 0 : return;
6399 : }
6400 : #endif
6401 :
6402 : /*************************************************************************
6403 : Conversion from power basis to barycentric representation.
6404 : This function has O(N^2) complexity.
6405 :
6406 : INPUT PARAMETERS:
6407 : A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
6408 : N - number of coefficients (polynomial degree plus 1)
6409 : * if given, only leading N elements of A are used
6410 : * if not given, automatically determined from size of A
6411 : C - offset (see below); 0.0 is used as default value.
6412 : S - scale (see below); 1.0 is used as default value. S<>0.
6413 :
6414 : OUTPUT PARAMETERS
6415 : P - polynomial in barycentric form
6416 :
6417 :
6418 : NOTES:
6419 : 1. this function accepts offset and scale, which can be set to improve
6420 : numerical properties of polynomial. For example, if you interpolate on
6421 : [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2,
6422 : x^3 and so on. In most cases you it is exactly what you need.
6423 :
6424 : However, if your interpolation model was built on [999,1001], you will
6425 : see significant growth of numerical errors when using {1, x, x^2, x^3}
6426 : as input basis. Converting from sum of 1, (x-1000), (x-1000)^2,
6427 : (x-1000)^3 will be better option (you have to specify 1000.0 as offset
6428 : C and 1.0 as scale S).
6429 :
6430 : 2. power basis is ill-conditioned and tricks described above can't solve
6431 : this problem completely. This function will return barycentric model
6432 : in any case, but for N>8 accuracy well degrade. However, N's less than
6433 : 5 are pretty safe.
6434 :
6435 : -- ALGLIB --
6436 : Copyright 30.09.2010 by Bochkanov Sergey
6437 : *************************************************************************/
6438 0 : void polynomialpow2bar(const real_1d_array &a, const ae_int_t n, const double c, const double s, barycentricinterpolant &p, const xparams _xparams)
6439 : {
6440 : jmp_buf _break_jump;
6441 : alglib_impl::ae_state _alglib_env_state;
6442 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6443 0 : if( setjmp(_break_jump) )
6444 : {
6445 : #if !defined(AE_NO_EXCEPTIONS)
6446 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6447 : #else
6448 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6449 : return;
6450 : #endif
6451 : }
6452 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6453 0 : if( _xparams.flags!=0x0 )
6454 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6455 0 : alglib_impl::polynomialpow2bar(const_cast<alglib_impl::ae_vector*>(a.c_ptr()), n, c, s, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6456 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6457 0 : return;
6458 : }
6459 :
6460 : /*************************************************************************
6461 : Conversion from power basis to barycentric representation.
6462 : This function has O(N^2) complexity.
6463 :
6464 : INPUT PARAMETERS:
6465 : A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
6466 : N - number of coefficients (polynomial degree plus 1)
6467 : * if given, only leading N elements of A are used
6468 : * if not given, automatically determined from size of A
6469 : C - offset (see below); 0.0 is used as default value.
6470 : S - scale (see below); 1.0 is used as default value. S<>0.
6471 :
6472 : OUTPUT PARAMETERS
6473 : P - polynomial in barycentric form
6474 :
6475 :
6476 : NOTES:
6477 : 1. this function accepts offset and scale, which can be set to improve
6478 : numerical properties of polynomial. For example, if you interpolate on
6479 : [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2,
6480 : x^3 and so on. In most cases you it is exactly what you need.
6481 :
6482 : However, if your interpolation model was built on [999,1001], you will
6483 : see significant growth of numerical errors when using {1, x, x^2, x^3}
6484 : as input basis. Converting from sum of 1, (x-1000), (x-1000)^2,
6485 : (x-1000)^3 will be better option (you have to specify 1000.0 as offset
6486 : C and 1.0 as scale S).
6487 :
6488 : 2. power basis is ill-conditioned and tricks described above can't solve
6489 : this problem completely. This function will return barycentric model
6490 : in any case, but for N>8 accuracy well degrade. However, N's less than
6491 : 5 are pretty safe.
6492 :
6493 : -- ALGLIB --
6494 : Copyright 30.09.2010 by Bochkanov Sergey
6495 : *************************************************************************/
6496 : #if !defined(AE_NO_EXCEPTIONS)
6497 0 : void polynomialpow2bar(const real_1d_array &a, barycentricinterpolant &p, const xparams _xparams)
6498 : {
6499 : jmp_buf _break_jump;
6500 : alglib_impl::ae_state _alglib_env_state;
6501 : ae_int_t n;
6502 : double c;
6503 : double s;
6504 :
6505 0 : n = a.length();
6506 0 : c = 0;
6507 0 : s = 1;
6508 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6509 0 : if( setjmp(_break_jump) )
6510 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6511 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6512 0 : if( _xparams.flags!=0x0 )
6513 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6514 0 : alglib_impl::polynomialpow2bar(const_cast<alglib_impl::ae_vector*>(a.c_ptr()), n, c, s, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6515 :
6516 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6517 0 : return;
6518 : }
6519 : #endif
6520 :
6521 : /*************************************************************************
6522 : Lagrange intepolant: generation of the model on the general grid.
6523 : This function has O(N^2) complexity.
6524 :
6525 : INPUT PARAMETERS:
6526 : X - abscissas, array[0..N-1]
6527 : Y - function values, array[0..N-1]
6528 : N - number of points, N>=1
6529 :
6530 : OUTPUT PARAMETERS
6531 : P - barycentric model which represents Lagrange interpolant
6532 : (see ratint unit info and BarycentricCalc() description for
6533 : more information).
6534 :
6535 : -- ALGLIB --
6536 : Copyright 02.12.2009 by Bochkanov Sergey
6537 : *************************************************************************/
6538 0 : void polynomialbuild(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams)
6539 : {
6540 : jmp_buf _break_jump;
6541 : alglib_impl::ae_state _alglib_env_state;
6542 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6543 0 : if( setjmp(_break_jump) )
6544 : {
6545 : #if !defined(AE_NO_EXCEPTIONS)
6546 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6547 : #else
6548 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6549 : return;
6550 : #endif
6551 : }
6552 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6553 0 : if( _xparams.flags!=0x0 )
6554 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6555 0 : alglib_impl::polynomialbuild(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6556 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6557 0 : return;
6558 : }
6559 :
6560 : /*************************************************************************
6561 : Lagrange intepolant: generation of the model on the general grid.
6562 : This function has O(N^2) complexity.
6563 :
6564 : INPUT PARAMETERS:
6565 : X - abscissas, array[0..N-1]
6566 : Y - function values, array[0..N-1]
6567 : N - number of points, N>=1
6568 :
6569 : OUTPUT PARAMETERS
6570 : P - barycentric model which represents Lagrange interpolant
6571 : (see ratint unit info and BarycentricCalc() description for
6572 : more information).
6573 :
6574 : -- ALGLIB --
6575 : Copyright 02.12.2009 by Bochkanov Sergey
6576 : *************************************************************************/
6577 : #if !defined(AE_NO_EXCEPTIONS)
6578 0 : void polynomialbuild(const real_1d_array &x, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams)
6579 : {
6580 : jmp_buf _break_jump;
6581 : alglib_impl::ae_state _alglib_env_state;
6582 : ae_int_t n;
6583 0 : if( (x.length()!=y.length()))
6584 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialbuild': looks like one of arguments has wrong size");
6585 0 : n = x.length();
6586 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6587 0 : if( setjmp(_break_jump) )
6588 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6589 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6590 0 : if( _xparams.flags!=0x0 )
6591 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6592 0 : alglib_impl::polynomialbuild(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6593 :
6594 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6595 0 : return;
6596 : }
6597 : #endif
6598 :
6599 : /*************************************************************************
6600 : Lagrange intepolant: generation of the model on equidistant grid.
6601 : This function has O(N) complexity.
6602 :
6603 : INPUT PARAMETERS:
6604 : A - left boundary of [A,B]
6605 : B - right boundary of [A,B]
6606 : Y - function values at the nodes, array[0..N-1]
6607 : N - number of points, N>=1
6608 : for N=1 a constant model is constructed.
6609 :
6610 : OUTPUT PARAMETERS
6611 : P - barycentric model which represents Lagrange interpolant
6612 : (see ratint unit info and BarycentricCalc() description for
6613 : more information).
6614 :
6615 : -- ALGLIB --
6616 : Copyright 03.12.2009 by Bochkanov Sergey
6617 : *************************************************************************/
6618 0 : void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams)
6619 : {
6620 : jmp_buf _break_jump;
6621 : alglib_impl::ae_state _alglib_env_state;
6622 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6623 0 : if( setjmp(_break_jump) )
6624 : {
6625 : #if !defined(AE_NO_EXCEPTIONS)
6626 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6627 : #else
6628 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6629 : return;
6630 : #endif
6631 : }
6632 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6633 0 : if( _xparams.flags!=0x0 )
6634 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6635 0 : alglib_impl::polynomialbuildeqdist(a, b, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6636 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6637 0 : return;
6638 : }
6639 :
6640 : /*************************************************************************
6641 : Lagrange intepolant: generation of the model on equidistant grid.
6642 : This function has O(N) complexity.
6643 :
6644 : INPUT PARAMETERS:
6645 : A - left boundary of [A,B]
6646 : B - right boundary of [A,B]
6647 : Y - function values at the nodes, array[0..N-1]
6648 : N - number of points, N>=1
6649 : for N=1 a constant model is constructed.
6650 :
6651 : OUTPUT PARAMETERS
6652 : P - barycentric model which represents Lagrange interpolant
6653 : (see ratint unit info and BarycentricCalc() description for
6654 : more information).
6655 :
6656 : -- ALGLIB --
6657 : Copyright 03.12.2009 by Bochkanov Sergey
6658 : *************************************************************************/
6659 : #if !defined(AE_NO_EXCEPTIONS)
6660 0 : void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams)
6661 : {
6662 : jmp_buf _break_jump;
6663 : alglib_impl::ae_state _alglib_env_state;
6664 : ae_int_t n;
6665 :
6666 0 : n = y.length();
6667 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6668 0 : if( setjmp(_break_jump) )
6669 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6670 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6671 0 : if( _xparams.flags!=0x0 )
6672 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6673 0 : alglib_impl::polynomialbuildeqdist(a, b, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6674 :
6675 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6676 0 : return;
6677 : }
6678 : #endif
6679 :
6680 : /*************************************************************************
6681 : Lagrange intepolant on Chebyshev grid (first kind).
6682 : This function has O(N) complexity.
6683 :
6684 : INPUT PARAMETERS:
6685 : A - left boundary of [A,B]
6686 : B - right boundary of [A,B]
6687 : Y - function values at the nodes, array[0..N-1],
6688 : Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
6689 : N - number of points, N>=1
6690 : for N=1 a constant model is constructed.
6691 :
6692 : OUTPUT PARAMETERS
6693 : P - barycentric model which represents Lagrange interpolant
6694 : (see ratint unit info and BarycentricCalc() description for
6695 : more information).
6696 :
6697 : -- ALGLIB --
6698 : Copyright 03.12.2009 by Bochkanov Sergey
6699 : *************************************************************************/
6700 0 : void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams)
6701 : {
6702 : jmp_buf _break_jump;
6703 : alglib_impl::ae_state _alglib_env_state;
6704 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6705 0 : if( setjmp(_break_jump) )
6706 : {
6707 : #if !defined(AE_NO_EXCEPTIONS)
6708 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6709 : #else
6710 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6711 : return;
6712 : #endif
6713 : }
6714 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6715 0 : if( _xparams.flags!=0x0 )
6716 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6717 0 : alglib_impl::polynomialbuildcheb1(a, b, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6718 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6719 0 : return;
6720 : }
6721 :
6722 : /*************************************************************************
6723 : Lagrange intepolant on Chebyshev grid (first kind).
6724 : This function has O(N) complexity.
6725 :
6726 : INPUT PARAMETERS:
6727 : A - left boundary of [A,B]
6728 : B - right boundary of [A,B]
6729 : Y - function values at the nodes, array[0..N-1],
6730 : Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
6731 : N - number of points, N>=1
6732 : for N=1 a constant model is constructed.
6733 :
6734 : OUTPUT PARAMETERS
6735 : P - barycentric model which represents Lagrange interpolant
6736 : (see ratint unit info and BarycentricCalc() description for
6737 : more information).
6738 :
6739 : -- ALGLIB --
6740 : Copyright 03.12.2009 by Bochkanov Sergey
6741 : *************************************************************************/
6742 : #if !defined(AE_NO_EXCEPTIONS)
6743 0 : void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams)
6744 : {
6745 : jmp_buf _break_jump;
6746 : alglib_impl::ae_state _alglib_env_state;
6747 : ae_int_t n;
6748 :
6749 0 : n = y.length();
6750 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6751 0 : if( setjmp(_break_jump) )
6752 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6753 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6754 0 : if( _xparams.flags!=0x0 )
6755 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6756 0 : alglib_impl::polynomialbuildcheb1(a, b, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6757 :
6758 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6759 0 : return;
6760 : }
6761 : #endif
6762 :
6763 : /*************************************************************************
6764 : Lagrange intepolant on Chebyshev grid (second kind).
6765 : This function has O(N) complexity.
6766 :
6767 : INPUT PARAMETERS:
6768 : A - left boundary of [A,B]
6769 : B - right boundary of [A,B]
6770 : Y - function values at the nodes, array[0..N-1],
6771 : Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
6772 : N - number of points, N>=1
6773 : for N=1 a constant model is constructed.
6774 :
6775 : OUTPUT PARAMETERS
6776 : P - barycentric model which represents Lagrange interpolant
6777 : (see ratint unit info and BarycentricCalc() description for
6778 : more information).
6779 :
6780 : -- ALGLIB --
6781 : Copyright 03.12.2009 by Bochkanov Sergey
6782 : *************************************************************************/
6783 0 : void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p, const xparams _xparams)
6784 : {
6785 : jmp_buf _break_jump;
6786 : alglib_impl::ae_state _alglib_env_state;
6787 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6788 0 : if( setjmp(_break_jump) )
6789 : {
6790 : #if !defined(AE_NO_EXCEPTIONS)
6791 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6792 : #else
6793 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6794 : return;
6795 : #endif
6796 : }
6797 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6798 0 : if( _xparams.flags!=0x0 )
6799 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6800 0 : alglib_impl::polynomialbuildcheb2(a, b, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6801 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6802 0 : return;
6803 : }
6804 :
6805 : /*************************************************************************
6806 : Lagrange intepolant on Chebyshev grid (second kind).
6807 : This function has O(N) complexity.
6808 :
6809 : INPUT PARAMETERS:
6810 : A - left boundary of [A,B]
6811 : B - right boundary of [A,B]
6812 : Y - function values at the nodes, array[0..N-1],
6813 : Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
6814 : N - number of points, N>=1
6815 : for N=1 a constant model is constructed.
6816 :
6817 : OUTPUT PARAMETERS
6818 : P - barycentric model which represents Lagrange interpolant
6819 : (see ratint unit info and BarycentricCalc() description for
6820 : more information).
6821 :
6822 : -- ALGLIB --
6823 : Copyright 03.12.2009 by Bochkanov Sergey
6824 : *************************************************************************/
6825 : #if !defined(AE_NO_EXCEPTIONS)
6826 0 : void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p, const xparams _xparams)
6827 : {
6828 : jmp_buf _break_jump;
6829 : alglib_impl::ae_state _alglib_env_state;
6830 : ae_int_t n;
6831 :
6832 0 : n = y.length();
6833 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6834 0 : if( setjmp(_break_jump) )
6835 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6836 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6837 0 : if( _xparams.flags!=0x0 )
6838 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6839 0 : alglib_impl::polynomialbuildcheb2(a, b, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), &_alglib_env_state);
6840 :
6841 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6842 0 : return;
6843 : }
6844 : #endif
6845 :
6846 : /*************************************************************************
6847 : Fast equidistant polynomial interpolation function with O(N) complexity
6848 :
6849 : INPUT PARAMETERS:
6850 : A - left boundary of [A,B]
6851 : B - right boundary of [A,B]
6852 : F - function values, array[0..N-1]
6853 : N - number of points on equidistant grid, N>=1
6854 : for N=1 a constant model is constructed.
6855 : T - position where P(x) is calculated
6856 :
6857 : RESULT
6858 : value of the Lagrange interpolant at T
6859 :
6860 : IMPORTANT
6861 : this function provides fast interface which is not overflow-safe
6862 : nor it is very precise.
6863 : the best option is to use PolynomialBuildEqDist()/BarycentricCalc()
6864 : subroutines unless you are pretty sure that your data will not result
6865 : in overflow.
6866 :
6867 : -- ALGLIB --
6868 : Copyright 02.12.2009 by Bochkanov Sergey
6869 : *************************************************************************/
6870 0 : double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams)
6871 : {
6872 : jmp_buf _break_jump;
6873 : alglib_impl::ae_state _alglib_env_state;
6874 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6875 0 : if( setjmp(_break_jump) )
6876 : {
6877 : #if !defined(AE_NO_EXCEPTIONS)
6878 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6879 : #else
6880 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6881 : return 0;
6882 : #endif
6883 : }
6884 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6885 0 : if( _xparams.flags!=0x0 )
6886 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6887 0 : double result = alglib_impl::polynomialcalceqdist(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
6888 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6889 0 : return *(reinterpret_cast<double*>(&result));
6890 : }
6891 :
6892 : /*************************************************************************
6893 : Fast equidistant polynomial interpolation function with O(N) complexity
6894 :
6895 : INPUT PARAMETERS:
6896 : A - left boundary of [A,B]
6897 : B - right boundary of [A,B]
6898 : F - function values, array[0..N-1]
6899 : N - number of points on equidistant grid, N>=1
6900 : for N=1 a constant model is constructed.
6901 : T - position where P(x) is calculated
6902 :
6903 : RESULT
6904 : value of the Lagrange interpolant at T
6905 :
6906 : IMPORTANT
6907 : this function provides fast interface which is not overflow-safe
6908 : nor it is very precise.
6909 : the best option is to use PolynomialBuildEqDist()/BarycentricCalc()
6910 : subroutines unless you are pretty sure that your data will not result
6911 : in overflow.
6912 :
6913 : -- ALGLIB --
6914 : Copyright 02.12.2009 by Bochkanov Sergey
6915 : *************************************************************************/
6916 : #if !defined(AE_NO_EXCEPTIONS)
6917 0 : double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams)
6918 : {
6919 : jmp_buf _break_jump;
6920 : alglib_impl::ae_state _alglib_env_state;
6921 : ae_int_t n;
6922 :
6923 0 : n = f.length();
6924 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6925 0 : if( setjmp(_break_jump) )
6926 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6927 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6928 0 : if( _xparams.flags!=0x0 )
6929 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6930 0 : double result = alglib_impl::polynomialcalceqdist(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
6931 :
6932 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6933 0 : return *(reinterpret_cast<double*>(&result));
6934 : }
6935 : #endif
6936 :
6937 : /*************************************************************************
6938 : Fast polynomial interpolation function on Chebyshev points (first kind)
6939 : with O(N) complexity.
6940 :
6941 : INPUT PARAMETERS:
6942 : A - left boundary of [A,B]
6943 : B - right boundary of [A,B]
6944 : F - function values, array[0..N-1]
6945 : N - number of points on Chebyshev grid (first kind),
6946 : X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))
6947 : for N=1 a constant model is constructed.
6948 : T - position where P(x) is calculated
6949 :
6950 : RESULT
6951 : value of the Lagrange interpolant at T
6952 :
6953 : IMPORTANT
6954 : this function provides fast interface which is not overflow-safe
6955 : nor it is very precise.
6956 : the best option is to use PolIntBuildCheb1()/BarycentricCalc()
6957 : subroutines unless you are pretty sure that your data will not result
6958 : in overflow.
6959 :
6960 : -- ALGLIB --
6961 : Copyright 02.12.2009 by Bochkanov Sergey
6962 : *************************************************************************/
6963 0 : double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams)
6964 : {
6965 : jmp_buf _break_jump;
6966 : alglib_impl::ae_state _alglib_env_state;
6967 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6968 0 : if( setjmp(_break_jump) )
6969 : {
6970 : #if !defined(AE_NO_EXCEPTIONS)
6971 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6972 : #else
6973 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6974 : return 0;
6975 : #endif
6976 : }
6977 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6978 0 : if( _xparams.flags!=0x0 )
6979 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6980 0 : double result = alglib_impl::polynomialcalccheb1(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
6981 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6982 0 : return *(reinterpret_cast<double*>(&result));
6983 : }
6984 :
6985 : /*************************************************************************
6986 : Fast polynomial interpolation function on Chebyshev points (first kind)
6987 : with O(N) complexity.
6988 :
6989 : INPUT PARAMETERS:
6990 : A - left boundary of [A,B]
6991 : B - right boundary of [A,B]
6992 : F - function values, array[0..N-1]
6993 : N - number of points on Chebyshev grid (first kind),
6994 : X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))
6995 : for N=1 a constant model is constructed.
6996 : T - position where P(x) is calculated
6997 :
6998 : RESULT
6999 : value of the Lagrange interpolant at T
7000 :
7001 : IMPORTANT
7002 : this function provides fast interface which is not overflow-safe
7003 : nor it is very precise.
7004 : the best option is to use PolIntBuildCheb1()/BarycentricCalc()
7005 : subroutines unless you are pretty sure that your data will not result
7006 : in overflow.
7007 :
7008 : -- ALGLIB --
7009 : Copyright 02.12.2009 by Bochkanov Sergey
7010 : *************************************************************************/
7011 : #if !defined(AE_NO_EXCEPTIONS)
7012 0 : double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams)
7013 : {
7014 : jmp_buf _break_jump;
7015 : alglib_impl::ae_state _alglib_env_state;
7016 : ae_int_t n;
7017 :
7018 0 : n = f.length();
7019 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7020 0 : if( setjmp(_break_jump) )
7021 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7022 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7023 0 : if( _xparams.flags!=0x0 )
7024 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7025 0 : double result = alglib_impl::polynomialcalccheb1(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
7026 :
7027 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7028 0 : return *(reinterpret_cast<double*>(&result));
7029 : }
7030 : #endif
7031 :
7032 : /*************************************************************************
7033 : Fast polynomial interpolation function on Chebyshev points (second kind)
7034 : with O(N) complexity.
7035 :
7036 : INPUT PARAMETERS:
7037 : A - left boundary of [A,B]
7038 : B - right boundary of [A,B]
7039 : F - function values, array[0..N-1]
7040 : N - number of points on Chebyshev grid (second kind),
7041 : X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))
7042 : for N=1 a constant model is constructed.
7043 : T - position where P(x) is calculated
7044 :
7045 : RESULT
7046 : value of the Lagrange interpolant at T
7047 :
7048 : IMPORTANT
7049 : this function provides fast interface which is not overflow-safe
7050 : nor it is very precise.
7051 : the best option is to use PolIntBuildCheb2()/BarycentricCalc()
7052 : subroutines unless you are pretty sure that your data will not result
7053 : in overflow.
7054 :
7055 : -- ALGLIB --
7056 : Copyright 02.12.2009 by Bochkanov Sergey
7057 : *************************************************************************/
7058 0 : double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t, const xparams _xparams)
7059 : {
7060 : jmp_buf _break_jump;
7061 : alglib_impl::ae_state _alglib_env_state;
7062 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7063 0 : if( setjmp(_break_jump) )
7064 : {
7065 : #if !defined(AE_NO_EXCEPTIONS)
7066 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7067 : #else
7068 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7069 : return 0;
7070 : #endif
7071 : }
7072 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7073 0 : if( _xparams.flags!=0x0 )
7074 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7075 0 : double result = alglib_impl::polynomialcalccheb2(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
7076 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7077 0 : return *(reinterpret_cast<double*>(&result));
7078 : }
7079 :
7080 : /*************************************************************************
7081 : Fast polynomial interpolation function on Chebyshev points (second kind)
7082 : with O(N) complexity.
7083 :
7084 : INPUT PARAMETERS:
7085 : A - left boundary of [A,B]
7086 : B - right boundary of [A,B]
7087 : F - function values, array[0..N-1]
7088 : N - number of points on Chebyshev grid (second kind),
7089 : X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))
7090 : for N=1 a constant model is constructed.
7091 : T - position where P(x) is calculated
7092 :
7093 : RESULT
7094 : value of the Lagrange interpolant at T
7095 :
7096 : IMPORTANT
7097 : this function provides fast interface which is not overflow-safe
7098 : nor it is very precise.
7099 : the best option is to use PolIntBuildCheb2()/BarycentricCalc()
7100 : subroutines unless you are pretty sure that your data will not result
7101 : in overflow.
7102 :
7103 : -- ALGLIB --
7104 : Copyright 02.12.2009 by Bochkanov Sergey
7105 : *************************************************************************/
7106 : #if !defined(AE_NO_EXCEPTIONS)
7107 0 : double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const double t, const xparams _xparams)
7108 : {
7109 : jmp_buf _break_jump;
7110 : alglib_impl::ae_state _alglib_env_state;
7111 : ae_int_t n;
7112 :
7113 0 : n = f.length();
7114 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7115 0 : if( setjmp(_break_jump) )
7116 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7117 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7118 0 : if( _xparams.flags!=0x0 )
7119 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7120 0 : double result = alglib_impl::polynomialcalccheb2(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
7121 :
7122 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7123 0 : return *(reinterpret_cast<double*>(&result));
7124 : }
7125 : #endif
7126 : #endif
7127 :
7128 : #if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD)
7129 : /*************************************************************************
7130 : Polynomial fitting report:
7131 : TaskRCond reciprocal of task's condition number
7132 : RMSError RMS error
7133 : AvgError average error
7134 : AvgRelError average relative error (for non-zero Y[I])
7135 : MaxError maximum error
7136 : *************************************************************************/
7137 0 : _polynomialfitreport_owner::_polynomialfitreport_owner()
7138 : {
7139 : jmp_buf _break_jump;
7140 : alglib_impl::ae_state _state;
7141 :
7142 0 : alglib_impl::ae_state_init(&_state);
7143 0 : if( setjmp(_break_jump) )
7144 : {
7145 0 : if( p_struct!=NULL )
7146 : {
7147 0 : alglib_impl::_polynomialfitreport_destroy(p_struct);
7148 0 : alglib_impl::ae_free(p_struct);
7149 : }
7150 0 : p_struct = NULL;
7151 : #if !defined(AE_NO_EXCEPTIONS)
7152 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7153 : #else
7154 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7155 : return;
7156 : #endif
7157 : }
7158 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7159 0 : p_struct = NULL;
7160 0 : p_struct = (alglib_impl::polynomialfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::polynomialfitreport), &_state);
7161 0 : memset(p_struct, 0, sizeof(alglib_impl::polynomialfitreport));
7162 0 : alglib_impl::_polynomialfitreport_init(p_struct, &_state, ae_false);
7163 0 : ae_state_clear(&_state);
7164 0 : }
7165 :
7166 0 : _polynomialfitreport_owner::_polynomialfitreport_owner(const _polynomialfitreport_owner &rhs)
7167 : {
7168 : jmp_buf _break_jump;
7169 : alglib_impl::ae_state _state;
7170 :
7171 0 : alglib_impl::ae_state_init(&_state);
7172 0 : if( setjmp(_break_jump) )
7173 : {
7174 0 : if( p_struct!=NULL )
7175 : {
7176 0 : alglib_impl::_polynomialfitreport_destroy(p_struct);
7177 0 : alglib_impl::ae_free(p_struct);
7178 : }
7179 0 : p_struct = NULL;
7180 : #if !defined(AE_NO_EXCEPTIONS)
7181 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7182 : #else
7183 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7184 : return;
7185 : #endif
7186 : }
7187 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7188 0 : p_struct = NULL;
7189 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: polynomialfitreport copy constructor failure (source is not initialized)", &_state);
7190 0 : p_struct = (alglib_impl::polynomialfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::polynomialfitreport), &_state);
7191 0 : memset(p_struct, 0, sizeof(alglib_impl::polynomialfitreport));
7192 0 : alglib_impl::_polynomialfitreport_init_copy(p_struct, const_cast<alglib_impl::polynomialfitreport*>(rhs.p_struct), &_state, ae_false);
7193 0 : ae_state_clear(&_state);
7194 0 : }
7195 :
7196 0 : _polynomialfitreport_owner& _polynomialfitreport_owner::operator=(const _polynomialfitreport_owner &rhs)
7197 : {
7198 0 : if( this==&rhs )
7199 0 : return *this;
7200 : jmp_buf _break_jump;
7201 : alglib_impl::ae_state _state;
7202 :
7203 0 : alglib_impl::ae_state_init(&_state);
7204 0 : if( setjmp(_break_jump) )
7205 : {
7206 : #if !defined(AE_NO_EXCEPTIONS)
7207 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7208 : #else
7209 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7210 : return *this;
7211 : #endif
7212 : }
7213 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7214 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: polynomialfitreport assignment constructor failure (destination is not initialized)", &_state);
7215 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: polynomialfitreport assignment constructor failure (source is not initialized)", &_state);
7216 0 : alglib_impl::_polynomialfitreport_destroy(p_struct);
7217 0 : memset(p_struct, 0, sizeof(alglib_impl::polynomialfitreport));
7218 0 : alglib_impl::_polynomialfitreport_init_copy(p_struct, const_cast<alglib_impl::polynomialfitreport*>(rhs.p_struct), &_state, ae_false);
7219 0 : ae_state_clear(&_state);
7220 0 : return *this;
7221 : }
7222 :
7223 0 : _polynomialfitreport_owner::~_polynomialfitreport_owner()
7224 : {
7225 0 : if( p_struct!=NULL )
7226 : {
7227 0 : alglib_impl::_polynomialfitreport_destroy(p_struct);
7228 0 : ae_free(p_struct);
7229 : }
7230 0 : }
7231 :
7232 0 : alglib_impl::polynomialfitreport* _polynomialfitreport_owner::c_ptr()
7233 : {
7234 0 : return p_struct;
7235 : }
7236 :
7237 0 : alglib_impl::polynomialfitreport* _polynomialfitreport_owner::c_ptr() const
7238 : {
7239 0 : return const_cast<alglib_impl::polynomialfitreport*>(p_struct);
7240 : }
7241 0 : polynomialfitreport::polynomialfitreport() : _polynomialfitreport_owner() ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror)
7242 : {
7243 0 : }
7244 :
7245 0 : polynomialfitreport::polynomialfitreport(const polynomialfitreport &rhs):_polynomialfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror)
7246 : {
7247 0 : }
7248 :
7249 0 : polynomialfitreport& polynomialfitreport::operator=(const polynomialfitreport &rhs)
7250 : {
7251 0 : if( this==&rhs )
7252 0 : return *this;
7253 0 : _polynomialfitreport_owner::operator=(rhs);
7254 0 : return *this;
7255 : }
7256 :
7257 0 : polynomialfitreport::~polynomialfitreport()
7258 : {
7259 0 : }
7260 :
7261 :
7262 : /*************************************************************************
7263 : Barycentric fitting report:
7264 : RMSError RMS error
7265 : AvgError average error
7266 : AvgRelError average relative error (for non-zero Y[I])
7267 : MaxError maximum error
7268 : TaskRCond reciprocal of task's condition number
7269 : *************************************************************************/
7270 0 : _barycentricfitreport_owner::_barycentricfitreport_owner()
7271 : {
7272 : jmp_buf _break_jump;
7273 : alglib_impl::ae_state _state;
7274 :
7275 0 : alglib_impl::ae_state_init(&_state);
7276 0 : if( setjmp(_break_jump) )
7277 : {
7278 0 : if( p_struct!=NULL )
7279 : {
7280 0 : alglib_impl::_barycentricfitreport_destroy(p_struct);
7281 0 : alglib_impl::ae_free(p_struct);
7282 : }
7283 0 : p_struct = NULL;
7284 : #if !defined(AE_NO_EXCEPTIONS)
7285 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7286 : #else
7287 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7288 : return;
7289 : #endif
7290 : }
7291 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7292 0 : p_struct = NULL;
7293 0 : p_struct = (alglib_impl::barycentricfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricfitreport), &_state);
7294 0 : memset(p_struct, 0, sizeof(alglib_impl::barycentricfitreport));
7295 0 : alglib_impl::_barycentricfitreport_init(p_struct, &_state, ae_false);
7296 0 : ae_state_clear(&_state);
7297 0 : }
7298 :
7299 0 : _barycentricfitreport_owner::_barycentricfitreport_owner(const _barycentricfitreport_owner &rhs)
7300 : {
7301 : jmp_buf _break_jump;
7302 : alglib_impl::ae_state _state;
7303 :
7304 0 : alglib_impl::ae_state_init(&_state);
7305 0 : if( setjmp(_break_jump) )
7306 : {
7307 0 : if( p_struct!=NULL )
7308 : {
7309 0 : alglib_impl::_barycentricfitreport_destroy(p_struct);
7310 0 : alglib_impl::ae_free(p_struct);
7311 : }
7312 0 : p_struct = NULL;
7313 : #if !defined(AE_NO_EXCEPTIONS)
7314 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7315 : #else
7316 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7317 : return;
7318 : #endif
7319 : }
7320 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7321 0 : p_struct = NULL;
7322 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricfitreport copy constructor failure (source is not initialized)", &_state);
7323 0 : p_struct = (alglib_impl::barycentricfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::barycentricfitreport), &_state);
7324 0 : memset(p_struct, 0, sizeof(alglib_impl::barycentricfitreport));
7325 0 : alglib_impl::_barycentricfitreport_init_copy(p_struct, const_cast<alglib_impl::barycentricfitreport*>(rhs.p_struct), &_state, ae_false);
7326 0 : ae_state_clear(&_state);
7327 0 : }
7328 :
7329 0 : _barycentricfitreport_owner& _barycentricfitreport_owner::operator=(const _barycentricfitreport_owner &rhs)
7330 : {
7331 0 : if( this==&rhs )
7332 0 : return *this;
7333 : jmp_buf _break_jump;
7334 : alglib_impl::ae_state _state;
7335 :
7336 0 : alglib_impl::ae_state_init(&_state);
7337 0 : if( setjmp(_break_jump) )
7338 : {
7339 : #if !defined(AE_NO_EXCEPTIONS)
7340 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7341 : #else
7342 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7343 : return *this;
7344 : #endif
7345 : }
7346 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7347 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: barycentricfitreport assignment constructor failure (destination is not initialized)", &_state);
7348 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: barycentricfitreport assignment constructor failure (source is not initialized)", &_state);
7349 0 : alglib_impl::_barycentricfitreport_destroy(p_struct);
7350 0 : memset(p_struct, 0, sizeof(alglib_impl::barycentricfitreport));
7351 0 : alglib_impl::_barycentricfitreport_init_copy(p_struct, const_cast<alglib_impl::barycentricfitreport*>(rhs.p_struct), &_state, ae_false);
7352 0 : ae_state_clear(&_state);
7353 0 : return *this;
7354 : }
7355 :
7356 0 : _barycentricfitreport_owner::~_barycentricfitreport_owner()
7357 : {
7358 0 : if( p_struct!=NULL )
7359 : {
7360 0 : alglib_impl::_barycentricfitreport_destroy(p_struct);
7361 0 : ae_free(p_struct);
7362 : }
7363 0 : }
7364 :
7365 0 : alglib_impl::barycentricfitreport* _barycentricfitreport_owner::c_ptr()
7366 : {
7367 0 : return p_struct;
7368 : }
7369 :
7370 0 : alglib_impl::barycentricfitreport* _barycentricfitreport_owner::c_ptr() const
7371 : {
7372 0 : return const_cast<alglib_impl::barycentricfitreport*>(p_struct);
7373 : }
7374 0 : barycentricfitreport::barycentricfitreport() : _barycentricfitreport_owner() ,taskrcond(p_struct->taskrcond),dbest(p_struct->dbest),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror)
7375 : {
7376 0 : }
7377 :
7378 0 : barycentricfitreport::barycentricfitreport(const barycentricfitreport &rhs):_barycentricfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),dbest(p_struct->dbest),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror)
7379 : {
7380 0 : }
7381 :
7382 0 : barycentricfitreport& barycentricfitreport::operator=(const barycentricfitreport &rhs)
7383 : {
7384 0 : if( this==&rhs )
7385 0 : return *this;
7386 0 : _barycentricfitreport_owner::operator=(rhs);
7387 0 : return *this;
7388 : }
7389 :
7390 0 : barycentricfitreport::~barycentricfitreport()
7391 : {
7392 0 : }
7393 :
7394 :
7395 : /*************************************************************************
7396 : Least squares fitting report. This structure contains informational fields
7397 : which are set by fitting functions provided by this unit.
7398 :
7399 : Different functions initialize different sets of fields, so you should
7400 : read documentation on specific function you used in order to know which
7401 : fields are initialized.
7402 :
7403 : TaskRCond reciprocal of task's condition number
7404 : IterationsCount number of internal iterations
7405 :
7406 : VarIdx if user-supplied gradient contains errors which were
7407 : detected by nonlinear fitter, this field is set to
7408 : index of the first component of gradient which is
7409 : suspected to be spoiled by bugs.
7410 :
7411 : RMSError RMS error
7412 : AvgError average error
7413 : AvgRelError average relative error (for non-zero Y[I])
7414 : MaxError maximum error
7415 :
7416 : WRMSError weighted RMS error
7417 :
7418 : CovPar covariance matrix for parameters, filled by some solvers
7419 : ErrPar vector of errors in parameters, filled by some solvers
7420 : ErrCurve vector of fit errors - variability of the best-fit
7421 : curve, filled by some solvers.
7422 : Noise vector of per-point noise estimates, filled by
7423 : some solvers.
7424 : R2 coefficient of determination (non-weighted, non-adjusted),
7425 : filled by some solvers.
7426 : *************************************************************************/
7427 0 : _lsfitreport_owner::_lsfitreport_owner()
7428 : {
7429 : jmp_buf _break_jump;
7430 : alglib_impl::ae_state _state;
7431 :
7432 0 : alglib_impl::ae_state_init(&_state);
7433 0 : if( setjmp(_break_jump) )
7434 : {
7435 0 : if( p_struct!=NULL )
7436 : {
7437 0 : alglib_impl::_lsfitreport_destroy(p_struct);
7438 0 : alglib_impl::ae_free(p_struct);
7439 : }
7440 0 : p_struct = NULL;
7441 : #if !defined(AE_NO_EXCEPTIONS)
7442 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7443 : #else
7444 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7445 : return;
7446 : #endif
7447 : }
7448 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7449 0 : p_struct = NULL;
7450 0 : p_struct = (alglib_impl::lsfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitreport), &_state);
7451 0 : memset(p_struct, 0, sizeof(alglib_impl::lsfitreport));
7452 0 : alglib_impl::_lsfitreport_init(p_struct, &_state, ae_false);
7453 0 : ae_state_clear(&_state);
7454 0 : }
7455 :
7456 0 : _lsfitreport_owner::_lsfitreport_owner(const _lsfitreport_owner &rhs)
7457 : {
7458 : jmp_buf _break_jump;
7459 : alglib_impl::ae_state _state;
7460 :
7461 0 : alglib_impl::ae_state_init(&_state);
7462 0 : if( setjmp(_break_jump) )
7463 : {
7464 0 : if( p_struct!=NULL )
7465 : {
7466 0 : alglib_impl::_lsfitreport_destroy(p_struct);
7467 0 : alglib_impl::ae_free(p_struct);
7468 : }
7469 0 : p_struct = NULL;
7470 : #if !defined(AE_NO_EXCEPTIONS)
7471 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7472 : #else
7473 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7474 : return;
7475 : #endif
7476 : }
7477 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7478 0 : p_struct = NULL;
7479 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitreport copy constructor failure (source is not initialized)", &_state);
7480 0 : p_struct = (alglib_impl::lsfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitreport), &_state);
7481 0 : memset(p_struct, 0, sizeof(alglib_impl::lsfitreport));
7482 0 : alglib_impl::_lsfitreport_init_copy(p_struct, const_cast<alglib_impl::lsfitreport*>(rhs.p_struct), &_state, ae_false);
7483 0 : ae_state_clear(&_state);
7484 0 : }
7485 :
7486 0 : _lsfitreport_owner& _lsfitreport_owner::operator=(const _lsfitreport_owner &rhs)
7487 : {
7488 0 : if( this==&rhs )
7489 0 : return *this;
7490 : jmp_buf _break_jump;
7491 : alglib_impl::ae_state _state;
7492 :
7493 0 : alglib_impl::ae_state_init(&_state);
7494 0 : if( setjmp(_break_jump) )
7495 : {
7496 : #if !defined(AE_NO_EXCEPTIONS)
7497 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7498 : #else
7499 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7500 : return *this;
7501 : #endif
7502 : }
7503 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7504 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: lsfitreport assignment constructor failure (destination is not initialized)", &_state);
7505 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitreport assignment constructor failure (source is not initialized)", &_state);
7506 0 : alglib_impl::_lsfitreport_destroy(p_struct);
7507 0 : memset(p_struct, 0, sizeof(alglib_impl::lsfitreport));
7508 0 : alglib_impl::_lsfitreport_init_copy(p_struct, const_cast<alglib_impl::lsfitreport*>(rhs.p_struct), &_state, ae_false);
7509 0 : ae_state_clear(&_state);
7510 0 : return *this;
7511 : }
7512 :
7513 0 : _lsfitreport_owner::~_lsfitreport_owner()
7514 : {
7515 0 : if( p_struct!=NULL )
7516 : {
7517 0 : alglib_impl::_lsfitreport_destroy(p_struct);
7518 0 : ae_free(p_struct);
7519 : }
7520 0 : }
7521 :
7522 0 : alglib_impl::lsfitreport* _lsfitreport_owner::c_ptr()
7523 : {
7524 0 : return p_struct;
7525 : }
7526 :
7527 0 : alglib_impl::lsfitreport* _lsfitreport_owner::c_ptr() const
7528 : {
7529 0 : return const_cast<alglib_impl::lsfitreport*>(p_struct);
7530 : }
7531 0 : lsfitreport::lsfitreport() : _lsfitreport_owner() ,taskrcond(p_struct->taskrcond),iterationscount(p_struct->iterationscount),varidx(p_struct->varidx),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror),wrmserror(p_struct->wrmserror),covpar(&p_struct->covpar),errpar(&p_struct->errpar),errcurve(&p_struct->errcurve),noise(&p_struct->noise),r2(p_struct->r2)
7532 : {
7533 0 : }
7534 :
7535 0 : lsfitreport::lsfitreport(const lsfitreport &rhs):_lsfitreport_owner(rhs) ,taskrcond(p_struct->taskrcond),iterationscount(p_struct->iterationscount),varidx(p_struct->varidx),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror),wrmserror(p_struct->wrmserror),covpar(&p_struct->covpar),errpar(&p_struct->errpar),errcurve(&p_struct->errcurve),noise(&p_struct->noise),r2(p_struct->r2)
7536 : {
7537 0 : }
7538 :
7539 0 : lsfitreport& lsfitreport::operator=(const lsfitreport &rhs)
7540 : {
7541 0 : if( this==&rhs )
7542 0 : return *this;
7543 0 : _lsfitreport_owner::operator=(rhs);
7544 0 : return *this;
7545 : }
7546 :
7547 0 : lsfitreport::~lsfitreport()
7548 : {
7549 0 : }
7550 :
7551 :
7552 : /*************************************************************************
7553 : Nonlinear fitter.
7554 :
7555 : You should use ALGLIB functions to work with fitter.
7556 : Never try to access its fields directly!
7557 : *************************************************************************/
7558 0 : _lsfitstate_owner::_lsfitstate_owner()
7559 : {
7560 : jmp_buf _break_jump;
7561 : alglib_impl::ae_state _state;
7562 :
7563 0 : alglib_impl::ae_state_init(&_state);
7564 0 : if( setjmp(_break_jump) )
7565 : {
7566 0 : if( p_struct!=NULL )
7567 : {
7568 0 : alglib_impl::_lsfitstate_destroy(p_struct);
7569 0 : alglib_impl::ae_free(p_struct);
7570 : }
7571 0 : p_struct = NULL;
7572 : #if !defined(AE_NO_EXCEPTIONS)
7573 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7574 : #else
7575 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7576 : return;
7577 : #endif
7578 : }
7579 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7580 0 : p_struct = NULL;
7581 0 : p_struct = (alglib_impl::lsfitstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitstate), &_state);
7582 0 : memset(p_struct, 0, sizeof(alglib_impl::lsfitstate));
7583 0 : alglib_impl::_lsfitstate_init(p_struct, &_state, ae_false);
7584 0 : ae_state_clear(&_state);
7585 0 : }
7586 :
7587 0 : _lsfitstate_owner::_lsfitstate_owner(const _lsfitstate_owner &rhs)
7588 : {
7589 : jmp_buf _break_jump;
7590 : alglib_impl::ae_state _state;
7591 :
7592 0 : alglib_impl::ae_state_init(&_state);
7593 0 : if( setjmp(_break_jump) )
7594 : {
7595 0 : if( p_struct!=NULL )
7596 : {
7597 0 : alglib_impl::_lsfitstate_destroy(p_struct);
7598 0 : alglib_impl::ae_free(p_struct);
7599 : }
7600 0 : p_struct = NULL;
7601 : #if !defined(AE_NO_EXCEPTIONS)
7602 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7603 : #else
7604 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7605 : return;
7606 : #endif
7607 : }
7608 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7609 0 : p_struct = NULL;
7610 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitstate copy constructor failure (source is not initialized)", &_state);
7611 0 : p_struct = (alglib_impl::lsfitstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::lsfitstate), &_state);
7612 0 : memset(p_struct, 0, sizeof(alglib_impl::lsfitstate));
7613 0 : alglib_impl::_lsfitstate_init_copy(p_struct, const_cast<alglib_impl::lsfitstate*>(rhs.p_struct), &_state, ae_false);
7614 0 : ae_state_clear(&_state);
7615 0 : }
7616 :
7617 0 : _lsfitstate_owner& _lsfitstate_owner::operator=(const _lsfitstate_owner &rhs)
7618 : {
7619 0 : if( this==&rhs )
7620 0 : return *this;
7621 : jmp_buf _break_jump;
7622 : alglib_impl::ae_state _state;
7623 :
7624 0 : alglib_impl::ae_state_init(&_state);
7625 0 : if( setjmp(_break_jump) )
7626 : {
7627 : #if !defined(AE_NO_EXCEPTIONS)
7628 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
7629 : #else
7630 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
7631 : return *this;
7632 : #endif
7633 : }
7634 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
7635 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: lsfitstate assignment constructor failure (destination is not initialized)", &_state);
7636 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: lsfitstate assignment constructor failure (source is not initialized)", &_state);
7637 0 : alglib_impl::_lsfitstate_destroy(p_struct);
7638 0 : memset(p_struct, 0, sizeof(alglib_impl::lsfitstate));
7639 0 : alglib_impl::_lsfitstate_init_copy(p_struct, const_cast<alglib_impl::lsfitstate*>(rhs.p_struct), &_state, ae_false);
7640 0 : ae_state_clear(&_state);
7641 0 : return *this;
7642 : }
7643 :
7644 0 : _lsfitstate_owner::~_lsfitstate_owner()
7645 : {
7646 0 : if( p_struct!=NULL )
7647 : {
7648 0 : alglib_impl::_lsfitstate_destroy(p_struct);
7649 0 : ae_free(p_struct);
7650 : }
7651 0 : }
7652 :
7653 0 : alglib_impl::lsfitstate* _lsfitstate_owner::c_ptr()
7654 : {
7655 0 : return p_struct;
7656 : }
7657 :
7658 0 : alglib_impl::lsfitstate* _lsfitstate_owner::c_ptr() const
7659 : {
7660 0 : return const_cast<alglib_impl::lsfitstate*>(p_struct);
7661 : }
7662 0 : lsfitstate::lsfitstate() : _lsfitstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),needfgh(p_struct->needfgh),xupdated(p_struct->xupdated),c(&p_struct->c),f(p_struct->f),g(&p_struct->g),h(&p_struct->h),x(&p_struct->x)
7663 : {
7664 0 : }
7665 :
7666 0 : lsfitstate::lsfitstate(const lsfitstate &rhs):_lsfitstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),needfgh(p_struct->needfgh),xupdated(p_struct->xupdated),c(&p_struct->c),f(p_struct->f),g(&p_struct->g),h(&p_struct->h),x(&p_struct->x)
7667 : {
7668 0 : }
7669 :
7670 0 : lsfitstate& lsfitstate::operator=(const lsfitstate &rhs)
7671 : {
7672 0 : if( this==&rhs )
7673 0 : return *this;
7674 0 : _lsfitstate_owner::operator=(rhs);
7675 0 : return *this;
7676 : }
7677 :
7678 0 : lsfitstate::~lsfitstate()
7679 : {
7680 0 : }
7681 :
7682 : /*************************************************************************
7683 : This subroutine fits piecewise linear curve to points with Ramer-Douglas-
7684 : Peucker algorithm, which stops after generating specified number of linear
7685 : sections.
7686 :
7687 : IMPORTANT:
7688 : * it does NOT perform least-squares fitting; it builds curve, but this
7689 : curve does not minimize some least squares metric. See description of
7690 : RDP algorithm (say, in Wikipedia) for more details on WHAT is performed.
7691 : * this function does NOT work with parametric curves (i.e. curves which
7692 : can be represented as {X(t),Y(t)}. It works with curves which can be
7693 : represented as Y(X). Thus, it is impossible to model figures like
7694 : circles with this functions.
7695 : If you want to work with parametric curves, you should use
7696 : ParametricRDPFixed() function provided by "Parametric" subpackage of
7697 : "Interpolation" package.
7698 :
7699 : INPUT PARAMETERS:
7700 : X - array of X-coordinates:
7701 : * at least N elements
7702 : * can be unordered (points are automatically sorted)
7703 : * this function may accept non-distinct X (see below for
7704 : more information on handling of such inputs)
7705 : Y - array of Y-coordinates:
7706 : * at least N elements
7707 : N - number of elements in X/Y
7708 : M - desired number of sections:
7709 : * at most M sections are generated by this function
7710 : * less than M sections can be generated if we have N<M
7711 : (or some X are non-distinct).
7712 :
7713 : OUTPUT PARAMETERS:
7714 : X2 - X-values of corner points for piecewise approximation,
7715 : has length NSections+1 or zero (for NSections=0).
7716 : Y2 - Y-values of corner points,
7717 : has length NSections+1 or zero (for NSections=0).
7718 : NSections- number of sections found by algorithm, NSections<=M,
7719 : NSections can be zero for degenerate datasets
7720 : (N<=1 or all X[] are non-distinct).
7721 :
7722 : NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of
7723 : curve, (X2[NSection-1],Y2[NSection-1]) is the last point.
7724 :
7725 : -- ALGLIB --
7726 : Copyright 02.10.2014 by Bochkanov Sergey
7727 : *************************************************************************/
7728 0 : void lstfitpiecewiselinearrdpfixed(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, real_1d_array &x2, real_1d_array &y2, ae_int_t &nsections, const xparams _xparams)
7729 : {
7730 : jmp_buf _break_jump;
7731 : alglib_impl::ae_state _alglib_env_state;
7732 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7733 0 : if( setjmp(_break_jump) )
7734 : {
7735 : #if !defined(AE_NO_EXCEPTIONS)
7736 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7737 : #else
7738 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7739 : return;
7740 : #endif
7741 : }
7742 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7743 0 : if( _xparams.flags!=0x0 )
7744 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7745 0 : alglib_impl::lstfitpiecewiselinearrdpfixed(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), &nsections, &_alglib_env_state);
7746 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7747 0 : return;
7748 : }
7749 :
7750 : /*************************************************************************
7751 : This subroutine fits piecewise linear curve to points with Ramer-Douglas-
7752 : Peucker algorithm, which stops after achieving desired precision.
7753 :
7754 : IMPORTANT:
7755 : * it performs non-least-squares fitting; it builds curve, but this curve
7756 : does not minimize some least squares metric. See description of RDP
7757 : algorithm (say, in Wikipedia) for more details on WHAT is performed.
7758 : * this function does NOT work with parametric curves (i.e. curves which
7759 : can be represented as {X(t),Y(t)}. It works with curves which can be
7760 : represented as Y(X). Thus, it is impossible to model figures like circles
7761 : with this functions.
7762 : If you want to work with parametric curves, you should use
7763 : ParametricRDPFixed() function provided by "Parametric" subpackage of
7764 : "Interpolation" package.
7765 :
7766 : INPUT PARAMETERS:
7767 : X - array of X-coordinates:
7768 : * at least N elements
7769 : * can be unordered (points are automatically sorted)
7770 : * this function may accept non-distinct X (see below for
7771 : more information on handling of such inputs)
7772 : Y - array of Y-coordinates:
7773 : * at least N elements
7774 : N - number of elements in X/Y
7775 : Eps - positive number, desired precision.
7776 :
7777 :
7778 : OUTPUT PARAMETERS:
7779 : X2 - X-values of corner points for piecewise approximation,
7780 : has length NSections+1 or zero (for NSections=0).
7781 : Y2 - Y-values of corner points,
7782 : has length NSections+1 or zero (for NSections=0).
7783 : NSections- number of sections found by algorithm,
7784 : NSections can be zero for degenerate datasets
7785 : (N<=1 or all X[] are non-distinct).
7786 :
7787 : NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of
7788 : curve, (X2[NSection-1],Y2[NSection-1]) is the last point.
7789 :
7790 : -- ALGLIB --
7791 : Copyright 02.10.2014 by Bochkanov Sergey
7792 : *************************************************************************/
7793 0 : void lstfitpiecewiselinearrdp(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double eps, real_1d_array &x2, real_1d_array &y2, ae_int_t &nsections, const xparams _xparams)
7794 : {
7795 : jmp_buf _break_jump;
7796 : alglib_impl::ae_state _alglib_env_state;
7797 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7798 0 : if( setjmp(_break_jump) )
7799 : {
7800 : #if !defined(AE_NO_EXCEPTIONS)
7801 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7802 : #else
7803 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7804 : return;
7805 : #endif
7806 : }
7807 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7808 0 : if( _xparams.flags!=0x0 )
7809 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7810 0 : alglib_impl::lstfitpiecewiselinearrdp(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, eps, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), const_cast<alglib_impl::ae_vector*>(y2.c_ptr()), &nsections, &_alglib_env_state);
7811 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7812 0 : return;
7813 : }
7814 :
7815 : /*************************************************************************
7816 : Fitting by polynomials in barycentric form. This function provides simple
7817 : unterface for unconstrained unweighted fitting. See PolynomialFitWC() if
7818 : you need constrained fitting.
7819 :
7820 : Task is linear, so linear least squares solver is used. Complexity of this
7821 : computational scheme is O(N*M^2), mostly dominated by least squares solver
7822 :
7823 : SEE ALSO:
7824 : PolynomialFitWC()
7825 :
7826 : NOTES:
7827 : you can convert P from barycentric form to the power or Chebyshev
7828 : basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
7829 : POLINT subpackage.
7830 :
7831 : ! COMMERCIAL EDITION OF ALGLIB:
7832 : !
7833 : ! Commercial Edition of ALGLIB includes following important improvements
7834 : ! of this function:
7835 : ! * high-performance native backend with same C# interface (C# version)
7836 : ! * multithreading support (C++ and C# versions)
7837 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7838 : ! (C++ and C# versions, x86/x64 platform)
7839 : !
7840 : ! We recommend you to read 'Working with commercial version' section of
7841 : ! ALGLIB Reference Manual in order to find out how to use performance-
7842 : ! related features provided by commercial edition of ALGLIB.
7843 :
7844 : INPUT PARAMETERS:
7845 : X - points, array[0..N-1].
7846 : Y - function values, array[0..N-1].
7847 : N - number of points, N>0
7848 : * if given, only leading N elements of X/Y are used
7849 : * if not given, automatically determined from sizes of X/Y
7850 : M - number of basis functions (= polynomial_degree + 1), M>=1
7851 :
7852 : OUTPUT PARAMETERS:
7853 : Info- same format as in LSFitLinearW() subroutine:
7854 : * Info>0 task is solved
7855 : * Info<=0 an error occured:
7856 : -4 means inconvergence of internal SVD
7857 : P - interpolant in barycentric form.
7858 : Rep - report, same format as in LSFitLinearW() subroutine.
7859 : Following fields are set:
7860 : * RMSError rms error on the (X,Y).
7861 : * AvgError average error on the (X,Y).
7862 : * AvgRelError average relative error on the non-zero Y
7863 : * MaxError maximum error
7864 : NON-WEIGHTED ERRORS ARE CALCULATED
7865 :
7866 : -- ALGLIB PROJECT --
7867 : Copyright 10.12.2009 by Bochkanov Sergey
7868 : *************************************************************************/
7869 0 : void polynomialfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams)
7870 : {
7871 : jmp_buf _break_jump;
7872 : alglib_impl::ae_state _alglib_env_state;
7873 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7874 0 : if( setjmp(_break_jump) )
7875 : {
7876 : #if !defined(AE_NO_EXCEPTIONS)
7877 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7878 : #else
7879 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7880 : return;
7881 : #endif
7882 : }
7883 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7884 0 : if( _xparams.flags!=0x0 )
7885 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7886 0 : alglib_impl::polynomialfit(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, &info, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), const_cast<alglib_impl::polynomialfitreport*>(rep.c_ptr()), &_alglib_env_state);
7887 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7888 0 : return;
7889 : }
7890 :
7891 : /*************************************************************************
7892 : Fitting by polynomials in barycentric form. This function provides simple
7893 : unterface for unconstrained unweighted fitting. See PolynomialFitWC() if
7894 : you need constrained fitting.
7895 :
7896 : Task is linear, so linear least squares solver is used. Complexity of this
7897 : computational scheme is O(N*M^2), mostly dominated by least squares solver
7898 :
7899 : SEE ALSO:
7900 : PolynomialFitWC()
7901 :
7902 : NOTES:
7903 : you can convert P from barycentric form to the power or Chebyshev
7904 : basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
7905 : POLINT subpackage.
7906 :
7907 : ! COMMERCIAL EDITION OF ALGLIB:
7908 : !
7909 : ! Commercial Edition of ALGLIB includes following important improvements
7910 : ! of this function:
7911 : ! * high-performance native backend with same C# interface (C# version)
7912 : ! * multithreading support (C++ and C# versions)
7913 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7914 : ! (C++ and C# versions, x86/x64 platform)
7915 : !
7916 : ! We recommend you to read 'Working with commercial version' section of
7917 : ! ALGLIB Reference Manual in order to find out how to use performance-
7918 : ! related features provided by commercial edition of ALGLIB.
7919 :
7920 : INPUT PARAMETERS:
7921 : X - points, array[0..N-1].
7922 : Y - function values, array[0..N-1].
7923 : N - number of points, N>0
7924 : * if given, only leading N elements of X/Y are used
7925 : * if not given, automatically determined from sizes of X/Y
7926 : M - number of basis functions (= polynomial_degree + 1), M>=1
7927 :
7928 : OUTPUT PARAMETERS:
7929 : Info- same format as in LSFitLinearW() subroutine:
7930 : * Info>0 task is solved
7931 : * Info<=0 an error occured:
7932 : -4 means inconvergence of internal SVD
7933 : P - interpolant in barycentric form.
7934 : Rep - report, same format as in LSFitLinearW() subroutine.
7935 : Following fields are set:
7936 : * RMSError rms error on the (X,Y).
7937 : * AvgError average error on the (X,Y).
7938 : * AvgRelError average relative error on the non-zero Y
7939 : * MaxError maximum error
7940 : NON-WEIGHTED ERRORS ARE CALCULATED
7941 :
7942 : -- ALGLIB PROJECT --
7943 : Copyright 10.12.2009 by Bochkanov Sergey
7944 : *************************************************************************/
7945 : #if !defined(AE_NO_EXCEPTIONS)
7946 0 : void polynomialfit(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams)
7947 : {
7948 : jmp_buf _break_jump;
7949 : alglib_impl::ae_state _alglib_env_state;
7950 : ae_int_t n;
7951 0 : if( (x.length()!=y.length()))
7952 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialfit': looks like one of arguments has wrong size");
7953 0 : n = x.length();
7954 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7955 0 : if( setjmp(_break_jump) )
7956 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7957 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7958 0 : if( _xparams.flags!=0x0 )
7959 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7960 0 : alglib_impl::polynomialfit(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, &info, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), const_cast<alglib_impl::polynomialfitreport*>(rep.c_ptr()), &_alglib_env_state);
7961 :
7962 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7963 0 : return;
7964 : }
7965 : #endif
7966 :
7967 : /*************************************************************************
7968 : Weighted fitting by polynomials in barycentric form, with constraints on
7969 : function values or first derivatives.
7970 :
7971 : Small regularizing term is used when solving constrained tasks (to improve
7972 : stability).
7973 :
7974 : Task is linear, so linear least squares solver is used. Complexity of this
7975 : computational scheme is O(N*M^2), mostly dominated by least squares solver
7976 :
7977 : SEE ALSO:
7978 : PolynomialFit()
7979 :
7980 : NOTES:
7981 : you can convert P from barycentric form to the power or Chebyshev
7982 : basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
7983 : POLINT subpackage.
7984 :
7985 : ! COMMERCIAL EDITION OF ALGLIB:
7986 : !
7987 : ! Commercial Edition of ALGLIB includes following important improvements
7988 : ! of this function:
7989 : ! * high-performance native backend with same C# interface (C# version)
7990 : ! * multithreading support (C++ and C# versions)
7991 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7992 : ! (C++ and C# versions, x86/x64 platform)
7993 : !
7994 : ! We recommend you to read 'Working with commercial version' section of
7995 : ! ALGLIB Reference Manual in order to find out how to use performance-
7996 : ! related features provided by commercial edition of ALGLIB.
7997 :
7998 : INPUT PARAMETERS:
7999 : X - points, array[0..N-1].
8000 : Y - function values, array[0..N-1].
8001 : W - weights, array[0..N-1]
8002 : Each summand in square sum of approximation deviations from
8003 : given values is multiplied by the square of corresponding
8004 : weight. Fill it by 1's if you don't want to solve weighted
8005 : task.
8006 : N - number of points, N>0.
8007 : * if given, only leading N elements of X/Y/W are used
8008 : * if not given, automatically determined from sizes of X/Y/W
8009 : XC - points where polynomial values/derivatives are constrained,
8010 : array[0..K-1].
8011 : YC - values of constraints, array[0..K-1]
8012 : DC - array[0..K-1], types of constraints:
8013 : * DC[i]=0 means that P(XC[i])=YC[i]
8014 : * DC[i]=1 means that P'(XC[i])=YC[i]
8015 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
8016 : K - number of constraints, 0<=K<M.
8017 : K=0 means no constraints (XC/YC/DC are not used in such cases)
8018 : M - number of basis functions (= polynomial_degree + 1), M>=1
8019 :
8020 : OUTPUT PARAMETERS:
8021 : Info- same format as in LSFitLinearW() subroutine:
8022 : * Info>0 task is solved
8023 : * Info<=0 an error occured:
8024 : -4 means inconvergence of internal SVD
8025 : -3 means inconsistent constraints
8026 : P - interpolant in barycentric form.
8027 : Rep - report, same format as in LSFitLinearW() subroutine.
8028 : Following fields are set:
8029 : * RMSError rms error on the (X,Y).
8030 : * AvgError average error on the (X,Y).
8031 : * AvgRelError average relative error on the non-zero Y
8032 : * MaxError maximum error
8033 : NON-WEIGHTED ERRORS ARE CALCULATED
8034 :
8035 : IMPORTANT:
8036 : this subroitine doesn't calculate task's condition number for K<>0.
8037 :
8038 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
8039 :
8040 : Setting constraints can lead to undesired results, like ill-conditioned
8041 : behavior, or inconsistency being detected. From the other side, it allows
8042 : us to improve quality of the fit. Here we summarize our experience with
8043 : constrained regression splines:
8044 : * even simple constraints can be inconsistent, see Wikipedia article on
8045 : this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
8046 : * the greater is M (given fixed constraints), the more chances that
8047 : constraints will be consistent
8048 : * in the general case, consistency of constraints is NOT GUARANTEED.
8049 : * in the one special cases, however, we can guarantee consistency. This
8050 : case is: M>1 and constraints on the function values (NOT DERIVATIVES)
8051 :
8052 : Our final recommendation is to use constraints WHEN AND ONLY when you
8053 : can't solve your task without them. Anything beyond special cases given
8054 : above is not guaranteed and may result in inconsistency.
8055 :
8056 : -- ALGLIB PROJECT --
8057 : Copyright 10.12.2009 by Bochkanov Sergey
8058 : *************************************************************************/
8059 0 : void polynomialfitwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams)
8060 : {
8061 : jmp_buf _break_jump;
8062 : alglib_impl::ae_state _alglib_env_state;
8063 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8064 0 : if( setjmp(_break_jump) )
8065 : {
8066 : #if !defined(AE_NO_EXCEPTIONS)
8067 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8068 : #else
8069 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8070 : return;
8071 : #endif
8072 : }
8073 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8074 0 : if( _xparams.flags!=0x0 )
8075 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8076 0 : alglib_impl::polynomialfitwc(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(xc.c_ptr()), const_cast<alglib_impl::ae_vector*>(yc.c_ptr()), const_cast<alglib_impl::ae_vector*>(dc.c_ptr()), k, m, &info, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), const_cast<alglib_impl::polynomialfitreport*>(rep.c_ptr()), &_alglib_env_state);
8077 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8078 0 : return;
8079 : }
8080 :
8081 : /*************************************************************************
8082 : Weighted fitting by polynomials in barycentric form, with constraints on
8083 : function values or first derivatives.
8084 :
8085 : Small regularizing term is used when solving constrained tasks (to improve
8086 : stability).
8087 :
8088 : Task is linear, so linear least squares solver is used. Complexity of this
8089 : computational scheme is O(N*M^2), mostly dominated by least squares solver
8090 :
8091 : SEE ALSO:
8092 : PolynomialFit()
8093 :
8094 : NOTES:
8095 : you can convert P from barycentric form to the power or Chebyshev
8096 : basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
8097 : POLINT subpackage.
8098 :
8099 : ! COMMERCIAL EDITION OF ALGLIB:
8100 : !
8101 : ! Commercial Edition of ALGLIB includes following important improvements
8102 : ! of this function:
8103 : ! * high-performance native backend with same C# interface (C# version)
8104 : ! * multithreading support (C++ and C# versions)
8105 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8106 : ! (C++ and C# versions, x86/x64 platform)
8107 : !
8108 : ! We recommend you to read 'Working with commercial version' section of
8109 : ! ALGLIB Reference Manual in order to find out how to use performance-
8110 : ! related features provided by commercial edition of ALGLIB.
8111 :
8112 : INPUT PARAMETERS:
8113 : X - points, array[0..N-1].
8114 : Y - function values, array[0..N-1].
8115 : W - weights, array[0..N-1]
8116 : Each summand in square sum of approximation deviations from
8117 : given values is multiplied by the square of corresponding
8118 : weight. Fill it by 1's if you don't want to solve weighted
8119 : task.
8120 : N - number of points, N>0.
8121 : * if given, only leading N elements of X/Y/W are used
8122 : * if not given, automatically determined from sizes of X/Y/W
8123 : XC - points where polynomial values/derivatives are constrained,
8124 : array[0..K-1].
8125 : YC - values of constraints, array[0..K-1]
8126 : DC - array[0..K-1], types of constraints:
8127 : * DC[i]=0 means that P(XC[i])=YC[i]
8128 : * DC[i]=1 means that P'(XC[i])=YC[i]
8129 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
8130 : K - number of constraints, 0<=K<M.
8131 : K=0 means no constraints (XC/YC/DC are not used in such cases)
8132 : M - number of basis functions (= polynomial_degree + 1), M>=1
8133 :
8134 : OUTPUT PARAMETERS:
8135 : Info- same format as in LSFitLinearW() subroutine:
8136 : * Info>0 task is solved
8137 : * Info<=0 an error occured:
8138 : -4 means inconvergence of internal SVD
8139 : -3 means inconsistent constraints
8140 : P - interpolant in barycentric form.
8141 : Rep - report, same format as in LSFitLinearW() subroutine.
8142 : Following fields are set:
8143 : * RMSError rms error on the (X,Y).
8144 : * AvgError average error on the (X,Y).
8145 : * AvgRelError average relative error on the non-zero Y
8146 : * MaxError maximum error
8147 : NON-WEIGHTED ERRORS ARE CALCULATED
8148 :
8149 : IMPORTANT:
8150 : this subroitine doesn't calculate task's condition number for K<>0.
8151 :
8152 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
8153 :
8154 : Setting constraints can lead to undesired results, like ill-conditioned
8155 : behavior, or inconsistency being detected. From the other side, it allows
8156 : us to improve quality of the fit. Here we summarize our experience with
8157 : constrained regression splines:
8158 : * even simple constraints can be inconsistent, see Wikipedia article on
8159 : this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
8160 : * the greater is M (given fixed constraints), the more chances that
8161 : constraints will be consistent
8162 : * in the general case, consistency of constraints is NOT GUARANTEED.
8163 : * in the one special cases, however, we can guarantee consistency. This
8164 : case is: M>1 and constraints on the function values (NOT DERIVATIVES)
8165 :
8166 : Our final recommendation is to use constraints WHEN AND ONLY when you
8167 : can't solve your task without them. Anything beyond special cases given
8168 : above is not guaranteed and may result in inconsistency.
8169 :
8170 : -- ALGLIB PROJECT --
8171 : Copyright 10.12.2009 by Bochkanov Sergey
8172 : *************************************************************************/
8173 : #if !defined(AE_NO_EXCEPTIONS)
8174 0 : void polynomialfitwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, barycentricinterpolant &p, polynomialfitreport &rep, const xparams _xparams)
8175 : {
8176 : jmp_buf _break_jump;
8177 : alglib_impl::ae_state _alglib_env_state;
8178 : ae_int_t n;
8179 : ae_int_t k;
8180 0 : if( (x.length()!=y.length()) || (x.length()!=w.length()))
8181 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
8182 0 : if( (xc.length()!=yc.length()) || (xc.length()!=dc.length()))
8183 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
8184 0 : n = x.length();
8185 0 : k = xc.length();
8186 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8187 0 : if( setjmp(_break_jump) )
8188 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8189 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8190 0 : if( _xparams.flags!=0x0 )
8191 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8192 0 : alglib_impl::polynomialfitwc(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(xc.c_ptr()), const_cast<alglib_impl::ae_vector*>(yc.c_ptr()), const_cast<alglib_impl::ae_vector*>(dc.c_ptr()), k, m, &info, const_cast<alglib_impl::barycentricinterpolant*>(p.c_ptr()), const_cast<alglib_impl::polynomialfitreport*>(rep.c_ptr()), &_alglib_env_state);
8193 :
8194 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8195 0 : return;
8196 : }
8197 : #endif
8198 :
8199 : /*************************************************************************
8200 : This function calculates value of four-parameter logistic (4PL) model at
8201 : specified point X. 4PL model has following form:
8202 :
8203 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B))
8204 :
8205 : INPUT PARAMETERS:
8206 : X - current point, X>=0:
8207 : * zero X is correctly handled even for B<=0
8208 : * negative X results in exception.
8209 : A, B, C, D- parameters of 4PL model:
8210 : * A is unconstrained
8211 : * B is unconstrained; zero or negative values are handled
8212 : correctly.
8213 : * C>0, non-positive value results in exception
8214 : * D is unconstrained
8215 :
8216 : RESULT:
8217 : model value at X
8218 :
8219 : NOTE: if B=0, denominator is assumed to be equal to 2.0 even for zero X
8220 : (strictly speaking, 0^0 is undefined).
8221 :
8222 : NOTE: this function also throws exception if all input parameters are
8223 : correct, but overflow was detected during calculations.
8224 :
8225 : NOTE: this function performs a lot of checks; if you need really high
8226 : performance, consider evaluating model yourself, without checking
8227 : for degenerate cases.
8228 :
8229 :
8230 : -- ALGLIB PROJECT --
8231 : Copyright 14.05.2014 by Bochkanov Sergey
8232 : *************************************************************************/
8233 0 : double logisticcalc4(const double x, const double a, const double b, const double c, const double d, const xparams _xparams)
8234 : {
8235 : jmp_buf _break_jump;
8236 : alglib_impl::ae_state _alglib_env_state;
8237 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8238 0 : if( setjmp(_break_jump) )
8239 : {
8240 : #if !defined(AE_NO_EXCEPTIONS)
8241 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8242 : #else
8243 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8244 : return 0;
8245 : #endif
8246 : }
8247 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8248 0 : if( _xparams.flags!=0x0 )
8249 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8250 0 : double result = alglib_impl::logisticcalc4(x, a, b, c, d, &_alglib_env_state);
8251 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8252 0 : return *(reinterpret_cast<double*>(&result));
8253 : }
8254 :
8255 : /*************************************************************************
8256 : This function calculates value of five-parameter logistic (5PL) model at
8257 : specified point X. 5PL model has following form:
8258 :
8259 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G)
8260 :
8261 : INPUT PARAMETERS:
8262 : X - current point, X>=0:
8263 : * zero X is correctly handled even for B<=0
8264 : * negative X results in exception.
8265 : A, B, C, D, G- parameters of 5PL model:
8266 : * A is unconstrained
8267 : * B is unconstrained; zero or negative values are handled
8268 : correctly.
8269 : * C>0, non-positive value results in exception
8270 : * D is unconstrained
8271 : * G>0, non-positive value results in exception
8272 :
8273 : RESULT:
8274 : model value at X
8275 :
8276 : NOTE: if B=0, denominator is assumed to be equal to Power(2.0,G) even for
8277 : zero X (strictly speaking, 0^0 is undefined).
8278 :
8279 : NOTE: this function also throws exception if all input parameters are
8280 : correct, but overflow was detected during calculations.
8281 :
8282 : NOTE: this function performs a lot of checks; if you need really high
8283 : performance, consider evaluating model yourself, without checking
8284 : for degenerate cases.
8285 :
8286 :
8287 : -- ALGLIB PROJECT --
8288 : Copyright 14.05.2014 by Bochkanov Sergey
8289 : *************************************************************************/
8290 0 : double logisticcalc5(const double x, const double a, const double b, const double c, const double d, const double g, const xparams _xparams)
8291 : {
8292 : jmp_buf _break_jump;
8293 : alglib_impl::ae_state _alglib_env_state;
8294 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8295 0 : if( setjmp(_break_jump) )
8296 : {
8297 : #if !defined(AE_NO_EXCEPTIONS)
8298 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8299 : #else
8300 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8301 : return 0;
8302 : #endif
8303 : }
8304 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8305 0 : if( _xparams.flags!=0x0 )
8306 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8307 0 : double result = alglib_impl::logisticcalc5(x, a, b, c, d, g, &_alglib_env_state);
8308 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8309 0 : return *(reinterpret_cast<double*>(&result));
8310 : }
8311 :
8312 : /*************************************************************************
8313 : This function fits four-parameter logistic (4PL) model to data provided
8314 : by user. 4PL model has following form:
8315 :
8316 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B))
8317 :
8318 : Here:
8319 : * A, D - unconstrained (see LogisticFit4EC() for constrained 4PL)
8320 : * B>=0
8321 : * C>0
8322 :
8323 : IMPORTANT: output of this function is constrained in such way that B>0.
8324 : Because 4PL model is symmetric with respect to B, there is no
8325 : need to explore B<0. Constraining B makes algorithm easier
8326 : to stabilize and debug.
8327 : Users who for some reason prefer to work with negative B's
8328 : should transform output themselves (swap A and D, replace B by
8329 : -B).
8330 :
8331 : 4PL fitting is implemented as follows:
8332 : * we perform small number of restarts from random locations which helps to
8333 : solve problem of bad local extrema. Locations are only partially random
8334 : - we use input data to determine good initial guess, but we include
8335 : controlled amount of randomness.
8336 : * we perform Levenberg-Marquardt fitting with very tight constraints on
8337 : parameters B and C - it allows us to find good initial guess for the
8338 : second stage without risk of running into "flat spot".
8339 : * second Levenberg-Marquardt round is performed without excessive
8340 : constraints. Results from the previous round are used as initial guess.
8341 : * after fitting is done, we compare results with best values found so far,
8342 : rewrite "best solution" if needed, and move to next random location.
8343 :
8344 : Overall algorithm is very stable and is not prone to bad local extrema.
8345 : Furthermore, it automatically scales when input data have very large or
8346 : very small range.
8347 :
8348 : INPUT PARAMETERS:
8349 : X - array[N], stores X-values.
8350 : MUST include only non-negative numbers (but may include
8351 : zero values). Can be unsorted.
8352 : Y - array[N], values to fit.
8353 : N - number of points. If N is less than length of X/Y, only
8354 : leading N elements are used.
8355 :
8356 : OUTPUT PARAMETERS:
8357 : A, B, C, D- parameters of 4PL model
8358 : Rep - fitting report. This structure has many fields, but ONLY
8359 : ONES LISTED BELOW ARE SET:
8360 : * Rep.IterationsCount - number of iterations performed
8361 : * Rep.RMSError - root-mean-square error
8362 : * Rep.AvgError - average absolute error
8363 : * Rep.AvgRelError - average relative error (calculated for
8364 : non-zero Y-values)
8365 : * Rep.MaxError - maximum absolute error
8366 : * Rep.R2 - coefficient of determination, R-squared. This
8367 : coefficient is calculated as R2=1-RSS/TSS (in case
8368 : of nonlinear regression there are multiple ways to
8369 : define R2, each of them giving different results).
8370 :
8371 : NOTE: for stability reasons the B parameter is restricted by [1/1000,1000]
8372 : range. It prevents algorithm from making trial steps deep into the
8373 : area of bad parameters.
8374 :
8375 : NOTE: after you obtained coefficients, you can evaluate model with
8376 : LogisticCalc4() function.
8377 :
8378 : NOTE: if you need better control over fitting process than provided by this
8379 : function, you may use LogisticFit45X().
8380 :
8381 : NOTE: step is automatically scaled according to scale of parameters being
8382 : fitted before we compare its length with EpsX. Thus, this function
8383 : can be used to fit data with very small or very large values without
8384 : changing EpsX.
8385 :
8386 :
8387 : -- ALGLIB PROJECT --
8388 : Copyright 14.02.2014 by Bochkanov Sergey
8389 : *************************************************************************/
8390 0 : void logisticfit4(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, double &a, double &b, double &c, double &d, lsfitreport &rep, const xparams _xparams)
8391 : {
8392 : jmp_buf _break_jump;
8393 : alglib_impl::ae_state _alglib_env_state;
8394 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8395 0 : if( setjmp(_break_jump) )
8396 : {
8397 : #if !defined(AE_NO_EXCEPTIONS)
8398 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8399 : #else
8400 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8401 : return;
8402 : #endif
8403 : }
8404 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8405 0 : if( _xparams.flags!=0x0 )
8406 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8407 0 : alglib_impl::logisticfit4(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, &a, &b, &c, &d, const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
8408 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8409 0 : return;
8410 : }
8411 :
8412 : /*************************************************************************
8413 : This function fits four-parameter logistic (4PL) model to data provided
8414 : by user, with optional constraints on parameters A and D. 4PL model has
8415 : following form:
8416 :
8417 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B))
8418 :
8419 : Here:
8420 : * A, D - with optional equality constraints
8421 : * B>=0
8422 : * C>0
8423 :
8424 : IMPORTANT: output of this function is constrained in such way that B>0.
8425 : Because 4PL model is symmetric with respect to B, there is no
8426 : need to explore B<0. Constraining B makes algorithm easier
8427 : to stabilize and debug.
8428 : Users who for some reason prefer to work with negative B's
8429 : should transform output themselves (swap A and D, replace B by
8430 : -B).
8431 :
8432 : 4PL fitting is implemented as follows:
8433 : * we perform small number of restarts from random locations which helps to
8434 : solve problem of bad local extrema. Locations are only partially random
8435 : - we use input data to determine good initial guess, but we include
8436 : controlled amount of randomness.
8437 : * we perform Levenberg-Marquardt fitting with very tight constraints on
8438 : parameters B and C - it allows us to find good initial guess for the
8439 : second stage without risk of running into "flat spot".
8440 : * second Levenberg-Marquardt round is performed without excessive
8441 : constraints. Results from the previous round are used as initial guess.
8442 : * after fitting is done, we compare results with best values found so far,
8443 : rewrite "best solution" if needed, and move to next random location.
8444 :
8445 : Overall algorithm is very stable and is not prone to bad local extrema.
8446 : Furthermore, it automatically scales when input data have very large or
8447 : very small range.
8448 :
8449 : INPUT PARAMETERS:
8450 : X - array[N], stores X-values.
8451 : MUST include only non-negative numbers (but may include
8452 : zero values). Can be unsorted.
8453 : Y - array[N], values to fit.
8454 : N - number of points. If N is less than length of X/Y, only
8455 : leading N elements are used.
8456 : CnstrLeft- optional equality constraint for model value at the left
8457 : boundary (at X=0). Specify NAN (Not-a-Number) if you do
8458 : not need constraint on the model value at X=0 (in C++ you
8459 : can pass alglib::fp_nan as parameter, in C# it will be
8460 : Double.NaN).
8461 : See below, section "EQUALITY CONSTRAINTS" for more
8462 : information about constraints.
8463 : CnstrRight- optional equality constraint for model value at X=infinity.
8464 : Specify NAN (Not-a-Number) if you do not need constraint
8465 : on the model value (in C++ you can pass alglib::fp_nan as
8466 : parameter, in C# it will be Double.NaN).
8467 : See below, section "EQUALITY CONSTRAINTS" for more
8468 : information about constraints.
8469 :
8470 : OUTPUT PARAMETERS:
8471 : A, B, C, D- parameters of 4PL model
8472 : Rep - fitting report. This structure has many fields, but ONLY
8473 : ONES LISTED BELOW ARE SET:
8474 : * Rep.IterationsCount - number of iterations performed
8475 : * Rep.RMSError - root-mean-square error
8476 : * Rep.AvgError - average absolute error
8477 : * Rep.AvgRelError - average relative error (calculated for
8478 : non-zero Y-values)
8479 : * Rep.MaxError - maximum absolute error
8480 : * Rep.R2 - coefficient of determination, R-squared. This
8481 : coefficient is calculated as R2=1-RSS/TSS (in case
8482 : of nonlinear regression there are multiple ways to
8483 : define R2, each of them giving different results).
8484 :
8485 : NOTE: for stability reasons the B parameter is restricted by [1/1000,1000]
8486 : range. It prevents algorithm from making trial steps deep into the
8487 : area of bad parameters.
8488 :
8489 : NOTE: after you obtained coefficients, you can evaluate model with
8490 : LogisticCalc4() function.
8491 :
8492 : NOTE: if you need better control over fitting process than provided by this
8493 : function, you may use LogisticFit45X().
8494 :
8495 : NOTE: step is automatically scaled according to scale of parameters being
8496 : fitted before we compare its length with EpsX. Thus, this function
8497 : can be used to fit data with very small or very large values without
8498 : changing EpsX.
8499 :
8500 : EQUALITY CONSTRAINTS ON PARAMETERS
8501 :
8502 : 4PL/5PL solver supports equality constraints on model values at the left
8503 : boundary (X=0) and right boundary (X=infinity). These constraints are
8504 : completely optional and you can specify both of them, only one - or no
8505 : constraints at all.
8506 :
8507 : Parameter CnstrLeft contains left constraint (or NAN for unconstrained
8508 : fitting), and CnstrRight contains right one. For 4PL, left constraint
8509 : ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on
8510 : D. That's because 4PL model is normalized in such way that B>=0.
8511 :
8512 :
8513 : -- ALGLIB PROJECT --
8514 : Copyright 14.02.2014 by Bochkanov Sergey
8515 : *************************************************************************/
8516 0 : void logisticfit4ec(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, double &a, double &b, double &c, double &d, lsfitreport &rep, const xparams _xparams)
8517 : {
8518 : jmp_buf _break_jump;
8519 : alglib_impl::ae_state _alglib_env_state;
8520 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8521 0 : if( setjmp(_break_jump) )
8522 : {
8523 : #if !defined(AE_NO_EXCEPTIONS)
8524 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8525 : #else
8526 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8527 : return;
8528 : #endif
8529 : }
8530 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8531 0 : if( _xparams.flags!=0x0 )
8532 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8533 0 : alglib_impl::logisticfit4ec(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, cnstrleft, cnstrright, &a, &b, &c, &d, const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
8534 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8535 0 : return;
8536 : }
8537 :
8538 : /*************************************************************************
8539 : This function fits five-parameter logistic (5PL) model to data provided
8540 : by user. 5PL model has following form:
8541 :
8542 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G)
8543 :
8544 : Here:
8545 : * A, D - unconstrained
8546 : * B - unconstrained
8547 : * C>0
8548 : * G>0
8549 :
8550 : IMPORTANT: unlike in 4PL fitting, output of this function is NOT
8551 : constrained in such way that B is guaranteed to be positive.
8552 : Furthermore, unlike 4PL, 5PL model is NOT symmetric with
8553 : respect to B, so you can NOT transform model to equivalent one,
8554 : with B having desired sign (>0 or <0).
8555 :
8556 : 5PL fitting is implemented as follows:
8557 : * we perform small number of restarts from random locations which helps to
8558 : solve problem of bad local extrema. Locations are only partially random
8559 : - we use input data to determine good initial guess, but we include
8560 : controlled amount of randomness.
8561 : * we perform Levenberg-Marquardt fitting with very tight constraints on
8562 : parameters B and C - it allows us to find good initial guess for the
8563 : second stage without risk of running into "flat spot". Parameter G is
8564 : fixed at G=1.
8565 : * second Levenberg-Marquardt round is performed without excessive
8566 : constraints on B and C, but with G still equal to 1. Results from the
8567 : previous round are used as initial guess.
8568 : * third Levenberg-Marquardt round relaxes constraints on G and tries two
8569 : different models - one with B>0 and one with B<0.
8570 : * after fitting is done, we compare results with best values found so far,
8571 : rewrite "best solution" if needed, and move to next random location.
8572 :
8573 : Overall algorithm is very stable and is not prone to bad local extrema.
8574 : Furthermore, it automatically scales when input data have very large or
8575 : very small range.
8576 :
8577 : INPUT PARAMETERS:
8578 : X - array[N], stores X-values.
8579 : MUST include only non-negative numbers (but may include
8580 : zero values). Can be unsorted.
8581 : Y - array[N], values to fit.
8582 : N - number of points. If N is less than length of X/Y, only
8583 : leading N elements are used.
8584 :
8585 : OUTPUT PARAMETERS:
8586 : A,B,C,D,G- parameters of 5PL model
8587 : Rep - fitting report. This structure has many fields, but ONLY
8588 : ONES LISTED BELOW ARE SET:
8589 : * Rep.IterationsCount - number of iterations performed
8590 : * Rep.RMSError - root-mean-square error
8591 : * Rep.AvgError - average absolute error
8592 : * Rep.AvgRelError - average relative error (calculated for
8593 : non-zero Y-values)
8594 : * Rep.MaxError - maximum absolute error
8595 : * Rep.R2 - coefficient of determination, R-squared. This
8596 : coefficient is calculated as R2=1-RSS/TSS (in case
8597 : of nonlinear regression there are multiple ways to
8598 : define R2, each of them giving different results).
8599 :
8600 : NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000]
8601 : range, and G is restricted by [1/10,10] range. It prevents algorithm
8602 : from making trial steps deep into the area of bad parameters.
8603 :
8604 : NOTE: after you obtained coefficients, you can evaluate model with
8605 : LogisticCalc5() function.
8606 :
8607 : NOTE: if you need better control over fitting process than provided by this
8608 : function, you may use LogisticFit45X().
8609 :
8610 : NOTE: step is automatically scaled according to scale of parameters being
8611 : fitted before we compare its length with EpsX. Thus, this function
8612 : can be used to fit data with very small or very large values without
8613 : changing EpsX.
8614 :
8615 :
8616 : -- ALGLIB PROJECT --
8617 : Copyright 14.02.2014 by Bochkanov Sergey
8618 : *************************************************************************/
8619 0 : void logisticfit5(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams)
8620 : {
8621 : jmp_buf _break_jump;
8622 : alglib_impl::ae_state _alglib_env_state;
8623 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8624 0 : if( setjmp(_break_jump) )
8625 : {
8626 : #if !defined(AE_NO_EXCEPTIONS)
8627 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8628 : #else
8629 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8630 : return;
8631 : #endif
8632 : }
8633 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8634 0 : if( _xparams.flags!=0x0 )
8635 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8636 0 : alglib_impl::logisticfit5(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, &a, &b, &c, &d, &g, const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
8637 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8638 0 : return;
8639 : }
8640 :
8641 : /*************************************************************************
8642 : This function fits five-parameter logistic (5PL) model to data provided
8643 : by user, subject to optional equality constraints on parameters A and D.
8644 : 5PL model has following form:
8645 :
8646 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G)
8647 :
8648 : Here:
8649 : * A, D - with optional equality constraints
8650 : * B - unconstrained
8651 : * C>0
8652 : * G>0
8653 :
8654 : IMPORTANT: unlike in 4PL fitting, output of this function is NOT
8655 : constrained in such way that B is guaranteed to be positive.
8656 : Furthermore, unlike 4PL, 5PL model is NOT symmetric with
8657 : respect to B, so you can NOT transform model to equivalent one,
8658 : with B having desired sign (>0 or <0).
8659 :
8660 : 5PL fitting is implemented as follows:
8661 : * we perform small number of restarts from random locations which helps to
8662 : solve problem of bad local extrema. Locations are only partially random
8663 : - we use input data to determine good initial guess, but we include
8664 : controlled amount of randomness.
8665 : * we perform Levenberg-Marquardt fitting with very tight constraints on
8666 : parameters B and C - it allows us to find good initial guess for the
8667 : second stage without risk of running into "flat spot". Parameter G is
8668 : fixed at G=1.
8669 : * second Levenberg-Marquardt round is performed without excessive
8670 : constraints on B and C, but with G still equal to 1. Results from the
8671 : previous round are used as initial guess.
8672 : * third Levenberg-Marquardt round relaxes constraints on G and tries two
8673 : different models - one with B>0 and one with B<0.
8674 : * after fitting is done, we compare results with best values found so far,
8675 : rewrite "best solution" if needed, and move to next random location.
8676 :
8677 : Overall algorithm is very stable and is not prone to bad local extrema.
8678 : Furthermore, it automatically scales when input data have very large or
8679 : very small range.
8680 :
8681 : INPUT PARAMETERS:
8682 : X - array[N], stores X-values.
8683 : MUST include only non-negative numbers (but may include
8684 : zero values). Can be unsorted.
8685 : Y - array[N], values to fit.
8686 : N - number of points. If N is less than length of X/Y, only
8687 : leading N elements are used.
8688 : CnstrLeft- optional equality constraint for model value at the left
8689 : boundary (at X=0). Specify NAN (Not-a-Number) if you do
8690 : not need constraint on the model value at X=0 (in C++ you
8691 : can pass alglib::fp_nan as parameter, in C# it will be
8692 : Double.NaN).
8693 : See below, section "EQUALITY CONSTRAINTS" for more
8694 : information about constraints.
8695 : CnstrRight- optional equality constraint for model value at X=infinity.
8696 : Specify NAN (Not-a-Number) if you do not need constraint
8697 : on the model value (in C++ you can pass alglib::fp_nan as
8698 : parameter, in C# it will be Double.NaN).
8699 : See below, section "EQUALITY CONSTRAINTS" for more
8700 : information about constraints.
8701 :
8702 : OUTPUT PARAMETERS:
8703 : A,B,C,D,G- parameters of 5PL model
8704 : Rep - fitting report. This structure has many fields, but ONLY
8705 : ONES LISTED BELOW ARE SET:
8706 : * Rep.IterationsCount - number of iterations performed
8707 : * Rep.RMSError - root-mean-square error
8708 : * Rep.AvgError - average absolute error
8709 : * Rep.AvgRelError - average relative error (calculated for
8710 : non-zero Y-values)
8711 : * Rep.MaxError - maximum absolute error
8712 : * Rep.R2 - coefficient of determination, R-squared. This
8713 : coefficient is calculated as R2=1-RSS/TSS (in case
8714 : of nonlinear regression there are multiple ways to
8715 : define R2, each of them giving different results).
8716 :
8717 : NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000]
8718 : range, and G is restricted by [1/10,10] range. It prevents algorithm
8719 : from making trial steps deep into the area of bad parameters.
8720 :
8721 : NOTE: after you obtained coefficients, you can evaluate model with
8722 : LogisticCalc5() function.
8723 :
8724 : NOTE: if you need better control over fitting process than provided by this
8725 : function, you may use LogisticFit45X().
8726 :
8727 : NOTE: step is automatically scaled according to scale of parameters being
8728 : fitted before we compare its length with EpsX. Thus, this function
8729 : can be used to fit data with very small or very large values without
8730 : changing EpsX.
8731 :
8732 : EQUALITY CONSTRAINTS ON PARAMETERS
8733 :
8734 : 5PL solver supports equality constraints on model values at the left
8735 : boundary (X=0) and right boundary (X=infinity). These constraints are
8736 : completely optional and you can specify both of them, only one - or no
8737 : constraints at all.
8738 :
8739 : Parameter CnstrLeft contains left constraint (or NAN for unconstrained
8740 : fitting), and CnstrRight contains right one.
8741 :
8742 : Unlike 4PL one, 5PL model is NOT symmetric with respect to change in sign
8743 : of B. Thus, negative B's are possible, and left constraint may constrain
8744 : parameter A (for positive B's) - or parameter D (for negative B's).
8745 : Similarly changes meaning of right constraint.
8746 :
8747 : You do not have to decide what parameter to constrain - algorithm will
8748 : automatically determine correct parameters as fitting progresses. However,
8749 : question highlighted above is important when you interpret fitting results.
8750 :
8751 :
8752 : -- ALGLIB PROJECT --
8753 : Copyright 14.02.2014 by Bochkanov Sergey
8754 : *************************************************************************/
8755 0 : void logisticfit5ec(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams)
8756 : {
8757 : jmp_buf _break_jump;
8758 : alglib_impl::ae_state _alglib_env_state;
8759 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8760 0 : if( setjmp(_break_jump) )
8761 : {
8762 : #if !defined(AE_NO_EXCEPTIONS)
8763 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8764 : #else
8765 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8766 : return;
8767 : #endif
8768 : }
8769 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8770 0 : if( _xparams.flags!=0x0 )
8771 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8772 0 : alglib_impl::logisticfit5ec(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, cnstrleft, cnstrright, &a, &b, &c, &d, &g, const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
8773 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8774 0 : return;
8775 : }
8776 :
8777 : /*************************************************************************
8778 : This is "expert" 4PL/5PL fitting function, which can be used if you need
8779 : better control over fitting process than provided by LogisticFit4() or
8780 : LogisticFit5().
8781 :
8782 : This function fits model of the form
8783 :
8784 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) (4PL model)
8785 :
8786 : or
8787 :
8788 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) (5PL model)
8789 :
8790 : Here:
8791 : * A, D - unconstrained
8792 : * B>=0 for 4PL, unconstrained for 5PL
8793 : * C>0
8794 : * G>0 (if present)
8795 :
8796 : INPUT PARAMETERS:
8797 : X - array[N], stores X-values.
8798 : MUST include only non-negative numbers (but may include
8799 : zero values). Can be unsorted.
8800 : Y - array[N], values to fit.
8801 : N - number of points. If N is less than length of X/Y, only
8802 : leading N elements are used.
8803 : CnstrLeft- optional equality constraint for model value at the left
8804 : boundary (at X=0). Specify NAN (Not-a-Number) if you do
8805 : not need constraint on the model value at X=0 (in C++ you
8806 : can pass alglib::fp_nan as parameter, in C# it will be
8807 : Double.NaN).
8808 : See below, section "EQUALITY CONSTRAINTS" for more
8809 : information about constraints.
8810 : CnstrRight- optional equality constraint for model value at X=infinity.
8811 : Specify NAN (Not-a-Number) if you do not need constraint
8812 : on the model value (in C++ you can pass alglib::fp_nan as
8813 : parameter, in C# it will be Double.NaN).
8814 : See below, section "EQUALITY CONSTRAINTS" for more
8815 : information about constraints.
8816 : Is4PL - whether 4PL or 5PL models are fitted
8817 : LambdaV - regularization coefficient, LambdaV>=0.
8818 : Set it to zero unless you know what you are doing.
8819 : EpsX - stopping condition (step size), EpsX>=0.
8820 : Zero value means that small step is automatically chosen.
8821 : See notes below for more information.
8822 : RsCnt - number of repeated restarts from random points. 4PL/5PL
8823 : models are prone to problem of bad local extrema. Utilizing
8824 : multiple random restarts allows us to improve algorithm
8825 : convergence.
8826 : RsCnt>=0.
8827 : Zero value means that function automatically choose small
8828 : amount of restarts (recommended).
8829 :
8830 : OUTPUT PARAMETERS:
8831 : A, B, C, D- parameters of 4PL model
8832 : G - parameter of 5PL model; for Is4PL=True, G=1 is returned.
8833 : Rep - fitting report. This structure has many fields, but ONLY
8834 : ONES LISTED BELOW ARE SET:
8835 : * Rep.IterationsCount - number of iterations performed
8836 : * Rep.RMSError - root-mean-square error
8837 : * Rep.AvgError - average absolute error
8838 : * Rep.AvgRelError - average relative error (calculated for
8839 : non-zero Y-values)
8840 : * Rep.MaxError - maximum absolute error
8841 : * Rep.R2 - coefficient of determination, R-squared. This
8842 : coefficient is calculated as R2=1-RSS/TSS (in case
8843 : of nonlinear regression there are multiple ways to
8844 : define R2, each of them giving different results).
8845 :
8846 : NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000]
8847 : range, and G is restricted by [1/10,10] range. It prevents algorithm
8848 : from making trial steps deep into the area of bad parameters.
8849 :
8850 : NOTE: after you obtained coefficients, you can evaluate model with
8851 : LogisticCalc5() function.
8852 :
8853 : NOTE: step is automatically scaled according to scale of parameters being
8854 : fitted before we compare its length with EpsX. Thus, this function
8855 : can be used to fit data with very small or very large values without
8856 : changing EpsX.
8857 :
8858 : EQUALITY CONSTRAINTS ON PARAMETERS
8859 :
8860 : 4PL/5PL solver supports equality constraints on model values at the left
8861 : boundary (X=0) and right boundary (X=infinity). These constraints are
8862 : completely optional and you can specify both of them, only one - or no
8863 : constraints at all.
8864 :
8865 : Parameter CnstrLeft contains left constraint (or NAN for unconstrained
8866 : fitting), and CnstrRight contains right one. For 4PL, left constraint
8867 : ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on
8868 : D. That's because 4PL model is normalized in such way that B>=0.
8869 :
8870 : For 5PL model things are different. Unlike 4PL one, 5PL model is NOT
8871 : symmetric with respect to change in sign of B. Thus, negative B's are
8872 : possible, and left constraint may constrain parameter A (for positive B's)
8873 : - or parameter D (for negative B's). Similarly changes meaning of right
8874 : constraint.
8875 :
8876 : You do not have to decide what parameter to constrain - algorithm will
8877 : automatically determine correct parameters as fitting progresses. However,
8878 : question highlighted above is important when you interpret fitting results.
8879 :
8880 :
8881 : -- ALGLIB PROJECT --
8882 : Copyright 14.02.2014 by Bochkanov Sergey
8883 : *************************************************************************/
8884 0 : void logisticfit45x(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const double cnstrleft, const double cnstrright, const bool is4pl, const double lambdav, const double epsx, const ae_int_t rscnt, double &a, double &b, double &c, double &d, double &g, lsfitreport &rep, const xparams _xparams)
8885 : {
8886 : jmp_buf _break_jump;
8887 : alglib_impl::ae_state _alglib_env_state;
8888 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8889 0 : if( setjmp(_break_jump) )
8890 : {
8891 : #if !defined(AE_NO_EXCEPTIONS)
8892 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8893 : #else
8894 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8895 : return;
8896 : #endif
8897 : }
8898 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8899 0 : if( _xparams.flags!=0x0 )
8900 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8901 0 : alglib_impl::logisticfit45x(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, cnstrleft, cnstrright, is4pl, lambdav, epsx, rscnt, &a, &b, &c, &d, &g, const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
8902 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8903 0 : return;
8904 : }
8905 :
8906 : /*************************************************************************
8907 : Weghted rational least squares fitting using Floater-Hormann rational
8908 : functions with optimal D chosen from [0,9], with constraints and
8909 : individual weights.
8910 :
8911 : Equidistant grid with M node on [min(x),max(x)] is used to build basis
8912 : functions. Different values of D are tried, optimal D (least WEIGHTED root
8913 : mean square error) is chosen. Task is linear, so linear least squares
8914 : solver is used. Complexity of this computational scheme is O(N*M^2)
8915 : (mostly dominated by the least squares solver).
8916 :
8917 : SEE ALSO
8918 : * BarycentricFitFloaterHormann(), "lightweight" fitting without invididual
8919 : weights and constraints.
8920 :
8921 : ! COMMERCIAL EDITION OF ALGLIB:
8922 : !
8923 : ! Commercial Edition of ALGLIB includes following important improvements
8924 : ! of this function:
8925 : ! * high-performance native backend with same C# interface (C# version)
8926 : ! * multithreading support (C++ and C# versions)
8927 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8928 : ! (C++ and C# versions, x86/x64 platform)
8929 : !
8930 : ! We recommend you to read 'Working with commercial version' section of
8931 : ! ALGLIB Reference Manual in order to find out how to use performance-
8932 : ! related features provided by commercial edition of ALGLIB.
8933 :
8934 : INPUT PARAMETERS:
8935 : X - points, array[0..N-1].
8936 : Y - function values, array[0..N-1].
8937 : W - weights, array[0..N-1]
8938 : Each summand in square sum of approximation deviations from
8939 : given values is multiplied by the square of corresponding
8940 : weight. Fill it by 1's if you don't want to solve weighted
8941 : task.
8942 : N - number of points, N>0.
8943 : XC - points where function values/derivatives are constrained,
8944 : array[0..K-1].
8945 : YC - values of constraints, array[0..K-1]
8946 : DC - array[0..K-1], types of constraints:
8947 : * DC[i]=0 means that S(XC[i])=YC[i]
8948 : * DC[i]=1 means that S'(XC[i])=YC[i]
8949 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
8950 : K - number of constraints, 0<=K<M.
8951 : K=0 means no constraints (XC/YC/DC are not used in such cases)
8952 : M - number of basis functions ( = number_of_nodes), M>=2.
8953 :
8954 : OUTPUT PARAMETERS:
8955 : Info- same format as in LSFitLinearWC() subroutine.
8956 : * Info>0 task is solved
8957 : * Info<=0 an error occured:
8958 : -4 means inconvergence of internal SVD
8959 : -3 means inconsistent constraints
8960 : -1 means another errors in parameters passed
8961 : (N<=0, for example)
8962 : B - barycentric interpolant.
8963 : Rep - report, same format as in LSFitLinearWC() subroutine.
8964 : Following fields are set:
8965 : * DBest best value of the D parameter
8966 : * RMSError rms error on the (X,Y).
8967 : * AvgError average error on the (X,Y).
8968 : * AvgRelError average relative error on the non-zero Y
8969 : * MaxError maximum error
8970 : NON-WEIGHTED ERRORS ARE CALCULATED
8971 :
8972 : IMPORTANT:
8973 : this subroutine doesn't calculate task's condition number for K<>0.
8974 :
8975 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
8976 :
8977 : Setting constraints can lead to undesired results, like ill-conditioned
8978 : behavior, or inconsistency being detected. From the other side, it allows
8979 : us to improve quality of the fit. Here we summarize our experience with
8980 : constrained barycentric interpolants:
8981 : * excessive constraints can be inconsistent. Floater-Hormann basis
8982 : functions aren't as flexible as splines (although they are very smooth).
8983 : * the more evenly constraints are spread across [min(x),max(x)], the more
8984 : chances that they will be consistent
8985 : * the greater is M (given fixed constraints), the more chances that
8986 : constraints will be consistent
8987 : * in the general case, consistency of constraints IS NOT GUARANTEED.
8988 : * in the several special cases, however, we CAN guarantee consistency.
8989 : * one of this cases is constraints on the function VALUES at the interval
8990 : boundaries. Note that consustency of the constraints on the function
8991 : DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines
8992 : which are more flexible).
8993 : * another special case is ONE constraint on the function value (OR, but
8994 : not AND, derivative) anywhere in the interval
8995 :
8996 : Our final recommendation is to use constraints WHEN AND ONLY WHEN you
8997 : can't solve your task without them. Anything beyond special cases given
8998 : above is not guaranteed and may result in inconsistency.
8999 :
9000 : -- ALGLIB PROJECT --
9001 : Copyright 18.08.2009 by Bochkanov Sergey
9002 : *************************************************************************/
9003 0 : void barycentricfitfloaterhormannwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, barycentricinterpolant &b, barycentricfitreport &rep, const xparams _xparams)
9004 : {
9005 : jmp_buf _break_jump;
9006 : alglib_impl::ae_state _alglib_env_state;
9007 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9008 0 : if( setjmp(_break_jump) )
9009 : {
9010 : #if !defined(AE_NO_EXCEPTIONS)
9011 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9012 : #else
9013 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9014 : return;
9015 : #endif
9016 : }
9017 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9018 0 : if( _xparams.flags!=0x0 )
9019 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9020 0 : alglib_impl::barycentricfitfloaterhormannwc(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(xc.c_ptr()), const_cast<alglib_impl::ae_vector*>(yc.c_ptr()), const_cast<alglib_impl::ae_vector*>(dc.c_ptr()), k, m, &info, const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), const_cast<alglib_impl::barycentricfitreport*>(rep.c_ptr()), &_alglib_env_state);
9021 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9022 0 : return;
9023 : }
9024 :
9025 : /*************************************************************************
9026 : Rational least squares fitting using Floater-Hormann rational functions
9027 : with optimal D chosen from [0,9].
9028 :
9029 : Equidistant grid with M node on [min(x),max(x)] is used to build basis
9030 : functions. Different values of D are tried, optimal D (least root mean
9031 : square error) is chosen. Task is linear, so linear least squares solver
9032 : is used. Complexity of this computational scheme is O(N*M^2) (mostly
9033 : dominated by the least squares solver).
9034 :
9035 : ! COMMERCIAL EDITION OF ALGLIB:
9036 : !
9037 : ! Commercial Edition of ALGLIB includes following important improvements
9038 : ! of this function:
9039 : ! * high-performance native backend with same C# interface (C# version)
9040 : ! * multithreading support (C++ and C# versions)
9041 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9042 : ! (C++ and C# versions, x86/x64 platform)
9043 : !
9044 : ! We recommend you to read 'Working with commercial version' section of
9045 : ! ALGLIB Reference Manual in order to find out how to use performance-
9046 : ! related features provided by commercial edition of ALGLIB.
9047 :
9048 : INPUT PARAMETERS:
9049 : X - points, array[0..N-1].
9050 : Y - function values, array[0..N-1].
9051 : N - number of points, N>0.
9052 : M - number of basis functions ( = number_of_nodes), M>=2.
9053 :
9054 : OUTPUT PARAMETERS:
9055 : Info- same format as in LSFitLinearWC() subroutine.
9056 : * Info>0 task is solved
9057 : * Info<=0 an error occured:
9058 : -4 means inconvergence of internal SVD
9059 : -3 means inconsistent constraints
9060 : B - barycentric interpolant.
9061 : Rep - report, same format as in LSFitLinearWC() subroutine.
9062 : Following fields are set:
9063 : * DBest best value of the D parameter
9064 : * RMSError rms error on the (X,Y).
9065 : * AvgError average error on the (X,Y).
9066 : * AvgRelError average relative error on the non-zero Y
9067 : * MaxError maximum error
9068 : NON-WEIGHTED ERRORS ARE CALCULATED
9069 :
9070 : -- ALGLIB PROJECT --
9071 : Copyright 18.08.2009 by Bochkanov Sergey
9072 : *************************************************************************/
9073 0 : void barycentricfitfloaterhormann(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, barycentricinterpolant &b, barycentricfitreport &rep, const xparams _xparams)
9074 : {
9075 : jmp_buf _break_jump;
9076 : alglib_impl::ae_state _alglib_env_state;
9077 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9078 0 : if( setjmp(_break_jump) )
9079 : {
9080 : #if !defined(AE_NO_EXCEPTIONS)
9081 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9082 : #else
9083 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9084 : return;
9085 : #endif
9086 : }
9087 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9088 0 : if( _xparams.flags!=0x0 )
9089 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9090 0 : alglib_impl::barycentricfitfloaterhormann(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, &info, const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), const_cast<alglib_impl::barycentricfitreport*>(rep.c_ptr()), &_alglib_env_state);
9091 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9092 0 : return;
9093 : }
9094 :
9095 : /*************************************************************************
9096 : Weighted fitting by cubic spline, with constraints on function values or
9097 : derivatives.
9098 :
9099 : Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build
9100 : basis functions. Basis functions are cubic splines with continuous second
9101 : derivatives and non-fixed first derivatives at interval ends. Small
9102 : regularizing term is used when solving constrained tasks (to improve
9103 : stability).
9104 :
9105 : Task is linear, so linear least squares solver is used. Complexity of this
9106 : computational scheme is O(N*M^2), mostly dominated by least squares solver
9107 :
9108 : SEE ALSO
9109 : Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible,
9110 : less smooth)
9111 : Spline1DFitCubic() - "lightweight" fitting by cubic splines,
9112 : without invididual weights and constraints
9113 :
9114 : ! COMMERCIAL EDITION OF ALGLIB:
9115 : !
9116 : ! Commercial Edition of ALGLIB includes following important improvements
9117 : ! of this function:
9118 : ! * high-performance native backend with same C# interface (C# version)
9119 : ! * multithreading support (C++ and C# versions)
9120 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9121 : ! (C++ and C# versions, x86/x64 platform)
9122 : !
9123 : ! We recommend you to read 'Working with commercial version' section of
9124 : ! ALGLIB Reference Manual in order to find out how to use performance-
9125 : ! related features provided by commercial edition of ALGLIB.
9126 :
9127 : INPUT PARAMETERS:
9128 : X - points, array[0..N-1].
9129 : Y - function values, array[0..N-1].
9130 : W - weights, array[0..N-1]
9131 : Each summand in square sum of approximation deviations from
9132 : given values is multiplied by the square of corresponding
9133 : weight. Fill it by 1's if you don't want to solve weighted
9134 : task.
9135 : N - number of points (optional):
9136 : * N>0
9137 : * if given, only first N elements of X/Y/W are processed
9138 : * if not given, automatically determined from X/Y/W sizes
9139 : XC - points where spline values/derivatives are constrained,
9140 : array[0..K-1].
9141 : YC - values of constraints, array[0..K-1]
9142 : DC - array[0..K-1], types of constraints:
9143 : * DC[i]=0 means that S(XC[i])=YC[i]
9144 : * DC[i]=1 means that S'(XC[i])=YC[i]
9145 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
9146 : K - number of constraints (optional):
9147 : * 0<=K<M.
9148 : * K=0 means no constraints (XC/YC/DC are not used)
9149 : * if given, only first K elements of XC/YC/DC are used
9150 : * if not given, automatically determined from XC/YC/DC
9151 : M - number of basis functions ( = number_of_nodes+2), M>=4.
9152 :
9153 : OUTPUT PARAMETERS:
9154 : Info- same format as in LSFitLinearWC() subroutine.
9155 : * Info>0 task is solved
9156 : * Info<=0 an error occured:
9157 : -4 means inconvergence of internal SVD
9158 : -3 means inconsistent constraints
9159 : S - spline interpolant.
9160 : Rep - report, same format as in LSFitLinearWC() subroutine.
9161 : Following fields are set:
9162 : * RMSError rms error on the (X,Y).
9163 : * AvgError average error on the (X,Y).
9164 : * AvgRelError average relative error on the non-zero Y
9165 : * MaxError maximum error
9166 : NON-WEIGHTED ERRORS ARE CALCULATED
9167 :
9168 : IMPORTANT:
9169 : this subroitine doesn't calculate task's condition number for K<>0.
9170 :
9171 :
9172 : ORDER OF POINTS
9173 :
9174 : Subroutine automatically sorts points, so caller may pass unsorted array.
9175 :
9176 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
9177 :
9178 : Setting constraints can lead to undesired results, like ill-conditioned
9179 : behavior, or inconsistency being detected. From the other side, it allows
9180 : us to improve quality of the fit. Here we summarize our experience with
9181 : constrained regression splines:
9182 : * excessive constraints can be inconsistent. Splines are piecewise cubic
9183 : functions, and it is easy to create an example, where large number of
9184 : constraints concentrated in small area will result in inconsistency.
9185 : Just because spline is not flexible enough to satisfy all of them. And
9186 : same constraints spread across the [min(x),max(x)] will be perfectly
9187 : consistent.
9188 : * the more evenly constraints are spread across [min(x),max(x)], the more
9189 : chances that they will be consistent
9190 : * the greater is M (given fixed constraints), the more chances that
9191 : constraints will be consistent
9192 : * in the general case, consistency of constraints IS NOT GUARANTEED.
9193 : * in the several special cases, however, we CAN guarantee consistency.
9194 : * one of this cases is constraints on the function values AND/OR its
9195 : derivatives at the interval boundaries.
9196 : * another special case is ONE constraint on the function value (OR, but
9197 : not AND, derivative) anywhere in the interval
9198 :
9199 : Our final recommendation is to use constraints WHEN AND ONLY WHEN you
9200 : can't solve your task without them. Anything beyond special cases given
9201 : above is not guaranteed and may result in inconsistency.
9202 :
9203 :
9204 : -- ALGLIB PROJECT --
9205 : Copyright 18.08.2009 by Bochkanov Sergey
9206 : *************************************************************************/
9207 0 : void spline1dfitcubicwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9208 : {
9209 : jmp_buf _break_jump;
9210 : alglib_impl::ae_state _alglib_env_state;
9211 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9212 0 : if( setjmp(_break_jump) )
9213 : {
9214 : #if !defined(AE_NO_EXCEPTIONS)
9215 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9216 : #else
9217 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9218 : return;
9219 : #endif
9220 : }
9221 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9222 0 : if( _xparams.flags!=0x0 )
9223 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9224 0 : alglib_impl::spline1dfitcubicwc(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(xc.c_ptr()), const_cast<alglib_impl::ae_vector*>(yc.c_ptr()), const_cast<alglib_impl::ae_vector*>(dc.c_ptr()), k, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9225 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9226 0 : return;
9227 : }
9228 :
9229 : /*************************************************************************
9230 : Weighted fitting by cubic spline, with constraints on function values or
9231 : derivatives.
9232 :
9233 : Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build
9234 : basis functions. Basis functions are cubic splines with continuous second
9235 : derivatives and non-fixed first derivatives at interval ends. Small
9236 : regularizing term is used when solving constrained tasks (to improve
9237 : stability).
9238 :
9239 : Task is linear, so linear least squares solver is used. Complexity of this
9240 : computational scheme is O(N*M^2), mostly dominated by least squares solver
9241 :
9242 : SEE ALSO
9243 : Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible,
9244 : less smooth)
9245 : Spline1DFitCubic() - "lightweight" fitting by cubic splines,
9246 : without invididual weights and constraints
9247 :
9248 : ! COMMERCIAL EDITION OF ALGLIB:
9249 : !
9250 : ! Commercial Edition of ALGLIB includes following important improvements
9251 : ! of this function:
9252 : ! * high-performance native backend with same C# interface (C# version)
9253 : ! * multithreading support (C++ and C# versions)
9254 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9255 : ! (C++ and C# versions, x86/x64 platform)
9256 : !
9257 : ! We recommend you to read 'Working with commercial version' section of
9258 : ! ALGLIB Reference Manual in order to find out how to use performance-
9259 : ! related features provided by commercial edition of ALGLIB.
9260 :
9261 : INPUT PARAMETERS:
9262 : X - points, array[0..N-1].
9263 : Y - function values, array[0..N-1].
9264 : W - weights, array[0..N-1]
9265 : Each summand in square sum of approximation deviations from
9266 : given values is multiplied by the square of corresponding
9267 : weight. Fill it by 1's if you don't want to solve weighted
9268 : task.
9269 : N - number of points (optional):
9270 : * N>0
9271 : * if given, only first N elements of X/Y/W are processed
9272 : * if not given, automatically determined from X/Y/W sizes
9273 : XC - points where spline values/derivatives are constrained,
9274 : array[0..K-1].
9275 : YC - values of constraints, array[0..K-1]
9276 : DC - array[0..K-1], types of constraints:
9277 : * DC[i]=0 means that S(XC[i])=YC[i]
9278 : * DC[i]=1 means that S'(XC[i])=YC[i]
9279 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
9280 : K - number of constraints (optional):
9281 : * 0<=K<M.
9282 : * K=0 means no constraints (XC/YC/DC are not used)
9283 : * if given, only first K elements of XC/YC/DC are used
9284 : * if not given, automatically determined from XC/YC/DC
9285 : M - number of basis functions ( = number_of_nodes+2), M>=4.
9286 :
9287 : OUTPUT PARAMETERS:
9288 : Info- same format as in LSFitLinearWC() subroutine.
9289 : * Info>0 task is solved
9290 : * Info<=0 an error occured:
9291 : -4 means inconvergence of internal SVD
9292 : -3 means inconsistent constraints
9293 : S - spline interpolant.
9294 : Rep - report, same format as in LSFitLinearWC() subroutine.
9295 : Following fields are set:
9296 : * RMSError rms error on the (X,Y).
9297 : * AvgError average error on the (X,Y).
9298 : * AvgRelError average relative error on the non-zero Y
9299 : * MaxError maximum error
9300 : NON-WEIGHTED ERRORS ARE CALCULATED
9301 :
9302 : IMPORTANT:
9303 : this subroitine doesn't calculate task's condition number for K<>0.
9304 :
9305 :
9306 : ORDER OF POINTS
9307 :
9308 : Subroutine automatically sorts points, so caller may pass unsorted array.
9309 :
9310 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
9311 :
9312 : Setting constraints can lead to undesired results, like ill-conditioned
9313 : behavior, or inconsistency being detected. From the other side, it allows
9314 : us to improve quality of the fit. Here we summarize our experience with
9315 : constrained regression splines:
9316 : * excessive constraints can be inconsistent. Splines are piecewise cubic
9317 : functions, and it is easy to create an example, where large number of
9318 : constraints concentrated in small area will result in inconsistency.
9319 : Just because spline is not flexible enough to satisfy all of them. And
9320 : same constraints spread across the [min(x),max(x)] will be perfectly
9321 : consistent.
9322 : * the more evenly constraints are spread across [min(x),max(x)], the more
9323 : chances that they will be consistent
9324 : * the greater is M (given fixed constraints), the more chances that
9325 : constraints will be consistent
9326 : * in the general case, consistency of constraints IS NOT GUARANTEED.
9327 : * in the several special cases, however, we CAN guarantee consistency.
9328 : * one of this cases is constraints on the function values AND/OR its
9329 : derivatives at the interval boundaries.
9330 : * another special case is ONE constraint on the function value (OR, but
9331 : not AND, derivative) anywhere in the interval
9332 :
9333 : Our final recommendation is to use constraints WHEN AND ONLY WHEN you
9334 : can't solve your task without them. Anything beyond special cases given
9335 : above is not guaranteed and may result in inconsistency.
9336 :
9337 :
9338 : -- ALGLIB PROJECT --
9339 : Copyright 18.08.2009 by Bochkanov Sergey
9340 : *************************************************************************/
9341 : #if !defined(AE_NO_EXCEPTIONS)
9342 0 : void spline1dfitcubicwc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9343 : {
9344 : jmp_buf _break_jump;
9345 : alglib_impl::ae_state _alglib_env_state;
9346 : ae_int_t n;
9347 : ae_int_t k;
9348 0 : if( (x.length()!=y.length()) || (x.length()!=w.length()))
9349 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size");
9350 0 : if( (xc.length()!=yc.length()) || (xc.length()!=dc.length()))
9351 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size");
9352 0 : n = x.length();
9353 0 : k = xc.length();
9354 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9355 0 : if( setjmp(_break_jump) )
9356 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9357 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9358 0 : if( _xparams.flags!=0x0 )
9359 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9360 0 : alglib_impl::spline1dfitcubicwc(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(xc.c_ptr()), const_cast<alglib_impl::ae_vector*>(yc.c_ptr()), const_cast<alglib_impl::ae_vector*>(dc.c_ptr()), k, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9361 :
9362 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9363 0 : return;
9364 : }
9365 : #endif
9366 :
9367 : /*************************************************************************
9368 : Weighted fitting by Hermite spline, with constraints on function values
9369 : or first derivatives.
9370 :
9371 : Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
9372 : basis functions. Basis functions are Hermite splines. Small regularizing
9373 : term is used when solving constrained tasks (to improve stability).
9374 :
9375 : Task is linear, so linear least squares solver is used. Complexity of this
9376 : computational scheme is O(N*M^2), mostly dominated by least squares solver
9377 :
9378 : SEE ALSO
9379 : Spline1DFitCubicWC() - fitting by Cubic splines (less flexible,
9380 : more smooth)
9381 : Spline1DFitHermite() - "lightweight" Hermite fitting, without
9382 : invididual weights and constraints
9383 :
9384 : ! COMMERCIAL EDITION OF ALGLIB:
9385 : !
9386 : ! Commercial Edition of ALGLIB includes following important improvements
9387 : ! of this function:
9388 : ! * high-performance native backend with same C# interface (C# version)
9389 : ! * multithreading support (C++ and C# versions)
9390 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9391 : ! (C++ and C# versions, x86/x64 platform)
9392 : !
9393 : ! We recommend you to read 'Working with commercial version' section of
9394 : ! ALGLIB Reference Manual in order to find out how to use performance-
9395 : ! related features provided by commercial edition of ALGLIB.
9396 :
9397 : INPUT PARAMETERS:
9398 : X - points, array[0..N-1].
9399 : Y - function values, array[0..N-1].
9400 : W - weights, array[0..N-1]
9401 : Each summand in square sum of approximation deviations from
9402 : given values is multiplied by the square of corresponding
9403 : weight. Fill it by 1's if you don't want to solve weighted
9404 : task.
9405 : N - number of points (optional):
9406 : * N>0
9407 : * if given, only first N elements of X/Y/W are processed
9408 : * if not given, automatically determined from X/Y/W sizes
9409 : XC - points where spline values/derivatives are constrained,
9410 : array[0..K-1].
9411 : YC - values of constraints, array[0..K-1]
9412 : DC - array[0..K-1], types of constraints:
9413 : * DC[i]=0 means that S(XC[i])=YC[i]
9414 : * DC[i]=1 means that S'(XC[i])=YC[i]
9415 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
9416 : K - number of constraints (optional):
9417 : * 0<=K<M.
9418 : * K=0 means no constraints (XC/YC/DC are not used)
9419 : * if given, only first K elements of XC/YC/DC are used
9420 : * if not given, automatically determined from XC/YC/DC
9421 : M - number of basis functions (= 2 * number of nodes),
9422 : M>=4,
9423 : M IS EVEN!
9424 :
9425 : OUTPUT PARAMETERS:
9426 : Info- same format as in LSFitLinearW() subroutine:
9427 : * Info>0 task is solved
9428 : * Info<=0 an error occured:
9429 : -4 means inconvergence of internal SVD
9430 : -3 means inconsistent constraints
9431 : -2 means odd M was passed (which is not supported)
9432 : -1 means another errors in parameters passed
9433 : (N<=0, for example)
9434 : S - spline interpolant.
9435 : Rep - report, same format as in LSFitLinearW() subroutine.
9436 : Following fields are set:
9437 : * RMSError rms error on the (X,Y).
9438 : * AvgError average error on the (X,Y).
9439 : * AvgRelError average relative error on the non-zero Y
9440 : * MaxError maximum error
9441 : NON-WEIGHTED ERRORS ARE CALCULATED
9442 :
9443 : IMPORTANT:
9444 : this subroitine doesn't calculate task's condition number for K<>0.
9445 :
9446 : IMPORTANT:
9447 : this subroitine supports only even M's
9448 :
9449 :
9450 : ORDER OF POINTS
9451 :
9452 : Subroutine automatically sorts points, so caller may pass unsorted array.
9453 :
9454 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
9455 :
9456 : Setting constraints can lead to undesired results, like ill-conditioned
9457 : behavior, or inconsistency being detected. From the other side, it allows
9458 : us to improve quality of the fit. Here we summarize our experience with
9459 : constrained regression splines:
9460 : * excessive constraints can be inconsistent. Splines are piecewise cubic
9461 : functions, and it is easy to create an example, where large number of
9462 : constraints concentrated in small area will result in inconsistency.
9463 : Just because spline is not flexible enough to satisfy all of them. And
9464 : same constraints spread across the [min(x),max(x)] will be perfectly
9465 : consistent.
9466 : * the more evenly constraints are spread across [min(x),max(x)], the more
9467 : chances that they will be consistent
9468 : * the greater is M (given fixed constraints), the more chances that
9469 : constraints will be consistent
9470 : * in the general case, consistency of constraints is NOT GUARANTEED.
9471 : * in the several special cases, however, we can guarantee consistency.
9472 : * one of this cases is M>=4 and constraints on the function value
9473 : (AND/OR its derivative) at the interval boundaries.
9474 : * another special case is M>=4 and ONE constraint on the function value
9475 : (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]
9476 :
9477 : Our final recommendation is to use constraints WHEN AND ONLY when you
9478 : can't solve your task without them. Anything beyond special cases given
9479 : above is not guaranteed and may result in inconsistency.
9480 :
9481 : -- ALGLIB PROJECT --
9482 : Copyright 18.08.2009 by Bochkanov Sergey
9483 : *************************************************************************/
9484 0 : void spline1dfithermitewc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t k, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9485 : {
9486 : jmp_buf _break_jump;
9487 : alglib_impl::ae_state _alglib_env_state;
9488 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9489 0 : if( setjmp(_break_jump) )
9490 : {
9491 : #if !defined(AE_NO_EXCEPTIONS)
9492 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9493 : #else
9494 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9495 : return;
9496 : #endif
9497 : }
9498 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9499 0 : if( _xparams.flags!=0x0 )
9500 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9501 0 : alglib_impl::spline1dfithermitewc(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(xc.c_ptr()), const_cast<alglib_impl::ae_vector*>(yc.c_ptr()), const_cast<alglib_impl::ae_vector*>(dc.c_ptr()), k, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9502 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9503 0 : return;
9504 : }
9505 :
9506 : /*************************************************************************
9507 : Weighted fitting by Hermite spline, with constraints on function values
9508 : or first derivatives.
9509 :
9510 : Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
9511 : basis functions. Basis functions are Hermite splines. Small regularizing
9512 : term is used when solving constrained tasks (to improve stability).
9513 :
9514 : Task is linear, so linear least squares solver is used. Complexity of this
9515 : computational scheme is O(N*M^2), mostly dominated by least squares solver
9516 :
9517 : SEE ALSO
9518 : Spline1DFitCubicWC() - fitting by Cubic splines (less flexible,
9519 : more smooth)
9520 : Spline1DFitHermite() - "lightweight" Hermite fitting, without
9521 : invididual weights and constraints
9522 :
9523 : ! COMMERCIAL EDITION OF ALGLIB:
9524 : !
9525 : ! Commercial Edition of ALGLIB includes following important improvements
9526 : ! of this function:
9527 : ! * high-performance native backend with same C# interface (C# version)
9528 : ! * multithreading support (C++ and C# versions)
9529 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9530 : ! (C++ and C# versions, x86/x64 platform)
9531 : !
9532 : ! We recommend you to read 'Working with commercial version' section of
9533 : ! ALGLIB Reference Manual in order to find out how to use performance-
9534 : ! related features provided by commercial edition of ALGLIB.
9535 :
9536 : INPUT PARAMETERS:
9537 : X - points, array[0..N-1].
9538 : Y - function values, array[0..N-1].
9539 : W - weights, array[0..N-1]
9540 : Each summand in square sum of approximation deviations from
9541 : given values is multiplied by the square of corresponding
9542 : weight. Fill it by 1's if you don't want to solve weighted
9543 : task.
9544 : N - number of points (optional):
9545 : * N>0
9546 : * if given, only first N elements of X/Y/W are processed
9547 : * if not given, automatically determined from X/Y/W sizes
9548 : XC - points where spline values/derivatives are constrained,
9549 : array[0..K-1].
9550 : YC - values of constraints, array[0..K-1]
9551 : DC - array[0..K-1], types of constraints:
9552 : * DC[i]=0 means that S(XC[i])=YC[i]
9553 : * DC[i]=1 means that S'(XC[i])=YC[i]
9554 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
9555 : K - number of constraints (optional):
9556 : * 0<=K<M.
9557 : * K=0 means no constraints (XC/YC/DC are not used)
9558 : * if given, only first K elements of XC/YC/DC are used
9559 : * if not given, automatically determined from XC/YC/DC
9560 : M - number of basis functions (= 2 * number of nodes),
9561 : M>=4,
9562 : M IS EVEN!
9563 :
9564 : OUTPUT PARAMETERS:
9565 : Info- same format as in LSFitLinearW() subroutine:
9566 : * Info>0 task is solved
9567 : * Info<=0 an error occured:
9568 : -4 means inconvergence of internal SVD
9569 : -3 means inconsistent constraints
9570 : -2 means odd M was passed (which is not supported)
9571 : -1 means another errors in parameters passed
9572 : (N<=0, for example)
9573 : S - spline interpolant.
9574 : Rep - report, same format as in LSFitLinearW() subroutine.
9575 : Following fields are set:
9576 : * RMSError rms error on the (X,Y).
9577 : * AvgError average error on the (X,Y).
9578 : * AvgRelError average relative error on the non-zero Y
9579 : * MaxError maximum error
9580 : NON-WEIGHTED ERRORS ARE CALCULATED
9581 :
9582 : IMPORTANT:
9583 : this subroitine doesn't calculate task's condition number for K<>0.
9584 :
9585 : IMPORTANT:
9586 : this subroitine supports only even M's
9587 :
9588 :
9589 : ORDER OF POINTS
9590 :
9591 : Subroutine automatically sorts points, so caller may pass unsorted array.
9592 :
9593 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
9594 :
9595 : Setting constraints can lead to undesired results, like ill-conditioned
9596 : behavior, or inconsistency being detected. From the other side, it allows
9597 : us to improve quality of the fit. Here we summarize our experience with
9598 : constrained regression splines:
9599 : * excessive constraints can be inconsistent. Splines are piecewise cubic
9600 : functions, and it is easy to create an example, where large number of
9601 : constraints concentrated in small area will result in inconsistency.
9602 : Just because spline is not flexible enough to satisfy all of them. And
9603 : same constraints spread across the [min(x),max(x)] will be perfectly
9604 : consistent.
9605 : * the more evenly constraints are spread across [min(x),max(x)], the more
9606 : chances that they will be consistent
9607 : * the greater is M (given fixed constraints), the more chances that
9608 : constraints will be consistent
9609 : * in the general case, consistency of constraints is NOT GUARANTEED.
9610 : * in the several special cases, however, we can guarantee consistency.
9611 : * one of this cases is M>=4 and constraints on the function value
9612 : (AND/OR its derivative) at the interval boundaries.
9613 : * another special case is M>=4 and ONE constraint on the function value
9614 : (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]
9615 :
9616 : Our final recommendation is to use constraints WHEN AND ONLY when you
9617 : can't solve your task without them. Anything beyond special cases given
9618 : above is not guaranteed and may result in inconsistency.
9619 :
9620 : -- ALGLIB PROJECT --
9621 : Copyright 18.08.2009 by Bochkanov Sergey
9622 : *************************************************************************/
9623 : #if !defined(AE_NO_EXCEPTIONS)
9624 0 : void spline1dfithermitewc(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &xc, const real_1d_array &yc, const integer_1d_array &dc, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9625 : {
9626 : jmp_buf _break_jump;
9627 : alglib_impl::ae_state _alglib_env_state;
9628 : ae_int_t n;
9629 : ae_int_t k;
9630 0 : if( (x.length()!=y.length()) || (x.length()!=w.length()))
9631 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
9632 0 : if( (xc.length()!=yc.length()) || (xc.length()!=dc.length()))
9633 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
9634 0 : n = x.length();
9635 0 : k = xc.length();
9636 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9637 0 : if( setjmp(_break_jump) )
9638 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9639 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9640 0 : if( _xparams.flags!=0x0 )
9641 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9642 0 : alglib_impl::spline1dfithermitewc(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(xc.c_ptr()), const_cast<alglib_impl::ae_vector*>(yc.c_ptr()), const_cast<alglib_impl::ae_vector*>(dc.c_ptr()), k, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9643 :
9644 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9645 0 : return;
9646 : }
9647 : #endif
9648 :
9649 : /*************************************************************************
9650 : Least squares fitting by cubic spline.
9651 :
9652 : This subroutine is "lightweight" alternative for more complex and feature-
9653 : rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information
9654 : about subroutine parameters (we don't duplicate it here because of length)
9655 :
9656 : ! COMMERCIAL EDITION OF ALGLIB:
9657 : !
9658 : ! Commercial Edition of ALGLIB includes following important improvements
9659 : ! of this function:
9660 : ! * high-performance native backend with same C# interface (C# version)
9661 : ! * multithreading support (C++ and C# versions)
9662 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9663 : ! (C++ and C# versions, x86/x64 platform)
9664 : !
9665 : ! We recommend you to read 'Working with commercial version' section of
9666 : ! ALGLIB Reference Manual in order to find out how to use performance-
9667 : ! related features provided by commercial edition of ALGLIB.
9668 :
9669 : -- ALGLIB PROJECT --
9670 : Copyright 18.08.2009 by Bochkanov Sergey
9671 : *************************************************************************/
9672 0 : void spline1dfitcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9673 : {
9674 : jmp_buf _break_jump;
9675 : alglib_impl::ae_state _alglib_env_state;
9676 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9677 0 : if( setjmp(_break_jump) )
9678 : {
9679 : #if !defined(AE_NO_EXCEPTIONS)
9680 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9681 : #else
9682 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9683 : return;
9684 : #endif
9685 : }
9686 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9687 0 : if( _xparams.flags!=0x0 )
9688 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9689 0 : alglib_impl::spline1dfitcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9690 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9691 0 : return;
9692 : }
9693 :
9694 : /*************************************************************************
9695 : Least squares fitting by cubic spline.
9696 :
9697 : This subroutine is "lightweight" alternative for more complex and feature-
9698 : rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information
9699 : about subroutine parameters (we don't duplicate it here because of length)
9700 :
9701 : ! COMMERCIAL EDITION OF ALGLIB:
9702 : !
9703 : ! Commercial Edition of ALGLIB includes following important improvements
9704 : ! of this function:
9705 : ! * high-performance native backend with same C# interface (C# version)
9706 : ! * multithreading support (C++ and C# versions)
9707 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9708 : ! (C++ and C# versions, x86/x64 platform)
9709 : !
9710 : ! We recommend you to read 'Working with commercial version' section of
9711 : ! ALGLIB Reference Manual in order to find out how to use performance-
9712 : ! related features provided by commercial edition of ALGLIB.
9713 :
9714 : -- ALGLIB PROJECT --
9715 : Copyright 18.08.2009 by Bochkanov Sergey
9716 : *************************************************************************/
9717 : #if !defined(AE_NO_EXCEPTIONS)
9718 0 : void spline1dfitcubic(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9719 : {
9720 : jmp_buf _break_jump;
9721 : alglib_impl::ae_state _alglib_env_state;
9722 : ae_int_t n;
9723 0 : if( (x.length()!=y.length()))
9724 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitcubic': looks like one of arguments has wrong size");
9725 0 : n = x.length();
9726 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9727 0 : if( setjmp(_break_jump) )
9728 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9729 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9730 0 : if( _xparams.flags!=0x0 )
9731 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9732 0 : alglib_impl::spline1dfitcubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9733 :
9734 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9735 0 : return;
9736 : }
9737 : #endif
9738 :
9739 : /*************************************************************************
9740 : Least squares fitting by Hermite spline.
9741 :
9742 : This subroutine is "lightweight" alternative for more complex and feature-
9743 : rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for
9744 : more information about subroutine parameters (we don't duplicate it here
9745 : because of length).
9746 :
9747 : ! COMMERCIAL EDITION OF ALGLIB:
9748 : !
9749 : ! Commercial Edition of ALGLIB includes following important improvements
9750 : ! of this function:
9751 : ! * high-performance native backend with same C# interface (C# version)
9752 : ! * multithreading support (C++ and C# versions)
9753 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9754 : ! (C++ and C# versions, x86/x64 platform)
9755 : !
9756 : ! We recommend you to read 'Working with commercial version' section of
9757 : ! ALGLIB Reference Manual in order to find out how to use performance-
9758 : ! related features provided by commercial edition of ALGLIB.
9759 :
9760 : -- ALGLIB PROJECT --
9761 : Copyright 18.08.2009 by Bochkanov Sergey
9762 : *************************************************************************/
9763 0 : void spline1dfithermite(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9764 : {
9765 : jmp_buf _break_jump;
9766 : alglib_impl::ae_state _alglib_env_state;
9767 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9768 0 : if( setjmp(_break_jump) )
9769 : {
9770 : #if !defined(AE_NO_EXCEPTIONS)
9771 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9772 : #else
9773 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9774 : return;
9775 : #endif
9776 : }
9777 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9778 0 : if( _xparams.flags!=0x0 )
9779 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9780 0 : alglib_impl::spline1dfithermite(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9781 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9782 0 : return;
9783 : }
9784 :
9785 : /*************************************************************************
9786 : Least squares fitting by Hermite spline.
9787 :
9788 : This subroutine is "lightweight" alternative for more complex and feature-
9789 : rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for
9790 : more information about subroutine parameters (we don't duplicate it here
9791 : because of length).
9792 :
9793 : ! COMMERCIAL EDITION OF ALGLIB:
9794 : !
9795 : ! Commercial Edition of ALGLIB includes following important improvements
9796 : ! of this function:
9797 : ! * high-performance native backend with same C# interface (C# version)
9798 : ! * multithreading support (C++ and C# versions)
9799 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9800 : ! (C++ and C# versions, x86/x64 platform)
9801 : !
9802 : ! We recommend you to read 'Working with commercial version' section of
9803 : ! ALGLIB Reference Manual in order to find out how to use performance-
9804 : ! related features provided by commercial edition of ALGLIB.
9805 :
9806 : -- ALGLIB PROJECT --
9807 : Copyright 18.08.2009 by Bochkanov Sergey
9808 : *************************************************************************/
9809 : #if !defined(AE_NO_EXCEPTIONS)
9810 0 : void spline1dfithermite(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
9811 : {
9812 : jmp_buf _break_jump;
9813 : alglib_impl::ae_state _alglib_env_state;
9814 : ae_int_t n;
9815 0 : if( (x.length()!=y.length()))
9816 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfithermite': looks like one of arguments has wrong size");
9817 0 : n = x.length();
9818 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9819 0 : if( setjmp(_break_jump) )
9820 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9821 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9822 0 : if( _xparams.flags!=0x0 )
9823 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9824 0 : alglib_impl::spline1dfithermite(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
9825 :
9826 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9827 0 : return;
9828 : }
9829 : #endif
9830 :
9831 : /*************************************************************************
9832 : Weighted linear least squares fitting.
9833 :
9834 : QR decomposition is used to reduce task to MxM, then triangular solver or
9835 : SVD-based solver is used depending on condition number of the system. It
9836 : allows to maximize speed and retain decent accuracy.
9837 :
9838 : IMPORTANT: if you want to perform polynomial fitting, it may be more
9839 : convenient to use PolynomialFit() function. This function gives
9840 : best results on polynomial problems and solves numerical
9841 : stability issues which arise when you fit high-degree
9842 : polynomials to your data.
9843 :
9844 : ! COMMERCIAL EDITION OF ALGLIB:
9845 : !
9846 : ! Commercial Edition of ALGLIB includes following important improvements
9847 : ! of this function:
9848 : ! * high-performance native backend with same C# interface (C# version)
9849 : ! * multithreading support (C++ and C# versions)
9850 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9851 : ! (C++ and C# versions, x86/x64 platform)
9852 : !
9853 : ! We recommend you to read 'Working with commercial version' section of
9854 : ! ALGLIB Reference Manual in order to find out how to use performance-
9855 : ! related features provided by commercial edition of ALGLIB.
9856 :
9857 : INPUT PARAMETERS:
9858 : Y - array[0..N-1] Function values in N points.
9859 : W - array[0..N-1] Weights corresponding to function values.
9860 : Each summand in square sum of approximation deviations
9861 : from given values is multiplied by the square of
9862 : corresponding weight.
9863 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
9864 : FMatrix[I, J] - value of J-th basis function in I-th point.
9865 : N - number of points used. N>=1.
9866 : M - number of basis functions, M>=1.
9867 :
9868 : OUTPUT PARAMETERS:
9869 : Info - error code:
9870 : * -4 internal SVD decomposition subroutine failed (very
9871 : rare and for degenerate systems only)
9872 : * -1 incorrect N/M were specified
9873 : * 1 task is solved
9874 : C - decomposition coefficients, array[0..M-1]
9875 : Rep - fitting report. Following fields are set:
9876 : * Rep.TaskRCond reciprocal of condition number
9877 : * R2 non-adjusted coefficient of determination
9878 : (non-weighted)
9879 : * RMSError rms error on the (X,Y).
9880 : * AvgError average error on the (X,Y).
9881 : * AvgRelError average relative error on the non-zero Y
9882 : * MaxError maximum error
9883 : NON-WEIGHTED ERRORS ARE CALCULATED
9884 :
9885 : ERRORS IN PARAMETERS
9886 :
9887 : This solver also calculates different kinds of errors in parameters and
9888 : fills corresponding fields of report:
9889 : * Rep.CovPar covariance matrix for parameters, array[K,K].
9890 : * Rep.ErrPar errors in parameters, array[K],
9891 : errpar = sqrt(diag(CovPar))
9892 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
9893 : best-fit curve from "ideal" best-fit curve built with
9894 : infinite number of samples, array[N].
9895 : errcurve = sqrt(diag(F*CovPar*F')),
9896 : where F is functions matrix.
9897 : * Rep.Noise vector of per-point estimates of noise, array[N]
9898 :
9899 : NOTE: noise in the data is estimated as follows:
9900 : * for fitting without user-supplied weights all points are
9901 : assumed to have same level of noise, which is estimated from
9902 : the data
9903 : * for fitting with user-supplied weights we assume that noise
9904 : level in I-th point is inversely proportional to Ith weight.
9905 : Coefficient of proportionality is estimated from the data.
9906 :
9907 : NOTE: we apply small amount of regularization when we invert squared
9908 : Jacobian and calculate covariance matrix. It guarantees that
9909 : algorithm won't divide by zero during inversion, but skews
9910 : error estimates a bit (fractional error is about 10^-9).
9911 :
9912 : However, we believe that this difference is insignificant for
9913 : all practical purposes except for the situation when you want
9914 : to compare ALGLIB results with "reference" implementation up
9915 : to the last significant digit.
9916 :
9917 : NOTE: covariance matrix is estimated using correction for degrees
9918 : of freedom (covariances are divided by N-M instead of dividing
9919 : by N).
9920 :
9921 : -- ALGLIB --
9922 : Copyright 17.08.2009 by Bochkanov Sergey
9923 : *************************************************************************/
9924 0 : void lsfitlinearw(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const ae_int_t n, const ae_int_t m, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
9925 : {
9926 : jmp_buf _break_jump;
9927 : alglib_impl::ae_state _alglib_env_state;
9928 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9929 0 : if( setjmp(_break_jump) )
9930 : {
9931 : #if !defined(AE_NO_EXCEPTIONS)
9932 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9933 : #else
9934 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9935 : return;
9936 : #endif
9937 : }
9938 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9939 0 : if( _xparams.flags!=0x0 )
9940 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9941 0 : alglib_impl::lsfitlinearw(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), n, m, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
9942 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9943 0 : return;
9944 : }
9945 :
9946 : /*************************************************************************
9947 : Weighted linear least squares fitting.
9948 :
9949 : QR decomposition is used to reduce task to MxM, then triangular solver or
9950 : SVD-based solver is used depending on condition number of the system. It
9951 : allows to maximize speed and retain decent accuracy.
9952 :
9953 : IMPORTANT: if you want to perform polynomial fitting, it may be more
9954 : convenient to use PolynomialFit() function. This function gives
9955 : best results on polynomial problems and solves numerical
9956 : stability issues which arise when you fit high-degree
9957 : polynomials to your data.
9958 :
9959 : ! COMMERCIAL EDITION OF ALGLIB:
9960 : !
9961 : ! Commercial Edition of ALGLIB includes following important improvements
9962 : ! of this function:
9963 : ! * high-performance native backend with same C# interface (C# version)
9964 : ! * multithreading support (C++ and C# versions)
9965 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9966 : ! (C++ and C# versions, x86/x64 platform)
9967 : !
9968 : ! We recommend you to read 'Working with commercial version' section of
9969 : ! ALGLIB Reference Manual in order to find out how to use performance-
9970 : ! related features provided by commercial edition of ALGLIB.
9971 :
9972 : INPUT PARAMETERS:
9973 : Y - array[0..N-1] Function values in N points.
9974 : W - array[0..N-1] Weights corresponding to function values.
9975 : Each summand in square sum of approximation deviations
9976 : from given values is multiplied by the square of
9977 : corresponding weight.
9978 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
9979 : FMatrix[I, J] - value of J-th basis function in I-th point.
9980 : N - number of points used. N>=1.
9981 : M - number of basis functions, M>=1.
9982 :
9983 : OUTPUT PARAMETERS:
9984 : Info - error code:
9985 : * -4 internal SVD decomposition subroutine failed (very
9986 : rare and for degenerate systems only)
9987 : * -1 incorrect N/M were specified
9988 : * 1 task is solved
9989 : C - decomposition coefficients, array[0..M-1]
9990 : Rep - fitting report. Following fields are set:
9991 : * Rep.TaskRCond reciprocal of condition number
9992 : * R2 non-adjusted coefficient of determination
9993 : (non-weighted)
9994 : * RMSError rms error on the (X,Y).
9995 : * AvgError average error on the (X,Y).
9996 : * AvgRelError average relative error on the non-zero Y
9997 : * MaxError maximum error
9998 : NON-WEIGHTED ERRORS ARE CALCULATED
9999 :
10000 : ERRORS IN PARAMETERS
10001 :
10002 : This solver also calculates different kinds of errors in parameters and
10003 : fills corresponding fields of report:
10004 : * Rep.CovPar covariance matrix for parameters, array[K,K].
10005 : * Rep.ErrPar errors in parameters, array[K],
10006 : errpar = sqrt(diag(CovPar))
10007 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
10008 : best-fit curve from "ideal" best-fit curve built with
10009 : infinite number of samples, array[N].
10010 : errcurve = sqrt(diag(F*CovPar*F')),
10011 : where F is functions matrix.
10012 : * Rep.Noise vector of per-point estimates of noise, array[N]
10013 :
10014 : NOTE: noise in the data is estimated as follows:
10015 : * for fitting without user-supplied weights all points are
10016 : assumed to have same level of noise, which is estimated from
10017 : the data
10018 : * for fitting with user-supplied weights we assume that noise
10019 : level in I-th point is inversely proportional to Ith weight.
10020 : Coefficient of proportionality is estimated from the data.
10021 :
10022 : NOTE: we apply small amount of regularization when we invert squared
10023 : Jacobian and calculate covariance matrix. It guarantees that
10024 : algorithm won't divide by zero during inversion, but skews
10025 : error estimates a bit (fractional error is about 10^-9).
10026 :
10027 : However, we believe that this difference is insignificant for
10028 : all practical purposes except for the situation when you want
10029 : to compare ALGLIB results with "reference" implementation up
10030 : to the last significant digit.
10031 :
10032 : NOTE: covariance matrix is estimated using correction for degrees
10033 : of freedom (covariances are divided by N-M instead of dividing
10034 : by N).
10035 :
10036 : -- ALGLIB --
10037 : Copyright 17.08.2009 by Bochkanov Sergey
10038 : *************************************************************************/
10039 : #if !defined(AE_NO_EXCEPTIONS)
10040 0 : void lsfitlinearw(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
10041 : {
10042 : jmp_buf _break_jump;
10043 : alglib_impl::ae_state _alglib_env_state;
10044 : ae_int_t n;
10045 : ae_int_t m;
10046 0 : if( (y.length()!=w.length()) || (y.length()!=fmatrix.rows()))
10047 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearw': looks like one of arguments has wrong size");
10048 0 : n = y.length();
10049 0 : m = fmatrix.cols();
10050 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10051 0 : if( setjmp(_break_jump) )
10052 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10053 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10054 0 : if( _xparams.flags!=0x0 )
10055 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10056 0 : alglib_impl::lsfitlinearw(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), n, m, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
10057 :
10058 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10059 0 : return;
10060 : }
10061 : #endif
10062 :
10063 : /*************************************************************************
10064 : Weighted constained linear least squares fitting.
10065 :
10066 : This is variation of LSFitLinearW(), which searchs for min|A*x=b| given
10067 : that K additional constaints C*x=bc are satisfied. It reduces original
10068 : task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW()
10069 : is called.
10070 :
10071 : IMPORTANT: if you want to perform polynomial fitting, it may be more
10072 : convenient to use PolynomialFit() function. This function gives
10073 : best results on polynomial problems and solves numerical
10074 : stability issues which arise when you fit high-degree
10075 : polynomials to your data.
10076 :
10077 : ! COMMERCIAL EDITION OF ALGLIB:
10078 : !
10079 : ! Commercial Edition of ALGLIB includes following important improvements
10080 : ! of this function:
10081 : ! * high-performance native backend with same C# interface (C# version)
10082 : ! * multithreading support (C++ and C# versions)
10083 : ! * hardware vendor (Intel) implementations of linear algebra primitives
10084 : ! (C++ and C# versions, x86/x64 platform)
10085 : !
10086 : ! We recommend you to read 'Working with commercial version' section of
10087 : ! ALGLIB Reference Manual in order to find out how to use performance-
10088 : ! related features provided by commercial edition of ALGLIB.
10089 :
10090 : INPUT PARAMETERS:
10091 : Y - array[0..N-1] Function values in N points.
10092 : W - array[0..N-1] Weights corresponding to function values.
10093 : Each summand in square sum of approximation deviations
10094 : from given values is multiplied by the square of
10095 : corresponding weight.
10096 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
10097 : FMatrix[I,J] - value of J-th basis function in I-th point.
10098 : CMatrix - a table of constaints, array[0..K-1,0..M].
10099 : I-th row of CMatrix corresponds to I-th linear constraint:
10100 : CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
10101 : N - number of points used. N>=1.
10102 : M - number of basis functions, M>=1.
10103 : K - number of constraints, 0 <= K < M
10104 : K=0 corresponds to absence of constraints.
10105 :
10106 : OUTPUT PARAMETERS:
10107 : Info - error code:
10108 : * -4 internal SVD decomposition subroutine failed (very
10109 : rare and for degenerate systems only)
10110 : * -3 either too many constraints (M or more),
10111 : degenerate constraints (some constraints are
10112 : repetead twice) or inconsistent constraints were
10113 : specified.
10114 : * 1 task is solved
10115 : C - decomposition coefficients, array[0..M-1]
10116 : Rep - fitting report. Following fields are set:
10117 : * R2 non-adjusted coefficient of determination
10118 : (non-weighted)
10119 : * RMSError rms error on the (X,Y).
10120 : * AvgError average error on the (X,Y).
10121 : * AvgRelError average relative error on the non-zero Y
10122 : * MaxError maximum error
10123 : NON-WEIGHTED ERRORS ARE CALCULATED
10124 :
10125 : IMPORTANT:
10126 : this subroitine doesn't calculate task's condition number for K<>0.
10127 :
10128 : ERRORS IN PARAMETERS
10129 :
10130 : This solver also calculates different kinds of errors in parameters and
10131 : fills corresponding fields of report:
10132 : * Rep.CovPar covariance matrix for parameters, array[K,K].
10133 : * Rep.ErrPar errors in parameters, array[K],
10134 : errpar = sqrt(diag(CovPar))
10135 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
10136 : best-fit curve from "ideal" best-fit curve built with
10137 : infinite number of samples, array[N].
10138 : errcurve = sqrt(diag(F*CovPar*F')),
10139 : where F is functions matrix.
10140 : * Rep.Noise vector of per-point estimates of noise, array[N]
10141 :
10142 : IMPORTANT: errors in parameters are calculated without taking into
10143 : account boundary/linear constraints! Presence of constraints
10144 : changes distribution of errors, but there is no easy way to
10145 : account for constraints when you calculate covariance matrix.
10146 :
10147 : NOTE: noise in the data is estimated as follows:
10148 : * for fitting without user-supplied weights all points are
10149 : assumed to have same level of noise, which is estimated from
10150 : the data
10151 : * for fitting with user-supplied weights we assume that noise
10152 : level in I-th point is inversely proportional to Ith weight.
10153 : Coefficient of proportionality is estimated from the data.
10154 :
10155 : NOTE: we apply small amount of regularization when we invert squared
10156 : Jacobian and calculate covariance matrix. It guarantees that
10157 : algorithm won't divide by zero during inversion, but skews
10158 : error estimates a bit (fractional error is about 10^-9).
10159 :
10160 : However, we believe that this difference is insignificant for
10161 : all practical purposes except for the situation when you want
10162 : to compare ALGLIB results with "reference" implementation up
10163 : to the last significant digit.
10164 :
10165 : NOTE: covariance matrix is estimated using correction for degrees
10166 : of freedom (covariances are divided by N-M instead of dividing
10167 : by N).
10168 :
10169 : -- ALGLIB --
10170 : Copyright 07.09.2009 by Bochkanov Sergey
10171 : *************************************************************************/
10172 0 : void lsfitlinearwc(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const real_2d_array &cmatrix, const ae_int_t n, const ae_int_t m, const ae_int_t k, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
10173 : {
10174 : jmp_buf _break_jump;
10175 : alglib_impl::ae_state _alglib_env_state;
10176 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10177 0 : if( setjmp(_break_jump) )
10178 : {
10179 : #if !defined(AE_NO_EXCEPTIONS)
10180 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10181 : #else
10182 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10183 : return;
10184 : #endif
10185 : }
10186 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10187 0 : if( _xparams.flags!=0x0 )
10188 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10189 0 : alglib_impl::lsfitlinearwc(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), const_cast<alglib_impl::ae_matrix*>(cmatrix.c_ptr()), n, m, k, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
10190 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10191 0 : return;
10192 : }
10193 :
10194 : /*************************************************************************
10195 : Weighted constained linear least squares fitting.
10196 :
10197 : This is variation of LSFitLinearW(), which searchs for min|A*x=b| given
10198 : that K additional constaints C*x=bc are satisfied. It reduces original
10199 : task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW()
10200 : is called.
10201 :
10202 : IMPORTANT: if you want to perform polynomial fitting, it may be more
10203 : convenient to use PolynomialFit() function. This function gives
10204 : best results on polynomial problems and solves numerical
10205 : stability issues which arise when you fit high-degree
10206 : polynomials to your data.
10207 :
10208 : ! COMMERCIAL EDITION OF ALGLIB:
10209 : !
10210 : ! Commercial Edition of ALGLIB includes following important improvements
10211 : ! of this function:
10212 : ! * high-performance native backend with same C# interface (C# version)
10213 : ! * multithreading support (C++ and C# versions)
10214 : ! * hardware vendor (Intel) implementations of linear algebra primitives
10215 : ! (C++ and C# versions, x86/x64 platform)
10216 : !
10217 : ! We recommend you to read 'Working with commercial version' section of
10218 : ! ALGLIB Reference Manual in order to find out how to use performance-
10219 : ! related features provided by commercial edition of ALGLIB.
10220 :
10221 : INPUT PARAMETERS:
10222 : Y - array[0..N-1] Function values in N points.
10223 : W - array[0..N-1] Weights corresponding to function values.
10224 : Each summand in square sum of approximation deviations
10225 : from given values is multiplied by the square of
10226 : corresponding weight.
10227 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
10228 : FMatrix[I,J] - value of J-th basis function in I-th point.
10229 : CMatrix - a table of constaints, array[0..K-1,0..M].
10230 : I-th row of CMatrix corresponds to I-th linear constraint:
10231 : CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
10232 : N - number of points used. N>=1.
10233 : M - number of basis functions, M>=1.
10234 : K - number of constraints, 0 <= K < M
10235 : K=0 corresponds to absence of constraints.
10236 :
10237 : OUTPUT PARAMETERS:
10238 : Info - error code:
10239 : * -4 internal SVD decomposition subroutine failed (very
10240 : rare and for degenerate systems only)
10241 : * -3 either too many constraints (M or more),
10242 : degenerate constraints (some constraints are
10243 : repetead twice) or inconsistent constraints were
10244 : specified.
10245 : * 1 task is solved
10246 : C - decomposition coefficients, array[0..M-1]
10247 : Rep - fitting report. Following fields are set:
10248 : * R2 non-adjusted coefficient of determination
10249 : (non-weighted)
10250 : * RMSError rms error on the (X,Y).
10251 : * AvgError average error on the (X,Y).
10252 : * AvgRelError average relative error on the non-zero Y
10253 : * MaxError maximum error
10254 : NON-WEIGHTED ERRORS ARE CALCULATED
10255 :
10256 : IMPORTANT:
10257 : this subroitine doesn't calculate task's condition number for K<>0.
10258 :
10259 : ERRORS IN PARAMETERS
10260 :
10261 : This solver also calculates different kinds of errors in parameters and
10262 : fills corresponding fields of report:
10263 : * Rep.CovPar covariance matrix for parameters, array[K,K].
10264 : * Rep.ErrPar errors in parameters, array[K],
10265 : errpar = sqrt(diag(CovPar))
10266 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
10267 : best-fit curve from "ideal" best-fit curve built with
10268 : infinite number of samples, array[N].
10269 : errcurve = sqrt(diag(F*CovPar*F')),
10270 : where F is functions matrix.
10271 : * Rep.Noise vector of per-point estimates of noise, array[N]
10272 :
10273 : IMPORTANT: errors in parameters are calculated without taking into
10274 : account boundary/linear constraints! Presence of constraints
10275 : changes distribution of errors, but there is no easy way to
10276 : account for constraints when you calculate covariance matrix.
10277 :
10278 : NOTE: noise in the data is estimated as follows:
10279 : * for fitting without user-supplied weights all points are
10280 : assumed to have same level of noise, which is estimated from
10281 : the data
10282 : * for fitting with user-supplied weights we assume that noise
10283 : level in I-th point is inversely proportional to Ith weight.
10284 : Coefficient of proportionality is estimated from the data.
10285 :
10286 : NOTE: we apply small amount of regularization when we invert squared
10287 : Jacobian and calculate covariance matrix. It guarantees that
10288 : algorithm won't divide by zero during inversion, but skews
10289 : error estimates a bit (fractional error is about 10^-9).
10290 :
10291 : However, we believe that this difference is insignificant for
10292 : all practical purposes except for the situation when you want
10293 : to compare ALGLIB results with "reference" implementation up
10294 : to the last significant digit.
10295 :
10296 : NOTE: covariance matrix is estimated using correction for degrees
10297 : of freedom (covariances are divided by N-M instead of dividing
10298 : by N).
10299 :
10300 : -- ALGLIB --
10301 : Copyright 07.09.2009 by Bochkanov Sergey
10302 : *************************************************************************/
10303 : #if !defined(AE_NO_EXCEPTIONS)
10304 0 : void lsfitlinearwc(const real_1d_array &y, const real_1d_array &w, const real_2d_array &fmatrix, const real_2d_array &cmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
10305 : {
10306 : jmp_buf _break_jump;
10307 : alglib_impl::ae_state _alglib_env_state;
10308 : ae_int_t n;
10309 : ae_int_t m;
10310 : ae_int_t k;
10311 0 : if( (y.length()!=w.length()) || (y.length()!=fmatrix.rows()))
10312 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size");
10313 0 : if( (fmatrix.cols()!=cmatrix.cols()-1))
10314 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size");
10315 0 : n = y.length();
10316 0 : m = fmatrix.cols();
10317 0 : k = cmatrix.rows();
10318 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10319 0 : if( setjmp(_break_jump) )
10320 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10321 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10322 0 : if( _xparams.flags!=0x0 )
10323 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10324 0 : alglib_impl::lsfitlinearwc(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), const_cast<alglib_impl::ae_matrix*>(cmatrix.c_ptr()), n, m, k, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
10325 :
10326 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10327 0 : return;
10328 : }
10329 : #endif
10330 :
10331 : /*************************************************************************
10332 : Linear least squares fitting.
10333 :
10334 : QR decomposition is used to reduce task to MxM, then triangular solver or
10335 : SVD-based solver is used depending on condition number of the system. It
10336 : allows to maximize speed and retain decent accuracy.
10337 :
10338 : IMPORTANT: if you want to perform polynomial fitting, it may be more
10339 : convenient to use PolynomialFit() function. This function gives
10340 : best results on polynomial problems and solves numerical
10341 : stability issues which arise when you fit high-degree
10342 : polynomials to your data.
10343 :
10344 : ! COMMERCIAL EDITION OF ALGLIB:
10345 : !
10346 : ! Commercial Edition of ALGLIB includes following important improvements
10347 : ! of this function:
10348 : ! * high-performance native backend with same C# interface (C# version)
10349 : ! * multithreading support (C++ and C# versions)
10350 : ! * hardware vendor (Intel) implementations of linear algebra primitives
10351 : ! (C++ and C# versions, x86/x64 platform)
10352 : !
10353 : ! We recommend you to read 'Working with commercial version' section of
10354 : ! ALGLIB Reference Manual in order to find out how to use performance-
10355 : ! related features provided by commercial edition of ALGLIB.
10356 :
10357 : INPUT PARAMETERS:
10358 : Y - array[0..N-1] Function values in N points.
10359 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
10360 : FMatrix[I, J] - value of J-th basis function in I-th point.
10361 : N - number of points used. N>=1.
10362 : M - number of basis functions, M>=1.
10363 :
10364 : OUTPUT PARAMETERS:
10365 : Info - error code:
10366 : * -4 internal SVD decomposition subroutine failed (very
10367 : rare and for degenerate systems only)
10368 : * 1 task is solved
10369 : C - decomposition coefficients, array[0..M-1]
10370 : Rep - fitting report. Following fields are set:
10371 : * Rep.TaskRCond reciprocal of condition number
10372 : * R2 non-adjusted coefficient of determination
10373 : (non-weighted)
10374 : * RMSError rms error on the (X,Y).
10375 : * AvgError average error on the (X,Y).
10376 : * AvgRelError average relative error on the non-zero Y
10377 : * MaxError maximum error
10378 : NON-WEIGHTED ERRORS ARE CALCULATED
10379 :
10380 : ERRORS IN PARAMETERS
10381 :
10382 : This solver also calculates different kinds of errors in parameters and
10383 : fills corresponding fields of report:
10384 : * Rep.CovPar covariance matrix for parameters, array[K,K].
10385 : * Rep.ErrPar errors in parameters, array[K],
10386 : errpar = sqrt(diag(CovPar))
10387 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
10388 : best-fit curve from "ideal" best-fit curve built with
10389 : infinite number of samples, array[N].
10390 : errcurve = sqrt(diag(F*CovPar*F')),
10391 : where F is functions matrix.
10392 : * Rep.Noise vector of per-point estimates of noise, array[N]
10393 :
10394 : NOTE: noise in the data is estimated as follows:
10395 : * for fitting without user-supplied weights all points are
10396 : assumed to have same level of noise, which is estimated from
10397 : the data
10398 : * for fitting with user-supplied weights we assume that noise
10399 : level in I-th point is inversely proportional to Ith weight.
10400 : Coefficient of proportionality is estimated from the data.
10401 :
10402 : NOTE: we apply small amount of regularization when we invert squared
10403 : Jacobian and calculate covariance matrix. It guarantees that
10404 : algorithm won't divide by zero during inversion, but skews
10405 : error estimates a bit (fractional error is about 10^-9).
10406 :
10407 : However, we believe that this difference is insignificant for
10408 : all practical purposes except for the situation when you want
10409 : to compare ALGLIB results with "reference" implementation up
10410 : to the last significant digit.
10411 :
10412 : NOTE: covariance matrix is estimated using correction for degrees
10413 : of freedom (covariances are divided by N-M instead of dividing
10414 : by N).
10415 :
10416 : -- ALGLIB --
10417 : Copyright 17.08.2009 by Bochkanov Sergey
10418 : *************************************************************************/
10419 0 : void lsfitlinear(const real_1d_array &y, const real_2d_array &fmatrix, const ae_int_t n, const ae_int_t m, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
10420 : {
10421 : jmp_buf _break_jump;
10422 : alglib_impl::ae_state _alglib_env_state;
10423 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10424 0 : if( setjmp(_break_jump) )
10425 : {
10426 : #if !defined(AE_NO_EXCEPTIONS)
10427 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10428 : #else
10429 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10430 : return;
10431 : #endif
10432 : }
10433 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10434 0 : if( _xparams.flags!=0x0 )
10435 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10436 0 : alglib_impl::lsfitlinear(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), n, m, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
10437 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10438 0 : return;
10439 : }
10440 :
10441 : /*************************************************************************
10442 : Linear least squares fitting.
10443 :
10444 : QR decomposition is used to reduce task to MxM, then triangular solver or
10445 : SVD-based solver is used depending on condition number of the system. It
10446 : allows to maximize speed and retain decent accuracy.
10447 :
10448 : IMPORTANT: if you want to perform polynomial fitting, it may be more
10449 : convenient to use PolynomialFit() function. This function gives
10450 : best results on polynomial problems and solves numerical
10451 : stability issues which arise when you fit high-degree
10452 : polynomials to your data.
10453 :
10454 : ! COMMERCIAL EDITION OF ALGLIB:
10455 : !
10456 : ! Commercial Edition of ALGLIB includes following important improvements
10457 : ! of this function:
10458 : ! * high-performance native backend with same C# interface (C# version)
10459 : ! * multithreading support (C++ and C# versions)
10460 : ! * hardware vendor (Intel) implementations of linear algebra primitives
10461 : ! (C++ and C# versions, x86/x64 platform)
10462 : !
10463 : ! We recommend you to read 'Working with commercial version' section of
10464 : ! ALGLIB Reference Manual in order to find out how to use performance-
10465 : ! related features provided by commercial edition of ALGLIB.
10466 :
10467 : INPUT PARAMETERS:
10468 : Y - array[0..N-1] Function values in N points.
10469 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
10470 : FMatrix[I, J] - value of J-th basis function in I-th point.
10471 : N - number of points used. N>=1.
10472 : M - number of basis functions, M>=1.
10473 :
10474 : OUTPUT PARAMETERS:
10475 : Info - error code:
10476 : * -4 internal SVD decomposition subroutine failed (very
10477 : rare and for degenerate systems only)
10478 : * 1 task is solved
10479 : C - decomposition coefficients, array[0..M-1]
10480 : Rep - fitting report. Following fields are set:
10481 : * Rep.TaskRCond reciprocal of condition number
10482 : * R2 non-adjusted coefficient of determination
10483 : (non-weighted)
10484 : * RMSError rms error on the (X,Y).
10485 : * AvgError average error on the (X,Y).
10486 : * AvgRelError average relative error on the non-zero Y
10487 : * MaxError maximum error
10488 : NON-WEIGHTED ERRORS ARE CALCULATED
10489 :
10490 : ERRORS IN PARAMETERS
10491 :
10492 : This solver also calculates different kinds of errors in parameters and
10493 : fills corresponding fields of report:
10494 : * Rep.CovPar covariance matrix for parameters, array[K,K].
10495 : * Rep.ErrPar errors in parameters, array[K],
10496 : errpar = sqrt(diag(CovPar))
10497 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
10498 : best-fit curve from "ideal" best-fit curve built with
10499 : infinite number of samples, array[N].
10500 : errcurve = sqrt(diag(F*CovPar*F')),
10501 : where F is functions matrix.
10502 : * Rep.Noise vector of per-point estimates of noise, array[N]
10503 :
10504 : NOTE: noise in the data is estimated as follows:
10505 : * for fitting without user-supplied weights all points are
10506 : assumed to have same level of noise, which is estimated from
10507 : the data
10508 : * for fitting with user-supplied weights we assume that noise
10509 : level in I-th point is inversely proportional to Ith weight.
10510 : Coefficient of proportionality is estimated from the data.
10511 :
10512 : NOTE: we apply small amount of regularization when we invert squared
10513 : Jacobian and calculate covariance matrix. It guarantees that
10514 : algorithm won't divide by zero during inversion, but skews
10515 : error estimates a bit (fractional error is about 10^-9).
10516 :
10517 : However, we believe that this difference is insignificant for
10518 : all practical purposes except for the situation when you want
10519 : to compare ALGLIB results with "reference" implementation up
10520 : to the last significant digit.
10521 :
10522 : NOTE: covariance matrix is estimated using correction for degrees
10523 : of freedom (covariances are divided by N-M instead of dividing
10524 : by N).
10525 :
10526 : -- ALGLIB --
10527 : Copyright 17.08.2009 by Bochkanov Sergey
10528 : *************************************************************************/
10529 : #if !defined(AE_NO_EXCEPTIONS)
10530 0 : void lsfitlinear(const real_1d_array &y, const real_2d_array &fmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
10531 : {
10532 : jmp_buf _break_jump;
10533 : alglib_impl::ae_state _alglib_env_state;
10534 : ae_int_t n;
10535 : ae_int_t m;
10536 0 : if( (y.length()!=fmatrix.rows()))
10537 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinear': looks like one of arguments has wrong size");
10538 0 : n = y.length();
10539 0 : m = fmatrix.cols();
10540 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10541 0 : if( setjmp(_break_jump) )
10542 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10543 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10544 0 : if( _xparams.flags!=0x0 )
10545 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10546 0 : alglib_impl::lsfitlinear(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), n, m, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
10547 :
10548 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10549 0 : return;
10550 : }
10551 : #endif
10552 :
10553 : /*************************************************************************
10554 : Constained linear least squares fitting.
10555 :
10556 : This is variation of LSFitLinear(), which searchs for min|A*x=b| given
10557 : that K additional constaints C*x=bc are satisfied. It reduces original
10558 : task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear()
10559 : is called.
10560 :
10561 : IMPORTANT: if you want to perform polynomial fitting, it may be more
10562 : convenient to use PolynomialFit() function. This function gives
10563 : best results on polynomial problems and solves numerical
10564 : stability issues which arise when you fit high-degree
10565 : polynomials to your data.
10566 :
10567 : ! COMMERCIAL EDITION OF ALGLIB:
10568 : !
10569 : ! Commercial Edition of ALGLIB includes following important improvements
10570 : ! of this function:
10571 : ! * high-performance native backend with same C# interface (C# version)
10572 : ! * multithreading support (C++ and C# versions)
10573 : ! * hardware vendor (Intel) implementations of linear algebra primitives
10574 : ! (C++ and C# versions, x86/x64 platform)
10575 : !
10576 : ! We recommend you to read 'Working with commercial version' section of
10577 : ! ALGLIB Reference Manual in order to find out how to use performance-
10578 : ! related features provided by commercial edition of ALGLIB.
10579 :
10580 : INPUT PARAMETERS:
10581 : Y - array[0..N-1] Function values in N points.
10582 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
10583 : FMatrix[I,J] - value of J-th basis function in I-th point.
10584 : CMatrix - a table of constaints, array[0..K-1,0..M].
10585 : I-th row of CMatrix corresponds to I-th linear constraint:
10586 : CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
10587 : N - number of points used. N>=1.
10588 : M - number of basis functions, M>=1.
10589 : K - number of constraints, 0 <= K < M
10590 : K=0 corresponds to absence of constraints.
10591 :
10592 : OUTPUT PARAMETERS:
10593 : Info - error code:
10594 : * -4 internal SVD decomposition subroutine failed (very
10595 : rare and for degenerate systems only)
10596 : * -3 either too many constraints (M or more),
10597 : degenerate constraints (some constraints are
10598 : repetead twice) or inconsistent constraints were
10599 : specified.
10600 : * 1 task is solved
10601 : C - decomposition coefficients, array[0..M-1]
10602 : Rep - fitting report. Following fields are set:
10603 : * R2 non-adjusted coefficient of determination
10604 : (non-weighted)
10605 : * RMSError rms error on the (X,Y).
10606 : * AvgError average error on the (X,Y).
10607 : * AvgRelError average relative error on the non-zero Y
10608 : * MaxError maximum error
10609 : NON-WEIGHTED ERRORS ARE CALCULATED
10610 :
10611 : IMPORTANT:
10612 : this subroitine doesn't calculate task's condition number for K<>0.
10613 :
10614 : ERRORS IN PARAMETERS
10615 :
10616 : This solver also calculates different kinds of errors in parameters and
10617 : fills corresponding fields of report:
10618 : * Rep.CovPar covariance matrix for parameters, array[K,K].
10619 : * Rep.ErrPar errors in parameters, array[K],
10620 : errpar = sqrt(diag(CovPar))
10621 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
10622 : best-fit curve from "ideal" best-fit curve built with
10623 : infinite number of samples, array[N].
10624 : errcurve = sqrt(diag(F*CovPar*F')),
10625 : where F is functions matrix.
10626 : * Rep.Noise vector of per-point estimates of noise, array[N]
10627 :
10628 : IMPORTANT: errors in parameters are calculated without taking into
10629 : account boundary/linear constraints! Presence of constraints
10630 : changes distribution of errors, but there is no easy way to
10631 : account for constraints when you calculate covariance matrix.
10632 :
10633 : NOTE: noise in the data is estimated as follows:
10634 : * for fitting without user-supplied weights all points are
10635 : assumed to have same level of noise, which is estimated from
10636 : the data
10637 : * for fitting with user-supplied weights we assume that noise
10638 : level in I-th point is inversely proportional to Ith weight.
10639 : Coefficient of proportionality is estimated from the data.
10640 :
10641 : NOTE: we apply small amount of regularization when we invert squared
10642 : Jacobian and calculate covariance matrix. It guarantees that
10643 : algorithm won't divide by zero during inversion, but skews
10644 : error estimates a bit (fractional error is about 10^-9).
10645 :
10646 : However, we believe that this difference is insignificant for
10647 : all practical purposes except for the situation when you want
10648 : to compare ALGLIB results with "reference" implementation up
10649 : to the last significant digit.
10650 :
10651 : NOTE: covariance matrix is estimated using correction for degrees
10652 : of freedom (covariances are divided by N-M instead of dividing
10653 : by N).
10654 :
10655 : -- ALGLIB --
10656 : Copyright 07.09.2009 by Bochkanov Sergey
10657 : *************************************************************************/
10658 0 : void lsfitlinearc(const real_1d_array &y, const real_2d_array &fmatrix, const real_2d_array &cmatrix, const ae_int_t n, const ae_int_t m, const ae_int_t k, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
10659 : {
10660 : jmp_buf _break_jump;
10661 : alglib_impl::ae_state _alglib_env_state;
10662 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10663 0 : if( setjmp(_break_jump) )
10664 : {
10665 : #if !defined(AE_NO_EXCEPTIONS)
10666 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10667 : #else
10668 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10669 : return;
10670 : #endif
10671 : }
10672 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10673 0 : if( _xparams.flags!=0x0 )
10674 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10675 0 : alglib_impl::lsfitlinearc(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), const_cast<alglib_impl::ae_matrix*>(cmatrix.c_ptr()), n, m, k, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
10676 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10677 0 : return;
10678 : }
10679 :
10680 : /*************************************************************************
10681 : Constained linear least squares fitting.
10682 :
10683 : This is variation of LSFitLinear(), which searchs for min|A*x=b| given
10684 : that K additional constaints C*x=bc are satisfied. It reduces original
10685 : task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear()
10686 : is called.
10687 :
10688 : IMPORTANT: if you want to perform polynomial fitting, it may be more
10689 : convenient to use PolynomialFit() function. This function gives
10690 : best results on polynomial problems and solves numerical
10691 : stability issues which arise when you fit high-degree
10692 : polynomials to your data.
10693 :
10694 : ! COMMERCIAL EDITION OF ALGLIB:
10695 : !
10696 : ! Commercial Edition of ALGLIB includes following important improvements
10697 : ! of this function:
10698 : ! * high-performance native backend with same C# interface (C# version)
10699 : ! * multithreading support (C++ and C# versions)
10700 : ! * hardware vendor (Intel) implementations of linear algebra primitives
10701 : ! (C++ and C# versions, x86/x64 platform)
10702 : !
10703 : ! We recommend you to read 'Working with commercial version' section of
10704 : ! ALGLIB Reference Manual in order to find out how to use performance-
10705 : ! related features provided by commercial edition of ALGLIB.
10706 :
10707 : INPUT PARAMETERS:
10708 : Y - array[0..N-1] Function values in N points.
10709 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
10710 : FMatrix[I,J] - value of J-th basis function in I-th point.
10711 : CMatrix - a table of constaints, array[0..K-1,0..M].
10712 : I-th row of CMatrix corresponds to I-th linear constraint:
10713 : CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
10714 : N - number of points used. N>=1.
10715 : M - number of basis functions, M>=1.
10716 : K - number of constraints, 0 <= K < M
10717 : K=0 corresponds to absence of constraints.
10718 :
10719 : OUTPUT PARAMETERS:
10720 : Info - error code:
10721 : * -4 internal SVD decomposition subroutine failed (very
10722 : rare and for degenerate systems only)
10723 : * -3 either too many constraints (M or more),
10724 : degenerate constraints (some constraints are
10725 : repetead twice) or inconsistent constraints were
10726 : specified.
10727 : * 1 task is solved
10728 : C - decomposition coefficients, array[0..M-1]
10729 : Rep - fitting report. Following fields are set:
10730 : * R2 non-adjusted coefficient of determination
10731 : (non-weighted)
10732 : * RMSError rms error on the (X,Y).
10733 : * AvgError average error on the (X,Y).
10734 : * AvgRelError average relative error on the non-zero Y
10735 : * MaxError maximum error
10736 : NON-WEIGHTED ERRORS ARE CALCULATED
10737 :
10738 : IMPORTANT:
10739 : this subroitine doesn't calculate task's condition number for K<>0.
10740 :
10741 : ERRORS IN PARAMETERS
10742 :
10743 : This solver also calculates different kinds of errors in parameters and
10744 : fills corresponding fields of report:
10745 : * Rep.CovPar covariance matrix for parameters, array[K,K].
10746 : * Rep.ErrPar errors in parameters, array[K],
10747 : errpar = sqrt(diag(CovPar))
10748 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
10749 : best-fit curve from "ideal" best-fit curve built with
10750 : infinite number of samples, array[N].
10751 : errcurve = sqrt(diag(F*CovPar*F')),
10752 : where F is functions matrix.
10753 : * Rep.Noise vector of per-point estimates of noise, array[N]
10754 :
10755 : IMPORTANT: errors in parameters are calculated without taking into
10756 : account boundary/linear constraints! Presence of constraints
10757 : changes distribution of errors, but there is no easy way to
10758 : account for constraints when you calculate covariance matrix.
10759 :
10760 : NOTE: noise in the data is estimated as follows:
10761 : * for fitting without user-supplied weights all points are
10762 : assumed to have same level of noise, which is estimated from
10763 : the data
10764 : * for fitting with user-supplied weights we assume that noise
10765 : level in I-th point is inversely proportional to Ith weight.
10766 : Coefficient of proportionality is estimated from the data.
10767 :
10768 : NOTE: we apply small amount of regularization when we invert squared
10769 : Jacobian and calculate covariance matrix. It guarantees that
10770 : algorithm won't divide by zero during inversion, but skews
10771 : error estimates a bit (fractional error is about 10^-9).
10772 :
10773 : However, we believe that this difference is insignificant for
10774 : all practical purposes except for the situation when you want
10775 : to compare ALGLIB results with "reference" implementation up
10776 : to the last significant digit.
10777 :
10778 : NOTE: covariance matrix is estimated using correction for degrees
10779 : of freedom (covariances are divided by N-M instead of dividing
10780 : by N).
10781 :
10782 : -- ALGLIB --
10783 : Copyright 07.09.2009 by Bochkanov Sergey
10784 : *************************************************************************/
10785 : #if !defined(AE_NO_EXCEPTIONS)
10786 0 : void lsfitlinearc(const real_1d_array &y, const real_2d_array &fmatrix, const real_2d_array &cmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
10787 : {
10788 : jmp_buf _break_jump;
10789 : alglib_impl::ae_state _alglib_env_state;
10790 : ae_int_t n;
10791 : ae_int_t m;
10792 : ae_int_t k;
10793 0 : if( (y.length()!=fmatrix.rows()))
10794 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size");
10795 0 : if( (fmatrix.cols()!=cmatrix.cols()-1))
10796 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size");
10797 0 : n = y.length();
10798 0 : m = fmatrix.cols();
10799 0 : k = cmatrix.rows();
10800 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10801 0 : if( setjmp(_break_jump) )
10802 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10803 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10804 0 : if( _xparams.flags!=0x0 )
10805 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10806 0 : alglib_impl::lsfitlinearc(const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_matrix*>(fmatrix.c_ptr()), const_cast<alglib_impl::ae_matrix*>(cmatrix.c_ptr()), n, m, k, &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
10807 :
10808 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10809 0 : return;
10810 : }
10811 : #endif
10812 :
10813 : /*************************************************************************
10814 : Weighted nonlinear least squares fitting using function values only.
10815 :
10816 : Combination of numerical differentiation and secant updates is used to
10817 : obtain function Jacobian.
10818 :
10819 : Nonlinear task min(F(c)) is solved, where
10820 :
10821 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
10822 :
10823 : * N is a number of points,
10824 : * M is a dimension of a space points belong to,
10825 : * K is a dimension of a space of parameters being fitted,
10826 : * w is an N-dimensional vector of weight coefficients,
10827 : * x is a set of N points, each of them is an M-dimensional vector,
10828 : * c is a K-dimensional vector of parameters being fitted
10829 :
10830 : This subroutine uses only f(c,x[i]).
10831 :
10832 : INPUT PARAMETERS:
10833 : X - array[0..N-1,0..M-1], points (one row = one point)
10834 : Y - array[0..N-1], function values.
10835 : W - weights, array[0..N-1]
10836 : C - array[0..K-1], initial approximation to the solution,
10837 : N - number of points, N>1
10838 : M - dimension of space
10839 : K - number of parameters being fitted
10840 : DiffStep- numerical differentiation step;
10841 : should not be very small or large;
10842 : large = loss of accuracy
10843 : small = growth of round-off errors
10844 :
10845 : OUTPUT PARAMETERS:
10846 : State - structure which stores algorithm state
10847 :
10848 : -- ALGLIB --
10849 : Copyright 18.10.2008 by Bochkanov Sergey
10850 : *************************************************************************/
10851 0 : void lsfitcreatewf(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const double diffstep, lsfitstate &state, const xparams _xparams)
10852 : {
10853 : jmp_buf _break_jump;
10854 : alglib_impl::ae_state _alglib_env_state;
10855 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10856 0 : if( setjmp(_break_jump) )
10857 : {
10858 : #if !defined(AE_NO_EXCEPTIONS)
10859 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10860 : #else
10861 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10862 : return;
10863 : #endif
10864 : }
10865 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10866 0 : if( _xparams.flags!=0x0 )
10867 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10868 0 : alglib_impl::lsfitcreatewf(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, diffstep, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
10869 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10870 0 : return;
10871 : }
10872 :
10873 : /*************************************************************************
10874 : Weighted nonlinear least squares fitting using function values only.
10875 :
10876 : Combination of numerical differentiation and secant updates is used to
10877 : obtain function Jacobian.
10878 :
10879 : Nonlinear task min(F(c)) is solved, where
10880 :
10881 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
10882 :
10883 : * N is a number of points,
10884 : * M is a dimension of a space points belong to,
10885 : * K is a dimension of a space of parameters being fitted,
10886 : * w is an N-dimensional vector of weight coefficients,
10887 : * x is a set of N points, each of them is an M-dimensional vector,
10888 : * c is a K-dimensional vector of parameters being fitted
10889 :
10890 : This subroutine uses only f(c,x[i]).
10891 :
10892 : INPUT PARAMETERS:
10893 : X - array[0..N-1,0..M-1], points (one row = one point)
10894 : Y - array[0..N-1], function values.
10895 : W - weights, array[0..N-1]
10896 : C - array[0..K-1], initial approximation to the solution,
10897 : N - number of points, N>1
10898 : M - dimension of space
10899 : K - number of parameters being fitted
10900 : DiffStep- numerical differentiation step;
10901 : should not be very small or large;
10902 : large = loss of accuracy
10903 : small = growth of round-off errors
10904 :
10905 : OUTPUT PARAMETERS:
10906 : State - structure which stores algorithm state
10907 :
10908 : -- ALGLIB --
10909 : Copyright 18.10.2008 by Bochkanov Sergey
10910 : *************************************************************************/
10911 : #if !defined(AE_NO_EXCEPTIONS)
10912 0 : void lsfitcreatewf(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const double diffstep, lsfitstate &state, const xparams _xparams)
10913 : {
10914 : jmp_buf _break_jump;
10915 : alglib_impl::ae_state _alglib_env_state;
10916 : ae_int_t n;
10917 : ae_int_t m;
10918 : ae_int_t k;
10919 0 : if( (x.rows()!=y.length()) || (x.rows()!=w.length()))
10920 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatewf': looks like one of arguments has wrong size");
10921 0 : n = x.rows();
10922 0 : m = x.cols();
10923 0 : k = c.length();
10924 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10925 0 : if( setjmp(_break_jump) )
10926 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10927 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10928 0 : if( _xparams.flags!=0x0 )
10929 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10930 0 : alglib_impl::lsfitcreatewf(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, diffstep, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
10931 :
10932 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10933 0 : return;
10934 : }
10935 : #endif
10936 :
10937 : /*************************************************************************
10938 : Nonlinear least squares fitting using function values only.
10939 :
10940 : Combination of numerical differentiation and secant updates is used to
10941 : obtain function Jacobian.
10942 :
10943 : Nonlinear task min(F(c)) is solved, where
10944 :
10945 : F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2,
10946 :
10947 : * N is a number of points,
10948 : * M is a dimension of a space points belong to,
10949 : * K is a dimension of a space of parameters being fitted,
10950 : * w is an N-dimensional vector of weight coefficients,
10951 : * x is a set of N points, each of them is an M-dimensional vector,
10952 : * c is a K-dimensional vector of parameters being fitted
10953 :
10954 : This subroutine uses only f(c,x[i]).
10955 :
10956 : INPUT PARAMETERS:
10957 : X - array[0..N-1,0..M-1], points (one row = one point)
10958 : Y - array[0..N-1], function values.
10959 : C - array[0..K-1], initial approximation to the solution,
10960 : N - number of points, N>1
10961 : M - dimension of space
10962 : K - number of parameters being fitted
10963 : DiffStep- numerical differentiation step;
10964 : should not be very small or large;
10965 : large = loss of accuracy
10966 : small = growth of round-off errors
10967 :
10968 : OUTPUT PARAMETERS:
10969 : State - structure which stores algorithm state
10970 :
10971 : -- ALGLIB --
10972 : Copyright 18.10.2008 by Bochkanov Sergey
10973 : *************************************************************************/
10974 0 : void lsfitcreatef(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const double diffstep, lsfitstate &state, const xparams _xparams)
10975 : {
10976 : jmp_buf _break_jump;
10977 : alglib_impl::ae_state _alglib_env_state;
10978 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10979 0 : if( setjmp(_break_jump) )
10980 : {
10981 : #if !defined(AE_NO_EXCEPTIONS)
10982 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10983 : #else
10984 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10985 : return;
10986 : #endif
10987 : }
10988 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10989 0 : if( _xparams.flags!=0x0 )
10990 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10991 0 : alglib_impl::lsfitcreatef(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, diffstep, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
10992 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10993 0 : return;
10994 : }
10995 :
10996 : /*************************************************************************
10997 : Nonlinear least squares fitting using function values only.
10998 :
10999 : Combination of numerical differentiation and secant updates is used to
11000 : obtain function Jacobian.
11001 :
11002 : Nonlinear task min(F(c)) is solved, where
11003 :
11004 : F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2,
11005 :
11006 : * N is a number of points,
11007 : * M is a dimension of a space points belong to,
11008 : * K is a dimension of a space of parameters being fitted,
11009 : * w is an N-dimensional vector of weight coefficients,
11010 : * x is a set of N points, each of them is an M-dimensional vector,
11011 : * c is a K-dimensional vector of parameters being fitted
11012 :
11013 : This subroutine uses only f(c,x[i]).
11014 :
11015 : INPUT PARAMETERS:
11016 : X - array[0..N-1,0..M-1], points (one row = one point)
11017 : Y - array[0..N-1], function values.
11018 : C - array[0..K-1], initial approximation to the solution,
11019 : N - number of points, N>1
11020 : M - dimension of space
11021 : K - number of parameters being fitted
11022 : DiffStep- numerical differentiation step;
11023 : should not be very small or large;
11024 : large = loss of accuracy
11025 : small = growth of round-off errors
11026 :
11027 : OUTPUT PARAMETERS:
11028 : State - structure which stores algorithm state
11029 :
11030 : -- ALGLIB --
11031 : Copyright 18.10.2008 by Bochkanov Sergey
11032 : *************************************************************************/
11033 : #if !defined(AE_NO_EXCEPTIONS)
11034 0 : void lsfitcreatef(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const double diffstep, lsfitstate &state, const xparams _xparams)
11035 : {
11036 : jmp_buf _break_jump;
11037 : alglib_impl::ae_state _alglib_env_state;
11038 : ae_int_t n;
11039 : ae_int_t m;
11040 : ae_int_t k;
11041 0 : if( (x.rows()!=y.length()))
11042 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatef': looks like one of arguments has wrong size");
11043 0 : n = x.rows();
11044 0 : m = x.cols();
11045 0 : k = c.length();
11046 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11047 0 : if( setjmp(_break_jump) )
11048 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11049 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11050 0 : if( _xparams.flags!=0x0 )
11051 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11052 0 : alglib_impl::lsfitcreatef(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, diffstep, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11053 :
11054 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11055 0 : return;
11056 : }
11057 : #endif
11058 :
11059 : /*************************************************************************
11060 : Weighted nonlinear least squares fitting using gradient only.
11061 :
11062 : Nonlinear task min(F(c)) is solved, where
11063 :
11064 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
11065 :
11066 : * N is a number of points,
11067 : * M is a dimension of a space points belong to,
11068 : * K is a dimension of a space of parameters being fitted,
11069 : * w is an N-dimensional vector of weight coefficients,
11070 : * x is a set of N points, each of them is an M-dimensional vector,
11071 : * c is a K-dimensional vector of parameters being fitted
11072 :
11073 : This subroutine uses only f(c,x[i]) and its gradient.
11074 :
11075 : INPUT PARAMETERS:
11076 : X - array[0..N-1,0..M-1], points (one row = one point)
11077 : Y - array[0..N-1], function values.
11078 : W - weights, array[0..N-1]
11079 : C - array[0..K-1], initial approximation to the solution,
11080 : N - number of points, N>1
11081 : M - dimension of space
11082 : K - number of parameters being fitted
11083 : CheapFG - boolean flag, which is:
11084 : * True if both function and gradient calculation complexity
11085 : are less than O(M^2). An improved algorithm can
11086 : be used which corresponds to FGJ scheme from
11087 : MINLM unit.
11088 : * False otherwise.
11089 : Standard Jacibian-bases Levenberg-Marquardt algo
11090 : will be used (FJ scheme).
11091 :
11092 : OUTPUT PARAMETERS:
11093 : State - structure which stores algorithm state
11094 :
11095 : See also:
11096 : LSFitResults
11097 : LSFitCreateFG (fitting without weights)
11098 : LSFitCreateWFGH (fitting using Hessian)
11099 : LSFitCreateFGH (fitting using Hessian, without weights)
11100 :
11101 : -- ALGLIB --
11102 : Copyright 17.08.2009 by Bochkanov Sergey
11103 : *************************************************************************/
11104 0 : void lsfitcreatewfg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const bool cheapfg, lsfitstate &state, const xparams _xparams)
11105 : {
11106 : jmp_buf _break_jump;
11107 : alglib_impl::ae_state _alglib_env_state;
11108 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11109 0 : if( setjmp(_break_jump) )
11110 : {
11111 : #if !defined(AE_NO_EXCEPTIONS)
11112 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11113 : #else
11114 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11115 : return;
11116 : #endif
11117 : }
11118 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11119 0 : if( _xparams.flags!=0x0 )
11120 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11121 0 : alglib_impl::lsfitcreatewfg(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, cheapfg, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11122 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11123 0 : return;
11124 : }
11125 :
11126 : /*************************************************************************
11127 : Weighted nonlinear least squares fitting using gradient only.
11128 :
11129 : Nonlinear task min(F(c)) is solved, where
11130 :
11131 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
11132 :
11133 : * N is a number of points,
11134 : * M is a dimension of a space points belong to,
11135 : * K is a dimension of a space of parameters being fitted,
11136 : * w is an N-dimensional vector of weight coefficients,
11137 : * x is a set of N points, each of them is an M-dimensional vector,
11138 : * c is a K-dimensional vector of parameters being fitted
11139 :
11140 : This subroutine uses only f(c,x[i]) and its gradient.
11141 :
11142 : INPUT PARAMETERS:
11143 : X - array[0..N-1,0..M-1], points (one row = one point)
11144 : Y - array[0..N-1], function values.
11145 : W - weights, array[0..N-1]
11146 : C - array[0..K-1], initial approximation to the solution,
11147 : N - number of points, N>1
11148 : M - dimension of space
11149 : K - number of parameters being fitted
11150 : CheapFG - boolean flag, which is:
11151 : * True if both function and gradient calculation complexity
11152 : are less than O(M^2). An improved algorithm can
11153 : be used which corresponds to FGJ scheme from
11154 : MINLM unit.
11155 : * False otherwise.
11156 : Standard Jacibian-bases Levenberg-Marquardt algo
11157 : will be used (FJ scheme).
11158 :
11159 : OUTPUT PARAMETERS:
11160 : State - structure which stores algorithm state
11161 :
11162 : See also:
11163 : LSFitResults
11164 : LSFitCreateFG (fitting without weights)
11165 : LSFitCreateWFGH (fitting using Hessian)
11166 : LSFitCreateFGH (fitting using Hessian, without weights)
11167 :
11168 : -- ALGLIB --
11169 : Copyright 17.08.2009 by Bochkanov Sergey
11170 : *************************************************************************/
11171 : #if !defined(AE_NO_EXCEPTIONS)
11172 0 : void lsfitcreatewfg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const bool cheapfg, lsfitstate &state, const xparams _xparams)
11173 : {
11174 : jmp_buf _break_jump;
11175 : alglib_impl::ae_state _alglib_env_state;
11176 : ae_int_t n;
11177 : ae_int_t m;
11178 : ae_int_t k;
11179 0 : if( (x.rows()!=y.length()) || (x.rows()!=w.length()))
11180 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatewfg': looks like one of arguments has wrong size");
11181 0 : n = x.rows();
11182 0 : m = x.cols();
11183 0 : k = c.length();
11184 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11185 0 : if( setjmp(_break_jump) )
11186 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11187 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11188 0 : if( _xparams.flags!=0x0 )
11189 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11190 0 : alglib_impl::lsfitcreatewfg(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, cheapfg, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11191 :
11192 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11193 0 : return;
11194 : }
11195 : #endif
11196 :
11197 : /*************************************************************************
11198 : Nonlinear least squares fitting using gradient only, without individual
11199 : weights.
11200 :
11201 : Nonlinear task min(F(c)) is solved, where
11202 :
11203 : F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
11204 :
11205 : * N is a number of points,
11206 : * M is a dimension of a space points belong to,
11207 : * K is a dimension of a space of parameters being fitted,
11208 : * x is a set of N points, each of them is an M-dimensional vector,
11209 : * c is a K-dimensional vector of parameters being fitted
11210 :
11211 : This subroutine uses only f(c,x[i]) and its gradient.
11212 :
11213 : INPUT PARAMETERS:
11214 : X - array[0..N-1,0..M-1], points (one row = one point)
11215 : Y - array[0..N-1], function values.
11216 : C - array[0..K-1], initial approximation to the solution,
11217 : N - number of points, N>1
11218 : M - dimension of space
11219 : K - number of parameters being fitted
11220 : CheapFG - boolean flag, which is:
11221 : * True if both function and gradient calculation complexity
11222 : are less than O(M^2). An improved algorithm can
11223 : be used which corresponds to FGJ scheme from
11224 : MINLM unit.
11225 : * False otherwise.
11226 : Standard Jacibian-bases Levenberg-Marquardt algo
11227 : will be used (FJ scheme).
11228 :
11229 : OUTPUT PARAMETERS:
11230 : State - structure which stores algorithm state
11231 :
11232 : -- ALGLIB --
11233 : Copyright 17.08.2009 by Bochkanov Sergey
11234 : *************************************************************************/
11235 0 : void lsfitcreatefg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, const bool cheapfg, lsfitstate &state, const xparams _xparams)
11236 : {
11237 : jmp_buf _break_jump;
11238 : alglib_impl::ae_state _alglib_env_state;
11239 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11240 0 : if( setjmp(_break_jump) )
11241 : {
11242 : #if !defined(AE_NO_EXCEPTIONS)
11243 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11244 : #else
11245 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11246 : return;
11247 : #endif
11248 : }
11249 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11250 0 : if( _xparams.flags!=0x0 )
11251 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11252 0 : alglib_impl::lsfitcreatefg(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, cheapfg, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11253 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11254 0 : return;
11255 : }
11256 :
11257 : /*************************************************************************
11258 : Nonlinear least squares fitting using gradient only, without individual
11259 : weights.
11260 :
11261 : Nonlinear task min(F(c)) is solved, where
11262 :
11263 : F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
11264 :
11265 : * N is a number of points,
11266 : * M is a dimension of a space points belong to,
11267 : * K is a dimension of a space of parameters being fitted,
11268 : * x is a set of N points, each of them is an M-dimensional vector,
11269 : * c is a K-dimensional vector of parameters being fitted
11270 :
11271 : This subroutine uses only f(c,x[i]) and its gradient.
11272 :
11273 : INPUT PARAMETERS:
11274 : X - array[0..N-1,0..M-1], points (one row = one point)
11275 : Y - array[0..N-1], function values.
11276 : C - array[0..K-1], initial approximation to the solution,
11277 : N - number of points, N>1
11278 : M - dimension of space
11279 : K - number of parameters being fitted
11280 : CheapFG - boolean flag, which is:
11281 : * True if both function and gradient calculation complexity
11282 : are less than O(M^2). An improved algorithm can
11283 : be used which corresponds to FGJ scheme from
11284 : MINLM unit.
11285 : * False otherwise.
11286 : Standard Jacibian-bases Levenberg-Marquardt algo
11287 : will be used (FJ scheme).
11288 :
11289 : OUTPUT PARAMETERS:
11290 : State - structure which stores algorithm state
11291 :
11292 : -- ALGLIB --
11293 : Copyright 17.08.2009 by Bochkanov Sergey
11294 : *************************************************************************/
11295 : #if !defined(AE_NO_EXCEPTIONS)
11296 0 : void lsfitcreatefg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const bool cheapfg, lsfitstate &state, const xparams _xparams)
11297 : {
11298 : jmp_buf _break_jump;
11299 : alglib_impl::ae_state _alglib_env_state;
11300 : ae_int_t n;
11301 : ae_int_t m;
11302 : ae_int_t k;
11303 0 : if( (x.rows()!=y.length()))
11304 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatefg': looks like one of arguments has wrong size");
11305 0 : n = x.rows();
11306 0 : m = x.cols();
11307 0 : k = c.length();
11308 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11309 0 : if( setjmp(_break_jump) )
11310 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11311 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11312 0 : if( _xparams.flags!=0x0 )
11313 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11314 0 : alglib_impl::lsfitcreatefg(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, cheapfg, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11315 :
11316 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11317 0 : return;
11318 : }
11319 : #endif
11320 :
11321 : /*************************************************************************
11322 : Weighted nonlinear least squares fitting using gradient/Hessian.
11323 :
11324 : Nonlinear task min(F(c)) is solved, where
11325 :
11326 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
11327 :
11328 : * N is a number of points,
11329 : * M is a dimension of a space points belong to,
11330 : * K is a dimension of a space of parameters being fitted,
11331 : * w is an N-dimensional vector of weight coefficients,
11332 : * x is a set of N points, each of them is an M-dimensional vector,
11333 : * c is a K-dimensional vector of parameters being fitted
11334 :
11335 : This subroutine uses f(c,x[i]), its gradient and its Hessian.
11336 :
11337 : INPUT PARAMETERS:
11338 : X - array[0..N-1,0..M-1], points (one row = one point)
11339 : Y - array[0..N-1], function values.
11340 : W - weights, array[0..N-1]
11341 : C - array[0..K-1], initial approximation to the solution,
11342 : N - number of points, N>1
11343 : M - dimension of space
11344 : K - number of parameters being fitted
11345 :
11346 : OUTPUT PARAMETERS:
11347 : State - structure which stores algorithm state
11348 :
11349 : -- ALGLIB --
11350 : Copyright 17.08.2009 by Bochkanov Sergey
11351 : *************************************************************************/
11352 0 : void lsfitcreatewfgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, lsfitstate &state, const xparams _xparams)
11353 : {
11354 : jmp_buf _break_jump;
11355 : alglib_impl::ae_state _alglib_env_state;
11356 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11357 0 : if( setjmp(_break_jump) )
11358 : {
11359 : #if !defined(AE_NO_EXCEPTIONS)
11360 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11361 : #else
11362 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11363 : return;
11364 : #endif
11365 : }
11366 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11367 0 : if( _xparams.flags!=0x0 )
11368 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11369 0 : alglib_impl::lsfitcreatewfgh(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11370 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11371 0 : return;
11372 : }
11373 :
11374 : /*************************************************************************
11375 : Weighted nonlinear least squares fitting using gradient/Hessian.
11376 :
11377 : Nonlinear task min(F(c)) is solved, where
11378 :
11379 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
11380 :
11381 : * N is a number of points,
11382 : * M is a dimension of a space points belong to,
11383 : * K is a dimension of a space of parameters being fitted,
11384 : * w is an N-dimensional vector of weight coefficients,
11385 : * x is a set of N points, each of them is an M-dimensional vector,
11386 : * c is a K-dimensional vector of parameters being fitted
11387 :
11388 : This subroutine uses f(c,x[i]), its gradient and its Hessian.
11389 :
11390 : INPUT PARAMETERS:
11391 : X - array[0..N-1,0..M-1], points (one row = one point)
11392 : Y - array[0..N-1], function values.
11393 : W - weights, array[0..N-1]
11394 : C - array[0..K-1], initial approximation to the solution,
11395 : N - number of points, N>1
11396 : M - dimension of space
11397 : K - number of parameters being fitted
11398 :
11399 : OUTPUT PARAMETERS:
11400 : State - structure which stores algorithm state
11401 :
11402 : -- ALGLIB --
11403 : Copyright 17.08.2009 by Bochkanov Sergey
11404 : *************************************************************************/
11405 : #if !defined(AE_NO_EXCEPTIONS)
11406 0 : void lsfitcreatewfgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &w, const real_1d_array &c, lsfitstate &state, const xparams _xparams)
11407 : {
11408 : jmp_buf _break_jump;
11409 : alglib_impl::ae_state _alglib_env_state;
11410 : ae_int_t n;
11411 : ae_int_t m;
11412 : ae_int_t k;
11413 0 : if( (x.rows()!=y.length()) || (x.rows()!=w.length()))
11414 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatewfgh': looks like one of arguments has wrong size");
11415 0 : n = x.rows();
11416 0 : m = x.cols();
11417 0 : k = c.length();
11418 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11419 0 : if( setjmp(_break_jump) )
11420 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11421 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11422 0 : if( _xparams.flags!=0x0 )
11423 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11424 0 : alglib_impl::lsfitcreatewfgh(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11425 :
11426 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11427 0 : return;
11428 : }
11429 : #endif
11430 :
11431 : /*************************************************************************
11432 : Nonlinear least squares fitting using gradient/Hessian, without individial
11433 : weights.
11434 :
11435 : Nonlinear task min(F(c)) is solved, where
11436 :
11437 : F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
11438 :
11439 : * N is a number of points,
11440 : * M is a dimension of a space points belong to,
11441 : * K is a dimension of a space of parameters being fitted,
11442 : * x is a set of N points, each of them is an M-dimensional vector,
11443 : * c is a K-dimensional vector of parameters being fitted
11444 :
11445 : This subroutine uses f(c,x[i]), its gradient and its Hessian.
11446 :
11447 : INPUT PARAMETERS:
11448 : X - array[0..N-1,0..M-1], points (one row = one point)
11449 : Y - array[0..N-1], function values.
11450 : C - array[0..K-1], initial approximation to the solution,
11451 : N - number of points, N>1
11452 : M - dimension of space
11453 : K - number of parameters being fitted
11454 :
11455 : OUTPUT PARAMETERS:
11456 : State - structure which stores algorithm state
11457 :
11458 :
11459 : -- ALGLIB --
11460 : Copyright 17.08.2009 by Bochkanov Sergey
11461 : *************************************************************************/
11462 0 : void lsfitcreatefgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const ae_int_t n, const ae_int_t m, const ae_int_t k, lsfitstate &state, const xparams _xparams)
11463 : {
11464 : jmp_buf _break_jump;
11465 : alglib_impl::ae_state _alglib_env_state;
11466 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11467 0 : if( setjmp(_break_jump) )
11468 : {
11469 : #if !defined(AE_NO_EXCEPTIONS)
11470 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11471 : #else
11472 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11473 : return;
11474 : #endif
11475 : }
11476 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11477 0 : if( _xparams.flags!=0x0 )
11478 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11479 0 : alglib_impl::lsfitcreatefgh(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11480 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11481 0 : return;
11482 : }
11483 :
11484 : /*************************************************************************
11485 : Nonlinear least squares fitting using gradient/Hessian, without individial
11486 : weights.
11487 :
11488 : Nonlinear task min(F(c)) is solved, where
11489 :
11490 : F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
11491 :
11492 : * N is a number of points,
11493 : * M is a dimension of a space points belong to,
11494 : * K is a dimension of a space of parameters being fitted,
11495 : * x is a set of N points, each of them is an M-dimensional vector,
11496 : * c is a K-dimensional vector of parameters being fitted
11497 :
11498 : This subroutine uses f(c,x[i]), its gradient and its Hessian.
11499 :
11500 : INPUT PARAMETERS:
11501 : X - array[0..N-1,0..M-1], points (one row = one point)
11502 : Y - array[0..N-1], function values.
11503 : C - array[0..K-1], initial approximation to the solution,
11504 : N - number of points, N>1
11505 : M - dimension of space
11506 : K - number of parameters being fitted
11507 :
11508 : OUTPUT PARAMETERS:
11509 : State - structure which stores algorithm state
11510 :
11511 :
11512 : -- ALGLIB --
11513 : Copyright 17.08.2009 by Bochkanov Sergey
11514 : *************************************************************************/
11515 : #if !defined(AE_NO_EXCEPTIONS)
11516 0 : void lsfitcreatefgh(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, lsfitstate &state, const xparams _xparams)
11517 : {
11518 : jmp_buf _break_jump;
11519 : alglib_impl::ae_state _alglib_env_state;
11520 : ae_int_t n;
11521 : ae_int_t m;
11522 : ae_int_t k;
11523 0 : if( (x.rows()!=y.length()))
11524 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitcreatefgh': looks like one of arguments has wrong size");
11525 0 : n = x.rows();
11526 0 : m = x.cols();
11527 0 : k = c.length();
11528 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11529 0 : if( setjmp(_break_jump) )
11530 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11531 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11532 0 : if( _xparams.flags!=0x0 )
11533 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11534 0 : alglib_impl::lsfitcreatefgh(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, m, k, const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11535 :
11536 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11537 0 : return;
11538 : }
11539 : #endif
11540 :
11541 : /*************************************************************************
11542 : Stopping conditions for nonlinear least squares fitting.
11543 :
11544 : INPUT PARAMETERS:
11545 : State - structure which stores algorithm state
11546 : EpsX - >=0
11547 : The subroutine finishes its work if on k+1-th iteration
11548 : the condition |v|<=EpsX is fulfilled, where:
11549 : * |.| means Euclidian norm
11550 : * v - scaled step vector, v[i]=dx[i]/s[i]
11551 : * dx - ste pvector, dx=X(k+1)-X(k)
11552 : * s - scaling coefficients set by LSFitSetScale()
11553 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
11554 : iterations is unlimited. Only Levenberg-Marquardt
11555 : iterations are counted (L-BFGS/CG iterations are NOT
11556 : counted because their cost is very low compared to that of
11557 : LM).
11558 :
11559 : NOTE
11560 :
11561 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
11562 : stopping criterion selection (according to the scheme used by MINLM unit).
11563 :
11564 :
11565 : -- ALGLIB --
11566 : Copyright 17.08.2009 by Bochkanov Sergey
11567 : *************************************************************************/
11568 0 : void lsfitsetcond(const lsfitstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams)
11569 : {
11570 : jmp_buf _break_jump;
11571 : alglib_impl::ae_state _alglib_env_state;
11572 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11573 0 : if( setjmp(_break_jump) )
11574 : {
11575 : #if !defined(AE_NO_EXCEPTIONS)
11576 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11577 : #else
11578 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11579 : return;
11580 : #endif
11581 : }
11582 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11583 0 : if( _xparams.flags!=0x0 )
11584 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11585 0 : alglib_impl::lsfitsetcond(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), epsx, maxits, &_alglib_env_state);
11586 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11587 0 : return;
11588 : }
11589 :
11590 : /*************************************************************************
11591 : This function sets maximum step length
11592 :
11593 : INPUT PARAMETERS:
11594 : State - structure which stores algorithm state
11595 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
11596 : want to limit step length.
11597 :
11598 : Use this subroutine when you optimize target function which contains exp()
11599 : or other fast growing functions, and optimization algorithm makes too
11600 : large steps which leads to overflow. This function allows us to reject
11601 : steps that are too large (and therefore expose us to the possible
11602 : overflow) without actually calculating function value at the x+stp*d.
11603 :
11604 : NOTE: non-zero StpMax leads to moderate performance degradation because
11605 : intermediate step of preconditioned L-BFGS optimization is incompatible
11606 : with limits on step size.
11607 :
11608 : -- ALGLIB --
11609 : Copyright 02.04.2010 by Bochkanov Sergey
11610 : *************************************************************************/
11611 0 : void lsfitsetstpmax(const lsfitstate &state, const double stpmax, const xparams _xparams)
11612 : {
11613 : jmp_buf _break_jump;
11614 : alglib_impl::ae_state _alglib_env_state;
11615 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11616 0 : if( setjmp(_break_jump) )
11617 : {
11618 : #if !defined(AE_NO_EXCEPTIONS)
11619 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11620 : #else
11621 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11622 : return;
11623 : #endif
11624 : }
11625 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11626 0 : if( _xparams.flags!=0x0 )
11627 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11628 0 : alglib_impl::lsfitsetstpmax(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
11629 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11630 0 : return;
11631 : }
11632 :
11633 : /*************************************************************************
11634 : This function turns on/off reporting.
11635 :
11636 : INPUT PARAMETERS:
11637 : State - structure which stores algorithm state
11638 : NeedXRep- whether iteration reports are needed or not
11639 :
11640 : When reports are needed, State.C (current parameters) and State.F (current
11641 : value of fitting function) are reported.
11642 :
11643 :
11644 : -- ALGLIB --
11645 : Copyright 15.08.2010 by Bochkanov Sergey
11646 : *************************************************************************/
11647 0 : void lsfitsetxrep(const lsfitstate &state, const bool needxrep, const xparams _xparams)
11648 : {
11649 : jmp_buf _break_jump;
11650 : alglib_impl::ae_state _alglib_env_state;
11651 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11652 0 : if( setjmp(_break_jump) )
11653 : {
11654 : #if !defined(AE_NO_EXCEPTIONS)
11655 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11656 : #else
11657 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11658 : return;
11659 : #endif
11660 : }
11661 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11662 0 : if( _xparams.flags!=0x0 )
11663 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11664 0 : alglib_impl::lsfitsetxrep(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
11665 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11666 0 : return;
11667 : }
11668 :
11669 : /*************************************************************************
11670 : This function sets scaling coefficients for underlying optimizer.
11671 :
11672 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
11673 : size and gradient are scaled before comparison with tolerances). Scale of
11674 : the I-th variable is a translation invariant measure of:
11675 : a) "how large" the variable is
11676 : b) how large the step should be to make significant changes in the function
11677 :
11678 : Generally, scale is NOT considered to be a form of preconditioner. But LM
11679 : optimizer is unique in that it uses scaling matrix both in the stopping
11680 : condition tests and as Marquardt damping factor.
11681 :
11682 : Proper scaling is very important for the algorithm performance. It is less
11683 : important for the quality of results, but still has some influence (it is
11684 : easier to converge when variables are properly scaled, so premature
11685 : stopping is possible when very badly scalled variables are combined with
11686 : relaxed stopping conditions).
11687 :
11688 : INPUT PARAMETERS:
11689 : State - structure stores algorithm state
11690 : S - array[N], non-zero scaling coefficients
11691 : S[i] may be negative, sign doesn't matter.
11692 :
11693 : -- ALGLIB --
11694 : Copyright 14.01.2011 by Bochkanov Sergey
11695 : *************************************************************************/
11696 0 : void lsfitsetscale(const lsfitstate &state, const real_1d_array &s, const xparams _xparams)
11697 : {
11698 : jmp_buf _break_jump;
11699 : alglib_impl::ae_state _alglib_env_state;
11700 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11701 0 : if( setjmp(_break_jump) )
11702 : {
11703 : #if !defined(AE_NO_EXCEPTIONS)
11704 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11705 : #else
11706 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11707 : return;
11708 : #endif
11709 : }
11710 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11711 0 : if( _xparams.flags!=0x0 )
11712 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11713 0 : alglib_impl::lsfitsetscale(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
11714 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11715 0 : return;
11716 : }
11717 :
11718 : /*************************************************************************
11719 : This function sets boundary constraints for underlying optimizer
11720 :
11721 : Boundary constraints are inactive by default (after initial creation).
11722 : They are preserved until explicitly turned off with another SetBC() call.
11723 :
11724 : INPUT PARAMETERS:
11725 : State - structure stores algorithm state
11726 : BndL - lower bounds, array[K].
11727 : If some (all) variables are unbounded, you may specify
11728 : very small number or -INF (latter is recommended because
11729 : it will allow solver to use better algorithm).
11730 : BndU - upper bounds, array[K].
11731 : If some (all) variables are unbounded, you may specify
11732 : very large number or +INF (latter is recommended because
11733 : it will allow solver to use better algorithm).
11734 :
11735 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
11736 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
11737 :
11738 : NOTE 2: unlike other constrained optimization algorithms, this solver has
11739 : following useful properties:
11740 : * bound constraints are always satisfied exactly
11741 : * function is evaluated only INSIDE area specified by bound constraints
11742 :
11743 : -- ALGLIB --
11744 : Copyright 14.01.2011 by Bochkanov Sergey
11745 : *************************************************************************/
11746 0 : void lsfitsetbc(const lsfitstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
11747 : {
11748 : jmp_buf _break_jump;
11749 : alglib_impl::ae_state _alglib_env_state;
11750 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11751 0 : if( setjmp(_break_jump) )
11752 : {
11753 : #if !defined(AE_NO_EXCEPTIONS)
11754 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11755 : #else
11756 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11757 : return;
11758 : #endif
11759 : }
11760 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11761 0 : if( _xparams.flags!=0x0 )
11762 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11763 0 : alglib_impl::lsfitsetbc(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
11764 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11765 0 : return;
11766 : }
11767 :
11768 : /*************************************************************************
11769 : This function sets linear constraints for underlying optimizer
11770 :
11771 : Linear constraints are inactive by default (after initial creation).
11772 : They are preserved until explicitly turned off with another SetLC() call.
11773 :
11774 : INPUT PARAMETERS:
11775 : State - structure stores algorithm state
11776 : C - linear constraints, array[K,N+1].
11777 : Each row of C represents one constraint, either equality
11778 : or inequality (see below):
11779 : * first N elements correspond to coefficients,
11780 : * last element corresponds to the right part.
11781 : All elements of C (including right part) must be finite.
11782 : CT - type of constraints, array[K]:
11783 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
11784 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
11785 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
11786 : K - number of equality/inequality constraints, K>=0:
11787 : * if given, only leading K elements of C/CT are used
11788 : * if not given, automatically determined from sizes of C/CT
11789 :
11790 : IMPORTANT: if you have linear constraints, it is strongly recommended to
11791 : set scale of variables with lsfitsetscale(). QP solver which is
11792 : used to calculate linearly constrained steps heavily relies on
11793 : good scaling of input problems.
11794 :
11795 : NOTE: linear (non-box) constraints are satisfied only approximately -
11796 : there always exists some violation due to numerical errors and
11797 : algorithmic limitations.
11798 :
11799 : NOTE: general linear constraints add significant overhead to solution
11800 : process. Although solver performs roughly same amount of iterations
11801 : (when compared with similar box-only constrained problem), each
11802 : iteration now involves solution of linearly constrained QP
11803 : subproblem, which requires ~3-5 times more Cholesky decompositions.
11804 : Thus, if you can reformulate your problem in such way this it has
11805 : only box constraints, it may be beneficial to do so.
11806 :
11807 : -- ALGLIB --
11808 : Copyright 29.04.2017 by Bochkanov Sergey
11809 : *************************************************************************/
11810 0 : void lsfitsetlc(const lsfitstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
11811 : {
11812 : jmp_buf _break_jump;
11813 : alglib_impl::ae_state _alglib_env_state;
11814 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11815 0 : if( setjmp(_break_jump) )
11816 : {
11817 : #if !defined(AE_NO_EXCEPTIONS)
11818 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11819 : #else
11820 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11821 : return;
11822 : #endif
11823 : }
11824 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11825 0 : if( _xparams.flags!=0x0 )
11826 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11827 0 : alglib_impl::lsfitsetlc(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
11828 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11829 0 : return;
11830 : }
11831 :
11832 : /*************************************************************************
11833 : This function sets linear constraints for underlying optimizer
11834 :
11835 : Linear constraints are inactive by default (after initial creation).
11836 : They are preserved until explicitly turned off with another SetLC() call.
11837 :
11838 : INPUT PARAMETERS:
11839 : State - structure stores algorithm state
11840 : C - linear constraints, array[K,N+1].
11841 : Each row of C represents one constraint, either equality
11842 : or inequality (see below):
11843 : * first N elements correspond to coefficients,
11844 : * last element corresponds to the right part.
11845 : All elements of C (including right part) must be finite.
11846 : CT - type of constraints, array[K]:
11847 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
11848 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
11849 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
11850 : K - number of equality/inequality constraints, K>=0:
11851 : * if given, only leading K elements of C/CT are used
11852 : * if not given, automatically determined from sizes of C/CT
11853 :
11854 : IMPORTANT: if you have linear constraints, it is strongly recommended to
11855 : set scale of variables with lsfitsetscale(). QP solver which is
11856 : used to calculate linearly constrained steps heavily relies on
11857 : good scaling of input problems.
11858 :
11859 : NOTE: linear (non-box) constraints are satisfied only approximately -
11860 : there always exists some violation due to numerical errors and
11861 : algorithmic limitations.
11862 :
11863 : NOTE: general linear constraints add significant overhead to solution
11864 : process. Although solver performs roughly same amount of iterations
11865 : (when compared with similar box-only constrained problem), each
11866 : iteration now involves solution of linearly constrained QP
11867 : subproblem, which requires ~3-5 times more Cholesky decompositions.
11868 : Thus, if you can reformulate your problem in such way this it has
11869 : only box constraints, it may be beneficial to do so.
11870 :
11871 : -- ALGLIB --
11872 : Copyright 29.04.2017 by Bochkanov Sergey
11873 : *************************************************************************/
11874 : #if !defined(AE_NO_EXCEPTIONS)
11875 0 : void lsfitsetlc(const lsfitstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams)
11876 : {
11877 : jmp_buf _break_jump;
11878 : alglib_impl::ae_state _alglib_env_state;
11879 : ae_int_t k;
11880 0 : if( (c.rows()!=ct.length()))
11881 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'lsfitsetlc': looks like one of arguments has wrong size");
11882 0 : k = c.rows();
11883 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11884 0 : if( setjmp(_break_jump) )
11885 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11886 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11887 0 : if( _xparams.flags!=0x0 )
11888 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11889 0 : alglib_impl::lsfitsetlc(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
11890 :
11891 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11892 0 : return;
11893 : }
11894 : #endif
11895 :
11896 : /*************************************************************************
11897 : This function provides reverse communication interface
11898 : Reverse communication interface is not documented or recommended to use.
11899 : See below for functions which provide better documented API
11900 : *************************************************************************/
11901 0 : bool lsfititeration(const lsfitstate &state, const xparams _xparams)
11902 : {
11903 : jmp_buf _break_jump;
11904 : alglib_impl::ae_state _alglib_env_state;
11905 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11906 0 : if( setjmp(_break_jump) )
11907 : {
11908 : #if !defined(AE_NO_EXCEPTIONS)
11909 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11910 : #else
11911 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11912 : return 0;
11913 : #endif
11914 : }
11915 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11916 0 : if( _xparams.flags!=0x0 )
11917 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11918 0 : ae_bool result = alglib_impl::lsfititeration(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
11919 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11920 0 : return *(reinterpret_cast<bool*>(&result));
11921 : }
11922 :
11923 :
11924 0 : void lsfitfit(lsfitstate &state,
11925 : void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr),
11926 : void (*rep)(const real_1d_array &c, double func, void *ptr),
11927 : void *ptr,
11928 : const xparams _xparams)
11929 : {
11930 : jmp_buf _break_jump;
11931 : alglib_impl::ae_state _alglib_env_state;
11932 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11933 0 : if( setjmp(_break_jump) )
11934 : {
11935 : #if !defined(AE_NO_EXCEPTIONS)
11936 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11937 : #else
11938 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11939 : return;
11940 : #endif
11941 : }
11942 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11943 0 : if( _xparams.flags!=0x0 )
11944 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11945 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'lsfitfit()' (func is NULL)", &_alglib_env_state);
11946 0 : while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) )
11947 : {
11948 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
11949 0 : if( state.needf )
11950 : {
11951 0 : func(state.c, state.x, state.f, ptr);
11952 0 : continue;
11953 : }
11954 0 : if( state.xupdated )
11955 : {
11956 0 : if( rep!=NULL )
11957 0 : rep(state.c, state.f, ptr);
11958 0 : continue;
11959 : }
11960 0 : goto lbl_no_callback;
11961 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
11962 0 : lbl_no_callback:
11963 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)", &_alglib_env_state);
11964 : }
11965 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11966 0 : }
11967 :
11968 :
11969 0 : void lsfitfit(lsfitstate &state,
11970 : void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr),
11971 : void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
11972 : void (*rep)(const real_1d_array &c, double func, void *ptr),
11973 : void *ptr,
11974 : const xparams _xparams)
11975 : {
11976 : jmp_buf _break_jump;
11977 : alglib_impl::ae_state _alglib_env_state;
11978 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11979 0 : if( setjmp(_break_jump) )
11980 : {
11981 : #if !defined(AE_NO_EXCEPTIONS)
11982 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11983 : #else
11984 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11985 : return;
11986 : #endif
11987 : }
11988 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11989 0 : if( _xparams.flags!=0x0 )
11990 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11991 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'lsfitfit()' (func is NULL)", &_alglib_env_state);
11992 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'lsfitfit()' (grad is NULL)", &_alglib_env_state);
11993 0 : while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) )
11994 : {
11995 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
11996 0 : if( state.needf )
11997 : {
11998 0 : func(state.c, state.x, state.f, ptr);
11999 0 : continue;
12000 : }
12001 0 : if( state.needfg )
12002 : {
12003 0 : grad(state.c, state.x, state.f, state.g, ptr);
12004 0 : continue;
12005 : }
12006 0 : if( state.xupdated )
12007 : {
12008 0 : if( rep!=NULL )
12009 0 : rep(state.c, state.f, ptr);
12010 0 : continue;
12011 : }
12012 0 : goto lbl_no_callback;
12013 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
12014 0 : lbl_no_callback:
12015 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)", &_alglib_env_state);
12016 : }
12017 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12018 0 : }
12019 :
12020 :
12021 0 : void lsfitfit(lsfitstate &state,
12022 : void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr),
12023 : void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
12024 : void (*hess)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr),
12025 : void (*rep)(const real_1d_array &c, double func, void *ptr),
12026 : void *ptr,
12027 : const xparams _xparams)
12028 : {
12029 : jmp_buf _break_jump;
12030 : alglib_impl::ae_state _alglib_env_state;
12031 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12032 0 : if( setjmp(_break_jump) )
12033 : {
12034 : #if !defined(AE_NO_EXCEPTIONS)
12035 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12036 : #else
12037 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12038 : return;
12039 : #endif
12040 : }
12041 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12042 0 : if( _xparams.flags!=0x0 )
12043 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12044 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'lsfitfit()' (func is NULL)", &_alglib_env_state);
12045 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'lsfitfit()' (grad is NULL)", &_alglib_env_state);
12046 0 : alglib_impl::ae_assert(hess!=NULL, "ALGLIB: error in 'lsfitfit()' (hess is NULL)", &_alglib_env_state);
12047 0 : while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) )
12048 : {
12049 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
12050 0 : if( state.needf )
12051 : {
12052 0 : func(state.c, state.x, state.f, ptr);
12053 0 : continue;
12054 : }
12055 0 : if( state.needfg )
12056 : {
12057 0 : grad(state.c, state.x, state.f, state.g, ptr);
12058 0 : continue;
12059 : }
12060 0 : if( state.needfgh )
12061 : {
12062 0 : hess(state.c, state.x, state.f, state.g, state.h, ptr);
12063 0 : continue;
12064 : }
12065 0 : if( state.xupdated )
12066 : {
12067 0 : if( rep!=NULL )
12068 0 : rep(state.c, state.f, ptr);
12069 0 : continue;
12070 : }
12071 0 : goto lbl_no_callback;
12072 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
12073 0 : lbl_no_callback:
12074 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)", &_alglib_env_state);
12075 : }
12076 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12077 0 : }
12078 :
12079 :
12080 :
12081 : /*************************************************************************
12082 : Nonlinear least squares fitting results.
12083 :
12084 : Called after return from LSFitFit().
12085 :
12086 : INPUT PARAMETERS:
12087 : State - algorithm state
12088 :
12089 : OUTPUT PARAMETERS:
12090 : Info - completion code:
12091 : * -8 optimizer detected NAN/INF in the target
12092 : function and/or gradient
12093 : * -7 gradient verification failed.
12094 : See LSFitSetGradientCheck() for more information.
12095 : * -3 inconsistent constraints
12096 : * 2 relative step is no more than EpsX.
12097 : * 5 MaxIts steps was taken
12098 : * 7 stopping conditions are too stringent,
12099 : further improvement is impossible
12100 : C - array[0..K-1], solution
12101 : Rep - optimization report. On success following fields are set:
12102 : * R2 non-adjusted coefficient of determination
12103 : (non-weighted)
12104 : * RMSError rms error on the (X,Y).
12105 : * AvgError average error on the (X,Y).
12106 : * AvgRelError average relative error on the non-zero Y
12107 : * MaxError maximum error
12108 : NON-WEIGHTED ERRORS ARE CALCULATED
12109 : * WRMSError weighted rms error on the (X,Y).
12110 :
12111 : ERRORS IN PARAMETERS
12112 :
12113 : This solver also calculates different kinds of errors in parameters and
12114 : fills corresponding fields of report:
12115 : * Rep.CovPar covariance matrix for parameters, array[K,K].
12116 : * Rep.ErrPar errors in parameters, array[K],
12117 : errpar = sqrt(diag(CovPar))
12118 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
12119 : best-fit curve from "ideal" best-fit curve built with
12120 : infinite number of samples, array[N].
12121 : errcurve = sqrt(diag(J*CovPar*J')),
12122 : where J is Jacobian matrix.
12123 : * Rep.Noise vector of per-point estimates of noise, array[N]
12124 :
12125 : IMPORTANT: errors in parameters are calculated without taking into
12126 : account boundary/linear constraints! Presence of constraints
12127 : changes distribution of errors, but there is no easy way to
12128 : account for constraints when you calculate covariance matrix.
12129 :
12130 : NOTE: noise in the data is estimated as follows:
12131 : * for fitting without user-supplied weights all points are
12132 : assumed to have same level of noise, which is estimated from
12133 : the data
12134 : * for fitting with user-supplied weights we assume that noise
12135 : level in I-th point is inversely proportional to Ith weight.
12136 : Coefficient of proportionality is estimated from the data.
12137 :
12138 : NOTE: we apply small amount of regularization when we invert squared
12139 : Jacobian and calculate covariance matrix. It guarantees that
12140 : algorithm won't divide by zero during inversion, but skews
12141 : error estimates a bit (fractional error is about 10^-9).
12142 :
12143 : However, we believe that this difference is insignificant for
12144 : all practical purposes except for the situation when you want
12145 : to compare ALGLIB results with "reference" implementation up
12146 : to the last significant digit.
12147 :
12148 : NOTE: covariance matrix is estimated using correction for degrees
12149 : of freedom (covariances are divided by N-M instead of dividing
12150 : by N).
12151 :
12152 : -- ALGLIB --
12153 : Copyright 17.08.2009 by Bochkanov Sergey
12154 : *************************************************************************/
12155 0 : void lsfitresults(const lsfitstate &state, ae_int_t &info, real_1d_array &c, lsfitreport &rep, const xparams _xparams)
12156 : {
12157 : jmp_buf _break_jump;
12158 : alglib_impl::ae_state _alglib_env_state;
12159 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12160 0 : if( setjmp(_break_jump) )
12161 : {
12162 : #if !defined(AE_NO_EXCEPTIONS)
12163 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12164 : #else
12165 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12166 : return;
12167 : #endif
12168 : }
12169 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12170 0 : if( _xparams.flags!=0x0 )
12171 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12172 0 : alglib_impl::lsfitresults(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &info, const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::lsfitreport*>(rep.c_ptr()), &_alglib_env_state);
12173 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12174 0 : return;
12175 : }
12176 :
12177 : /*************************************************************************
12178 : This subroutine turns on verification of the user-supplied analytic
12179 : gradient:
12180 : * user calls this subroutine before fitting begins
12181 : * LSFitFit() is called
12182 : * prior to actual fitting, for each point in data set X_i and each
12183 : component of parameters being fited C_j algorithm performs following
12184 : steps:
12185 : * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j],
12186 : where C_j is j-th parameter and S[j] is a scale of j-th parameter
12187 : * if needed, steps are bounded with respect to constraints on C[]
12188 : * F(X_i|C) is evaluated at these trial points
12189 : * we perform one more evaluation in the middle point of the interval
12190 : * we build cubic model using function values and derivatives at trial
12191 : points and we compare its prediction with actual value in the middle
12192 : point
12193 : * in case difference between prediction and actual value is higher than
12194 : some predetermined threshold, algorithm stops with completion code -7;
12195 : Rep.VarIdx is set to index of the parameter with incorrect derivative.
12196 : * after verification is over, algorithm proceeds to the actual optimization.
12197 :
12198 : NOTE 1: verification needs N*K (points count * parameters count) gradient
12199 : evaluations. It is very costly and you should use it only for low
12200 : dimensional problems, when you want to be sure that you've
12201 : correctly calculated analytic derivatives. You should not use it
12202 : in the production code (unless you want to check derivatives
12203 : provided by some third party).
12204 :
12205 : NOTE 2: you should carefully choose TestStep. Value which is too large
12206 : (so large that function behaviour is significantly non-cubic) will
12207 : lead to false alarms. You may use different step for different
12208 : parameters by means of setting scale with LSFitSetScale().
12209 :
12210 : NOTE 3: this function may lead to false positives. In case it reports that
12211 : I-th derivative was calculated incorrectly, you may decrease test
12212 : step and try one more time - maybe your function changes too
12213 : sharply and your step is too large for such rapidly chanding
12214 : function.
12215 :
12216 : NOTE 4: this function works only for optimizers created with LSFitCreateWFG()
12217 : or LSFitCreateFG() constructors.
12218 :
12219 : INPUT PARAMETERS:
12220 : State - structure used to store algorithm state
12221 : TestStep - verification step:
12222 : * TestStep=0 turns verification off
12223 : * TestStep>0 activates verification
12224 :
12225 : -- ALGLIB --
12226 : Copyright 15.06.2012 by Bochkanov Sergey
12227 : *************************************************************************/
12228 0 : void lsfitsetgradientcheck(const lsfitstate &state, const double teststep, const xparams _xparams)
12229 : {
12230 : jmp_buf _break_jump;
12231 : alglib_impl::ae_state _alglib_env_state;
12232 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12233 0 : if( setjmp(_break_jump) )
12234 : {
12235 : #if !defined(AE_NO_EXCEPTIONS)
12236 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12237 : #else
12238 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12239 : return;
12240 : #endif
12241 : }
12242 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12243 0 : if( _xparams.flags!=0x0 )
12244 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12245 0 : alglib_impl::lsfitsetgradientcheck(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), teststep, &_alglib_env_state);
12246 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12247 0 : return;
12248 : }
12249 : #endif
12250 :
12251 : #if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD)
12252 :
12253 : #endif
12254 :
12255 : #if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD)
12256 : /*************************************************************************
12257 : 2-dimensional spline inteprolant
12258 : *************************************************************************/
12259 0 : _spline2dinterpolant_owner::_spline2dinterpolant_owner()
12260 : {
12261 : jmp_buf _break_jump;
12262 : alglib_impl::ae_state _state;
12263 :
12264 0 : alglib_impl::ae_state_init(&_state);
12265 0 : if( setjmp(_break_jump) )
12266 : {
12267 0 : if( p_struct!=NULL )
12268 : {
12269 0 : alglib_impl::_spline2dinterpolant_destroy(p_struct);
12270 0 : alglib_impl::ae_free(p_struct);
12271 : }
12272 0 : p_struct = NULL;
12273 : #if !defined(AE_NO_EXCEPTIONS)
12274 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12275 : #else
12276 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12277 : return;
12278 : #endif
12279 : }
12280 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12281 0 : p_struct = NULL;
12282 0 : p_struct = (alglib_impl::spline2dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dinterpolant), &_state);
12283 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dinterpolant));
12284 0 : alglib_impl::_spline2dinterpolant_init(p_struct, &_state, ae_false);
12285 0 : ae_state_clear(&_state);
12286 0 : }
12287 :
12288 0 : _spline2dinterpolant_owner::_spline2dinterpolant_owner(const _spline2dinterpolant_owner &rhs)
12289 : {
12290 : jmp_buf _break_jump;
12291 : alglib_impl::ae_state _state;
12292 :
12293 0 : alglib_impl::ae_state_init(&_state);
12294 0 : if( setjmp(_break_jump) )
12295 : {
12296 0 : if( p_struct!=NULL )
12297 : {
12298 0 : alglib_impl::_spline2dinterpolant_destroy(p_struct);
12299 0 : alglib_impl::ae_free(p_struct);
12300 : }
12301 0 : p_struct = NULL;
12302 : #if !defined(AE_NO_EXCEPTIONS)
12303 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12304 : #else
12305 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12306 : return;
12307 : #endif
12308 : }
12309 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12310 0 : p_struct = NULL;
12311 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dinterpolant copy constructor failure (source is not initialized)", &_state);
12312 0 : p_struct = (alglib_impl::spline2dinterpolant*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dinterpolant), &_state);
12313 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dinterpolant));
12314 0 : alglib_impl::_spline2dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline2dinterpolant*>(rhs.p_struct), &_state, ae_false);
12315 0 : ae_state_clear(&_state);
12316 0 : }
12317 :
12318 0 : _spline2dinterpolant_owner& _spline2dinterpolant_owner::operator=(const _spline2dinterpolant_owner &rhs)
12319 : {
12320 0 : if( this==&rhs )
12321 0 : return *this;
12322 : jmp_buf _break_jump;
12323 : alglib_impl::ae_state _state;
12324 :
12325 0 : alglib_impl::ae_state_init(&_state);
12326 0 : if( setjmp(_break_jump) )
12327 : {
12328 : #if !defined(AE_NO_EXCEPTIONS)
12329 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12330 : #else
12331 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12332 : return *this;
12333 : #endif
12334 : }
12335 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12336 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline2dinterpolant assignment constructor failure (destination is not initialized)", &_state);
12337 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dinterpolant assignment constructor failure (source is not initialized)", &_state);
12338 0 : alglib_impl::_spline2dinterpolant_destroy(p_struct);
12339 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dinterpolant));
12340 0 : alglib_impl::_spline2dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline2dinterpolant*>(rhs.p_struct), &_state, ae_false);
12341 0 : ae_state_clear(&_state);
12342 0 : return *this;
12343 : }
12344 :
12345 0 : _spline2dinterpolant_owner::~_spline2dinterpolant_owner()
12346 : {
12347 0 : if( p_struct!=NULL )
12348 : {
12349 0 : alglib_impl::_spline2dinterpolant_destroy(p_struct);
12350 0 : ae_free(p_struct);
12351 : }
12352 0 : }
12353 :
12354 0 : alglib_impl::spline2dinterpolant* _spline2dinterpolant_owner::c_ptr()
12355 : {
12356 0 : return p_struct;
12357 : }
12358 :
12359 0 : alglib_impl::spline2dinterpolant* _spline2dinterpolant_owner::c_ptr() const
12360 : {
12361 0 : return const_cast<alglib_impl::spline2dinterpolant*>(p_struct);
12362 : }
12363 0 : spline2dinterpolant::spline2dinterpolant() : _spline2dinterpolant_owner()
12364 : {
12365 0 : }
12366 :
12367 0 : spline2dinterpolant::spline2dinterpolant(const spline2dinterpolant &rhs):_spline2dinterpolant_owner(rhs)
12368 : {
12369 0 : }
12370 :
12371 0 : spline2dinterpolant& spline2dinterpolant::operator=(const spline2dinterpolant &rhs)
12372 : {
12373 0 : if( this==&rhs )
12374 0 : return *this;
12375 0 : _spline2dinterpolant_owner::operator=(rhs);
12376 0 : return *this;
12377 : }
12378 :
12379 0 : spline2dinterpolant::~spline2dinterpolant()
12380 : {
12381 0 : }
12382 :
12383 :
12384 : /*************************************************************************
12385 : Nonlinear least squares solver used to fit 2D splines to data
12386 : *************************************************************************/
12387 0 : _spline2dbuilder_owner::_spline2dbuilder_owner()
12388 : {
12389 : jmp_buf _break_jump;
12390 : alglib_impl::ae_state _state;
12391 :
12392 0 : alglib_impl::ae_state_init(&_state);
12393 0 : if( setjmp(_break_jump) )
12394 : {
12395 0 : if( p_struct!=NULL )
12396 : {
12397 0 : alglib_impl::_spline2dbuilder_destroy(p_struct);
12398 0 : alglib_impl::ae_free(p_struct);
12399 : }
12400 0 : p_struct = NULL;
12401 : #if !defined(AE_NO_EXCEPTIONS)
12402 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12403 : #else
12404 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12405 : return;
12406 : #endif
12407 : }
12408 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12409 0 : p_struct = NULL;
12410 0 : p_struct = (alglib_impl::spline2dbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dbuilder), &_state);
12411 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dbuilder));
12412 0 : alglib_impl::_spline2dbuilder_init(p_struct, &_state, ae_false);
12413 0 : ae_state_clear(&_state);
12414 0 : }
12415 :
12416 0 : _spline2dbuilder_owner::_spline2dbuilder_owner(const _spline2dbuilder_owner &rhs)
12417 : {
12418 : jmp_buf _break_jump;
12419 : alglib_impl::ae_state _state;
12420 :
12421 0 : alglib_impl::ae_state_init(&_state);
12422 0 : if( setjmp(_break_jump) )
12423 : {
12424 0 : if( p_struct!=NULL )
12425 : {
12426 0 : alglib_impl::_spline2dbuilder_destroy(p_struct);
12427 0 : alglib_impl::ae_free(p_struct);
12428 : }
12429 0 : p_struct = NULL;
12430 : #if !defined(AE_NO_EXCEPTIONS)
12431 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12432 : #else
12433 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12434 : return;
12435 : #endif
12436 : }
12437 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12438 0 : p_struct = NULL;
12439 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dbuilder copy constructor failure (source is not initialized)", &_state);
12440 0 : p_struct = (alglib_impl::spline2dbuilder*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dbuilder), &_state);
12441 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dbuilder));
12442 0 : alglib_impl::_spline2dbuilder_init_copy(p_struct, const_cast<alglib_impl::spline2dbuilder*>(rhs.p_struct), &_state, ae_false);
12443 0 : ae_state_clear(&_state);
12444 0 : }
12445 :
12446 0 : _spline2dbuilder_owner& _spline2dbuilder_owner::operator=(const _spline2dbuilder_owner &rhs)
12447 : {
12448 0 : if( this==&rhs )
12449 0 : return *this;
12450 : jmp_buf _break_jump;
12451 : alglib_impl::ae_state _state;
12452 :
12453 0 : alglib_impl::ae_state_init(&_state);
12454 0 : if( setjmp(_break_jump) )
12455 : {
12456 : #if !defined(AE_NO_EXCEPTIONS)
12457 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12458 : #else
12459 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12460 : return *this;
12461 : #endif
12462 : }
12463 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12464 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline2dbuilder assignment constructor failure (destination is not initialized)", &_state);
12465 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dbuilder assignment constructor failure (source is not initialized)", &_state);
12466 0 : alglib_impl::_spline2dbuilder_destroy(p_struct);
12467 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dbuilder));
12468 0 : alglib_impl::_spline2dbuilder_init_copy(p_struct, const_cast<alglib_impl::spline2dbuilder*>(rhs.p_struct), &_state, ae_false);
12469 0 : ae_state_clear(&_state);
12470 0 : return *this;
12471 : }
12472 :
12473 0 : _spline2dbuilder_owner::~_spline2dbuilder_owner()
12474 : {
12475 0 : if( p_struct!=NULL )
12476 : {
12477 0 : alglib_impl::_spline2dbuilder_destroy(p_struct);
12478 0 : ae_free(p_struct);
12479 : }
12480 0 : }
12481 :
12482 0 : alglib_impl::spline2dbuilder* _spline2dbuilder_owner::c_ptr()
12483 : {
12484 0 : return p_struct;
12485 : }
12486 :
12487 0 : alglib_impl::spline2dbuilder* _spline2dbuilder_owner::c_ptr() const
12488 : {
12489 0 : return const_cast<alglib_impl::spline2dbuilder*>(p_struct);
12490 : }
12491 0 : spline2dbuilder::spline2dbuilder() : _spline2dbuilder_owner()
12492 : {
12493 0 : }
12494 :
12495 0 : spline2dbuilder::spline2dbuilder(const spline2dbuilder &rhs):_spline2dbuilder_owner(rhs)
12496 : {
12497 0 : }
12498 :
12499 0 : spline2dbuilder& spline2dbuilder::operator=(const spline2dbuilder &rhs)
12500 : {
12501 0 : if( this==&rhs )
12502 0 : return *this;
12503 0 : _spline2dbuilder_owner::operator=(rhs);
12504 0 : return *this;
12505 : }
12506 :
12507 0 : spline2dbuilder::~spline2dbuilder()
12508 : {
12509 0 : }
12510 :
12511 :
12512 : /*************************************************************************
12513 : Spline 2D fitting report:
12514 : rmserror RMS error
12515 : avgerror average error
12516 : maxerror maximum error
12517 : r2 coefficient of determination, R-squared, 1-RSS/TSS
12518 : *************************************************************************/
12519 0 : _spline2dfitreport_owner::_spline2dfitreport_owner()
12520 : {
12521 : jmp_buf _break_jump;
12522 : alglib_impl::ae_state _state;
12523 :
12524 0 : alglib_impl::ae_state_init(&_state);
12525 0 : if( setjmp(_break_jump) )
12526 : {
12527 0 : if( p_struct!=NULL )
12528 : {
12529 0 : alglib_impl::_spline2dfitreport_destroy(p_struct);
12530 0 : alglib_impl::ae_free(p_struct);
12531 : }
12532 0 : p_struct = NULL;
12533 : #if !defined(AE_NO_EXCEPTIONS)
12534 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12535 : #else
12536 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12537 : return;
12538 : #endif
12539 : }
12540 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12541 0 : p_struct = NULL;
12542 0 : p_struct = (alglib_impl::spline2dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dfitreport), &_state);
12543 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dfitreport));
12544 0 : alglib_impl::_spline2dfitreport_init(p_struct, &_state, ae_false);
12545 0 : ae_state_clear(&_state);
12546 0 : }
12547 :
12548 0 : _spline2dfitreport_owner::_spline2dfitreport_owner(const _spline2dfitreport_owner &rhs)
12549 : {
12550 : jmp_buf _break_jump;
12551 : alglib_impl::ae_state _state;
12552 :
12553 0 : alglib_impl::ae_state_init(&_state);
12554 0 : if( setjmp(_break_jump) )
12555 : {
12556 0 : if( p_struct!=NULL )
12557 : {
12558 0 : alglib_impl::_spline2dfitreport_destroy(p_struct);
12559 0 : alglib_impl::ae_free(p_struct);
12560 : }
12561 0 : p_struct = NULL;
12562 : #if !defined(AE_NO_EXCEPTIONS)
12563 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12564 : #else
12565 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12566 : return;
12567 : #endif
12568 : }
12569 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12570 0 : p_struct = NULL;
12571 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dfitreport copy constructor failure (source is not initialized)", &_state);
12572 0 : p_struct = (alglib_impl::spline2dfitreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::spline2dfitreport), &_state);
12573 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dfitreport));
12574 0 : alglib_impl::_spline2dfitreport_init_copy(p_struct, const_cast<alglib_impl::spline2dfitreport*>(rhs.p_struct), &_state, ae_false);
12575 0 : ae_state_clear(&_state);
12576 0 : }
12577 :
12578 0 : _spline2dfitreport_owner& _spline2dfitreport_owner::operator=(const _spline2dfitreport_owner &rhs)
12579 : {
12580 0 : if( this==&rhs )
12581 0 : return *this;
12582 : jmp_buf _break_jump;
12583 : alglib_impl::ae_state _state;
12584 :
12585 0 : alglib_impl::ae_state_init(&_state);
12586 0 : if( setjmp(_break_jump) )
12587 : {
12588 : #if !defined(AE_NO_EXCEPTIONS)
12589 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12590 : #else
12591 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12592 : return *this;
12593 : #endif
12594 : }
12595 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12596 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: spline2dfitreport assignment constructor failure (destination is not initialized)", &_state);
12597 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: spline2dfitreport assignment constructor failure (source is not initialized)", &_state);
12598 0 : alglib_impl::_spline2dfitreport_destroy(p_struct);
12599 0 : memset(p_struct, 0, sizeof(alglib_impl::spline2dfitreport));
12600 0 : alglib_impl::_spline2dfitreport_init_copy(p_struct, const_cast<alglib_impl::spline2dfitreport*>(rhs.p_struct), &_state, ae_false);
12601 0 : ae_state_clear(&_state);
12602 0 : return *this;
12603 : }
12604 :
12605 0 : _spline2dfitreport_owner::~_spline2dfitreport_owner()
12606 : {
12607 0 : if( p_struct!=NULL )
12608 : {
12609 0 : alglib_impl::_spline2dfitreport_destroy(p_struct);
12610 0 : ae_free(p_struct);
12611 : }
12612 0 : }
12613 :
12614 0 : alglib_impl::spline2dfitreport* _spline2dfitreport_owner::c_ptr()
12615 : {
12616 0 : return p_struct;
12617 : }
12618 :
12619 0 : alglib_impl::spline2dfitreport* _spline2dfitreport_owner::c_ptr() const
12620 : {
12621 0 : return const_cast<alglib_impl::spline2dfitreport*>(p_struct);
12622 : }
12623 0 : spline2dfitreport::spline2dfitreport() : _spline2dfitreport_owner() ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2)
12624 : {
12625 0 : }
12626 :
12627 0 : spline2dfitreport::spline2dfitreport(const spline2dfitreport &rhs):_spline2dfitreport_owner(rhs) ,rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),maxerror(p_struct->maxerror),r2(p_struct->r2)
12628 : {
12629 0 : }
12630 :
12631 0 : spline2dfitreport& spline2dfitreport::operator=(const spline2dfitreport &rhs)
12632 : {
12633 0 : if( this==&rhs )
12634 0 : return *this;
12635 0 : _spline2dfitreport_owner::operator=(rhs);
12636 0 : return *this;
12637 : }
12638 :
12639 0 : spline2dfitreport::~spline2dfitreport()
12640 : {
12641 0 : }
12642 :
12643 :
12644 : /*************************************************************************
12645 : This function serializes data structure to string.
12646 :
12647 : Important properties of s_out:
12648 : * it contains alphanumeric characters, dots, underscores, minus signs
12649 : * these symbols are grouped into words, which are separated by spaces
12650 : and Windows-style (CR+LF) newlines
12651 : * although serializer uses spaces and CR+LF as separators, you can
12652 : replace any separator character by arbitrary combination of spaces,
12653 : tabs, Windows or Unix newlines. It allows flexible reformatting of
12654 : the string in case you want to include it into text or XML file.
12655 : But you should not insert separators into the middle of the "words"
12656 : nor you should change case of letters.
12657 : * s_out can be freely moved between 32-bit and 64-bit systems, little
12658 : and big endian machines, and so on. You can serialize structure on
12659 : 32-bit machine and unserialize it on 64-bit one (or vice versa), or
12660 : serialize it on SPARC and unserialize on x86. You can also
12661 : serialize it in C++ version of ALGLIB and unserialize in C# one,
12662 : and vice versa.
12663 : *************************************************************************/
12664 0 : void spline2dserialize(spline2dinterpolant &obj, std::string &s_out)
12665 : {
12666 : jmp_buf _break_jump;
12667 : alglib_impl::ae_state state;
12668 : alglib_impl::ae_serializer serializer;
12669 : alglib_impl::ae_int_t ssize;
12670 :
12671 0 : alglib_impl::ae_state_init(&state);
12672 0 : if( setjmp(_break_jump) )
12673 : {
12674 : #if !defined(AE_NO_EXCEPTIONS)
12675 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
12676 : #else
12677 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
12678 : return;
12679 : #endif
12680 : }
12681 0 : ae_state_set_break_jump(&state, &_break_jump);
12682 0 : alglib_impl::ae_serializer_init(&serializer);
12683 0 : alglib_impl::ae_serializer_alloc_start(&serializer);
12684 0 : alglib_impl::spline2dalloc(&serializer, obj.c_ptr(), &state);
12685 0 : ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer);
12686 0 : s_out.clear();
12687 0 : s_out.reserve((size_t)(ssize+1));
12688 0 : alglib_impl::ae_serializer_sstart_str(&serializer, &s_out);
12689 0 : alglib_impl::spline2dserialize(&serializer, obj.c_ptr(), &state);
12690 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
12691 0 : alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state);
12692 0 : alglib_impl::ae_serializer_clear(&serializer);
12693 0 : alglib_impl::ae_state_clear(&state);
12694 0 : }
12695 : /*************************************************************************
12696 : This function unserializes data structure from string.
12697 : *************************************************************************/
12698 0 : void spline2dunserialize(const std::string &s_in, spline2dinterpolant &obj)
12699 : {
12700 : jmp_buf _break_jump;
12701 : alglib_impl::ae_state state;
12702 : alglib_impl::ae_serializer serializer;
12703 :
12704 0 : alglib_impl::ae_state_init(&state);
12705 0 : if( setjmp(_break_jump) )
12706 : {
12707 : #if !defined(AE_NO_EXCEPTIONS)
12708 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
12709 : #else
12710 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
12711 : return;
12712 : #endif
12713 : }
12714 0 : ae_state_set_break_jump(&state, &_break_jump);
12715 0 : alglib_impl::ae_serializer_init(&serializer);
12716 0 : alglib_impl::ae_serializer_ustart_str(&serializer, &s_in);
12717 0 : alglib_impl::spline2dunserialize(&serializer, obj.c_ptr(), &state);
12718 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
12719 0 : alglib_impl::ae_serializer_clear(&serializer);
12720 0 : alglib_impl::ae_state_clear(&state);
12721 0 : }
12722 :
12723 :
12724 : /*************************************************************************
12725 : This function serializes data structure to C++ stream.
12726 :
12727 : Data stream generated by this function is same as string representation
12728 : generated by string version of serializer - alphanumeric characters,
12729 : dots, underscores, minus signs, which are grouped into words separated by
12730 : spaces and CR+LF.
12731 :
12732 : We recommend you to read comments on string version of serializer to find
12733 : out more about serialization of AlGLIB objects.
12734 : *************************************************************************/
12735 0 : void spline2dserialize(spline2dinterpolant &obj, std::ostream &s_out)
12736 : {
12737 : jmp_buf _break_jump;
12738 : alglib_impl::ae_state state;
12739 : alglib_impl::ae_serializer serializer;
12740 :
12741 0 : alglib_impl::ae_state_init(&state);
12742 0 : if( setjmp(_break_jump) )
12743 : {
12744 : #if !defined(AE_NO_EXCEPTIONS)
12745 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
12746 : #else
12747 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
12748 : return;
12749 : #endif
12750 : }
12751 0 : ae_state_set_break_jump(&state, &_break_jump);
12752 0 : alglib_impl::ae_serializer_init(&serializer);
12753 0 : alglib_impl::ae_serializer_alloc_start(&serializer);
12754 0 : alglib_impl::spline2dalloc(&serializer, obj.c_ptr(), &state);
12755 0 : alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask
12756 0 : alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out);
12757 0 : alglib_impl::spline2dserialize(&serializer, obj.c_ptr(), &state);
12758 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
12759 0 : alglib_impl::ae_serializer_clear(&serializer);
12760 0 : alglib_impl::ae_state_clear(&state);
12761 0 : }
12762 : /*************************************************************************
12763 : This function unserializes data structure from stream.
12764 : *************************************************************************/
12765 0 : void spline2dunserialize(const std::istream &s_in, spline2dinterpolant &obj)
12766 : {
12767 : jmp_buf _break_jump;
12768 : alglib_impl::ae_state state;
12769 : alglib_impl::ae_serializer serializer;
12770 :
12771 0 : alglib_impl::ae_state_init(&state);
12772 0 : if( setjmp(_break_jump) )
12773 : {
12774 : #if !defined(AE_NO_EXCEPTIONS)
12775 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
12776 : #else
12777 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
12778 : return;
12779 : #endif
12780 : }
12781 0 : ae_state_set_break_jump(&state, &_break_jump);
12782 0 : alglib_impl::ae_serializer_init(&serializer);
12783 0 : alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in);
12784 0 : alglib_impl::spline2dunserialize(&serializer, obj.c_ptr(), &state);
12785 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
12786 0 : alglib_impl::ae_serializer_clear(&serializer);
12787 0 : alglib_impl::ae_state_clear(&state);
12788 0 : }
12789 :
12790 : /*************************************************************************
12791 : This subroutine calculates the value of the bilinear or bicubic spline at
12792 : the given point X.
12793 :
12794 : Input parameters:
12795 : C - 2D spline object.
12796 : Built by spline2dbuildbilinearv or spline2dbuildbicubicv.
12797 : X, Y- point
12798 :
12799 : Result:
12800 : S(x,y)
12801 :
12802 : -- ALGLIB PROJECT --
12803 : Copyright 05.07.2007 by Bochkanov Sergey
12804 : *************************************************************************/
12805 0 : double spline2dcalc(const spline2dinterpolant &c, const double x, const double y, const xparams _xparams)
12806 : {
12807 : jmp_buf _break_jump;
12808 : alglib_impl::ae_state _alglib_env_state;
12809 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12810 0 : if( setjmp(_break_jump) )
12811 : {
12812 : #if !defined(AE_NO_EXCEPTIONS)
12813 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12814 : #else
12815 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12816 : return 0;
12817 : #endif
12818 : }
12819 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12820 0 : if( _xparams.flags!=0x0 )
12821 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12822 0 : double result = alglib_impl::spline2dcalc(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, &_alglib_env_state);
12823 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12824 0 : return *(reinterpret_cast<double*>(&result));
12825 : }
12826 :
12827 : /*************************************************************************
12828 : This subroutine calculates the value of the bilinear or bicubic spline at
12829 : the given point X and its derivatives.
12830 :
12831 : Input parameters:
12832 : C - spline interpolant.
12833 : X, Y- point
12834 :
12835 : Output parameters:
12836 : F - S(x,y)
12837 : FX - dS(x,y)/dX
12838 : FY - dS(x,y)/dY
12839 : FXY - d2S(x,y)/dXdY
12840 :
12841 : -- ALGLIB PROJECT --
12842 : Copyright 05.07.2007 by Bochkanov Sergey
12843 : *************************************************************************/
12844 0 : void spline2ddiff(const spline2dinterpolant &c, const double x, const double y, double &f, double &fx, double &fy, double &fxy, const xparams _xparams)
12845 : {
12846 : jmp_buf _break_jump;
12847 : alglib_impl::ae_state _alglib_env_state;
12848 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12849 0 : if( setjmp(_break_jump) )
12850 : {
12851 : #if !defined(AE_NO_EXCEPTIONS)
12852 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12853 : #else
12854 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12855 : return;
12856 : #endif
12857 : }
12858 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12859 0 : if( _xparams.flags!=0x0 )
12860 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12861 0 : alglib_impl::spline2ddiff(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, &f, &fx, &fy, &fxy, &_alglib_env_state);
12862 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12863 0 : return;
12864 : }
12865 :
12866 : /*************************************************************************
12867 : This subroutine calculates bilinear or bicubic vector-valued spline at the
12868 : given point (X,Y).
12869 :
12870 : If you need just some specific component of vector-valued spline, you can
12871 : use spline2dcalcvi() function.
12872 :
12873 : INPUT PARAMETERS:
12874 : C - spline interpolant.
12875 : X, Y- point
12876 : F - output buffer, possibly preallocated array. In case array size
12877 : is large enough to store result, it is not reallocated. Array
12878 : which is too short will be reallocated
12879 :
12880 : OUTPUT PARAMETERS:
12881 : F - array[D] (or larger) which stores function values
12882 :
12883 : -- ALGLIB PROJECT --
12884 : Copyright 01.02.2018 by Bochkanov Sergey
12885 : *************************************************************************/
12886 0 : void spline2dcalcvbuf(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f, const xparams _xparams)
12887 : {
12888 : jmp_buf _break_jump;
12889 : alglib_impl::ae_state _alglib_env_state;
12890 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12891 0 : if( setjmp(_break_jump) )
12892 : {
12893 : #if !defined(AE_NO_EXCEPTIONS)
12894 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12895 : #else
12896 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12897 : return;
12898 : #endif
12899 : }
12900 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12901 0 : if( _xparams.flags!=0x0 )
12902 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12903 0 : alglib_impl::spline2dcalcvbuf(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), &_alglib_env_state);
12904 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12905 0 : return;
12906 : }
12907 :
12908 : /*************************************************************************
12909 : This subroutine calculates specific component of vector-valued bilinear or
12910 : bicubic spline at the given point (X,Y).
12911 :
12912 : INPUT PARAMETERS:
12913 : C - spline interpolant.
12914 : X, Y- point
12915 : I - component index, in [0,D). An exception is generated for out
12916 : of range values.
12917 :
12918 : RESULT:
12919 : value of I-th component
12920 :
12921 : -- ALGLIB PROJECT --
12922 : Copyright 01.02.2018 by Bochkanov Sergey
12923 : *************************************************************************/
12924 0 : double spline2dcalcvi(const spline2dinterpolant &c, const double x, const double y, const ae_int_t i, const xparams _xparams)
12925 : {
12926 : jmp_buf _break_jump;
12927 : alglib_impl::ae_state _alglib_env_state;
12928 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12929 0 : if( setjmp(_break_jump) )
12930 : {
12931 : #if !defined(AE_NO_EXCEPTIONS)
12932 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12933 : #else
12934 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12935 : return 0;
12936 : #endif
12937 : }
12938 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12939 0 : if( _xparams.flags!=0x0 )
12940 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12941 0 : double result = alglib_impl::spline2dcalcvi(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, i, &_alglib_env_state);
12942 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12943 0 : return *(reinterpret_cast<double*>(&result));
12944 : }
12945 :
12946 : /*************************************************************************
12947 : This subroutine calculates bilinear or bicubic vector-valued spline at the
12948 : given point (X,Y).
12949 :
12950 : INPUT PARAMETERS:
12951 : C - spline interpolant.
12952 : X, Y- point
12953 :
12954 : OUTPUT PARAMETERS:
12955 : F - array[D] which stores function values. F is out-parameter and
12956 : it is reallocated after call to this function. In case you
12957 : want to reuse previously allocated F, you may use
12958 : Spline2DCalcVBuf(), which reallocates F only when it is too
12959 : small.
12960 :
12961 : -- ALGLIB PROJECT --
12962 : Copyright 16.04.2012 by Bochkanov Sergey
12963 : *************************************************************************/
12964 0 : void spline2dcalcv(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f, const xparams _xparams)
12965 : {
12966 : jmp_buf _break_jump;
12967 : alglib_impl::ae_state _alglib_env_state;
12968 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12969 0 : if( setjmp(_break_jump) )
12970 : {
12971 : #if !defined(AE_NO_EXCEPTIONS)
12972 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12973 : #else
12974 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12975 : return;
12976 : #endif
12977 : }
12978 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12979 0 : if( _xparams.flags!=0x0 )
12980 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12981 0 : alglib_impl::spline2dcalcv(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), &_alglib_env_state);
12982 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12983 0 : return;
12984 : }
12985 :
12986 : /*************************************************************************
12987 : This subroutine calculates value of specific component of bilinear or
12988 : bicubic vector-valued spline and its derivatives.
12989 :
12990 : Input parameters:
12991 : C - spline interpolant.
12992 : X, Y- point
12993 : I - component index, in [0,D)
12994 :
12995 : Output parameters:
12996 : F - S(x,y)
12997 : FX - dS(x,y)/dX
12998 : FY - dS(x,y)/dY
12999 : FXY - d2S(x,y)/dXdY
13000 :
13001 : -- ALGLIB PROJECT --
13002 : Copyright 05.07.2007 by Bochkanov Sergey
13003 : *************************************************************************/
13004 0 : void spline2ddiffvi(const spline2dinterpolant &c, const double x, const double y, const ae_int_t i, double &f, double &fx, double &fy, double &fxy, const xparams _xparams)
13005 : {
13006 : jmp_buf _break_jump;
13007 : alglib_impl::ae_state _alglib_env_state;
13008 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13009 0 : if( setjmp(_break_jump) )
13010 : {
13011 : #if !defined(AE_NO_EXCEPTIONS)
13012 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13013 : #else
13014 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13015 : return;
13016 : #endif
13017 : }
13018 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13019 0 : if( _xparams.flags!=0x0 )
13020 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13021 0 : alglib_impl::spline2ddiffvi(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, i, &f, &fx, &fy, &fxy, &_alglib_env_state);
13022 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13023 0 : return;
13024 : }
13025 :
13026 : /*************************************************************************
13027 : This subroutine performs linear transformation of the spline argument.
13028 :
13029 : Input parameters:
13030 : C - spline interpolant
13031 : AX, BX - transformation coefficients: x = A*t + B
13032 : AY, BY - transformation coefficients: y = A*u + B
13033 : Result:
13034 : C - transformed spline
13035 :
13036 : -- ALGLIB PROJECT --
13037 : Copyright 30.06.2007 by Bochkanov Sergey
13038 : *************************************************************************/
13039 0 : void spline2dlintransxy(const spline2dinterpolant &c, const double ax, const double bx, const double ay, const double by, const xparams _xparams)
13040 : {
13041 : jmp_buf _break_jump;
13042 : alglib_impl::ae_state _alglib_env_state;
13043 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13044 0 : if( setjmp(_break_jump) )
13045 : {
13046 : #if !defined(AE_NO_EXCEPTIONS)
13047 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13048 : #else
13049 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13050 : return;
13051 : #endif
13052 : }
13053 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13054 0 : if( _xparams.flags!=0x0 )
13055 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13056 0 : alglib_impl::spline2dlintransxy(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), ax, bx, ay, by, &_alglib_env_state);
13057 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13058 0 : return;
13059 : }
13060 :
13061 : /*************************************************************************
13062 : This subroutine performs linear transformation of the spline.
13063 :
13064 : Input parameters:
13065 : C - spline interpolant.
13066 : A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B
13067 :
13068 : Output parameters:
13069 : C - transformed spline
13070 :
13071 : -- ALGLIB PROJECT --
13072 : Copyright 30.06.2007 by Bochkanov Sergey
13073 : *************************************************************************/
13074 0 : void spline2dlintransf(const spline2dinterpolant &c, const double a, const double b, const xparams _xparams)
13075 : {
13076 : jmp_buf _break_jump;
13077 : alglib_impl::ae_state _alglib_env_state;
13078 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13079 0 : if( setjmp(_break_jump) )
13080 : {
13081 : #if !defined(AE_NO_EXCEPTIONS)
13082 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13083 : #else
13084 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13085 : return;
13086 : #endif
13087 : }
13088 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13089 0 : if( _xparams.flags!=0x0 )
13090 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13091 0 : alglib_impl::spline2dlintransf(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
13092 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13093 0 : return;
13094 : }
13095 :
13096 : /*************************************************************************
13097 : This subroutine makes the copy of the spline model.
13098 :
13099 : Input parameters:
13100 : C - spline interpolant
13101 :
13102 : Output parameters:
13103 : CC - spline copy
13104 :
13105 : -- ALGLIB PROJECT --
13106 : Copyright 29.06.2007 by Bochkanov Sergey
13107 : *************************************************************************/
13108 0 : void spline2dcopy(const spline2dinterpolant &c, spline2dinterpolant &cc, const xparams _xparams)
13109 : {
13110 : jmp_buf _break_jump;
13111 : alglib_impl::ae_state _alglib_env_state;
13112 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13113 0 : if( setjmp(_break_jump) )
13114 : {
13115 : #if !defined(AE_NO_EXCEPTIONS)
13116 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13117 : #else
13118 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13119 : return;
13120 : #endif
13121 : }
13122 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13123 0 : if( _xparams.flags!=0x0 )
13124 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13125 0 : alglib_impl::spline2dcopy(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), const_cast<alglib_impl::spline2dinterpolant*>(cc.c_ptr()), &_alglib_env_state);
13126 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13127 0 : return;
13128 : }
13129 :
13130 : /*************************************************************************
13131 : Bicubic spline resampling
13132 :
13133 : Input parameters:
13134 : A - function values at the old grid,
13135 : array[0..OldHeight-1, 0..OldWidth-1]
13136 : OldHeight - old grid height, OldHeight>1
13137 : OldWidth - old grid width, OldWidth>1
13138 : NewHeight - new grid height, NewHeight>1
13139 : NewWidth - new grid width, NewWidth>1
13140 :
13141 : Output parameters:
13142 : B - function values at the new grid,
13143 : array[0..NewHeight-1, 0..NewWidth-1]
13144 :
13145 : -- ALGLIB routine --
13146 : 15 May, 2007
13147 : Copyright by Bochkanov Sergey
13148 : *************************************************************************/
13149 0 : void spline2dresamplebicubic(const real_2d_array &a, const ae_int_t oldheight, const ae_int_t oldwidth, real_2d_array &b, const ae_int_t newheight, const ae_int_t newwidth, const xparams _xparams)
13150 : {
13151 : jmp_buf _break_jump;
13152 : alglib_impl::ae_state _alglib_env_state;
13153 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13154 0 : if( setjmp(_break_jump) )
13155 : {
13156 : #if !defined(AE_NO_EXCEPTIONS)
13157 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13158 : #else
13159 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13160 : return;
13161 : #endif
13162 : }
13163 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13164 0 : if( _xparams.flags!=0x0 )
13165 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13166 0 : alglib_impl::spline2dresamplebicubic(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), oldheight, oldwidth, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), newheight, newwidth, &_alglib_env_state);
13167 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13168 0 : return;
13169 : }
13170 :
13171 : /*************************************************************************
13172 : Bilinear spline resampling
13173 :
13174 : Input parameters:
13175 : A - function values at the old grid,
13176 : array[0..OldHeight-1, 0..OldWidth-1]
13177 : OldHeight - old grid height, OldHeight>1
13178 : OldWidth - old grid width, OldWidth>1
13179 : NewHeight - new grid height, NewHeight>1
13180 : NewWidth - new grid width, NewWidth>1
13181 :
13182 : Output parameters:
13183 : B - function values at the new grid,
13184 : array[0..NewHeight-1, 0..NewWidth-1]
13185 :
13186 : -- ALGLIB routine --
13187 : 09.07.2007
13188 : Copyright by Bochkanov Sergey
13189 : *************************************************************************/
13190 0 : void spline2dresamplebilinear(const real_2d_array &a, const ae_int_t oldheight, const ae_int_t oldwidth, real_2d_array &b, const ae_int_t newheight, const ae_int_t newwidth, const xparams _xparams)
13191 : {
13192 : jmp_buf _break_jump;
13193 : alglib_impl::ae_state _alglib_env_state;
13194 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13195 0 : if( setjmp(_break_jump) )
13196 : {
13197 : #if !defined(AE_NO_EXCEPTIONS)
13198 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13199 : #else
13200 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13201 : return;
13202 : #endif
13203 : }
13204 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13205 0 : if( _xparams.flags!=0x0 )
13206 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13207 0 : alglib_impl::spline2dresamplebilinear(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), oldheight, oldwidth, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), newheight, newwidth, &_alglib_env_state);
13208 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13209 0 : return;
13210 : }
13211 :
13212 : /*************************************************************************
13213 : This subroutine builds bilinear vector-valued spline.
13214 :
13215 : Input parameters:
13216 : X - spline abscissas, array[0..N-1]
13217 : Y - spline ordinates, array[0..M-1]
13218 : F - function values, array[0..M*N*D-1]:
13219 : * first D elements store D values at (X[0],Y[0])
13220 : * next D elements store D values at (X[1],Y[0])
13221 : * general form - D function values at (X[i],Y[j]) are stored
13222 : at F[D*(J*N+I)...D*(J*N+I)+D-1].
13223 : M,N - grid size, M>=2, N>=2
13224 : D - vector dimension, D>=1
13225 :
13226 : Output parameters:
13227 : C - spline interpolant
13228 :
13229 : -- ALGLIB PROJECT --
13230 : Copyright 16.04.2012 by Bochkanov Sergey
13231 : *************************************************************************/
13232 0 : void spline2dbuildbilinearv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &f, const ae_int_t d, spline2dinterpolant &c, const xparams _xparams)
13233 : {
13234 : jmp_buf _break_jump;
13235 : alglib_impl::ae_state _alglib_env_state;
13236 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13237 0 : if( setjmp(_break_jump) )
13238 : {
13239 : #if !defined(AE_NO_EXCEPTIONS)
13240 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13241 : #else
13242 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13243 : return;
13244 : #endif
13245 : }
13246 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13247 0 : if( _xparams.flags!=0x0 )
13248 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13249 0 : alglib_impl::spline2dbuildbilinearv(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), m, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), d, const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), &_alglib_env_state);
13250 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13251 0 : return;
13252 : }
13253 :
13254 : /*************************************************************************
13255 : This subroutine builds bicubic vector-valued spline.
13256 :
13257 : Input parameters:
13258 : X - spline abscissas, array[0..N-1]
13259 : Y - spline ordinates, array[0..M-1]
13260 : F - function values, array[0..M*N*D-1]:
13261 : * first D elements store D values at (X[0],Y[0])
13262 : * next D elements store D values at (X[1],Y[0])
13263 : * general form - D function values at (X[i],Y[j]) are stored
13264 : at F[D*(J*N+I)...D*(J*N+I)+D-1].
13265 : M,N - grid size, M>=2, N>=2
13266 : D - vector dimension, D>=1
13267 :
13268 : Output parameters:
13269 : C - spline interpolant
13270 :
13271 : -- ALGLIB PROJECT --
13272 : Copyright 16.04.2012 by Bochkanov Sergey
13273 : *************************************************************************/
13274 0 : void spline2dbuildbicubicv(const real_1d_array &x, const ae_int_t n, const real_1d_array &y, const ae_int_t m, const real_1d_array &f, const ae_int_t d, spline2dinterpolant &c, const xparams _xparams)
13275 : {
13276 : jmp_buf _break_jump;
13277 : alglib_impl::ae_state _alglib_env_state;
13278 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13279 0 : if( setjmp(_break_jump) )
13280 : {
13281 : #if !defined(AE_NO_EXCEPTIONS)
13282 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13283 : #else
13284 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13285 : return;
13286 : #endif
13287 : }
13288 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13289 0 : if( _xparams.flags!=0x0 )
13290 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13291 0 : alglib_impl::spline2dbuildbicubicv(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), m, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), d, const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), &_alglib_env_state);
13292 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13293 0 : return;
13294 : }
13295 :
13296 : /*************************************************************************
13297 : This subroutine unpacks two-dimensional spline into the coefficients table
13298 :
13299 : Input parameters:
13300 : C - spline interpolant.
13301 :
13302 : Result:
13303 : M, N- grid size (x-axis and y-axis)
13304 : D - number of components
13305 : Tbl - coefficients table, unpacked format,
13306 : D - components: [0..(N-1)*(M-1)*D-1, 0..19].
13307 : For T=0..D-1 (component index), I = 0...N-2 (x index),
13308 : J=0..M-2 (y index):
13309 : K := T + I*D + J*D*(N-1)
13310 :
13311 : K-th row stores decomposition for T-th component of the
13312 : vector-valued function
13313 :
13314 : Tbl[K,0] = X[i]
13315 : Tbl[K,1] = X[i+1]
13316 : Tbl[K,2] = Y[j]
13317 : Tbl[K,3] = Y[j+1]
13318 : Tbl[K,4] = C00
13319 : Tbl[K,5] = C01
13320 : Tbl[K,6] = C02
13321 : Tbl[K,7] = C03
13322 : Tbl[K,8] = C10
13323 : Tbl[K,9] = C11
13324 : ...
13325 : Tbl[K,19] = C33
13326 : On each grid square spline is equals to:
13327 : S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3)
13328 : t = x-x[j]
13329 : u = y-y[i]
13330 :
13331 : -- ALGLIB PROJECT --
13332 : Copyright 16.04.2012 by Bochkanov Sergey
13333 : *************************************************************************/
13334 0 : void spline2dunpackv(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, ae_int_t &d, real_2d_array &tbl, const xparams _xparams)
13335 : {
13336 : jmp_buf _break_jump;
13337 : alglib_impl::ae_state _alglib_env_state;
13338 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13339 0 : if( setjmp(_break_jump) )
13340 : {
13341 : #if !defined(AE_NO_EXCEPTIONS)
13342 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13343 : #else
13344 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13345 : return;
13346 : #endif
13347 : }
13348 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13349 0 : if( _xparams.flags!=0x0 )
13350 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13351 0 : alglib_impl::spline2dunpackv(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), &m, &n, &d, const_cast<alglib_impl::ae_matrix*>(tbl.c_ptr()), &_alglib_env_state);
13352 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13353 0 : return;
13354 : }
13355 :
13356 : /*************************************************************************
13357 : This subroutine was deprecated in ALGLIB 3.6.0
13358 :
13359 : We recommend you to switch to Spline2DBuildBilinearV(), which is more
13360 : flexible and accepts its arguments in more convenient order.
13361 :
13362 : -- ALGLIB PROJECT --
13363 : Copyright 05.07.2007 by Bochkanov Sergey
13364 : *************************************************************************/
13365 0 : void spline2dbuildbilinear(const real_1d_array &x, const real_1d_array &y, const real_2d_array &f, const ae_int_t m, const ae_int_t n, spline2dinterpolant &c, const xparams _xparams)
13366 : {
13367 : jmp_buf _break_jump;
13368 : alglib_impl::ae_state _alglib_env_state;
13369 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13370 0 : if( setjmp(_break_jump) )
13371 : {
13372 : #if !defined(AE_NO_EXCEPTIONS)
13373 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13374 : #else
13375 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13376 : return;
13377 : #endif
13378 : }
13379 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13380 0 : if( _xparams.flags!=0x0 )
13381 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13382 0 : alglib_impl::spline2dbuildbilinear(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_matrix*>(f.c_ptr()), m, n, const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), &_alglib_env_state);
13383 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13384 0 : return;
13385 : }
13386 :
13387 : /*************************************************************************
13388 : This subroutine was deprecated in ALGLIB 3.6.0
13389 :
13390 : We recommend you to switch to Spline2DBuildBicubicV(), which is more
13391 : flexible and accepts its arguments in more convenient order.
13392 :
13393 : -- ALGLIB PROJECT --
13394 : Copyright 05.07.2007 by Bochkanov Sergey
13395 : *************************************************************************/
13396 0 : void spline2dbuildbicubic(const real_1d_array &x, const real_1d_array &y, const real_2d_array &f, const ae_int_t m, const ae_int_t n, spline2dinterpolant &c, const xparams _xparams)
13397 : {
13398 : jmp_buf _break_jump;
13399 : alglib_impl::ae_state _alglib_env_state;
13400 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13401 0 : if( setjmp(_break_jump) )
13402 : {
13403 : #if !defined(AE_NO_EXCEPTIONS)
13404 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13405 : #else
13406 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13407 : return;
13408 : #endif
13409 : }
13410 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13411 0 : if( _xparams.flags!=0x0 )
13412 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13413 0 : alglib_impl::spline2dbuildbicubic(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_matrix*>(f.c_ptr()), m, n, const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), &_alglib_env_state);
13414 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13415 0 : return;
13416 : }
13417 :
13418 : /*************************************************************************
13419 : This subroutine was deprecated in ALGLIB 3.6.0
13420 :
13421 : We recommend you to switch to Spline2DUnpackV(), which is more flexible
13422 : and accepts its arguments in more convenient order.
13423 :
13424 : -- ALGLIB PROJECT --
13425 : Copyright 29.06.2007 by Bochkanov Sergey
13426 : *************************************************************************/
13427 0 : void spline2dunpack(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, real_2d_array &tbl, const xparams _xparams)
13428 : {
13429 : jmp_buf _break_jump;
13430 : alglib_impl::ae_state _alglib_env_state;
13431 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13432 0 : if( setjmp(_break_jump) )
13433 : {
13434 : #if !defined(AE_NO_EXCEPTIONS)
13435 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13436 : #else
13437 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13438 : return;
13439 : #endif
13440 : }
13441 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13442 0 : if( _xparams.flags!=0x0 )
13443 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13444 0 : alglib_impl::spline2dunpack(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), &m, &n, const_cast<alglib_impl::ae_matrix*>(tbl.c_ptr()), &_alglib_env_state);
13445 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13446 0 : return;
13447 : }
13448 :
13449 : /*************************************************************************
13450 : This subroutine creates least squares solver used to fit 2D splines to
13451 : irregularly sampled (scattered) data.
13452 :
13453 : Solver object is used to perform spline fits as follows:
13454 : * solver object is created with spline2dbuildercreate() function
13455 : * dataset is added with spline2dbuildersetpoints() function
13456 : * fit area is chosen:
13457 : * spline2dbuildersetarea() - for user-defined area
13458 : * spline2dbuildersetareaauto() - for automatically chosen area
13459 : * number of grid nodes is chosen with spline2dbuildersetgrid()
13460 : * prior term is chosen with one of the following functions:
13461 : * spline2dbuildersetlinterm() to set linear prior
13462 : * spline2dbuildersetconstterm() to set constant prior
13463 : * spline2dbuildersetzeroterm() to set zero prior
13464 : * spline2dbuildersetuserterm() to set user-defined constant prior
13465 : * solver algorithm is chosen with either:
13466 : * spline2dbuildersetalgoblocklls() - BlockLLS algorithm, medium-scale problems
13467 : * spline2dbuildersetalgofastddm() - FastDDM algorithm, large-scale problems
13468 : * finally, fitting itself is performed with spline2dfit() function.
13469 :
13470 : Most of the steps above can be omitted, solver is configured with good
13471 : defaults. The minimum is to call:
13472 : * spline2dbuildercreate() to create solver object
13473 : * spline2dbuildersetpoints() to specify dataset
13474 : * spline2dbuildersetgrid() to tell how many nodes you need
13475 : * spline2dfit() to perform fit
13476 :
13477 : ! COMMERCIAL EDITION OF ALGLIB:
13478 : !
13479 : ! Commercial Edition of ALGLIB includes following important improvements
13480 : ! of this function:
13481 : ! * high-performance native backend with same C# interface (C# version)
13482 : ! * multithreading support (C++ and C# versions)
13483 : ! * hardware vendor (Intel) implementations of linear algebra primitives
13484 : ! (C++ and C# versions, x86/x64 platform)
13485 : !
13486 : ! We recommend you to read 'Working with commercial version' section of
13487 : ! ALGLIB Reference Manual in order to find out how to use performance-
13488 : ! related features provided by commercial edition of ALGLIB.
13489 :
13490 : INPUT PARAMETERS:
13491 : D - positive number, number of Y-components: D=1 for simple scalar
13492 : fit, D>1 for vector-valued spline fitting.
13493 :
13494 : OUTPUT PARAMETERS:
13495 : S - solver object
13496 :
13497 : -- ALGLIB PROJECT --
13498 : Copyright 29.01.2018 by Bochkanov Sergey
13499 : *************************************************************************/
13500 0 : void spline2dbuildercreate(const ae_int_t d, spline2dbuilder &state, const xparams _xparams)
13501 : {
13502 : jmp_buf _break_jump;
13503 : alglib_impl::ae_state _alglib_env_state;
13504 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13505 0 : if( setjmp(_break_jump) )
13506 : {
13507 : #if !defined(AE_NO_EXCEPTIONS)
13508 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13509 : #else
13510 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13511 : return;
13512 : #endif
13513 : }
13514 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13515 0 : if( _xparams.flags!=0x0 )
13516 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13517 0 : alglib_impl::spline2dbuildercreate(d, const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), &_alglib_env_state);
13518 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13519 0 : return;
13520 : }
13521 :
13522 : /*************************************************************************
13523 : This function sets constant prior term (model is a sum of bicubic spline
13524 : and global prior, which can be linear, constant, user-defined constant or
13525 : zero).
13526 :
13527 : Constant prior term is determined by least squares fitting.
13528 :
13529 : INPUT PARAMETERS:
13530 : S - spline builder
13531 : V - value for user-defined prior
13532 :
13533 : -- ALGLIB --
13534 : Copyright 01.02.2018 by Bochkanov Sergey
13535 : *************************************************************************/
13536 0 : void spline2dbuildersetuserterm(const spline2dbuilder &state, const double v, const xparams _xparams)
13537 : {
13538 : jmp_buf _break_jump;
13539 : alglib_impl::ae_state _alglib_env_state;
13540 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13541 0 : if( setjmp(_break_jump) )
13542 : {
13543 : #if !defined(AE_NO_EXCEPTIONS)
13544 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13545 : #else
13546 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13547 : return;
13548 : #endif
13549 : }
13550 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13551 0 : if( _xparams.flags!=0x0 )
13552 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13553 0 : alglib_impl::spline2dbuildersetuserterm(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), v, &_alglib_env_state);
13554 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13555 0 : return;
13556 : }
13557 :
13558 : /*************************************************************************
13559 : This function sets linear prior term (model is a sum of bicubic spline and
13560 : global prior, which can be linear, constant, user-defined constant or
13561 : zero).
13562 :
13563 : Linear prior term is determined by least squares fitting.
13564 :
13565 : INPUT PARAMETERS:
13566 : S - spline builder
13567 :
13568 : -- ALGLIB --
13569 : Copyright 01.02.2018 by Bochkanov Sergey
13570 : *************************************************************************/
13571 0 : void spline2dbuildersetlinterm(const spline2dbuilder &state, const xparams _xparams)
13572 : {
13573 : jmp_buf _break_jump;
13574 : alglib_impl::ae_state _alglib_env_state;
13575 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13576 0 : if( setjmp(_break_jump) )
13577 : {
13578 : #if !defined(AE_NO_EXCEPTIONS)
13579 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13580 : #else
13581 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13582 : return;
13583 : #endif
13584 : }
13585 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13586 0 : if( _xparams.flags!=0x0 )
13587 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13588 0 : alglib_impl::spline2dbuildersetlinterm(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), &_alglib_env_state);
13589 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13590 0 : return;
13591 : }
13592 :
13593 : /*************************************************************************
13594 : This function sets constant prior term (model is a sum of bicubic spline
13595 : and global prior, which can be linear, constant, user-defined constant or
13596 : zero).
13597 :
13598 : Constant prior term is determined by least squares fitting.
13599 :
13600 : INPUT PARAMETERS:
13601 : S - spline builder
13602 :
13603 : -- ALGLIB --
13604 : Copyright 01.02.2018 by Bochkanov Sergey
13605 : *************************************************************************/
13606 0 : void spline2dbuildersetconstterm(const spline2dbuilder &state, const xparams _xparams)
13607 : {
13608 : jmp_buf _break_jump;
13609 : alglib_impl::ae_state _alglib_env_state;
13610 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13611 0 : if( setjmp(_break_jump) )
13612 : {
13613 : #if !defined(AE_NO_EXCEPTIONS)
13614 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13615 : #else
13616 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13617 : return;
13618 : #endif
13619 : }
13620 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13621 0 : if( _xparams.flags!=0x0 )
13622 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13623 0 : alglib_impl::spline2dbuildersetconstterm(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), &_alglib_env_state);
13624 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13625 0 : return;
13626 : }
13627 :
13628 : /*************************************************************************
13629 : This function sets zero prior term (model is a sum of bicubic spline and
13630 : global prior, which can be linear, constant, user-defined constant or
13631 : zero).
13632 :
13633 : INPUT PARAMETERS:
13634 : S - spline builder
13635 :
13636 : -- ALGLIB --
13637 : Copyright 01.02.2018 by Bochkanov Sergey
13638 : *************************************************************************/
13639 0 : void spline2dbuildersetzeroterm(const spline2dbuilder &state, const xparams _xparams)
13640 : {
13641 : jmp_buf _break_jump;
13642 : alglib_impl::ae_state _alglib_env_state;
13643 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13644 0 : if( setjmp(_break_jump) )
13645 : {
13646 : #if !defined(AE_NO_EXCEPTIONS)
13647 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13648 : #else
13649 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13650 : return;
13651 : #endif
13652 : }
13653 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13654 0 : if( _xparams.flags!=0x0 )
13655 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13656 0 : alglib_impl::spline2dbuildersetzeroterm(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), &_alglib_env_state);
13657 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13658 0 : return;
13659 : }
13660 :
13661 : /*************************************************************************
13662 : This function adds dataset to the builder object.
13663 :
13664 : This function overrides results of the previous calls, i.e. multiple calls
13665 : of this function will result in only the last set being added.
13666 :
13667 : INPUT PARAMETERS:
13668 : S - spline 2D builder object
13669 : XY - points, array[N,2+D]. One row corresponds to one point
13670 : in the dataset. First 2 elements are coordinates, next
13671 : D elements are function values. Array may be larger than
13672 : specified, in this case only leading [N,NX+NY] elements
13673 : will be used.
13674 : N - number of points in the dataset
13675 :
13676 : -- ALGLIB --
13677 : Copyright 05.02.2018 by Bochkanov Sergey
13678 : *************************************************************************/
13679 0 : void spline2dbuildersetpoints(const spline2dbuilder &state, const real_2d_array &xy, const ae_int_t n, const xparams _xparams)
13680 : {
13681 : jmp_buf _break_jump;
13682 : alglib_impl::ae_state _alglib_env_state;
13683 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13684 0 : if( setjmp(_break_jump) )
13685 : {
13686 : #if !defined(AE_NO_EXCEPTIONS)
13687 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13688 : #else
13689 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13690 : return;
13691 : #endif
13692 : }
13693 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13694 0 : if( _xparams.flags!=0x0 )
13695 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13696 0 : alglib_impl::spline2dbuildersetpoints(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, &_alglib_env_state);
13697 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13698 0 : return;
13699 : }
13700 :
13701 : /*************************************************************************
13702 : This function sets area where 2D spline interpolant is built. "Auto" means
13703 : that area extent is determined automatically from dataset extent.
13704 :
13705 : INPUT PARAMETERS:
13706 : S - spline 2D builder object
13707 :
13708 : -- ALGLIB --
13709 : Copyright 05.02.2018 by Bochkanov Sergey
13710 : *************************************************************************/
13711 0 : void spline2dbuildersetareaauto(const spline2dbuilder &state, const xparams _xparams)
13712 : {
13713 : jmp_buf _break_jump;
13714 : alglib_impl::ae_state _alglib_env_state;
13715 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13716 0 : if( setjmp(_break_jump) )
13717 : {
13718 : #if !defined(AE_NO_EXCEPTIONS)
13719 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13720 : #else
13721 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13722 : return;
13723 : #endif
13724 : }
13725 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13726 0 : if( _xparams.flags!=0x0 )
13727 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13728 0 : alglib_impl::spline2dbuildersetareaauto(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), &_alglib_env_state);
13729 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13730 0 : return;
13731 : }
13732 :
13733 : /*************************************************************************
13734 : This function sets area where 2D spline interpolant is built to
13735 : user-defined one: [XA,XB]*[YA,YB]
13736 :
13737 : INPUT PARAMETERS:
13738 : S - spline 2D builder object
13739 : XA,XB - spatial extent in the first (X) dimension, XA<XB
13740 : YA,YB - spatial extent in the second (Y) dimension, YA<YB
13741 :
13742 : -- ALGLIB --
13743 : Copyright 05.02.2018 by Bochkanov Sergey
13744 : *************************************************************************/
13745 0 : void spline2dbuildersetarea(const spline2dbuilder &state, const double xa, const double xb, const double ya, const double yb, const xparams _xparams)
13746 : {
13747 : jmp_buf _break_jump;
13748 : alglib_impl::ae_state _alglib_env_state;
13749 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13750 0 : if( setjmp(_break_jump) )
13751 : {
13752 : #if !defined(AE_NO_EXCEPTIONS)
13753 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13754 : #else
13755 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13756 : return;
13757 : #endif
13758 : }
13759 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13760 0 : if( _xparams.flags!=0x0 )
13761 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13762 0 : alglib_impl::spline2dbuildersetarea(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), xa, xb, ya, yb, &_alglib_env_state);
13763 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13764 0 : return;
13765 : }
13766 :
13767 : /*************************************************************************
13768 : This function sets nodes count for 2D spline interpolant. Fitting is
13769 : performed on area defined with one of the "setarea" functions; this one
13770 : sets number of nodes placed upon the fitting area.
13771 :
13772 : INPUT PARAMETERS:
13773 : S - spline 2D builder object
13774 : KX - nodes count for the first (X) dimension; fitting interval
13775 : [XA,XB] is separated into KX-1 subintervals, with KX nodes
13776 : created at the boundaries.
13777 : KY - nodes count for the first (Y) dimension; fitting interval
13778 : [YA,YB] is separated into KY-1 subintervals, with KY nodes
13779 : created at the boundaries.
13780 :
13781 : NOTE: at least 4 nodes is created in each dimension, so KX and KY are
13782 : silently increased if needed.
13783 :
13784 : -- ALGLIB --
13785 : Copyright 05.02.2018 by Bochkanov Sergey
13786 : *************************************************************************/
13787 0 : void spline2dbuildersetgrid(const spline2dbuilder &state, const ae_int_t kx, const ae_int_t ky, const xparams _xparams)
13788 : {
13789 : jmp_buf _break_jump;
13790 : alglib_impl::ae_state _alglib_env_state;
13791 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13792 0 : if( setjmp(_break_jump) )
13793 : {
13794 : #if !defined(AE_NO_EXCEPTIONS)
13795 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13796 : #else
13797 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13798 : return;
13799 : #endif
13800 : }
13801 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13802 0 : if( _xparams.flags!=0x0 )
13803 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13804 0 : alglib_impl::spline2dbuildersetgrid(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), kx, ky, &_alglib_env_state);
13805 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13806 0 : return;
13807 : }
13808 :
13809 : /*************************************************************************
13810 : This function allows you to choose least squares solver used to perform
13811 : fitting. This function sets solver algorithm to "FastDDM", which performs
13812 : fast parallel fitting by splitting problem into smaller chunks and merging
13813 : results together.
13814 :
13815 : This solver is optimized for large-scale problems, starting from 256x256
13816 : grids, and up to 10000x10000 grids. Of course, it will work for smaller
13817 : grids too.
13818 :
13819 : More detailed description of the algorithm is given below:
13820 : * algorithm generates hierarchy of nested grids, ranging from ~16x16
13821 : (topmost "layer" of the model) to ~KX*KY one (final layer). Upper layers
13822 : model global behavior of the function, lower layers are used to model
13823 : fine details. Moving from layer to layer doubles grid density.
13824 : * fitting is started from topmost layer, subsequent layers are fitted
13825 : using residuals from previous ones.
13826 : * user may choose to skip generation of upper layers and generate only a
13827 : few bottom ones, which will result in much better performance and
13828 : parallelization efficiency, at the cost of algorithm inability to "patch"
13829 : large holes in the dataset.
13830 : * every layer is regularized using progressively increasing regularization
13831 : coefficient; thus, increasing LambdaV penalizes fine details first,
13832 : leaving lower frequencies almost intact for a while.
13833 : * after fitting is done, all layers are merged together into one bicubic
13834 : spline
13835 :
13836 : IMPORTANT: regularization coefficient used by this solver is different
13837 : from the one used by BlockLLS. Latter utilizes nonlinearity
13838 : penalty, which is global in nature (large regularization
13839 : results in global linear trend being extracted); this solver
13840 : uses another, localized form of penalty, which is suitable for
13841 : parallel processing.
13842 :
13843 : Notes on memory and performance:
13844 : * memory requirements: most memory is consumed during modeling of the
13845 : higher layers; ~[512*NPoints] bytes is required for a model with full
13846 : hierarchy of grids being generated. However, if you skip a few topmost
13847 : layers, you will get nearly constant (wrt. points count and grid size)
13848 : memory consumption.
13849 : * serial running time: O(K*K)+O(NPoints) for a KxK grid
13850 : * parallelism potential: good. You may get nearly linear speed-up when
13851 : performing fitting with just a few layers. Adding more layers results in
13852 : model becoming more global, which somewhat reduces efficiency of the
13853 : parallel code.
13854 :
13855 : ! COMMERCIAL EDITION OF ALGLIB:
13856 : !
13857 : ! Commercial Edition of ALGLIB includes following important improvements
13858 : ! of this function:
13859 : ! * high-performance native backend with same C# interface (C# version)
13860 : ! * multithreading support (C++ and C# versions)
13861 : ! * hardware vendor (Intel) implementations of linear algebra primitives
13862 : ! (C++ and C# versions, x86/x64 platform)
13863 : !
13864 : ! We recommend you to read 'Working with commercial version' section of
13865 : ! ALGLIB Reference Manual in order to find out how to use performance-
13866 : ! related features provided by commercial edition of ALGLIB.
13867 :
13868 : INPUT PARAMETERS:
13869 : S - spline 2D builder object
13870 : NLayers - number of layers in the model:
13871 : * NLayers>=1 means that up to chosen number of bottom
13872 : layers is fitted
13873 : * NLayers=0 means that maximum number of layers is chosen
13874 : (according to current grid size)
13875 : * NLayers<=-1 means that up to |NLayers| topmost layers is
13876 : skipped
13877 : Recommendations:
13878 : * good "default" value is 2 layers
13879 : * you may need more layers, if your dataset is very
13880 : irregular and you want to "patch" large holes. For a
13881 : grid step H (equal to AreaWidth/GridSize) you may expect
13882 : that last layer reproduces variations at distance H (and
13883 : can patch holes that wide); that higher layers operate
13884 : at distances 2*H, 4*H, 8*H and so on.
13885 : * good value for "bullletproof" mode is NLayers=0, which
13886 : results in complete hierarchy of layers being generated.
13887 : LambdaV - regularization coefficient, chosen in such a way that it
13888 : penalizes bottom layers (fine details) first.
13889 : LambdaV>=0, zero value means that no penalty is applied.
13890 :
13891 : -- ALGLIB --
13892 : Copyright 05.02.2018 by Bochkanov Sergey
13893 : *************************************************************************/
13894 0 : void spline2dbuildersetalgofastddm(const spline2dbuilder &state, const ae_int_t nlayers, const double lambdav, const xparams _xparams)
13895 : {
13896 : jmp_buf _break_jump;
13897 : alglib_impl::ae_state _alglib_env_state;
13898 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13899 0 : if( setjmp(_break_jump) )
13900 : {
13901 : #if !defined(AE_NO_EXCEPTIONS)
13902 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13903 : #else
13904 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13905 : return;
13906 : #endif
13907 : }
13908 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13909 0 : if( _xparams.flags!=0x0 )
13910 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13911 0 : alglib_impl::spline2dbuildersetalgofastddm(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), nlayers, lambdav, &_alglib_env_state);
13912 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13913 0 : return;
13914 : }
13915 :
13916 : /*************************************************************************
13917 : This function allows you to choose least squares solver used to perform
13918 : fitting. This function sets solver algorithm to "BlockLLS", which performs
13919 : least squares fitting with fast sparse direct solver, with optional
13920 : nonsmoothness penalty being applied.
13921 :
13922 : Nonlinearity penalty has the following form:
13923 :
13924 : [ ]
13925 : P() ~ Lambda* integral[ (d2S/dx2)^2 + 2*(d2S/dxdy)^2 + (d2S/dy2)^2 ]dxdy
13926 : [ ]
13927 :
13928 : here integral is calculated over entire grid, and "~" means "proportional"
13929 : because integral is normalized after calcilation. Extremely large values
13930 : of Lambda result in linear fit being performed.
13931 :
13932 : NOTE: this algorithm is the most robust and controllable one, but it is
13933 : limited by 512x512 grids and (say) up to 1.000.000 points. However,
13934 : ALGLIB has one more spline solver: FastDDM algorithm, which is
13935 : intended for really large-scale problems (in 10M-100M range). FastDDM
13936 : algorithm also has better parallelism properties.
13937 :
13938 : More information on BlockLLS solver:
13939 : * memory requirements: ~[32*K^3+256*NPoints] bytes for KxK grid with
13940 : NPoints-sized dataset
13941 : * serial running time: O(K^4+NPoints)
13942 : * parallelism potential: limited. You may get some sublinear gain when
13943 : working with large grids (K's in 256..512 range)
13944 :
13945 : ! COMMERCIAL EDITION OF ALGLIB:
13946 : !
13947 : ! Commercial Edition of ALGLIB includes following important improvements
13948 : ! of this function:
13949 : ! * high-performance native backend with same C# interface (C# version)
13950 : ! * multithreading support (C++ and C# versions)
13951 : ! * hardware vendor (Intel) implementations of linear algebra primitives
13952 : ! (C++ and C# versions, x86/x64 platform)
13953 : !
13954 : ! We recommend you to read 'Working with commercial version' section of
13955 : ! ALGLIB Reference Manual in order to find out how to use performance-
13956 : ! related features provided by commercial edition of ALGLIB.
13957 :
13958 : INPUT PARAMETERS:
13959 : S - spline 2D builder object
13960 : LambdaNS- non-negative value:
13961 : * positive value means that some smoothing is applied
13962 : * zero value means that no smoothing is applied, and
13963 : corresponding entries of design matrix are numerically
13964 : zero and dropped from consideration.
13965 :
13966 : -- ALGLIB --
13967 : Copyright 05.02.2018 by Bochkanov Sergey
13968 : *************************************************************************/
13969 0 : void spline2dbuildersetalgoblocklls(const spline2dbuilder &state, const double lambdans, const xparams _xparams)
13970 : {
13971 : jmp_buf _break_jump;
13972 : alglib_impl::ae_state _alglib_env_state;
13973 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13974 0 : if( setjmp(_break_jump) )
13975 : {
13976 : #if !defined(AE_NO_EXCEPTIONS)
13977 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13978 : #else
13979 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13980 : return;
13981 : #endif
13982 : }
13983 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13984 0 : if( _xparams.flags!=0x0 )
13985 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13986 0 : alglib_impl::spline2dbuildersetalgoblocklls(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), lambdans, &_alglib_env_state);
13987 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13988 0 : return;
13989 : }
13990 :
13991 : /*************************************************************************
13992 : This function allows you to choose least squares solver used to perform
13993 : fitting. This function sets solver algorithm to "NaiveLLS".
13994 :
13995 : IMPORTANT: NaiveLLS is NOT intended to be used in real life code! This
13996 : algorithm solves problem by generated dense (K^2)x(K^2+NPoints)
13997 : matrix and solves linear least squares problem with dense
13998 : solver.
13999 :
14000 : It is here just to test BlockLLS against reference solver
14001 : (and maybe for someone trying to compare well optimized solver
14002 : against straightforward approach to the LLS problem).
14003 :
14004 : More information on naive LLS solver:
14005 : * memory requirements: ~[8*K^4+256*NPoints] bytes for KxK grid.
14006 : * serial running time: O(K^6+NPoints) for KxK grid
14007 : * when compared with BlockLLS, NaiveLLS has ~K larger memory demand and
14008 : ~K^2 larger running time.
14009 :
14010 : INPUT PARAMETERS:
14011 : S - spline 2D builder object
14012 : LambdaNS- nonsmoothness penalty
14013 :
14014 : -- ALGLIB --
14015 : Copyright 05.02.2018 by Bochkanov Sergey
14016 : *************************************************************************/
14017 0 : void spline2dbuildersetalgonaivells(const spline2dbuilder &state, const double lambdans, const xparams _xparams)
14018 : {
14019 : jmp_buf _break_jump;
14020 : alglib_impl::ae_state _alglib_env_state;
14021 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14022 0 : if( setjmp(_break_jump) )
14023 : {
14024 : #if !defined(AE_NO_EXCEPTIONS)
14025 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14026 : #else
14027 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14028 : return;
14029 : #endif
14030 : }
14031 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14032 0 : if( _xparams.flags!=0x0 )
14033 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14034 0 : alglib_impl::spline2dbuildersetalgonaivells(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), lambdans, &_alglib_env_state);
14035 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14036 0 : return;
14037 : }
14038 :
14039 : /*************************************************************************
14040 : This function fits bicubic spline to current dataset, using current area/
14041 : grid and current LLS solver.
14042 :
14043 : ! COMMERCIAL EDITION OF ALGLIB:
14044 : !
14045 : ! Commercial Edition of ALGLIB includes following important improvements
14046 : ! of this function:
14047 : ! * high-performance native backend with same C# interface (C# version)
14048 : ! * multithreading support (C++ and C# versions)
14049 : ! * hardware vendor (Intel) implementations of linear algebra primitives
14050 : ! (C++ and C# versions, x86/x64 platform)
14051 : !
14052 : ! We recommend you to read 'Working with commercial version' section of
14053 : ! ALGLIB Reference Manual in order to find out how to use performance-
14054 : ! related features provided by commercial edition of ALGLIB.
14055 :
14056 : INPUT PARAMETERS:
14057 : State - spline 2D builder object
14058 :
14059 : OUTPUT PARAMETERS:
14060 : S - 2D spline, fit result
14061 : Rep - fitting report, which provides some additional info about
14062 : errors, R2 coefficient and so on.
14063 :
14064 : -- ALGLIB --
14065 : Copyright 05.02.2018 by Bochkanov Sergey
14066 : *************************************************************************/
14067 0 : void spline2dfit(const spline2dbuilder &state, spline2dinterpolant &s, spline2dfitreport &rep, const xparams _xparams)
14068 : {
14069 : jmp_buf _break_jump;
14070 : alglib_impl::ae_state _alglib_env_state;
14071 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14072 0 : if( setjmp(_break_jump) )
14073 : {
14074 : #if !defined(AE_NO_EXCEPTIONS)
14075 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14076 : #else
14077 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14078 : return;
14079 : #endif
14080 : }
14081 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14082 0 : if( _xparams.flags!=0x0 )
14083 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14084 0 : alglib_impl::spline2dfit(const_cast<alglib_impl::spline2dbuilder*>(state.c_ptr()), const_cast<alglib_impl::spline2dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline2dfitreport*>(rep.c_ptr()), &_alglib_env_state);
14085 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14086 0 : return;
14087 : }
14088 : #endif
14089 :
14090 : #if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD)
14091 :
14092 : #endif
14093 :
14094 : #if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD)
14095 : /*************************************************************************
14096 : Buffer object which is used to perform nearest neighbor requests in the
14097 : multithreaded mode (multiple threads working with same KD-tree object).
14098 :
14099 : This object should be created with KDTreeCreateBuffer().
14100 : *************************************************************************/
14101 0 : _rbfcalcbuffer_owner::_rbfcalcbuffer_owner()
14102 : {
14103 : jmp_buf _break_jump;
14104 : alglib_impl::ae_state _state;
14105 :
14106 0 : alglib_impl::ae_state_init(&_state);
14107 0 : if( setjmp(_break_jump) )
14108 : {
14109 0 : if( p_struct!=NULL )
14110 : {
14111 0 : alglib_impl::_rbfcalcbuffer_destroy(p_struct);
14112 0 : alglib_impl::ae_free(p_struct);
14113 : }
14114 0 : p_struct = NULL;
14115 : #if !defined(AE_NO_EXCEPTIONS)
14116 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14117 : #else
14118 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14119 : return;
14120 : #endif
14121 : }
14122 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14123 0 : p_struct = NULL;
14124 0 : p_struct = (alglib_impl::rbfcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfcalcbuffer), &_state);
14125 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfcalcbuffer));
14126 0 : alglib_impl::_rbfcalcbuffer_init(p_struct, &_state, ae_false);
14127 0 : ae_state_clear(&_state);
14128 0 : }
14129 :
14130 0 : _rbfcalcbuffer_owner::_rbfcalcbuffer_owner(const _rbfcalcbuffer_owner &rhs)
14131 : {
14132 : jmp_buf _break_jump;
14133 : alglib_impl::ae_state _state;
14134 :
14135 0 : alglib_impl::ae_state_init(&_state);
14136 0 : if( setjmp(_break_jump) )
14137 : {
14138 0 : if( p_struct!=NULL )
14139 : {
14140 0 : alglib_impl::_rbfcalcbuffer_destroy(p_struct);
14141 0 : alglib_impl::ae_free(p_struct);
14142 : }
14143 0 : p_struct = NULL;
14144 : #if !defined(AE_NO_EXCEPTIONS)
14145 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14146 : #else
14147 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14148 : return;
14149 : #endif
14150 : }
14151 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14152 0 : p_struct = NULL;
14153 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfcalcbuffer copy constructor failure (source is not initialized)", &_state);
14154 0 : p_struct = (alglib_impl::rbfcalcbuffer*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfcalcbuffer), &_state);
14155 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfcalcbuffer));
14156 0 : alglib_impl::_rbfcalcbuffer_init_copy(p_struct, const_cast<alglib_impl::rbfcalcbuffer*>(rhs.p_struct), &_state, ae_false);
14157 0 : ae_state_clear(&_state);
14158 0 : }
14159 :
14160 0 : _rbfcalcbuffer_owner& _rbfcalcbuffer_owner::operator=(const _rbfcalcbuffer_owner &rhs)
14161 : {
14162 0 : if( this==&rhs )
14163 0 : return *this;
14164 : jmp_buf _break_jump;
14165 : alglib_impl::ae_state _state;
14166 :
14167 0 : alglib_impl::ae_state_init(&_state);
14168 0 : if( setjmp(_break_jump) )
14169 : {
14170 : #if !defined(AE_NO_EXCEPTIONS)
14171 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14172 : #else
14173 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14174 : return *this;
14175 : #endif
14176 : }
14177 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14178 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: rbfcalcbuffer assignment constructor failure (destination is not initialized)", &_state);
14179 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfcalcbuffer assignment constructor failure (source is not initialized)", &_state);
14180 0 : alglib_impl::_rbfcalcbuffer_destroy(p_struct);
14181 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfcalcbuffer));
14182 0 : alglib_impl::_rbfcalcbuffer_init_copy(p_struct, const_cast<alglib_impl::rbfcalcbuffer*>(rhs.p_struct), &_state, ae_false);
14183 0 : ae_state_clear(&_state);
14184 0 : return *this;
14185 : }
14186 :
14187 0 : _rbfcalcbuffer_owner::~_rbfcalcbuffer_owner()
14188 : {
14189 0 : if( p_struct!=NULL )
14190 : {
14191 0 : alglib_impl::_rbfcalcbuffer_destroy(p_struct);
14192 0 : ae_free(p_struct);
14193 : }
14194 0 : }
14195 :
14196 0 : alglib_impl::rbfcalcbuffer* _rbfcalcbuffer_owner::c_ptr()
14197 : {
14198 0 : return p_struct;
14199 : }
14200 :
14201 0 : alglib_impl::rbfcalcbuffer* _rbfcalcbuffer_owner::c_ptr() const
14202 : {
14203 0 : return const_cast<alglib_impl::rbfcalcbuffer*>(p_struct);
14204 : }
14205 0 : rbfcalcbuffer::rbfcalcbuffer() : _rbfcalcbuffer_owner()
14206 : {
14207 0 : }
14208 :
14209 0 : rbfcalcbuffer::rbfcalcbuffer(const rbfcalcbuffer &rhs):_rbfcalcbuffer_owner(rhs)
14210 : {
14211 0 : }
14212 :
14213 0 : rbfcalcbuffer& rbfcalcbuffer::operator=(const rbfcalcbuffer &rhs)
14214 : {
14215 0 : if( this==&rhs )
14216 0 : return *this;
14217 0 : _rbfcalcbuffer_owner::operator=(rhs);
14218 0 : return *this;
14219 : }
14220 :
14221 0 : rbfcalcbuffer::~rbfcalcbuffer()
14222 : {
14223 0 : }
14224 :
14225 :
14226 : /*************************************************************************
14227 : RBF model.
14228 :
14229 : Never try to directly work with fields of this object - always use ALGLIB
14230 : functions to use this object.
14231 : *************************************************************************/
14232 0 : _rbfmodel_owner::_rbfmodel_owner()
14233 : {
14234 : jmp_buf _break_jump;
14235 : alglib_impl::ae_state _state;
14236 :
14237 0 : alglib_impl::ae_state_init(&_state);
14238 0 : if( setjmp(_break_jump) )
14239 : {
14240 0 : if( p_struct!=NULL )
14241 : {
14242 0 : alglib_impl::_rbfmodel_destroy(p_struct);
14243 0 : alglib_impl::ae_free(p_struct);
14244 : }
14245 0 : p_struct = NULL;
14246 : #if !defined(AE_NO_EXCEPTIONS)
14247 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14248 : #else
14249 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14250 : return;
14251 : #endif
14252 : }
14253 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14254 0 : p_struct = NULL;
14255 0 : p_struct = (alglib_impl::rbfmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfmodel), &_state);
14256 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfmodel));
14257 0 : alglib_impl::_rbfmodel_init(p_struct, &_state, ae_false);
14258 0 : ae_state_clear(&_state);
14259 0 : }
14260 :
14261 0 : _rbfmodel_owner::_rbfmodel_owner(const _rbfmodel_owner &rhs)
14262 : {
14263 : jmp_buf _break_jump;
14264 : alglib_impl::ae_state _state;
14265 :
14266 0 : alglib_impl::ae_state_init(&_state);
14267 0 : if( setjmp(_break_jump) )
14268 : {
14269 0 : if( p_struct!=NULL )
14270 : {
14271 0 : alglib_impl::_rbfmodel_destroy(p_struct);
14272 0 : alglib_impl::ae_free(p_struct);
14273 : }
14274 0 : p_struct = NULL;
14275 : #if !defined(AE_NO_EXCEPTIONS)
14276 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14277 : #else
14278 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14279 : return;
14280 : #endif
14281 : }
14282 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14283 0 : p_struct = NULL;
14284 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfmodel copy constructor failure (source is not initialized)", &_state);
14285 0 : p_struct = (alglib_impl::rbfmodel*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfmodel), &_state);
14286 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfmodel));
14287 0 : alglib_impl::_rbfmodel_init_copy(p_struct, const_cast<alglib_impl::rbfmodel*>(rhs.p_struct), &_state, ae_false);
14288 0 : ae_state_clear(&_state);
14289 0 : }
14290 :
14291 0 : _rbfmodel_owner& _rbfmodel_owner::operator=(const _rbfmodel_owner &rhs)
14292 : {
14293 0 : if( this==&rhs )
14294 0 : return *this;
14295 : jmp_buf _break_jump;
14296 : alglib_impl::ae_state _state;
14297 :
14298 0 : alglib_impl::ae_state_init(&_state);
14299 0 : if( setjmp(_break_jump) )
14300 : {
14301 : #if !defined(AE_NO_EXCEPTIONS)
14302 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14303 : #else
14304 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14305 : return *this;
14306 : #endif
14307 : }
14308 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14309 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: rbfmodel assignment constructor failure (destination is not initialized)", &_state);
14310 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfmodel assignment constructor failure (source is not initialized)", &_state);
14311 0 : alglib_impl::_rbfmodel_destroy(p_struct);
14312 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfmodel));
14313 0 : alglib_impl::_rbfmodel_init_copy(p_struct, const_cast<alglib_impl::rbfmodel*>(rhs.p_struct), &_state, ae_false);
14314 0 : ae_state_clear(&_state);
14315 0 : return *this;
14316 : }
14317 :
14318 0 : _rbfmodel_owner::~_rbfmodel_owner()
14319 : {
14320 0 : if( p_struct!=NULL )
14321 : {
14322 0 : alglib_impl::_rbfmodel_destroy(p_struct);
14323 0 : ae_free(p_struct);
14324 : }
14325 0 : }
14326 :
14327 0 : alglib_impl::rbfmodel* _rbfmodel_owner::c_ptr()
14328 : {
14329 0 : return p_struct;
14330 : }
14331 :
14332 0 : alglib_impl::rbfmodel* _rbfmodel_owner::c_ptr() const
14333 : {
14334 0 : return const_cast<alglib_impl::rbfmodel*>(p_struct);
14335 : }
14336 0 : rbfmodel::rbfmodel() : _rbfmodel_owner()
14337 : {
14338 0 : }
14339 :
14340 0 : rbfmodel::rbfmodel(const rbfmodel &rhs):_rbfmodel_owner(rhs)
14341 : {
14342 0 : }
14343 :
14344 0 : rbfmodel& rbfmodel::operator=(const rbfmodel &rhs)
14345 : {
14346 0 : if( this==&rhs )
14347 0 : return *this;
14348 0 : _rbfmodel_owner::operator=(rhs);
14349 0 : return *this;
14350 : }
14351 :
14352 0 : rbfmodel::~rbfmodel()
14353 : {
14354 0 : }
14355 :
14356 :
14357 : /*************************************************************************
14358 : RBF solution report:
14359 : * TerminationType - termination type, positive values - success,
14360 : non-positive - failure.
14361 :
14362 : Fields which are set by modern RBF solvers (hierarchical):
14363 : * RMSError - root-mean-square error; NAN for old solvers (ML, QNN)
14364 : * MaxError - maximum error; NAN for old solvers (ML, QNN)
14365 : *************************************************************************/
14366 0 : _rbfreport_owner::_rbfreport_owner()
14367 : {
14368 : jmp_buf _break_jump;
14369 : alglib_impl::ae_state _state;
14370 :
14371 0 : alglib_impl::ae_state_init(&_state);
14372 0 : if( setjmp(_break_jump) )
14373 : {
14374 0 : if( p_struct!=NULL )
14375 : {
14376 0 : alglib_impl::_rbfreport_destroy(p_struct);
14377 0 : alglib_impl::ae_free(p_struct);
14378 : }
14379 0 : p_struct = NULL;
14380 : #if !defined(AE_NO_EXCEPTIONS)
14381 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14382 : #else
14383 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14384 : return;
14385 : #endif
14386 : }
14387 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14388 0 : p_struct = NULL;
14389 0 : p_struct = (alglib_impl::rbfreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfreport), &_state);
14390 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfreport));
14391 0 : alglib_impl::_rbfreport_init(p_struct, &_state, ae_false);
14392 0 : ae_state_clear(&_state);
14393 0 : }
14394 :
14395 0 : _rbfreport_owner::_rbfreport_owner(const _rbfreport_owner &rhs)
14396 : {
14397 : jmp_buf _break_jump;
14398 : alglib_impl::ae_state _state;
14399 :
14400 0 : alglib_impl::ae_state_init(&_state);
14401 0 : if( setjmp(_break_jump) )
14402 : {
14403 0 : if( p_struct!=NULL )
14404 : {
14405 0 : alglib_impl::_rbfreport_destroy(p_struct);
14406 0 : alglib_impl::ae_free(p_struct);
14407 : }
14408 0 : p_struct = NULL;
14409 : #if !defined(AE_NO_EXCEPTIONS)
14410 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14411 : #else
14412 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14413 : return;
14414 : #endif
14415 : }
14416 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14417 0 : p_struct = NULL;
14418 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfreport copy constructor failure (source is not initialized)", &_state);
14419 0 : p_struct = (alglib_impl::rbfreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::rbfreport), &_state);
14420 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfreport));
14421 0 : alglib_impl::_rbfreport_init_copy(p_struct, const_cast<alglib_impl::rbfreport*>(rhs.p_struct), &_state, ae_false);
14422 0 : ae_state_clear(&_state);
14423 0 : }
14424 :
14425 0 : _rbfreport_owner& _rbfreport_owner::operator=(const _rbfreport_owner &rhs)
14426 : {
14427 0 : if( this==&rhs )
14428 0 : return *this;
14429 : jmp_buf _break_jump;
14430 : alglib_impl::ae_state _state;
14431 :
14432 0 : alglib_impl::ae_state_init(&_state);
14433 0 : if( setjmp(_break_jump) )
14434 : {
14435 : #if !defined(AE_NO_EXCEPTIONS)
14436 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14437 : #else
14438 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14439 : return *this;
14440 : #endif
14441 : }
14442 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14443 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: rbfreport assignment constructor failure (destination is not initialized)", &_state);
14444 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: rbfreport assignment constructor failure (source is not initialized)", &_state);
14445 0 : alglib_impl::_rbfreport_destroy(p_struct);
14446 0 : memset(p_struct, 0, sizeof(alglib_impl::rbfreport));
14447 0 : alglib_impl::_rbfreport_init_copy(p_struct, const_cast<alglib_impl::rbfreport*>(rhs.p_struct), &_state, ae_false);
14448 0 : ae_state_clear(&_state);
14449 0 : return *this;
14450 : }
14451 :
14452 0 : _rbfreport_owner::~_rbfreport_owner()
14453 : {
14454 0 : if( p_struct!=NULL )
14455 : {
14456 0 : alglib_impl::_rbfreport_destroy(p_struct);
14457 0 : ae_free(p_struct);
14458 : }
14459 0 : }
14460 :
14461 0 : alglib_impl::rbfreport* _rbfreport_owner::c_ptr()
14462 : {
14463 0 : return p_struct;
14464 : }
14465 :
14466 0 : alglib_impl::rbfreport* _rbfreport_owner::c_ptr() const
14467 : {
14468 0 : return const_cast<alglib_impl::rbfreport*>(p_struct);
14469 : }
14470 0 : rbfreport::rbfreport() : _rbfreport_owner() ,rmserror(p_struct->rmserror),maxerror(p_struct->maxerror),arows(p_struct->arows),acols(p_struct->acols),annz(p_struct->annz),iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype)
14471 : {
14472 0 : }
14473 :
14474 0 : rbfreport::rbfreport(const rbfreport &rhs):_rbfreport_owner(rhs) ,rmserror(p_struct->rmserror),maxerror(p_struct->maxerror),arows(p_struct->arows),acols(p_struct->acols),annz(p_struct->annz),iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype)
14475 : {
14476 0 : }
14477 :
14478 0 : rbfreport& rbfreport::operator=(const rbfreport &rhs)
14479 : {
14480 0 : if( this==&rhs )
14481 0 : return *this;
14482 0 : _rbfreport_owner::operator=(rhs);
14483 0 : return *this;
14484 : }
14485 :
14486 0 : rbfreport::~rbfreport()
14487 : {
14488 0 : }
14489 :
14490 :
14491 : /*************************************************************************
14492 : This function serializes data structure to string.
14493 :
14494 : Important properties of s_out:
14495 : * it contains alphanumeric characters, dots, underscores, minus signs
14496 : * these symbols are grouped into words, which are separated by spaces
14497 : and Windows-style (CR+LF) newlines
14498 : * although serializer uses spaces and CR+LF as separators, you can
14499 : replace any separator character by arbitrary combination of spaces,
14500 : tabs, Windows or Unix newlines. It allows flexible reformatting of
14501 : the string in case you want to include it into text or XML file.
14502 : But you should not insert separators into the middle of the "words"
14503 : nor you should change case of letters.
14504 : * s_out can be freely moved between 32-bit and 64-bit systems, little
14505 : and big endian machines, and so on. You can serialize structure on
14506 : 32-bit machine and unserialize it on 64-bit one (or vice versa), or
14507 : serialize it on SPARC and unserialize on x86. You can also
14508 : serialize it in C++ version of ALGLIB and unserialize in C# one,
14509 : and vice versa.
14510 : *************************************************************************/
14511 0 : void rbfserialize(rbfmodel &obj, std::string &s_out)
14512 : {
14513 : jmp_buf _break_jump;
14514 : alglib_impl::ae_state state;
14515 : alglib_impl::ae_serializer serializer;
14516 : alglib_impl::ae_int_t ssize;
14517 :
14518 0 : alglib_impl::ae_state_init(&state);
14519 0 : if( setjmp(_break_jump) )
14520 : {
14521 : #if !defined(AE_NO_EXCEPTIONS)
14522 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
14523 : #else
14524 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
14525 : return;
14526 : #endif
14527 : }
14528 0 : ae_state_set_break_jump(&state, &_break_jump);
14529 0 : alglib_impl::ae_serializer_init(&serializer);
14530 0 : alglib_impl::ae_serializer_alloc_start(&serializer);
14531 0 : alglib_impl::rbfalloc(&serializer, obj.c_ptr(), &state);
14532 0 : ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer);
14533 0 : s_out.clear();
14534 0 : s_out.reserve((size_t)(ssize+1));
14535 0 : alglib_impl::ae_serializer_sstart_str(&serializer, &s_out);
14536 0 : alglib_impl::rbfserialize(&serializer, obj.c_ptr(), &state);
14537 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
14538 0 : alglib_impl::ae_assert( s_out.length()<=(size_t)ssize, "ALGLIB: serialization integrity error", &state);
14539 0 : alglib_impl::ae_serializer_clear(&serializer);
14540 0 : alglib_impl::ae_state_clear(&state);
14541 0 : }
14542 : /*************************************************************************
14543 : This function unserializes data structure from string.
14544 : *************************************************************************/
14545 0 : void rbfunserialize(const std::string &s_in, rbfmodel &obj)
14546 : {
14547 : jmp_buf _break_jump;
14548 : alglib_impl::ae_state state;
14549 : alglib_impl::ae_serializer serializer;
14550 :
14551 0 : alglib_impl::ae_state_init(&state);
14552 0 : if( setjmp(_break_jump) )
14553 : {
14554 : #if !defined(AE_NO_EXCEPTIONS)
14555 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
14556 : #else
14557 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
14558 : return;
14559 : #endif
14560 : }
14561 0 : ae_state_set_break_jump(&state, &_break_jump);
14562 0 : alglib_impl::ae_serializer_init(&serializer);
14563 0 : alglib_impl::ae_serializer_ustart_str(&serializer, &s_in);
14564 0 : alglib_impl::rbfunserialize(&serializer, obj.c_ptr(), &state);
14565 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
14566 0 : alglib_impl::ae_serializer_clear(&serializer);
14567 0 : alglib_impl::ae_state_clear(&state);
14568 0 : }
14569 :
14570 :
14571 : /*************************************************************************
14572 : This function serializes data structure to C++ stream.
14573 :
14574 : Data stream generated by this function is same as string representation
14575 : generated by string version of serializer - alphanumeric characters,
14576 : dots, underscores, minus signs, which are grouped into words separated by
14577 : spaces and CR+LF.
14578 :
14579 : We recommend you to read comments on string version of serializer to find
14580 : out more about serialization of AlGLIB objects.
14581 : *************************************************************************/
14582 0 : void rbfserialize(rbfmodel &obj, std::ostream &s_out)
14583 : {
14584 : jmp_buf _break_jump;
14585 : alglib_impl::ae_state state;
14586 : alglib_impl::ae_serializer serializer;
14587 :
14588 0 : alglib_impl::ae_state_init(&state);
14589 0 : if( setjmp(_break_jump) )
14590 : {
14591 : #if !defined(AE_NO_EXCEPTIONS)
14592 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
14593 : #else
14594 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
14595 : return;
14596 : #endif
14597 : }
14598 0 : ae_state_set_break_jump(&state, &_break_jump);
14599 0 : alglib_impl::ae_serializer_init(&serializer);
14600 0 : alglib_impl::ae_serializer_alloc_start(&serializer);
14601 0 : alglib_impl::rbfalloc(&serializer, obj.c_ptr(), &state);
14602 0 : alglib_impl::ae_serializer_get_alloc_size(&serializer); // not actually needed, but we have to ask
14603 0 : alglib_impl::ae_serializer_sstart_stream(&serializer, &s_out);
14604 0 : alglib_impl::rbfserialize(&serializer, obj.c_ptr(), &state);
14605 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
14606 0 : alglib_impl::ae_serializer_clear(&serializer);
14607 0 : alglib_impl::ae_state_clear(&state);
14608 0 : }
14609 : /*************************************************************************
14610 : This function unserializes data structure from stream.
14611 : *************************************************************************/
14612 0 : void rbfunserialize(const std::istream &s_in, rbfmodel &obj)
14613 : {
14614 : jmp_buf _break_jump;
14615 : alglib_impl::ae_state state;
14616 : alglib_impl::ae_serializer serializer;
14617 :
14618 0 : alglib_impl::ae_state_init(&state);
14619 0 : if( setjmp(_break_jump) )
14620 : {
14621 : #if !defined(AE_NO_EXCEPTIONS)
14622 0 : _ALGLIB_CPP_EXCEPTION(state.error_msg);
14623 : #else
14624 : _ALGLIB_SET_ERROR_FLAG(state.error_msg);
14625 : return;
14626 : #endif
14627 : }
14628 0 : ae_state_set_break_jump(&state, &_break_jump);
14629 0 : alglib_impl::ae_serializer_init(&serializer);
14630 0 : alglib_impl::ae_serializer_ustart_stream(&serializer, &s_in);
14631 0 : alglib_impl::rbfunserialize(&serializer, obj.c_ptr(), &state);
14632 0 : alglib_impl::ae_serializer_stop(&serializer, &state);
14633 0 : alglib_impl::ae_serializer_clear(&serializer);
14634 0 : alglib_impl::ae_state_clear(&state);
14635 0 : }
14636 :
14637 : /*************************************************************************
14638 : This function creates RBF model for a scalar (NY=1) or vector (NY>1)
14639 : function in a NX-dimensional space (NX>=1).
14640 :
14641 : Newly created model is empty. It can be used for interpolation right after
14642 : creation, but it just returns zeros. You have to add points to the model,
14643 : tune interpolation settings, and then call model construction function
14644 : rbfbuildmodel() which will update model according to your specification.
14645 :
14646 : USAGE:
14647 : 1. User creates model with rbfcreate()
14648 : 2. User adds dataset with rbfsetpoints() (points do NOT have to be on a
14649 : regular grid) or rbfsetpointsandscales().
14650 : 3. (OPTIONAL) User chooses polynomial term by calling:
14651 : * rbflinterm() to set linear term
14652 : * rbfconstterm() to set constant term
14653 : * rbfzeroterm() to set zero term
14654 : By default, linear term is used.
14655 : 4. User tweaks algorithm properties with rbfsetalgohierarchical() method
14656 : (or chooses one of the legacy algorithms - QNN (rbfsetalgoqnn) or ML
14657 : (rbfsetalgomultilayer)).
14658 : 5. User calls rbfbuildmodel() function which rebuilds model according to
14659 : the specification
14660 : 6. User may call rbfcalc() to calculate model value at the specified point,
14661 : rbfgridcalc() to calculate model values at the points of the regular
14662 : grid. User may extract model coefficients with rbfunpack() call.
14663 :
14664 : IMPORTANT: we recommend you to use latest model construction algorithm -
14665 : hierarchical RBFs, which is activated by rbfsetalgohierarchical()
14666 : function. This algorithm is the fastest one, and most memory-
14667 : efficient.
14668 : However, it is incompatible with older versions of ALGLIB
14669 : (pre-3.11). So, if you serialize hierarchical model, you will
14670 : be unable to load it in pre-3.11 ALGLIB. Other model types (QNN
14671 : and RBF-ML) are still backward-compatible.
14672 :
14673 : INPUT PARAMETERS:
14674 : NX - dimension of the space, NX>=1
14675 : NY - function dimension, NY>=1
14676 :
14677 : OUTPUT PARAMETERS:
14678 : S - RBF model (initially equals to zero)
14679 :
14680 : NOTE 1: memory requirements. RBF models require amount of memory which is
14681 : proportional to the number of data points. Some additional memory
14682 : is allocated during model construction, but most of this memory is
14683 : freed after model coefficients are calculated. Amount of this
14684 : additional memory depends on model construction algorithm being
14685 : used.
14686 :
14687 : NOTE 2: prior to ALGLIB version 3.11, RBF models supported only NX=2 or
14688 : NX=3. Any attempt to create single-dimensional or more than
14689 : 3-dimensional RBF model resulted in exception.
14690 :
14691 : ALGLIB 3.11 supports any NX>0, but models created with NX!=2 and
14692 : NX!=3 are incompatible with (a) older versions of ALGLIB, (b) old
14693 : model construction algorithms (QNN or RBF-ML).
14694 :
14695 : So, if you create a model with NX=2 or NX=3, then, depending on
14696 : specific model construction algorithm being chosen, you will (QNN
14697 : and RBF-ML) or will not (HierarchicalRBF) get backward compatibility
14698 : with older versions of ALGLIB. You have a choice here.
14699 :
14700 : However, if you create a model with NX neither 2 nor 3, you have
14701 : no backward compatibility from the start, and you are forced to
14702 : use hierarchical RBFs and ALGLIB 3.11 or later.
14703 :
14704 : -- ALGLIB --
14705 : Copyright 13.12.2011, 20.06.2016 by Bochkanov Sergey
14706 : *************************************************************************/
14707 0 : void rbfcreate(const ae_int_t nx, const ae_int_t ny, rbfmodel &s, const xparams _xparams)
14708 : {
14709 : jmp_buf _break_jump;
14710 : alglib_impl::ae_state _alglib_env_state;
14711 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14712 0 : if( setjmp(_break_jump) )
14713 : {
14714 : #if !defined(AE_NO_EXCEPTIONS)
14715 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14716 : #else
14717 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14718 : return;
14719 : #endif
14720 : }
14721 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14722 0 : if( _xparams.flags!=0x0 )
14723 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14724 0 : alglib_impl::rbfcreate(nx, ny, const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
14725 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14726 0 : return;
14727 : }
14728 :
14729 : /*************************************************************************
14730 : This function creates buffer structure which can be used to perform
14731 : parallel RBF model evaluations (with one RBF model instance being
14732 : used from multiple threads, as long as different threads use different
14733 : instances of buffer).
14734 :
14735 : This buffer object can be used with rbftscalcbuf() function (here "ts"
14736 : stands for "thread-safe", "buf" is a suffix which denotes function which
14737 : reuses previously allocated output space).
14738 :
14739 : How to use it:
14740 : * create RBF model structure with rbfcreate()
14741 : * load data, tune parameters
14742 : * call rbfbuildmodel()
14743 : * call rbfcreatecalcbuffer(), once per thread working with RBF model (you
14744 : should call this function only AFTER call to rbfbuildmodel(), see below
14745 : for more information)
14746 : * call rbftscalcbuf() from different threads, with each thread working
14747 : with its own copy of buffer object.
14748 :
14749 : INPUT PARAMETERS
14750 : S - RBF model
14751 :
14752 : OUTPUT PARAMETERS
14753 : Buf - external buffer.
14754 :
14755 :
14756 : IMPORTANT: buffer object should be used only with RBF model object which
14757 : was used to initialize buffer. Any attempt to use buffer with
14758 : different object is dangerous - you may get memory violation
14759 : error because sizes of internal arrays do not fit to dimensions
14760 : of RBF structure.
14761 :
14762 : IMPORTANT: you should call this function only for model which was built
14763 : with rbfbuildmodel() function, after successful invocation of
14764 : rbfbuildmodel(). Sizes of some internal structures are
14765 : determined only after model is built, so buffer object created
14766 : before model construction stage will be useless (and any
14767 : attempt to use it will result in exception).
14768 :
14769 : -- ALGLIB --
14770 : Copyright 02.04.2016 by Sergey Bochkanov
14771 : *************************************************************************/
14772 0 : void rbfcreatecalcbuffer(const rbfmodel &s, rbfcalcbuffer &buf, const xparams _xparams)
14773 : {
14774 : jmp_buf _break_jump;
14775 : alglib_impl::ae_state _alglib_env_state;
14776 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14777 0 : if( setjmp(_break_jump) )
14778 : {
14779 : #if !defined(AE_NO_EXCEPTIONS)
14780 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14781 : #else
14782 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14783 : return;
14784 : #endif
14785 : }
14786 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14787 0 : if( _xparams.flags!=0x0 )
14788 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14789 0 : alglib_impl::rbfcreatecalcbuffer(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::rbfcalcbuffer*>(buf.c_ptr()), &_alglib_env_state);
14790 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14791 0 : return;
14792 : }
14793 :
14794 : /*************************************************************************
14795 : This function adds dataset.
14796 :
14797 : This function overrides results of the previous calls, i.e. multiple calls
14798 : of this function will result in only the last set being added.
14799 :
14800 : IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of
14801 : per-dimension scales. Interpolation radii are multiplied by the
14802 : scale vector. It may be useful if you have mixed spatio-temporal
14803 : data (say, a set of 3D slices recorded at different times).
14804 : You should call rbfsetpointsandscales() function to use this
14805 : feature.
14806 :
14807 : INPUT PARAMETERS:
14808 : S - RBF model, initialized by rbfcreate() call.
14809 : XY - points, array[N,NX+NY]. One row corresponds to one point
14810 : in the dataset. First NX elements are coordinates, next
14811 : NY elements are function values. Array may be larger than
14812 : specified, in this case only leading [N,NX+NY] elements
14813 : will be used.
14814 : N - number of points in the dataset
14815 :
14816 : After you've added dataset and (optionally) tuned algorithm settings you
14817 : should call rbfbuildmodel() in order to build a model for you.
14818 :
14819 : NOTE: dataset added by this function is not saved during model serialization.
14820 : MODEL ITSELF is serialized, but data used to build it are not.
14821 :
14822 : So, if you 1) add dataset to empty RBF model, 2) serialize and
14823 : unserialize it, then you will get an empty RBF model with no dataset
14824 : being attached.
14825 :
14826 : From the other side, if you call rbfbuildmodel() between (1) and (2),
14827 : then after (2) you will get your fully constructed RBF model - but
14828 : again with no dataset attached, so subsequent calls to rbfbuildmodel()
14829 : will produce empty model.
14830 :
14831 :
14832 : -- ALGLIB --
14833 : Copyright 13.12.2011 by Bochkanov Sergey
14834 : *************************************************************************/
14835 0 : void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const ae_int_t n, const xparams _xparams)
14836 : {
14837 : jmp_buf _break_jump;
14838 : alglib_impl::ae_state _alglib_env_state;
14839 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14840 0 : if( setjmp(_break_jump) )
14841 : {
14842 : #if !defined(AE_NO_EXCEPTIONS)
14843 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14844 : #else
14845 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14846 : return;
14847 : #endif
14848 : }
14849 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14850 0 : if( _xparams.flags!=0x0 )
14851 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14852 0 : alglib_impl::rbfsetpoints(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, &_alglib_env_state);
14853 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14854 0 : return;
14855 : }
14856 :
14857 : /*************************************************************************
14858 : This function adds dataset.
14859 :
14860 : This function overrides results of the previous calls, i.e. multiple calls
14861 : of this function will result in only the last set being added.
14862 :
14863 : IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of
14864 : per-dimension scales. Interpolation radii are multiplied by the
14865 : scale vector. It may be useful if you have mixed spatio-temporal
14866 : data (say, a set of 3D slices recorded at different times).
14867 : You should call rbfsetpointsandscales() function to use this
14868 : feature.
14869 :
14870 : INPUT PARAMETERS:
14871 : S - RBF model, initialized by rbfcreate() call.
14872 : XY - points, array[N,NX+NY]. One row corresponds to one point
14873 : in the dataset. First NX elements are coordinates, next
14874 : NY elements are function values. Array may be larger than
14875 : specified, in this case only leading [N,NX+NY] elements
14876 : will be used.
14877 : N - number of points in the dataset
14878 :
14879 : After you've added dataset and (optionally) tuned algorithm settings you
14880 : should call rbfbuildmodel() in order to build a model for you.
14881 :
14882 : NOTE: dataset added by this function is not saved during model serialization.
14883 : MODEL ITSELF is serialized, but data used to build it are not.
14884 :
14885 : So, if you 1) add dataset to empty RBF model, 2) serialize and
14886 : unserialize it, then you will get an empty RBF model with no dataset
14887 : being attached.
14888 :
14889 : From the other side, if you call rbfbuildmodel() between (1) and (2),
14890 : then after (2) you will get your fully constructed RBF model - but
14891 : again with no dataset attached, so subsequent calls to rbfbuildmodel()
14892 : will produce empty model.
14893 :
14894 :
14895 : -- ALGLIB --
14896 : Copyright 13.12.2011 by Bochkanov Sergey
14897 : *************************************************************************/
14898 : #if !defined(AE_NO_EXCEPTIONS)
14899 0 : void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const xparams _xparams)
14900 : {
14901 : jmp_buf _break_jump;
14902 : alglib_impl::ae_state _alglib_env_state;
14903 : ae_int_t n;
14904 :
14905 0 : n = xy.rows();
14906 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14907 0 : if( setjmp(_break_jump) )
14908 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14909 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14910 0 : if( _xparams.flags!=0x0 )
14911 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14912 0 : alglib_impl::rbfsetpoints(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, &_alglib_env_state);
14913 :
14914 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14915 0 : return;
14916 : }
14917 : #endif
14918 :
14919 : /*************************************************************************
14920 : This function adds dataset and a vector of per-dimension scales.
14921 :
14922 : It may be useful if you have mixed spatio-temporal data - say, a set of 3D
14923 : slices recorded at different times. Such data typically require different
14924 : RBF radii for spatial and temporal dimensions. ALGLIB solves this problem
14925 : by specifying single RBF radius, which is (optionally) multiplied by the
14926 : scale vector.
14927 :
14928 : This function overrides results of the previous calls, i.e. multiple calls
14929 : of this function will result in only the last set being added.
14930 :
14931 : IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So,
14932 : using this function results in RBF models which can be used in
14933 : ALGLIB 3.11 or later. Previous versions of the library will be
14934 : unable to unserialize models produced by HierarchicalRBF algo.
14935 :
14936 : Any attempt to use this function with RBF-ML or QNN algorithms
14937 : will result in -3 error code being returned (incorrect
14938 : algorithm).
14939 :
14940 : INPUT PARAMETERS:
14941 : R - RBF model, initialized by rbfcreate() call.
14942 : XY - points, array[N,NX+NY]. One row corresponds to one point
14943 : in the dataset. First NX elements are coordinates, next
14944 : NY elements are function values. Array may be larger than
14945 : specified, in this case only leading [N,NX+NY] elements
14946 : will be used.
14947 : N - number of points in the dataset
14948 : S - array[NX], scale vector, S[i]>0.
14949 :
14950 : After you've added dataset and (optionally) tuned algorithm settings you
14951 : should call rbfbuildmodel() in order to build a model for you.
14952 :
14953 : NOTE: dataset added by this function is not saved during model serialization.
14954 : MODEL ITSELF is serialized, but data used to build it are not.
14955 :
14956 : So, if you 1) add dataset to empty RBF model, 2) serialize and
14957 : unserialize it, then you will get an empty RBF model with no dataset
14958 : being attached.
14959 :
14960 : From the other side, if you call rbfbuildmodel() between (1) and (2),
14961 : then after (2) you will get your fully constructed RBF model - but
14962 : again with no dataset attached, so subsequent calls to rbfbuildmodel()
14963 : will produce empty model.
14964 :
14965 :
14966 : -- ALGLIB --
14967 : Copyright 20.06.2016 by Bochkanov Sergey
14968 : *************************************************************************/
14969 0 : void rbfsetpointsandscales(const rbfmodel &r, const real_2d_array &xy, const ae_int_t n, const real_1d_array &s, const xparams _xparams)
14970 : {
14971 : jmp_buf _break_jump;
14972 : alglib_impl::ae_state _alglib_env_state;
14973 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14974 0 : if( setjmp(_break_jump) )
14975 : {
14976 : #if !defined(AE_NO_EXCEPTIONS)
14977 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14978 : #else
14979 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14980 : return;
14981 : #endif
14982 : }
14983 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14984 0 : if( _xparams.flags!=0x0 )
14985 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14986 0 : alglib_impl::rbfsetpointsandscales(const_cast<alglib_impl::rbfmodel*>(r.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
14987 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14988 0 : return;
14989 : }
14990 :
14991 : /*************************************************************************
14992 : This function adds dataset and a vector of per-dimension scales.
14993 :
14994 : It may be useful if you have mixed spatio-temporal data - say, a set of 3D
14995 : slices recorded at different times. Such data typically require different
14996 : RBF radii for spatial and temporal dimensions. ALGLIB solves this problem
14997 : by specifying single RBF radius, which is (optionally) multiplied by the
14998 : scale vector.
14999 :
15000 : This function overrides results of the previous calls, i.e. multiple calls
15001 : of this function will result in only the last set being added.
15002 :
15003 : IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So,
15004 : using this function results in RBF models which can be used in
15005 : ALGLIB 3.11 or later. Previous versions of the library will be
15006 : unable to unserialize models produced by HierarchicalRBF algo.
15007 :
15008 : Any attempt to use this function with RBF-ML or QNN algorithms
15009 : will result in -3 error code being returned (incorrect
15010 : algorithm).
15011 :
15012 : INPUT PARAMETERS:
15013 : R - RBF model, initialized by rbfcreate() call.
15014 : XY - points, array[N,NX+NY]. One row corresponds to one point
15015 : in the dataset. First NX elements are coordinates, next
15016 : NY elements are function values. Array may be larger than
15017 : specified, in this case only leading [N,NX+NY] elements
15018 : will be used.
15019 : N - number of points in the dataset
15020 : S - array[NX], scale vector, S[i]>0.
15021 :
15022 : After you've added dataset and (optionally) tuned algorithm settings you
15023 : should call rbfbuildmodel() in order to build a model for you.
15024 :
15025 : NOTE: dataset added by this function is not saved during model serialization.
15026 : MODEL ITSELF is serialized, but data used to build it are not.
15027 :
15028 : So, if you 1) add dataset to empty RBF model, 2) serialize and
15029 : unserialize it, then you will get an empty RBF model with no dataset
15030 : being attached.
15031 :
15032 : From the other side, if you call rbfbuildmodel() between (1) and (2),
15033 : then after (2) you will get your fully constructed RBF model - but
15034 : again with no dataset attached, so subsequent calls to rbfbuildmodel()
15035 : will produce empty model.
15036 :
15037 :
15038 : -- ALGLIB --
15039 : Copyright 20.06.2016 by Bochkanov Sergey
15040 : *************************************************************************/
15041 : #if !defined(AE_NO_EXCEPTIONS)
15042 0 : void rbfsetpointsandscales(const rbfmodel &r, const real_2d_array &xy, const real_1d_array &s, const xparams _xparams)
15043 : {
15044 : jmp_buf _break_jump;
15045 : alglib_impl::ae_state _alglib_env_state;
15046 : ae_int_t n;
15047 :
15048 0 : n = xy.rows();
15049 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15050 0 : if( setjmp(_break_jump) )
15051 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15052 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15053 0 : if( _xparams.flags!=0x0 )
15054 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15055 0 : alglib_impl::rbfsetpointsandscales(const_cast<alglib_impl::rbfmodel*>(r.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
15056 :
15057 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15058 0 : return;
15059 : }
15060 : #endif
15061 :
15062 : /*************************************************************************
15063 : DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction
15064 : algorithm, Hierarchical RBF. This algorithm is faster and
15065 : requires less memory than QNN and RBF-ML. It is especially good
15066 : for large-scale interpolation problems. So, we recommend you to
15067 : consider Hierarchical RBF as default option.
15068 :
15069 : ==========================================================================
15070 :
15071 : This function sets RBF interpolation algorithm. ALGLIB supports several
15072 : RBF algorithms with different properties.
15073 :
15074 : This algorithm is called RBF-QNN and it is good for point sets with
15075 : following properties:
15076 : a) all points are distinct
15077 : b) all points are well separated.
15078 : c) points distribution is approximately uniform. There is no "contour
15079 : lines", clusters of points, or other small-scale structures.
15080 :
15081 : Algorithm description:
15082 : 1) interpolation centers are allocated to data points
15083 : 2) interpolation radii are calculated as distances to the nearest centers
15084 : times Q coefficient (where Q is a value from [0.75,1.50]).
15085 : 3) after performing (2) radii are transformed in order to avoid situation
15086 : when single outlier has very large radius and influences many points
15087 : across all dataset. Transformation has following form:
15088 : new_r[i] = min(r[i],Z*median(r[]))
15089 : where r[i] is I-th radius, median() is a median radius across entire
15090 : dataset, Z is user-specified value which controls amount of deviation
15091 : from median radius.
15092 :
15093 : When (a) is violated, we will be unable to build RBF model. When (b) or
15094 : (c) are violated, model will be built, but interpolation quality will be
15095 : low. See http://www.alglib.net/interpolation/ for more information on this
15096 : subject.
15097 :
15098 : This algorithm is used by default.
15099 :
15100 : Additional Q parameter controls smoothness properties of the RBF basis:
15101 : * Q<0.75 will give perfectly conditioned basis, but terrible smoothness
15102 : properties (RBF interpolant will have sharp peaks around function values)
15103 : * Q around 1.0 gives good balance between smoothness and condition number
15104 : * Q>1.5 will lead to badly conditioned systems and slow convergence of the
15105 : underlying linear solver (although smoothness will be very good)
15106 : * Q>2.0 will effectively make optimizer useless because it won't converge
15107 : within reasonable amount of iterations. It is possible to set such large
15108 : Q, but it is advised not to do so.
15109 :
15110 : INPUT PARAMETERS:
15111 : S - RBF model, initialized by RBFCreate() call
15112 : Q - Q parameter, Q>0, recommended value - 1.0
15113 : Z - Z parameter, Z>0, recommended value - 5.0
15114 :
15115 : NOTE: this function has some serialization-related subtleties. We
15116 : recommend you to study serialization examples from ALGLIB Reference
15117 : Manual if you want to perform serialization of your models.
15118 :
15119 :
15120 : -- ALGLIB --
15121 : Copyright 13.12.2011 by Bochkanov Sergey
15122 : *************************************************************************/
15123 0 : void rbfsetalgoqnn(const rbfmodel &s, const double q, const double z, const xparams _xparams)
15124 : {
15125 : jmp_buf _break_jump;
15126 : alglib_impl::ae_state _alglib_env_state;
15127 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15128 0 : if( setjmp(_break_jump) )
15129 : {
15130 : #if !defined(AE_NO_EXCEPTIONS)
15131 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15132 : #else
15133 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15134 : return;
15135 : #endif
15136 : }
15137 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15138 0 : if( _xparams.flags!=0x0 )
15139 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15140 0 : alglib_impl::rbfsetalgoqnn(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), q, z, &_alglib_env_state);
15141 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15142 0 : return;
15143 : }
15144 :
15145 : /*************************************************************************
15146 : DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction
15147 : algorithm, Hierarchical RBF. This algorithm is faster and
15148 : requires less memory than QNN and RBF-ML. It is especially good
15149 : for large-scale interpolation problems. So, we recommend you to
15150 : consider Hierarchical RBF as default option.
15151 :
15152 : ==========================================================================
15153 :
15154 : This function sets RBF interpolation algorithm. ALGLIB supports several
15155 : RBF algorithms with different properties.
15156 :
15157 : This algorithm is called RBF-QNN and it is good for point sets with
15158 : following properties:
15159 : a) all points are distinct
15160 : b) all points are well separated.
15161 : c) points distribution is approximately uniform. There is no "contour
15162 : lines", clusters of points, or other small-scale structures.
15163 :
15164 : Algorithm description:
15165 : 1) interpolation centers are allocated to data points
15166 : 2) interpolation radii are calculated as distances to the nearest centers
15167 : times Q coefficient (where Q is a value from [0.75,1.50]).
15168 : 3) after performing (2) radii are transformed in order to avoid situation
15169 : when single outlier has very large radius and influences many points
15170 : across all dataset. Transformation has following form:
15171 : new_r[i] = min(r[i],Z*median(r[]))
15172 : where r[i] is I-th radius, median() is a median radius across entire
15173 : dataset, Z is user-specified value which controls amount of deviation
15174 : from median radius.
15175 :
15176 : When (a) is violated, we will be unable to build RBF model. When (b) or
15177 : (c) are violated, model will be built, but interpolation quality will be
15178 : low. See http://www.alglib.net/interpolation/ for more information on this
15179 : subject.
15180 :
15181 : This algorithm is used by default.
15182 :
15183 : Additional Q parameter controls smoothness properties of the RBF basis:
15184 : * Q<0.75 will give perfectly conditioned basis, but terrible smoothness
15185 : properties (RBF interpolant will have sharp peaks around function values)
15186 : * Q around 1.0 gives good balance between smoothness and condition number
15187 : * Q>1.5 will lead to badly conditioned systems and slow convergence of the
15188 : underlying linear solver (although smoothness will be very good)
15189 : * Q>2.0 will effectively make optimizer useless because it won't converge
15190 : within reasonable amount of iterations. It is possible to set such large
15191 : Q, but it is advised not to do so.
15192 :
15193 : INPUT PARAMETERS:
15194 : S - RBF model, initialized by RBFCreate() call
15195 : Q - Q parameter, Q>0, recommended value - 1.0
15196 : Z - Z parameter, Z>0, recommended value - 5.0
15197 :
15198 : NOTE: this function has some serialization-related subtleties. We
15199 : recommend you to study serialization examples from ALGLIB Reference
15200 : Manual if you want to perform serialization of your models.
15201 :
15202 :
15203 : -- ALGLIB --
15204 : Copyright 13.12.2011 by Bochkanov Sergey
15205 : *************************************************************************/
15206 : #if !defined(AE_NO_EXCEPTIONS)
15207 0 : void rbfsetalgoqnn(const rbfmodel &s, const xparams _xparams)
15208 : {
15209 : jmp_buf _break_jump;
15210 : alglib_impl::ae_state _alglib_env_state;
15211 : double q;
15212 : double z;
15213 :
15214 0 : q = 1.0;
15215 0 : z = 5.0;
15216 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15217 0 : if( setjmp(_break_jump) )
15218 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15219 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15220 0 : if( _xparams.flags!=0x0 )
15221 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15222 0 : alglib_impl::rbfsetalgoqnn(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), q, z, &_alglib_env_state);
15223 :
15224 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15225 0 : return;
15226 : }
15227 : #endif
15228 :
15229 : /*************************************************************************
15230 : DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction
15231 : algorithm, Hierarchical RBF. This algorithm is faster and
15232 : requires less memory than QNN and RBF-ML. It is especially good
15233 : for large-scale interpolation problems. So, we recommend you to
15234 : consider Hierarchical RBF as default option.
15235 :
15236 : ==========================================================================
15237 :
15238 : This function sets RBF interpolation algorithm. ALGLIB supports several
15239 : RBF algorithms with different properties.
15240 :
15241 : This algorithm is called RBF-ML. It builds multilayer RBF model, i.e.
15242 : model with subsequently decreasing radii, which allows us to combine
15243 : smoothness (due to large radii of the first layers) with exactness (due
15244 : to small radii of the last layers) and fast convergence.
15245 :
15246 : Internally RBF-ML uses many different means of acceleration, from sparse
15247 : matrices to KD-trees, which results in algorithm whose working time is
15248 : roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a
15249 : number of points, Density is an average density if points per unit of the
15250 : interpolation space, RBase is an initial radius, NLayers is a number of
15251 : layers.
15252 :
15253 : RBF-ML is good for following kinds of interpolation problems:
15254 : 1. "exact" problems (perfect fit) with well separated points
15255 : 2. least squares problems with arbitrary distribution of points (algorithm
15256 : gives perfect fit where it is possible, and resorts to least squares
15257 : fit in the hard areas).
15258 : 3. noisy problems where we want to apply some controlled amount of
15259 : smoothing.
15260 :
15261 : INPUT PARAMETERS:
15262 : S - RBF model, initialized by RBFCreate() call
15263 : RBase - RBase parameter, RBase>0
15264 : NLayers - NLayers parameter, NLayers>0, recommended value to start
15265 : with - about 5.
15266 : LambdaV - regularization value, can be useful when solving problem
15267 : in the least squares sense. Optimal lambda is problem-
15268 : dependent and require trial and error. In our experience,
15269 : good lambda can be as large as 0.1, and you can use 0.001
15270 : as initial guess.
15271 : Default value - 0.01, which is used when LambdaV is not
15272 : given. You can specify zero value, but it is not
15273 : recommended to do so.
15274 :
15275 : TUNING ALGORITHM
15276 :
15277 : In order to use this algorithm you have to choose three parameters:
15278 : * initial radius RBase
15279 : * number of layers in the model NLayers
15280 : * regularization coefficient LambdaV
15281 :
15282 : Initial radius is easy to choose - you can pick any number several times
15283 : larger than the average distance between points. Algorithm won't break
15284 : down if you choose radius which is too large (model construction time will
15285 : increase, but model will be built correctly).
15286 :
15287 : Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
15288 : by the last layer) will be smaller than the typical distance between
15289 : points. In case model error is too large, you can increase number of
15290 : layers. Having more layers will make model construction and evaluation
15291 : proportionally slower, but it will allow you to have model which precisely
15292 : fits your data. From the other side, if you want to suppress noise, you
15293 : can DECREASE number of layers to make your model less flexible.
15294 :
15295 : Regularization coefficient LambdaV controls smoothness of the individual
15296 : models built for each layer. We recommend you to use default value in case
15297 : you don't want to tune this parameter, because having non-zero LambdaV
15298 : accelerates and stabilizes internal iterative algorithm. In case you want
15299 : to suppress noise you can use LambdaV as additional parameter (larger
15300 : value = more smoothness) to tune.
15301 :
15302 : TYPICAL ERRORS
15303 :
15304 : 1. Using initial radius which is too large. Memory requirements of the
15305 : RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is
15306 : an average density of points per unit of the interpolation space). In
15307 : the extreme case of the very large RBase we will need O(N^2) units of
15308 : memory - and many layers in order to decrease radius to some reasonably
15309 : small value.
15310 :
15311 : 2. Using too small number of layers - RBF models with large radius are not
15312 : flexible enough to reproduce small variations in the target function.
15313 : You need many layers with different radii, from large to small, in
15314 : order to have good model.
15315 :
15316 : 3. Using initial radius which is too small. You will get model with
15317 : "holes" in the areas which are too far away from interpolation centers.
15318 : However, algorithm will work correctly (and quickly) in this case.
15319 :
15320 : 4. Using too many layers - you will get too large and too slow model. This
15321 : model will perfectly reproduce your function, but maybe you will be
15322 : able to achieve similar results with less layers (and less memory).
15323 :
15324 : -- ALGLIB --
15325 : Copyright 02.03.2012 by Bochkanov Sergey
15326 : *************************************************************************/
15327 0 : void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdav, const xparams _xparams)
15328 : {
15329 : jmp_buf _break_jump;
15330 : alglib_impl::ae_state _alglib_env_state;
15331 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15332 0 : if( setjmp(_break_jump) )
15333 : {
15334 : #if !defined(AE_NO_EXCEPTIONS)
15335 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15336 : #else
15337 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15338 : return;
15339 : #endif
15340 : }
15341 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15342 0 : if( _xparams.flags!=0x0 )
15343 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15344 0 : alglib_impl::rbfsetalgomultilayer(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), rbase, nlayers, lambdav, &_alglib_env_state);
15345 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15346 0 : return;
15347 : }
15348 :
15349 : /*************************************************************************
15350 : DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction
15351 : algorithm, Hierarchical RBF. This algorithm is faster and
15352 : requires less memory than QNN and RBF-ML. It is especially good
15353 : for large-scale interpolation problems. So, we recommend you to
15354 : consider Hierarchical RBF as default option.
15355 :
15356 : ==========================================================================
15357 :
15358 : This function sets RBF interpolation algorithm. ALGLIB supports several
15359 : RBF algorithms with different properties.
15360 :
15361 : This algorithm is called RBF-ML. It builds multilayer RBF model, i.e.
15362 : model with subsequently decreasing radii, which allows us to combine
15363 : smoothness (due to large radii of the first layers) with exactness (due
15364 : to small radii of the last layers) and fast convergence.
15365 :
15366 : Internally RBF-ML uses many different means of acceleration, from sparse
15367 : matrices to KD-trees, which results in algorithm whose working time is
15368 : roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a
15369 : number of points, Density is an average density if points per unit of the
15370 : interpolation space, RBase is an initial radius, NLayers is a number of
15371 : layers.
15372 :
15373 : RBF-ML is good for following kinds of interpolation problems:
15374 : 1. "exact" problems (perfect fit) with well separated points
15375 : 2. least squares problems with arbitrary distribution of points (algorithm
15376 : gives perfect fit where it is possible, and resorts to least squares
15377 : fit in the hard areas).
15378 : 3. noisy problems where we want to apply some controlled amount of
15379 : smoothing.
15380 :
15381 : INPUT PARAMETERS:
15382 : S - RBF model, initialized by RBFCreate() call
15383 : RBase - RBase parameter, RBase>0
15384 : NLayers - NLayers parameter, NLayers>0, recommended value to start
15385 : with - about 5.
15386 : LambdaV - regularization value, can be useful when solving problem
15387 : in the least squares sense. Optimal lambda is problem-
15388 : dependent and require trial and error. In our experience,
15389 : good lambda can be as large as 0.1, and you can use 0.001
15390 : as initial guess.
15391 : Default value - 0.01, which is used when LambdaV is not
15392 : given. You can specify zero value, but it is not
15393 : recommended to do so.
15394 :
15395 : TUNING ALGORITHM
15396 :
15397 : In order to use this algorithm you have to choose three parameters:
15398 : * initial radius RBase
15399 : * number of layers in the model NLayers
15400 : * regularization coefficient LambdaV
15401 :
15402 : Initial radius is easy to choose - you can pick any number several times
15403 : larger than the average distance between points. Algorithm won't break
15404 : down if you choose radius which is too large (model construction time will
15405 : increase, but model will be built correctly).
15406 :
15407 : Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
15408 : by the last layer) will be smaller than the typical distance between
15409 : points. In case model error is too large, you can increase number of
15410 : layers. Having more layers will make model construction and evaluation
15411 : proportionally slower, but it will allow you to have model which precisely
15412 : fits your data. From the other side, if you want to suppress noise, you
15413 : can DECREASE number of layers to make your model less flexible.
15414 :
15415 : Regularization coefficient LambdaV controls smoothness of the individual
15416 : models built for each layer. We recommend you to use default value in case
15417 : you don't want to tune this parameter, because having non-zero LambdaV
15418 : accelerates and stabilizes internal iterative algorithm. In case you want
15419 : to suppress noise you can use LambdaV as additional parameter (larger
15420 : value = more smoothness) to tune.
15421 :
15422 : TYPICAL ERRORS
15423 :
15424 : 1. Using initial radius which is too large. Memory requirements of the
15425 : RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is
15426 : an average density of points per unit of the interpolation space). In
15427 : the extreme case of the very large RBase we will need O(N^2) units of
15428 : memory - and many layers in order to decrease radius to some reasonably
15429 : small value.
15430 :
15431 : 2. Using too small number of layers - RBF models with large radius are not
15432 : flexible enough to reproduce small variations in the target function.
15433 : You need many layers with different radii, from large to small, in
15434 : order to have good model.
15435 :
15436 : 3. Using initial radius which is too small. You will get model with
15437 : "holes" in the areas which are too far away from interpolation centers.
15438 : However, algorithm will work correctly (and quickly) in this case.
15439 :
15440 : 4. Using too many layers - you will get too large and too slow model. This
15441 : model will perfectly reproduce your function, but maybe you will be
15442 : able to achieve similar results with less layers (and less memory).
15443 :
15444 : -- ALGLIB --
15445 : Copyright 02.03.2012 by Bochkanov Sergey
15446 : *************************************************************************/
15447 : #if !defined(AE_NO_EXCEPTIONS)
15448 0 : void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const xparams _xparams)
15449 : {
15450 : jmp_buf _break_jump;
15451 : alglib_impl::ae_state _alglib_env_state;
15452 : double lambdav;
15453 :
15454 0 : lambdav = 0.01;
15455 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15456 0 : if( setjmp(_break_jump) )
15457 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15458 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15459 0 : if( _xparams.flags!=0x0 )
15460 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15461 0 : alglib_impl::rbfsetalgomultilayer(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), rbase, nlayers, lambdav, &_alglib_env_state);
15462 :
15463 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15464 0 : return;
15465 : }
15466 : #endif
15467 :
15468 : /*************************************************************************
15469 : This function sets RBF interpolation algorithm. ALGLIB supports several
15470 : RBF algorithms with different properties.
15471 :
15472 : This algorithm is called Hierarchical RBF. It similar to its previous
15473 : incarnation, RBF-ML, i.e. it also builds a sequence of models with
15474 : decreasing radii. However, it uses more economical way of building upper
15475 : layers (ones with large radii), which results in faster model construction
15476 : and evaluation, as well as smaller memory footprint during construction.
15477 :
15478 : This algorithm has following important features:
15479 : * ability to handle millions of points
15480 : * controllable smoothing via nonlinearity penalization
15481 : * support for NX-dimensional models with NX=1 or NX>3 (unlike QNN or RBF-ML)
15482 : * support for specification of per-dimensional radii via scale vector,
15483 : which is set by means of rbfsetpointsandscales() function. This feature
15484 : is useful if you solve spatio-temporal interpolation problems, where
15485 : different radii are required for spatial and temporal dimensions.
15486 :
15487 : Running times are roughly proportional to:
15488 : * N*log(N)*NLayers - for model construction
15489 : * N*NLayers - for model evaluation
15490 : You may see that running time does not depend on search radius or points
15491 : density, just on number of layers in the hierarchy.
15492 :
15493 : IMPORTANT: this model construction algorithm was introduced in ALGLIB 3.11
15494 : and produces models which are INCOMPATIBLE with previous
15495 : versions of ALGLIB. You can not unserialize models produced
15496 : with this function in ALGLIB 3.10 or earlier.
15497 :
15498 : INPUT PARAMETERS:
15499 : S - RBF model, initialized by rbfcreate() call
15500 : RBase - RBase parameter, RBase>0
15501 : NLayers - NLayers parameter, NLayers>0, recommended value to start
15502 : with - about 5.
15503 : LambdaNS- >=0, nonlinearity penalty coefficient, negative values are
15504 : not allowed. This parameter adds controllable smoothing to
15505 : the problem, which may reduce noise. Specification of non-
15506 : zero lambda means that in addition to fitting error solver
15507 : will also minimize LambdaNS*|S''(x)|^2 (appropriately
15508 : generalized to multiple dimensions.
15509 :
15510 : Specification of exactly zero value means that no penalty
15511 : is added (we do not even evaluate matrix of second
15512 : derivatives which is necessary for smoothing).
15513 :
15514 : Calculation of nonlinearity penalty is costly - it results
15515 : in several-fold increase of model construction time.
15516 : Evaluation time remains the same.
15517 :
15518 : Optimal lambda is problem-dependent and requires trial
15519 : and error. Good value to start from is 1e-5...1e-6,
15520 : which corresponds to slightly noticeable smoothing of the
15521 : function. Value 1e-2 usually means that quite heavy
15522 : smoothing is applied.
15523 :
15524 : TUNING ALGORITHM
15525 :
15526 : In order to use this algorithm you have to choose three parameters:
15527 : * initial radius RBase
15528 : * number of layers in the model NLayers
15529 : * penalty coefficient LambdaNS
15530 :
15531 : Initial radius is easy to choose - you can pick any number several times
15532 : larger than the average distance between points. Algorithm won't break
15533 : down if you choose radius which is too large (model construction time will
15534 : increase, but model will be built correctly).
15535 :
15536 : Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
15537 : by the last layer) will be smaller than the typical distance between
15538 : points. In case model error is too large, you can increase number of
15539 : layers. Having more layers will make model construction and evaluation
15540 : proportionally slower, but it will allow you to have model which precisely
15541 : fits your data. From the other side, if you want to suppress noise, you
15542 : can DECREASE number of layers to make your model less flexible (or specify
15543 : non-zero LambdaNS).
15544 :
15545 : TYPICAL ERRORS
15546 :
15547 : 1. Using too small number of layers - RBF models with large radius are not
15548 : flexible enough to reproduce small variations in the target function.
15549 : You need many layers with different radii, from large to small, in
15550 : order to have good model.
15551 :
15552 : 2. Using initial radius which is too small. You will get model with
15553 : "holes" in the areas which are too far away from interpolation centers.
15554 : However, algorithm will work correctly (and quickly) in this case.
15555 :
15556 : -- ALGLIB --
15557 : Copyright 20.06.2016 by Bochkanov Sergey
15558 : *************************************************************************/
15559 0 : void rbfsetalgohierarchical(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdans, const xparams _xparams)
15560 : {
15561 : jmp_buf _break_jump;
15562 : alglib_impl::ae_state _alglib_env_state;
15563 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15564 0 : if( setjmp(_break_jump) )
15565 : {
15566 : #if !defined(AE_NO_EXCEPTIONS)
15567 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15568 : #else
15569 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15570 : return;
15571 : #endif
15572 : }
15573 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15574 0 : if( _xparams.flags!=0x0 )
15575 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15576 0 : alglib_impl::rbfsetalgohierarchical(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), rbase, nlayers, lambdans, &_alglib_env_state);
15577 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15578 0 : return;
15579 : }
15580 :
15581 : /*************************************************************************
15582 : This function sets linear term (model is a sum of radial basis functions
15583 : plus linear polynomial). This function won't have effect until next call
15584 : to RBFBuildModel().
15585 :
15586 : INPUT PARAMETERS:
15587 : S - RBF model, initialized by RBFCreate() call
15588 :
15589 : NOTE: this function has some serialization-related subtleties. We
15590 : recommend you to study serialization examples from ALGLIB Reference
15591 : Manual if you want to perform serialization of your models.
15592 :
15593 : -- ALGLIB --
15594 : Copyright 13.12.2011 by Bochkanov Sergey
15595 : *************************************************************************/
15596 0 : void rbfsetlinterm(const rbfmodel &s, const xparams _xparams)
15597 : {
15598 : jmp_buf _break_jump;
15599 : alglib_impl::ae_state _alglib_env_state;
15600 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15601 0 : if( setjmp(_break_jump) )
15602 : {
15603 : #if !defined(AE_NO_EXCEPTIONS)
15604 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15605 : #else
15606 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15607 : return;
15608 : #endif
15609 : }
15610 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15611 0 : if( _xparams.flags!=0x0 )
15612 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15613 0 : alglib_impl::rbfsetlinterm(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
15614 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15615 0 : return;
15616 : }
15617 :
15618 : /*************************************************************************
15619 : This function sets constant term (model is a sum of radial basis functions
15620 : plus constant). This function won't have effect until next call to
15621 : RBFBuildModel().
15622 :
15623 : INPUT PARAMETERS:
15624 : S - RBF model, initialized by RBFCreate() call
15625 :
15626 : NOTE: this function has some serialization-related subtleties. We
15627 : recommend you to study serialization examples from ALGLIB Reference
15628 : Manual if you want to perform serialization of your models.
15629 :
15630 : -- ALGLIB --
15631 : Copyright 13.12.2011 by Bochkanov Sergey
15632 : *************************************************************************/
15633 0 : void rbfsetconstterm(const rbfmodel &s, const xparams _xparams)
15634 : {
15635 : jmp_buf _break_jump;
15636 : alglib_impl::ae_state _alglib_env_state;
15637 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15638 0 : if( setjmp(_break_jump) )
15639 : {
15640 : #if !defined(AE_NO_EXCEPTIONS)
15641 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15642 : #else
15643 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15644 : return;
15645 : #endif
15646 : }
15647 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15648 0 : if( _xparams.flags!=0x0 )
15649 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15650 0 : alglib_impl::rbfsetconstterm(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
15651 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15652 0 : return;
15653 : }
15654 :
15655 : /*************************************************************************
15656 : This function sets zero term (model is a sum of radial basis functions
15657 : without polynomial term). This function won't have effect until next call
15658 : to RBFBuildModel().
15659 :
15660 : INPUT PARAMETERS:
15661 : S - RBF model, initialized by RBFCreate() call
15662 :
15663 : NOTE: this function has some serialization-related subtleties. We
15664 : recommend you to study serialization examples from ALGLIB Reference
15665 : Manual if you want to perform serialization of your models.
15666 :
15667 : -- ALGLIB --
15668 : Copyright 13.12.2011 by Bochkanov Sergey
15669 : *************************************************************************/
15670 0 : void rbfsetzeroterm(const rbfmodel &s, const xparams _xparams)
15671 : {
15672 : jmp_buf _break_jump;
15673 : alglib_impl::ae_state _alglib_env_state;
15674 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15675 0 : if( setjmp(_break_jump) )
15676 : {
15677 : #if !defined(AE_NO_EXCEPTIONS)
15678 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15679 : #else
15680 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15681 : return;
15682 : #endif
15683 : }
15684 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15685 0 : if( _xparams.flags!=0x0 )
15686 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15687 0 : alglib_impl::rbfsetzeroterm(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
15688 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15689 0 : return;
15690 : }
15691 :
15692 : /*************************************************************************
15693 : This function sets basis function type, which can be:
15694 : * 0 for classic Gaussian
15695 : * 1 for fast and compact bell-like basis function, which becomes exactly
15696 : zero at distance equal to 3*R (default option).
15697 :
15698 : INPUT PARAMETERS:
15699 : S - RBF model, initialized by RBFCreate() call
15700 : BF - basis function type:
15701 : * 0 - classic Gaussian
15702 : * 1 - fast and compact one
15703 :
15704 : -- ALGLIB --
15705 : Copyright 01.02.2017 by Bochkanov Sergey
15706 : *************************************************************************/
15707 0 : void rbfsetv2bf(const rbfmodel &s, const ae_int_t bf, const xparams _xparams)
15708 : {
15709 : jmp_buf _break_jump;
15710 : alglib_impl::ae_state _alglib_env_state;
15711 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15712 0 : if( setjmp(_break_jump) )
15713 : {
15714 : #if !defined(AE_NO_EXCEPTIONS)
15715 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15716 : #else
15717 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15718 : return;
15719 : #endif
15720 : }
15721 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15722 0 : if( _xparams.flags!=0x0 )
15723 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15724 0 : alglib_impl::rbfsetv2bf(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), bf, &_alglib_env_state);
15725 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15726 0 : return;
15727 : }
15728 :
15729 : /*************************************************************************
15730 : This function sets stopping criteria of the underlying linear solver for
15731 : hierarchical (version 2) RBF constructor.
15732 :
15733 : INPUT PARAMETERS:
15734 : S - RBF model, initialized by RBFCreate() call
15735 : MaxIts - this criterion will stop algorithm after MaxIts iterations.
15736 : Typically a few hundreds iterations is required, with 400
15737 : being a good default value to start experimentation.
15738 : Zero value means that default value will be selected.
15739 :
15740 : -- ALGLIB --
15741 : Copyright 01.02.2017 by Bochkanov Sergey
15742 : *************************************************************************/
15743 0 : void rbfsetv2its(const rbfmodel &s, const ae_int_t maxits, const xparams _xparams)
15744 : {
15745 : jmp_buf _break_jump;
15746 : alglib_impl::ae_state _alglib_env_state;
15747 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15748 0 : if( setjmp(_break_jump) )
15749 : {
15750 : #if !defined(AE_NO_EXCEPTIONS)
15751 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15752 : #else
15753 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15754 : return;
15755 : #endif
15756 : }
15757 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15758 0 : if( _xparams.flags!=0x0 )
15759 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15760 0 : alglib_impl::rbfsetv2its(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), maxits, &_alglib_env_state);
15761 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15762 0 : return;
15763 : }
15764 :
15765 : /*************************************************************************
15766 : This function sets support radius parameter of hierarchical (version 2)
15767 : RBF constructor.
15768 :
15769 : Hierarchical RBF model achieves great speed-up by removing from the model
15770 : excessive (too dense) nodes. Say, if you have RBF radius equal to 1 meter,
15771 : and two nodes are just 1 millimeter apart, you may remove one of them
15772 : without reducing model quality.
15773 :
15774 : Support radius parameter is used to justify which points need removal, and
15775 : which do not. If two points are less than SUPPORT_R*CUR_RADIUS units of
15776 : distance apart, one of them is removed from the model. The larger support
15777 : radius is, the faster model construction AND evaluation are. However,
15778 : too large values result in "bumpy" models.
15779 :
15780 : INPUT PARAMETERS:
15781 : S - RBF model, initialized by RBFCreate() call
15782 : R - support radius coefficient, >=0.
15783 : Recommended values are [0.1,0.4] range, with 0.1 being
15784 : default value.
15785 :
15786 : -- ALGLIB --
15787 : Copyright 01.02.2017 by Bochkanov Sergey
15788 : *************************************************************************/
15789 0 : void rbfsetv2supportr(const rbfmodel &s, const double r, const xparams _xparams)
15790 : {
15791 : jmp_buf _break_jump;
15792 : alglib_impl::ae_state _alglib_env_state;
15793 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15794 0 : if( setjmp(_break_jump) )
15795 : {
15796 : #if !defined(AE_NO_EXCEPTIONS)
15797 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15798 : #else
15799 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15800 : return;
15801 : #endif
15802 : }
15803 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15804 0 : if( _xparams.flags!=0x0 )
15805 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15806 0 : alglib_impl::rbfsetv2supportr(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), r, &_alglib_env_state);
15807 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15808 0 : return;
15809 : }
15810 :
15811 : /*************************************************************************
15812 : This function builds RBF model and returns report (contains some
15813 : information which can be used for evaluation of the algorithm properties).
15814 :
15815 : Call to this function modifies RBF model by calculating its centers/radii/
15816 : weights and saving them into RBFModel structure. Initially RBFModel
15817 : contain zero coefficients, but after call to this function we will have
15818 : coefficients which were calculated in order to fit our dataset.
15819 :
15820 : After you called this function you can call RBFCalc(), RBFGridCalc() and
15821 : other model calculation functions.
15822 :
15823 : INPUT PARAMETERS:
15824 : S - RBF model, initialized by RBFCreate() call
15825 : Rep - report:
15826 : * Rep.TerminationType:
15827 : * -5 - non-distinct basis function centers were detected,
15828 : interpolation aborted; only QNN returns this
15829 : error code, other algorithms can handle non-
15830 : distinct nodes.
15831 : * -4 - nonconvergence of the internal SVD solver
15832 : * -3 incorrect model construction algorithm was chosen:
15833 : QNN or RBF-ML, combined with one of the incompatible
15834 : features - NX=1 or NX>3; points with per-dimension
15835 : scales.
15836 : * 1 - successful termination
15837 : * 8 - a termination request was submitted via
15838 : rbfrequesttermination() function.
15839 :
15840 : Fields which are set only by modern RBF solvers (hierarchical
15841 : or nonnegative; older solvers like QNN and ML initialize these
15842 : fields by NANs):
15843 : * rep.rmserror - root-mean-square error at nodes
15844 : * rep.maxerror - maximum error at nodes
15845 :
15846 : Fields are used for debugging purposes:
15847 : * Rep.IterationsCount - iterations count of the LSQR solver
15848 : * Rep.NMV - number of matrix-vector products
15849 : * Rep.ARows - rows count for the system matrix
15850 : * Rep.ACols - columns count for the system matrix
15851 : * Rep.ANNZ - number of significantly non-zero elements
15852 : (elements above some algorithm-determined threshold)
15853 :
15854 : NOTE: failure to build model will leave current state of the structure
15855 : unchanged.
15856 :
15857 : -- ALGLIB --
15858 : Copyright 13.12.2011 by Bochkanov Sergey
15859 : *************************************************************************/
15860 0 : void rbfbuildmodel(const rbfmodel &s, rbfreport &rep, const xparams _xparams)
15861 : {
15862 : jmp_buf _break_jump;
15863 : alglib_impl::ae_state _alglib_env_state;
15864 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15865 0 : if( setjmp(_break_jump) )
15866 : {
15867 : #if !defined(AE_NO_EXCEPTIONS)
15868 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15869 : #else
15870 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15871 : return;
15872 : #endif
15873 : }
15874 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15875 0 : if( _xparams.flags!=0x0 )
15876 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15877 0 : alglib_impl::rbfbuildmodel(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::rbfreport*>(rep.c_ptr()), &_alglib_env_state);
15878 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15879 0 : return;
15880 : }
15881 :
15882 : /*************************************************************************
15883 : This function calculates values of the RBF model in the given point.
15884 :
15885 : IMPORTANT: this function works only with modern (hierarchical) RBFs. It
15886 : can not be used with legacy (version 1) RBFs because older RBF
15887 : code does not support 1-dimensional models.
15888 :
15889 : This function should be used when we have NY=1 (scalar function) and NX=1
15890 : (1-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If
15891 : you have 2-dimensional space, use rbfcalc3(). If you have general
15892 : situation (NX-dimensional space, NY-dimensional function) you should use
15893 : generic rbfcalc().
15894 :
15895 : If you want to perform parallel model evaluation from multiple threads,
15896 : use rbftscalcbuf() with per-thread buffer object.
15897 :
15898 : This function returns 0.0 when:
15899 : * model is not initialized
15900 : * NX<>1
15901 : * NY<>1
15902 :
15903 : INPUT PARAMETERS:
15904 : S - RBF model
15905 : X0 - X-coordinate, finite number
15906 :
15907 : RESULT:
15908 : value of the model or 0.0 (as defined above)
15909 :
15910 : -- ALGLIB --
15911 : Copyright 13.12.2011 by Bochkanov Sergey
15912 : *************************************************************************/
15913 0 : double rbfcalc1(const rbfmodel &s, const double x0, const xparams _xparams)
15914 : {
15915 : jmp_buf _break_jump;
15916 : alglib_impl::ae_state _alglib_env_state;
15917 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15918 0 : if( setjmp(_break_jump) )
15919 : {
15920 : #if !defined(AE_NO_EXCEPTIONS)
15921 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15922 : #else
15923 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15924 : return 0;
15925 : #endif
15926 : }
15927 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15928 0 : if( _xparams.flags!=0x0 )
15929 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15930 0 : double result = alglib_impl::rbfcalc1(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), x0, &_alglib_env_state);
15931 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15932 0 : return *(reinterpret_cast<double*>(&result));
15933 : }
15934 :
15935 : /*************************************************************************
15936 : This function calculates values of the RBF model in the given point.
15937 :
15938 : This function should be used when we have NY=1 (scalar function) and NX=2
15939 : (2-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If
15940 : you have general situation (NX-dimensional space, NY-dimensional function)
15941 : you should use generic rbfcalc().
15942 :
15943 : If you want to calculate function values many times, consider using
15944 : rbfgridcalc2v(), which is far more efficient than many subsequent calls to
15945 : rbfcalc2().
15946 :
15947 : If you want to perform parallel model evaluation from multiple threads,
15948 : use rbftscalcbuf() with per-thread buffer object.
15949 :
15950 : This function returns 0.0 when:
15951 : * model is not initialized
15952 : * NX<>2
15953 : *NY<>1
15954 :
15955 : INPUT PARAMETERS:
15956 : S - RBF model
15957 : X0 - first coordinate, finite number
15958 : X1 - second coordinate, finite number
15959 :
15960 : RESULT:
15961 : value of the model or 0.0 (as defined above)
15962 :
15963 : -- ALGLIB --
15964 : Copyright 13.12.2011 by Bochkanov Sergey
15965 : *************************************************************************/
15966 0 : double rbfcalc2(const rbfmodel &s, const double x0, const double x1, const xparams _xparams)
15967 : {
15968 : jmp_buf _break_jump;
15969 : alglib_impl::ae_state _alglib_env_state;
15970 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15971 0 : if( setjmp(_break_jump) )
15972 : {
15973 : #if !defined(AE_NO_EXCEPTIONS)
15974 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15975 : #else
15976 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15977 : return 0;
15978 : #endif
15979 : }
15980 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15981 0 : if( _xparams.flags!=0x0 )
15982 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15983 0 : double result = alglib_impl::rbfcalc2(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), x0, x1, &_alglib_env_state);
15984 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15985 0 : return *(reinterpret_cast<double*>(&result));
15986 : }
15987 :
15988 : /*************************************************************************
15989 : This function calculates value of the RBF model in the given point.
15990 :
15991 : This function should be used when we have NY=1 (scalar function) and NX=3
15992 : (3-dimensional space). If you have 2-dimensional space, use rbfcalc2(). If
15993 : you have general situation (NX-dimensional space, NY-dimensional function)
15994 : you should use generic rbfcalc().
15995 :
15996 : If you want to calculate function values many times, consider using
15997 : rbfgridcalc3v(), which is far more efficient than many subsequent calls to
15998 : rbfcalc3().
15999 :
16000 : If you want to perform parallel model evaluation from multiple threads,
16001 : use rbftscalcbuf() with per-thread buffer object.
16002 :
16003 : This function returns 0.0 when:
16004 : * model is not initialized
16005 : * NX<>3
16006 : *NY<>1
16007 :
16008 : INPUT PARAMETERS:
16009 : S - RBF model
16010 : X0 - first coordinate, finite number
16011 : X1 - second coordinate, finite number
16012 : X2 - third coordinate, finite number
16013 :
16014 : RESULT:
16015 : value of the model or 0.0 (as defined above)
16016 :
16017 : -- ALGLIB --
16018 : Copyright 13.12.2011 by Bochkanov Sergey
16019 : *************************************************************************/
16020 0 : double rbfcalc3(const rbfmodel &s, const double x0, const double x1, const double x2, const xparams _xparams)
16021 : {
16022 : jmp_buf _break_jump;
16023 : alglib_impl::ae_state _alglib_env_state;
16024 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16025 0 : if( setjmp(_break_jump) )
16026 : {
16027 : #if !defined(AE_NO_EXCEPTIONS)
16028 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16029 : #else
16030 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16031 : return 0;
16032 : #endif
16033 : }
16034 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16035 0 : if( _xparams.flags!=0x0 )
16036 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16037 0 : double result = alglib_impl::rbfcalc3(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), x0, x1, x2, &_alglib_env_state);
16038 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16039 0 : return *(reinterpret_cast<double*>(&result));
16040 : }
16041 :
16042 : /*************************************************************************
16043 : This function calculates values of the RBF model at the given point.
16044 :
16045 : This is general function which can be used for arbitrary NX (dimension of
16046 : the space of arguments) and NY (dimension of the function itself). However
16047 : when you have NY=1 you may find more convenient to use rbfcalc2() or
16048 : rbfcalc3().
16049 :
16050 : If you want to perform parallel model evaluation from multiple threads,
16051 : use rbftscalcbuf() with per-thread buffer object.
16052 :
16053 : This function returns 0.0 when model is not initialized.
16054 :
16055 : INPUT PARAMETERS:
16056 : S - RBF model
16057 : X - coordinates, array[NX].
16058 : X may have more than NX elements, in this case only
16059 : leading NX will be used.
16060 :
16061 : OUTPUT PARAMETERS:
16062 : Y - function value, array[NY]. Y is out-parameter and
16063 : reallocated after call to this function. In case you want
16064 : to reuse previously allocated Y, you may use RBFCalcBuf(),
16065 : which reallocates Y only when it is too small.
16066 :
16067 : -- ALGLIB --
16068 : Copyright 13.12.2011 by Bochkanov Sergey
16069 : *************************************************************************/
16070 0 : void rbfcalc(const rbfmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
16071 : {
16072 : jmp_buf _break_jump;
16073 : alglib_impl::ae_state _alglib_env_state;
16074 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16075 0 : if( setjmp(_break_jump) )
16076 : {
16077 : #if !defined(AE_NO_EXCEPTIONS)
16078 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16079 : #else
16080 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16081 : return;
16082 : #endif
16083 : }
16084 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16085 0 : if( _xparams.flags!=0x0 )
16086 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16087 0 : alglib_impl::rbfcalc(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
16088 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16089 0 : return;
16090 : }
16091 :
16092 : /*************************************************************************
16093 : This function calculates values of the RBF model at the given point.
16094 :
16095 : Same as rbfcalc(), but does not reallocate Y when in is large enough to
16096 : store function values.
16097 :
16098 : If you want to perform parallel model evaluation from multiple threads,
16099 : use rbftscalcbuf() with per-thread buffer object.
16100 :
16101 : INPUT PARAMETERS:
16102 : S - RBF model
16103 : X - coordinates, array[NX].
16104 : X may have more than NX elements, in this case only
16105 : leading NX will be used.
16106 : Y - possibly preallocated array
16107 :
16108 : OUTPUT PARAMETERS:
16109 : Y - function value, array[NY]. Y is not reallocated when it
16110 : is larger than NY.
16111 :
16112 : -- ALGLIB --
16113 : Copyright 13.12.2011 by Bochkanov Sergey
16114 : *************************************************************************/
16115 0 : void rbfcalcbuf(const rbfmodel &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
16116 : {
16117 : jmp_buf _break_jump;
16118 : alglib_impl::ae_state _alglib_env_state;
16119 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16120 0 : if( setjmp(_break_jump) )
16121 : {
16122 : #if !defined(AE_NO_EXCEPTIONS)
16123 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16124 : #else
16125 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16126 : return;
16127 : #endif
16128 : }
16129 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16130 0 : if( _xparams.flags!=0x0 )
16131 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16132 0 : alglib_impl::rbfcalcbuf(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
16133 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16134 0 : return;
16135 : }
16136 :
16137 : /*************************************************************************
16138 : This function calculates values of the RBF model at the given point, using
16139 : external buffer object (internal temporaries of RBF model are not
16140 : modified).
16141 :
16142 : This function allows to use same RBF model object in different threads,
16143 : assuming that different threads use different instances of buffer
16144 : structure.
16145 :
16146 : INPUT PARAMETERS:
16147 : S - RBF model, may be shared between different threads
16148 : Buf - buffer object created for this particular instance of RBF
16149 : model with rbfcreatecalcbuffer().
16150 : X - coordinates, array[NX].
16151 : X may have more than NX elements, in this case only
16152 : leading NX will be used.
16153 : Y - possibly preallocated array
16154 :
16155 : OUTPUT PARAMETERS:
16156 : Y - function value, array[NY]. Y is not reallocated when it
16157 : is larger than NY.
16158 :
16159 : -- ALGLIB --
16160 : Copyright 13.12.2011 by Bochkanov Sergey
16161 : *************************************************************************/
16162 0 : void rbftscalcbuf(const rbfmodel &s, const rbfcalcbuffer &buf, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
16163 : {
16164 : jmp_buf _break_jump;
16165 : alglib_impl::ae_state _alglib_env_state;
16166 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16167 0 : if( setjmp(_break_jump) )
16168 : {
16169 : #if !defined(AE_NO_EXCEPTIONS)
16170 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16171 : #else
16172 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16173 : return;
16174 : #endif
16175 : }
16176 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16177 0 : if( _xparams.flags!=0x0 )
16178 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16179 0 : alglib_impl::rbftscalcbuf(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::rbfcalcbuffer*>(buf.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
16180 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16181 0 : return;
16182 : }
16183 :
16184 : /*************************************************************************
16185 : This is legacy function for gridded calculation of RBF model.
16186 :
16187 : It is superseded by rbfgridcalc2v() and rbfgridcalc2vsubset() functions.
16188 :
16189 : -- ALGLIB --
16190 : Copyright 13.12.2011 by Bochkanov Sergey
16191 : *************************************************************************/
16192 0 : void rbfgridcalc2(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, real_2d_array &y, const xparams _xparams)
16193 : {
16194 : jmp_buf _break_jump;
16195 : alglib_impl::ae_state _alglib_env_state;
16196 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16197 0 : if( setjmp(_break_jump) )
16198 : {
16199 : #if !defined(AE_NO_EXCEPTIONS)
16200 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16201 : #else
16202 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16203 : return;
16204 : #endif
16205 : }
16206 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16207 0 : if( _xparams.flags!=0x0 )
16208 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16209 0 : alglib_impl::rbfgridcalc2(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x0.c_ptr()), n0, const_cast<alglib_impl::ae_vector*>(x1.c_ptr()), n1, const_cast<alglib_impl::ae_matrix*>(y.c_ptr()), &_alglib_env_state);
16210 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16211 0 : return;
16212 : }
16213 :
16214 : /*************************************************************************
16215 : This function calculates values of the RBF model at the regular grid,
16216 : which has N0*N1 points, with Point[I,J] = (X0[I], X1[J]). Vector-valued
16217 : RBF models are supported.
16218 :
16219 : This function returns 0.0 when:
16220 : * model is not initialized
16221 : * NX<>2
16222 :
16223 : ! COMMERCIAL EDITION OF ALGLIB:
16224 : !
16225 : ! Commercial Edition of ALGLIB includes following important improvements
16226 : ! of this function:
16227 : ! * high-performance native backend with same C# interface (C# version)
16228 : ! * multithreading support (C++ and C# versions)
16229 : !
16230 : ! We recommend you to read 'Working with commercial version' section of
16231 : ! ALGLIB Reference Manual in order to find out how to use performance-
16232 : ! related features provided by commercial edition of ALGLIB.
16233 :
16234 : NOTE: Parallel processing is implemented only for modern (hierarchical)
16235 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
16236 : processed serially.
16237 :
16238 : INPUT PARAMETERS:
16239 : S - RBF model, used in read-only mode, can be shared between
16240 : multiple invocations of this function from multiple
16241 : threads.
16242 :
16243 : X0 - array of grid nodes, first coordinates, array[N0].
16244 : Must be ordered by ascending. Exception is generated
16245 : if the array is not correctly ordered.
16246 : N0 - grid size (number of nodes) in the first dimension
16247 :
16248 : X1 - array of grid nodes, second coordinates, array[N1]
16249 : Must be ordered by ascending. Exception is generated
16250 : if the array is not correctly ordered.
16251 : N1 - grid size (number of nodes) in the second dimension
16252 :
16253 : OUTPUT PARAMETERS:
16254 : Y - function values, array[NY*N0*N1], where NY is a number of
16255 : "output" vector values (this function supports vector-
16256 : valued RBF models). Y is out-variable and is reallocated
16257 : by this function.
16258 : Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), for:
16259 : * K=0...NY-1
16260 : * I0=0...N0-1
16261 : * I1=0...N1-1
16262 :
16263 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
16264 : X[i]=X[i+1] for some i. It does not provide you any performance
16265 : benefits due to duplication of points, just convenience and
16266 : flexibility.
16267 :
16268 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
16269 : structure in multiple threads calling this function for different
16270 : grids.
16271 :
16272 : NOTE: if you need function values on some subset of regular grid, which
16273 : may be described as "several compact and dense islands", you may
16274 : use rbfgridcalc2vsubset().
16275 :
16276 : -- ALGLIB --
16277 : Copyright 27.01.2017 by Bochkanov Sergey
16278 : *************************************************************************/
16279 0 : void rbfgridcalc2v(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, real_1d_array &y, const xparams _xparams)
16280 : {
16281 : jmp_buf _break_jump;
16282 : alglib_impl::ae_state _alglib_env_state;
16283 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16284 0 : if( setjmp(_break_jump) )
16285 : {
16286 : #if !defined(AE_NO_EXCEPTIONS)
16287 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16288 : #else
16289 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16290 : return;
16291 : #endif
16292 : }
16293 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16294 0 : if( _xparams.flags!=0x0 )
16295 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16296 0 : alglib_impl::rbfgridcalc2v(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x0.c_ptr()), n0, const_cast<alglib_impl::ae_vector*>(x1.c_ptr()), n1, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
16297 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16298 0 : return;
16299 : }
16300 :
16301 : /*************************************************************************
16302 : This function calculates values of the RBF model at some subset of regular
16303 : grid:
16304 : * grid has N0*N1 points, with Point[I,J] = (X0[I], X1[J])
16305 : * only values at some subset of this grid are required
16306 : Vector-valued RBF models are supported.
16307 :
16308 : This function returns 0.0 when:
16309 : * model is not initialized
16310 : * NX<>2
16311 :
16312 : ! COMMERCIAL EDITION OF ALGLIB:
16313 : !
16314 : ! Commercial Edition of ALGLIB includes following important improvements
16315 : ! of this function:
16316 : ! * high-performance native backend with same C# interface (C# version)
16317 : ! * multithreading support (C++ and C# versions)
16318 : !
16319 : ! We recommend you to read 'Working with commercial version' section of
16320 : ! ALGLIB Reference Manual in order to find out how to use performance-
16321 : ! related features provided by commercial edition of ALGLIB.
16322 :
16323 : NOTE: Parallel processing is implemented only for modern (hierarchical)
16324 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
16325 : processed serially.
16326 :
16327 : INPUT PARAMETERS:
16328 : S - RBF model, used in read-only mode, can be shared between
16329 : multiple invocations of this function from multiple
16330 : threads.
16331 :
16332 : X0 - array of grid nodes, first coordinates, array[N0].
16333 : Must be ordered by ascending. Exception is generated
16334 : if the array is not correctly ordered.
16335 : N0 - grid size (number of nodes) in the first dimension
16336 :
16337 : X1 - array of grid nodes, second coordinates, array[N1]
16338 : Must be ordered by ascending. Exception is generated
16339 : if the array is not correctly ordered.
16340 : N1 - grid size (number of nodes) in the second dimension
16341 :
16342 : FlagY - array[N0*N1]:
16343 : * Y[I0+I1*N0] corresponds to node (X0[I0],X1[I1])
16344 : * it is a "bitmap" array which contains False for nodes
16345 : which are NOT calculated, and True for nodes which are
16346 : required.
16347 :
16348 : OUTPUT PARAMETERS:
16349 : Y - function values, array[NY*N0*N1*N2], where NY is a number
16350 : of "output" vector values (this function supports vector-
16351 : valued RBF models):
16352 : * Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]),
16353 : for K=0...NY-1, I0=0...N0-1, I1=0...N1-1.
16354 : * elements of Y[] which correspond to FlagY[]=True are
16355 : loaded by model values (which may be exactly zero for
16356 : some nodes).
16357 : * elements of Y[] which correspond to FlagY[]=False MAY be
16358 : initialized by zeros OR may be calculated. This function
16359 : processes grid as a hierarchy of nested blocks and
16360 : micro-rows. If just one element of micro-row is required,
16361 : entire micro-row (up to 8 nodes in the current version,
16362 : but no promises) is calculated.
16363 :
16364 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
16365 : X[i]=X[i+1] for some i. It does not provide you any performance
16366 : benefits due to duplication of points, just convenience and
16367 : flexibility.
16368 :
16369 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
16370 : structure in multiple threads calling this function for different
16371 : grids.
16372 :
16373 : -- ALGLIB --
16374 : Copyright 04.03.2016 by Bochkanov Sergey
16375 : *************************************************************************/
16376 0 : void rbfgridcalc2vsubset(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const boolean_1d_array &flagy, real_1d_array &y, const xparams _xparams)
16377 : {
16378 : jmp_buf _break_jump;
16379 : alglib_impl::ae_state _alglib_env_state;
16380 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16381 0 : if( setjmp(_break_jump) )
16382 : {
16383 : #if !defined(AE_NO_EXCEPTIONS)
16384 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16385 : #else
16386 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16387 : return;
16388 : #endif
16389 : }
16390 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16391 0 : if( _xparams.flags!=0x0 )
16392 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16393 0 : alglib_impl::rbfgridcalc2vsubset(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x0.c_ptr()), n0, const_cast<alglib_impl::ae_vector*>(x1.c_ptr()), n1, const_cast<alglib_impl::ae_vector*>(flagy.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
16394 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16395 0 : return;
16396 : }
16397 :
16398 : /*************************************************************************
16399 : This function calculates values of the RBF model at the regular grid,
16400 : which has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]).
16401 : Vector-valued RBF models are supported.
16402 :
16403 : This function returns 0.0 when:
16404 : * model is not initialized
16405 : * NX<>3
16406 :
16407 : ! COMMERCIAL EDITION OF ALGLIB:
16408 : !
16409 : ! Commercial Edition of ALGLIB includes following important improvements
16410 : ! of this function:
16411 : ! * high-performance native backend with same C# interface (C# version)
16412 : ! * multithreading support (C++ and C# versions)
16413 : !
16414 : ! We recommend you to read 'Working with commercial version' section of
16415 : ! ALGLIB Reference Manual in order to find out how to use performance-
16416 : ! related features provided by commercial edition of ALGLIB.
16417 :
16418 : NOTE: Parallel processing is implemented only for modern (hierarchical)
16419 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
16420 : processed serially.
16421 :
16422 : INPUT PARAMETERS:
16423 : S - RBF model, used in read-only mode, can be shared between
16424 : multiple invocations of this function from multiple
16425 : threads.
16426 :
16427 : X0 - array of grid nodes, first coordinates, array[N0].
16428 : Must be ordered by ascending. Exception is generated
16429 : if the array is not correctly ordered.
16430 : N0 - grid size (number of nodes) in the first dimension
16431 :
16432 : X1 - array of grid nodes, second coordinates, array[N1]
16433 : Must be ordered by ascending. Exception is generated
16434 : if the array is not correctly ordered.
16435 : N1 - grid size (number of nodes) in the second dimension
16436 :
16437 : X2 - array of grid nodes, third coordinates, array[N2]
16438 : Must be ordered by ascending. Exception is generated
16439 : if the array is not correctly ordered.
16440 : N2 - grid size (number of nodes) in the third dimension
16441 :
16442 : OUTPUT PARAMETERS:
16443 : Y - function values, array[NY*N0*N1*N2], where NY is a number
16444 : of "output" vector values (this function supports vector-
16445 : valued RBF models). Y is out-variable and is reallocated
16446 : by this function.
16447 : Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), for:
16448 : * K=0...NY-1
16449 : * I0=0...N0-1
16450 : * I1=0...N1-1
16451 : * I2=0...N2-1
16452 :
16453 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
16454 : X[i]=X[i+1] for some i. It does not provide you any performance
16455 : benefits due to duplication of points, just convenience and
16456 : flexibility.
16457 :
16458 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
16459 : structure in multiple threads calling this function for different
16460 : grids.
16461 :
16462 : NOTE: if you need function values on some subset of regular grid, which
16463 : may be described as "several compact and dense islands", you may
16464 : use rbfgridcalc3vsubset().
16465 :
16466 : -- ALGLIB --
16467 : Copyright 04.03.2016 by Bochkanov Sergey
16468 : *************************************************************************/
16469 0 : void rbfgridcalc3v(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const real_1d_array &x2, const ae_int_t n2, real_1d_array &y, const xparams _xparams)
16470 : {
16471 : jmp_buf _break_jump;
16472 : alglib_impl::ae_state _alglib_env_state;
16473 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16474 0 : if( setjmp(_break_jump) )
16475 : {
16476 : #if !defined(AE_NO_EXCEPTIONS)
16477 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16478 : #else
16479 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16480 : return;
16481 : #endif
16482 : }
16483 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16484 0 : if( _xparams.flags!=0x0 )
16485 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16486 0 : alglib_impl::rbfgridcalc3v(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x0.c_ptr()), n0, const_cast<alglib_impl::ae_vector*>(x1.c_ptr()), n1, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
16487 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16488 0 : return;
16489 : }
16490 :
16491 : /*************************************************************************
16492 : This function calculates values of the RBF model at some subset of regular
16493 : grid:
16494 : * grid has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K])
16495 : * only values at some subset of this grid are required
16496 : Vector-valued RBF models are supported.
16497 :
16498 : This function returns 0.0 when:
16499 : * model is not initialized
16500 : * NX<>3
16501 :
16502 : ! COMMERCIAL EDITION OF ALGLIB:
16503 : !
16504 : ! Commercial Edition of ALGLIB includes following important improvements
16505 : ! of this function:
16506 : ! * high-performance native backend with same C# interface (C# version)
16507 : ! * multithreading support (C++ and C# versions)
16508 : !
16509 : ! We recommend you to read 'Working with commercial version' section of
16510 : ! ALGLIB Reference Manual in order to find out how to use performance-
16511 : ! related features provided by commercial edition of ALGLIB.
16512 :
16513 : NOTE: Parallel processing is implemented only for modern (hierarchical)
16514 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
16515 : processed serially.
16516 :
16517 : INPUT PARAMETERS:
16518 : S - RBF model, used in read-only mode, can be shared between
16519 : multiple invocations of this function from multiple
16520 : threads.
16521 :
16522 : X0 - array of grid nodes, first coordinates, array[N0].
16523 : Must be ordered by ascending. Exception is generated
16524 : if the array is not correctly ordered.
16525 : N0 - grid size (number of nodes) in the first dimension
16526 :
16527 : X1 - array of grid nodes, second coordinates, array[N1]
16528 : Must be ordered by ascending. Exception is generated
16529 : if the array is not correctly ordered.
16530 : N1 - grid size (number of nodes) in the second dimension
16531 :
16532 : X2 - array of grid nodes, third coordinates, array[N2]
16533 : Must be ordered by ascending. Exception is generated
16534 : if the array is not correctly ordered.
16535 : N2 - grid size (number of nodes) in the third dimension
16536 :
16537 : FlagY - array[N0*N1*N2]:
16538 : * Y[I0+I1*N0+I2*N0*N1] corresponds to node (X0[I0],X1[I1],X2[I2])
16539 : * it is a "bitmap" array which contains False for nodes
16540 : which are NOT calculated, and True for nodes which are
16541 : required.
16542 :
16543 : OUTPUT PARAMETERS:
16544 : Y - function values, array[NY*N0*N1*N2], where NY is a number
16545 : of "output" vector values (this function supports vector-
16546 : valued RBF models):
16547 : * Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]),
16548 : for K=0...NY-1, I0=0...N0-1, I1=0...N1-1, I2=0...N2-1.
16549 : * elements of Y[] which correspond to FlagY[]=True are
16550 : loaded by model values (which may be exactly zero for
16551 : some nodes).
16552 : * elements of Y[] which correspond to FlagY[]=False MAY be
16553 : initialized by zeros OR may be calculated. This function
16554 : processes grid as a hierarchy of nested blocks and
16555 : micro-rows. If just one element of micro-row is required,
16556 : entire micro-row (up to 8 nodes in the current version,
16557 : but no promises) is calculated.
16558 :
16559 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
16560 : X[i]=X[i+1] for some i. It does not provide you any performance
16561 : benefits due to duplication of points, just convenience and
16562 : flexibility.
16563 :
16564 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
16565 : structure in multiple threads calling this function for different
16566 : grids.
16567 :
16568 : -- ALGLIB --
16569 : Copyright 04.03.2016 by Bochkanov Sergey
16570 : *************************************************************************/
16571 0 : void rbfgridcalc3vsubset(const rbfmodel &s, const real_1d_array &x0, const ae_int_t n0, const real_1d_array &x1, const ae_int_t n1, const real_1d_array &x2, const ae_int_t n2, const boolean_1d_array &flagy, real_1d_array &y, const xparams _xparams)
16572 : {
16573 : jmp_buf _break_jump;
16574 : alglib_impl::ae_state _alglib_env_state;
16575 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16576 0 : if( setjmp(_break_jump) )
16577 : {
16578 : #if !defined(AE_NO_EXCEPTIONS)
16579 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16580 : #else
16581 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16582 : return;
16583 : #endif
16584 : }
16585 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16586 0 : if( _xparams.flags!=0x0 )
16587 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16588 0 : alglib_impl::rbfgridcalc3vsubset(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x0.c_ptr()), n0, const_cast<alglib_impl::ae_vector*>(x1.c_ptr()), n1, const_cast<alglib_impl::ae_vector*>(x2.c_ptr()), n2, const_cast<alglib_impl::ae_vector*>(flagy.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
16589 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16590 0 : return;
16591 : }
16592 :
16593 : /*************************************************************************
16594 : This function "unpacks" RBF model by extracting its coefficients.
16595 :
16596 : INPUT PARAMETERS:
16597 : S - RBF model
16598 :
16599 : OUTPUT PARAMETERS:
16600 : NX - dimensionality of argument
16601 : NY - dimensionality of the target function
16602 : XWR - model information, array[NC,NX+NY+1].
16603 : One row of the array corresponds to one basis function:
16604 : * first NX columns - coordinates of the center
16605 : * next NY columns - weights, one per dimension of the
16606 : function being modelled
16607 : For ModelVersion=1:
16608 : * last column - radius, same for all dimensions of
16609 : the function being modelled
16610 : For ModelVersion=2:
16611 : * last NX columns - radii, one per dimension
16612 : NC - number of the centers
16613 : V - polynomial term , array[NY,NX+1]. One row per one
16614 : dimension of the function being modelled. First NX
16615 : elements are linear coefficients, V[NX] is equal to the
16616 : constant part.
16617 : ModelVersion-version of the RBF model:
16618 : * 1 - for models created by QNN and RBF-ML algorithms,
16619 : compatible with ALGLIB 3.10 or earlier.
16620 : * 2 - for models created by HierarchicalRBF, requires
16621 : ALGLIB 3.11 or later
16622 :
16623 : -- ALGLIB --
16624 : Copyright 13.12.2011 by Bochkanov Sergey
16625 : *************************************************************************/
16626 0 : void rbfunpack(const rbfmodel &s, ae_int_t &nx, ae_int_t &ny, real_2d_array &xwr, ae_int_t &nc, real_2d_array &v, ae_int_t &modelversion, const xparams _xparams)
16627 : {
16628 : jmp_buf _break_jump;
16629 : alglib_impl::ae_state _alglib_env_state;
16630 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16631 0 : if( setjmp(_break_jump) )
16632 : {
16633 : #if !defined(AE_NO_EXCEPTIONS)
16634 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16635 : #else
16636 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16637 : return;
16638 : #endif
16639 : }
16640 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16641 0 : if( _xparams.flags!=0x0 )
16642 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16643 0 : alglib_impl::rbfunpack(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &nx, &ny, const_cast<alglib_impl::ae_matrix*>(xwr.c_ptr()), &nc, const_cast<alglib_impl::ae_matrix*>(v.c_ptr()), &modelversion, &_alglib_env_state);
16644 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16645 0 : return;
16646 : }
16647 :
16648 : /*************************************************************************
16649 : This function returns model version.
16650 :
16651 : INPUT PARAMETERS:
16652 : S - RBF model
16653 :
16654 : RESULT:
16655 : * 1 - for models created by QNN and RBF-ML algorithms,
16656 : compatible with ALGLIB 3.10 or earlier.
16657 : * 2 - for models created by HierarchicalRBF, requires
16658 : ALGLIB 3.11 or later
16659 :
16660 : -- ALGLIB --
16661 : Copyright 06.07.2016 by Bochkanov Sergey
16662 : *************************************************************************/
16663 0 : ae_int_t rbfgetmodelversion(const rbfmodel &s, const xparams _xparams)
16664 : {
16665 : jmp_buf _break_jump;
16666 : alglib_impl::ae_state _alglib_env_state;
16667 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16668 0 : if( setjmp(_break_jump) )
16669 : {
16670 : #if !defined(AE_NO_EXCEPTIONS)
16671 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16672 : #else
16673 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16674 : return 0;
16675 : #endif
16676 : }
16677 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16678 0 : if( _xparams.flags!=0x0 )
16679 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16680 0 : alglib_impl::ae_int_t result = alglib_impl::rbfgetmodelversion(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
16681 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16682 0 : return *(reinterpret_cast<ae_int_t*>(&result));
16683 : }
16684 :
16685 : /*************************************************************************
16686 : This function is used to peek into hierarchical RBF construction process
16687 : from some other thread and get current progress indicator. It returns
16688 : value in [0,1].
16689 :
16690 : IMPORTANT: only HRBFs (hierarchical RBFs) support peeking into progress
16691 : indicator. Legacy RBF-ML and RBF-QNN do not support it. You
16692 : will always get 0 value.
16693 :
16694 : INPUT PARAMETERS:
16695 : S - RBF model object
16696 :
16697 : RESULT:
16698 : progress value, in [0,1]
16699 :
16700 : -- ALGLIB --
16701 : Copyright 17.11.2018 by Bochkanov Sergey
16702 : *************************************************************************/
16703 0 : double rbfpeekprogress(const rbfmodel &s, const xparams _xparams)
16704 : {
16705 : jmp_buf _break_jump;
16706 : alglib_impl::ae_state _alglib_env_state;
16707 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16708 0 : if( setjmp(_break_jump) )
16709 : {
16710 : #if !defined(AE_NO_EXCEPTIONS)
16711 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16712 : #else
16713 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16714 : return 0;
16715 : #endif
16716 : }
16717 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16718 0 : if( _xparams.flags!=0x0 )
16719 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16720 0 : double result = alglib_impl::rbfpeekprogress(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
16721 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16722 0 : return *(reinterpret_cast<double*>(&result));
16723 : }
16724 :
16725 : /*************************************************************************
16726 : This function is used to submit a request for termination of the
16727 : hierarchical RBF construction process from some other thread. As result,
16728 : RBF construction is terminated smoothly (with proper deallocation of all
16729 : necessary resources) and resultant model is filled by zeros.
16730 :
16731 : A rep.terminationtype=8 will be returned upon receiving such request.
16732 :
16733 : IMPORTANT: only HRBFs (hierarchical RBFs) support termination requests.
16734 : Legacy RBF-ML and RBF-QNN do not support it. An attempt to
16735 : terminate their construction will be ignored.
16736 :
16737 : IMPORTANT: termination request flag is cleared when the model construction
16738 : starts. Thus, any pre-construction termination requests will be
16739 : silently ignored - only ones submitted AFTER construction has
16740 : actually began will be handled.
16741 :
16742 : INPUT PARAMETERS:
16743 : S - RBF model object
16744 :
16745 : -- ALGLIB --
16746 : Copyright 17.11.2018 by Bochkanov Sergey
16747 : *************************************************************************/
16748 0 : void rbfrequesttermination(const rbfmodel &s, const xparams _xparams)
16749 : {
16750 : jmp_buf _break_jump;
16751 : alglib_impl::ae_state _alglib_env_state;
16752 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16753 0 : if( setjmp(_break_jump) )
16754 : {
16755 : #if !defined(AE_NO_EXCEPTIONS)
16756 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16757 : #else
16758 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16759 : return;
16760 : #endif
16761 : }
16762 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16763 0 : if( _xparams.flags!=0x0 )
16764 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16765 0 : alglib_impl::rbfrequesttermination(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
16766 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16767 0 : return;
16768 : }
16769 : #endif
16770 :
16771 : #if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD)
16772 : /*************************************************************************
16773 : This function is left for backward compatibility.
16774 : Use fitspheremc() instead.
16775 :
16776 :
16777 : -- ALGLIB --
16778 : Copyright 14.04.2017 by Bochkanov Sergey
16779 : *************************************************************************/
16780 0 : void nsfitspheremcc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rhi, const xparams _xparams)
16781 : {
16782 : jmp_buf _break_jump;
16783 : alglib_impl::ae_state _alglib_env_state;
16784 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16785 0 : if( setjmp(_break_jump) )
16786 : {
16787 : #if !defined(AE_NO_EXCEPTIONS)
16788 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16789 : #else
16790 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16791 : return;
16792 : #endif
16793 : }
16794 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16795 0 : if( _xparams.flags!=0x0 )
16796 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16797 0 : alglib_impl::nsfitspheremcc(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rhi, &_alglib_env_state);
16798 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16799 0 : return;
16800 : }
16801 :
16802 : /*************************************************************************
16803 : This function is left for backward compatibility.
16804 : Use fitspheremi() instead.
16805 :
16806 : -- ALGLIB --
16807 : Copyright 14.04.2017 by Bochkanov Sergey
16808 : *************************************************************************/
16809 0 : void nsfitspheremic(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, const xparams _xparams)
16810 : {
16811 : jmp_buf _break_jump;
16812 : alglib_impl::ae_state _alglib_env_state;
16813 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16814 0 : if( setjmp(_break_jump) )
16815 : {
16816 : #if !defined(AE_NO_EXCEPTIONS)
16817 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16818 : #else
16819 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16820 : return;
16821 : #endif
16822 : }
16823 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16824 0 : if( _xparams.flags!=0x0 )
16825 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16826 0 : alglib_impl::nsfitspheremic(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rlo, &_alglib_env_state);
16827 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16828 0 : return;
16829 : }
16830 :
16831 : /*************************************************************************
16832 : This function is left for backward compatibility.
16833 : Use fitspheremz() instead.
16834 :
16835 : -- ALGLIB --
16836 : Copyright 14.04.2017 by Bochkanov Sergey
16837 : *************************************************************************/
16838 0 : void nsfitspheremzc(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams)
16839 : {
16840 : jmp_buf _break_jump;
16841 : alglib_impl::ae_state _alglib_env_state;
16842 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16843 0 : if( setjmp(_break_jump) )
16844 : {
16845 : #if !defined(AE_NO_EXCEPTIONS)
16846 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16847 : #else
16848 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16849 : return;
16850 : #endif
16851 : }
16852 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16853 0 : if( _xparams.flags!=0x0 )
16854 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16855 0 : alglib_impl::nsfitspheremzc(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state);
16856 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16857 0 : return;
16858 : }
16859 :
16860 : /*************************************************************************
16861 : This function is left for backward compatibility.
16862 : Use fitspherex() instead.
16863 :
16864 : -- ALGLIB --
16865 : Copyright 14.04.2017 by Bochkanov Sergey
16866 : *************************************************************************/
16867 0 : void nsfitspherex(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nx, const ae_int_t problemtype, const double epsx, const ae_int_t aulits, const double penalty, real_1d_array &cx, double &rlo, double &rhi, const xparams _xparams)
16868 : {
16869 : jmp_buf _break_jump;
16870 : alglib_impl::ae_state _alglib_env_state;
16871 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16872 0 : if( setjmp(_break_jump) )
16873 : {
16874 : #if !defined(AE_NO_EXCEPTIONS)
16875 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16876 : #else
16877 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16878 : return;
16879 : #endif
16880 : }
16881 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16882 0 : if( _xparams.flags!=0x0 )
16883 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16884 0 : alglib_impl::nsfitspherex(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nx, problemtype, epsx, aulits, penalty, const_cast<alglib_impl::ae_vector*>(cx.c_ptr()), &rlo, &rhi, &_alglib_env_state);
16885 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16886 0 : return;
16887 : }
16888 :
16889 : /*************************************************************************
16890 : This function is an obsolete and deprecated version of fitting by
16891 : penalized cubic spline.
16892 :
16893 : It was superseded by spline1dfit(), which is an orders of magnitude faster
16894 : and more memory-efficient implementation.
16895 :
16896 : Do NOT use this function in the new code!
16897 :
16898 : -- ALGLIB PROJECT --
16899 : Copyright 18.08.2009 by Bochkanov Sergey
16900 : *************************************************************************/
16901 0 : void spline1dfitpenalized(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
16902 : {
16903 : jmp_buf _break_jump;
16904 : alglib_impl::ae_state _alglib_env_state;
16905 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16906 0 : if( setjmp(_break_jump) )
16907 : {
16908 : #if !defined(AE_NO_EXCEPTIONS)
16909 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16910 : #else
16911 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16912 : return;
16913 : #endif
16914 : }
16915 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16916 0 : if( _xparams.flags!=0x0 )
16917 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16918 0 : alglib_impl::spline1dfitpenalized(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, rho, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
16919 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16920 0 : return;
16921 : }
16922 :
16923 : /*************************************************************************
16924 : This function is an obsolete and deprecated version of fitting by
16925 : penalized cubic spline.
16926 :
16927 : It was superseded by spline1dfit(), which is an orders of magnitude faster
16928 : and more memory-efficient implementation.
16929 :
16930 : Do NOT use this function in the new code!
16931 :
16932 : -- ALGLIB PROJECT --
16933 : Copyright 18.08.2009 by Bochkanov Sergey
16934 : *************************************************************************/
16935 : #if !defined(AE_NO_EXCEPTIONS)
16936 0 : void spline1dfitpenalized(const real_1d_array &x, const real_1d_array &y, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
16937 : {
16938 : jmp_buf _break_jump;
16939 : alglib_impl::ae_state _alglib_env_state;
16940 : ae_int_t n;
16941 0 : if( (x.length()!=y.length()))
16942 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitpenalized': looks like one of arguments has wrong size");
16943 0 : n = x.length();
16944 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16945 0 : if( setjmp(_break_jump) )
16946 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16947 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16948 0 : if( _xparams.flags!=0x0 )
16949 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16950 0 : alglib_impl::spline1dfitpenalized(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), n, m, rho, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
16951 :
16952 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16953 0 : return;
16954 : }
16955 : #endif
16956 :
16957 : /*************************************************************************
16958 : This function is an obsolete and deprecated version of fitting by
16959 : penalized cubic spline.
16960 :
16961 : It was superseded by spline1dfit(), which is an orders of magnitude faster
16962 : and more memory-efficient implementation.
16963 :
16964 : Do NOT use this function in the new code!
16965 :
16966 : -- ALGLIB PROJECT --
16967 : Copyright 19.10.2010 by Bochkanov Sergey
16968 : *************************************************************************/
16969 0 : void spline1dfitpenalizedw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
16970 : {
16971 : jmp_buf _break_jump;
16972 : alglib_impl::ae_state _alglib_env_state;
16973 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16974 0 : if( setjmp(_break_jump) )
16975 : {
16976 : #if !defined(AE_NO_EXCEPTIONS)
16977 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16978 : #else
16979 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16980 : return;
16981 : #endif
16982 : }
16983 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16984 0 : if( _xparams.flags!=0x0 )
16985 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16986 0 : alglib_impl::spline1dfitpenalizedw(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, m, rho, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
16987 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16988 0 : return;
16989 : }
16990 :
16991 : /*************************************************************************
16992 : This function is an obsolete and deprecated version of fitting by
16993 : penalized cubic spline.
16994 :
16995 : It was superseded by spline1dfit(), which is an orders of magnitude faster
16996 : and more memory-efficient implementation.
16997 :
16998 : Do NOT use this function in the new code!
16999 :
17000 : -- ALGLIB PROJECT --
17001 : Copyright 19.10.2010 by Bochkanov Sergey
17002 : *************************************************************************/
17003 : #if !defined(AE_NO_EXCEPTIONS)
17004 0 : void spline1dfitpenalizedw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t m, const double rho, ae_int_t &info, spline1dinterpolant &s, spline1dfitreport &rep, const xparams _xparams)
17005 : {
17006 : jmp_buf _break_jump;
17007 : alglib_impl::ae_state _alglib_env_state;
17008 : ae_int_t n;
17009 0 : if( (x.length()!=y.length()) || (x.length()!=w.length()))
17010 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spline1dfitpenalizedw': looks like one of arguments has wrong size");
17011 0 : n = x.length();
17012 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17013 0 : if( setjmp(_break_jump) )
17014 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17015 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17016 0 : if( _xparams.flags!=0x0 )
17017 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17018 0 : alglib_impl::spline1dfitpenalizedw(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), n, m, rho, &info, const_cast<alglib_impl::spline1dinterpolant*>(s.c_ptr()), const_cast<alglib_impl::spline1dfitreport*>(rep.c_ptr()), &_alglib_env_state);
17019 :
17020 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17021 0 : return;
17022 : }
17023 : #endif
17024 : #endif
17025 : }
17026 :
17027 : /////////////////////////////////////////////////////////////////////////
17028 : //
17029 : // THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
17030 : //
17031 : /////////////////////////////////////////////////////////////////////////
17032 : namespace alglib_impl
17033 : {
17034 : #if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD)
17035 : static double idw_w0 = 1.0;
17036 : static double idw_meps = 1.0E-50;
17037 : static ae_int_t idw_defaultnlayers = 16;
17038 : static double idw_defaultlambda0 = 0.3333;
17039 : static void idw_errormetricsviacalc(idwbuilder* state,
17040 : idwmodel* model,
17041 : idwreport* rep,
17042 : ae_state *_state);
17043 :
17044 :
17045 : #endif
17046 : #if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD)
17047 : static void ratint_barycentricnormalize(barycentricinterpolant* b,
17048 : ae_state *_state);
17049 :
17050 :
17051 : #endif
17052 : #if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD)
17053 :
17054 :
17055 : #endif
17056 : #if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD)
17057 :
17058 :
17059 : #endif
17060 : #if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD)
17061 : static double spline1d_lambdareg = 1.0e-9;
17062 : static double spline1d_cholreg = 1.0e-12;
17063 : static void spline1d_spline1dgriddiffcubicinternal(/* Real */ ae_vector* x,
17064 : /* Real */ ae_vector* y,
17065 : ae_int_t n,
17066 : ae_int_t boundltype,
17067 : double boundl,
17068 : ae_int_t boundrtype,
17069 : double boundr,
17070 : /* Real */ ae_vector* d,
17071 : /* Real */ ae_vector* a1,
17072 : /* Real */ ae_vector* a2,
17073 : /* Real */ ae_vector* a3,
17074 : /* Real */ ae_vector* b,
17075 : /* Real */ ae_vector* dt,
17076 : ae_state *_state);
17077 : static void spline1d_heapsortpoints(/* Real */ ae_vector* x,
17078 : /* Real */ ae_vector* y,
17079 : ae_int_t n,
17080 : ae_state *_state);
17081 : static void spline1d_heapsortppoints(/* Real */ ae_vector* x,
17082 : /* Real */ ae_vector* y,
17083 : /* Integer */ ae_vector* p,
17084 : ae_int_t n,
17085 : ae_state *_state);
17086 : static void spline1d_solvetridiagonal(/* Real */ ae_vector* a,
17087 : /* Real */ ae_vector* b,
17088 : /* Real */ ae_vector* c,
17089 : /* Real */ ae_vector* d,
17090 : ae_int_t n,
17091 : /* Real */ ae_vector* x,
17092 : ae_state *_state);
17093 : static void spline1d_solvecyclictridiagonal(/* Real */ ae_vector* a,
17094 : /* Real */ ae_vector* b,
17095 : /* Real */ ae_vector* c,
17096 : /* Real */ ae_vector* d,
17097 : ae_int_t n,
17098 : /* Real */ ae_vector* x,
17099 : ae_state *_state);
17100 : static double spline1d_diffthreepoint(double t,
17101 : double x0,
17102 : double f0,
17103 : double x1,
17104 : double f1,
17105 : double x2,
17106 : double f2,
17107 : ae_state *_state);
17108 : static void spline1d_hermitecalc(double p0,
17109 : double m0,
17110 : double p1,
17111 : double m1,
17112 : double t,
17113 : double* s,
17114 : double* ds,
17115 : ae_state *_state);
17116 : static double spline1d_rescaleval(double a0,
17117 : double b0,
17118 : double a1,
17119 : double b1,
17120 : double t,
17121 : ae_state *_state);
17122 :
17123 :
17124 : #endif
17125 : #if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD)
17126 : static void parametric_pspline2par(/* Real */ ae_matrix* xy,
17127 : ae_int_t n,
17128 : ae_int_t pt,
17129 : /* Real */ ae_vector* p,
17130 : ae_state *_state);
17131 : static void parametric_pspline3par(/* Real */ ae_matrix* xy,
17132 : ae_int_t n,
17133 : ae_int_t pt,
17134 : /* Real */ ae_vector* p,
17135 : ae_state *_state);
17136 : static void parametric_rdpanalyzesectionpar(/* Real */ ae_matrix* xy,
17137 : ae_int_t i0,
17138 : ae_int_t i1,
17139 : ae_int_t d,
17140 : ae_int_t* worstidx,
17141 : double* worsterror,
17142 : ae_state *_state);
17143 :
17144 :
17145 : #endif
17146 : #if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD)
17147 : static void spline3d_spline3ddiff(spline3dinterpolant* c,
17148 : double x,
17149 : double y,
17150 : double z,
17151 : double* f,
17152 : double* fx,
17153 : double* fy,
17154 : double* fxy,
17155 : ae_state *_state);
17156 :
17157 :
17158 : #endif
17159 : #if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD)
17160 :
17161 :
17162 : #endif
17163 : #if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD)
17164 : static void lsfit_rdpanalyzesection(/* Real */ ae_vector* x,
17165 : /* Real */ ae_vector* y,
17166 : ae_int_t i0,
17167 : ae_int_t i1,
17168 : ae_int_t* worstidx,
17169 : double* worsterror,
17170 : ae_state *_state);
17171 : static void lsfit_rdprecursive(/* Real */ ae_vector* x,
17172 : /* Real */ ae_vector* y,
17173 : ae_int_t i0,
17174 : ae_int_t i1,
17175 : double eps,
17176 : /* Real */ ae_vector* xout,
17177 : /* Real */ ae_vector* yout,
17178 : ae_int_t* nout,
17179 : ae_state *_state);
17180 : static void lsfit_logisticfitinternal(/* Real */ ae_vector* x,
17181 : /* Real */ ae_vector* y,
17182 : ae_int_t n,
17183 : ae_bool is4pl,
17184 : double lambdav,
17185 : minlmstate* state,
17186 : minlmreport* replm,
17187 : /* Real */ ae_vector* p1,
17188 : double* flast,
17189 : ae_state *_state);
17190 : static void lsfit_logisticfit45errors(/* Real */ ae_vector* x,
17191 : /* Real */ ae_vector* y,
17192 : ae_int_t n,
17193 : double a,
17194 : double b,
17195 : double c,
17196 : double d,
17197 : double g,
17198 : lsfitreport* rep,
17199 : ae_state *_state);
17200 : static void lsfit_spline1dfitinternal(ae_int_t st,
17201 : /* Real */ ae_vector* x,
17202 : /* Real */ ae_vector* y,
17203 : /* Real */ ae_vector* w,
17204 : ae_int_t n,
17205 : /* Real */ ae_vector* xc,
17206 : /* Real */ ae_vector* yc,
17207 : /* Integer */ ae_vector* dc,
17208 : ae_int_t k,
17209 : ae_int_t m,
17210 : ae_int_t* info,
17211 : spline1dinterpolant* s,
17212 : spline1dfitreport* rep,
17213 : ae_state *_state);
17214 : static void lsfit_lsfitlinearinternal(/* Real */ ae_vector* y,
17215 : /* Real */ ae_vector* w,
17216 : /* Real */ ae_matrix* fmatrix,
17217 : ae_int_t n,
17218 : ae_int_t m,
17219 : ae_int_t* info,
17220 : /* Real */ ae_vector* c,
17221 : lsfitreport* rep,
17222 : ae_state *_state);
17223 : static void lsfit_lsfitclearrequestfields(lsfitstate* state,
17224 : ae_state *_state);
17225 : static void lsfit_barycentriccalcbasis(barycentricinterpolant* b,
17226 : double t,
17227 : /* Real */ ae_vector* y,
17228 : ae_state *_state);
17229 : static void lsfit_internalchebyshevfit(/* Real */ ae_vector* x,
17230 : /* Real */ ae_vector* y,
17231 : /* Real */ ae_vector* w,
17232 : ae_int_t n,
17233 : /* Real */ ae_vector* xc,
17234 : /* Real */ ae_vector* yc,
17235 : /* Integer */ ae_vector* dc,
17236 : ae_int_t k,
17237 : ae_int_t m,
17238 : ae_int_t* info,
17239 : /* Real */ ae_vector* c,
17240 : lsfitreport* rep,
17241 : ae_state *_state);
17242 : static void lsfit_barycentricfitwcfixedd(/* Real */ ae_vector* x,
17243 : /* Real */ ae_vector* y,
17244 : /* Real */ ae_vector* w,
17245 : ae_int_t n,
17246 : /* Real */ ae_vector* xc,
17247 : /* Real */ ae_vector* yc,
17248 : /* Integer */ ae_vector* dc,
17249 : ae_int_t k,
17250 : ae_int_t m,
17251 : ae_int_t d,
17252 : ae_int_t* info,
17253 : barycentricinterpolant* b,
17254 : barycentricfitreport* rep,
17255 : ae_state *_state);
17256 : static void lsfit_clearreport(lsfitreport* rep, ae_state *_state);
17257 : static void lsfit_estimateerrors(/* Real */ ae_matrix* f1,
17258 : /* Real */ ae_vector* f0,
17259 : /* Real */ ae_vector* y,
17260 : /* Real */ ae_vector* w,
17261 : /* Real */ ae_vector* x,
17262 : /* Real */ ae_vector* s,
17263 : ae_int_t n,
17264 : ae_int_t k,
17265 : lsfitreport* rep,
17266 : /* Real */ ae_matrix* z,
17267 : ae_int_t zkind,
17268 : ae_state *_state);
17269 :
17270 :
17271 : #endif
17272 : #if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD)
17273 : static double rbfv2_defaultlambdareg = 1.0E-6;
17274 : static double rbfv2_defaultsupportr = 0.10;
17275 : static ae_int_t rbfv2_defaultmaxits = 400;
17276 : static ae_int_t rbfv2_defaultbf = 1;
17277 : static ae_int_t rbfv2_maxnodesize = 6;
17278 : static double rbfv2_complexitymultiplier = 100.0;
17279 : static ae_bool rbfv2_rbfv2buildlinearmodel(/* Real */ ae_matrix* x,
17280 : /* Real */ ae_matrix* y,
17281 : ae_int_t n,
17282 : ae_int_t nx,
17283 : ae_int_t ny,
17284 : ae_int_t modeltype,
17285 : /* Real */ ae_matrix* v,
17286 : ae_state *_state);
17287 : static void rbfv2_allocatecalcbuffer(rbfv2model* s,
17288 : rbfv2calcbuffer* buf,
17289 : ae_state *_state);
17290 : static void rbfv2_convertandappendtree(kdtree* curtree,
17291 : ae_int_t n,
17292 : ae_int_t nx,
17293 : ae_int_t ny,
17294 : /* Integer */ ae_vector* kdnodes,
17295 : /* Real */ ae_vector* kdsplits,
17296 : /* Real */ ae_vector* cw,
17297 : ae_state *_state);
17298 : static void rbfv2_converttreerec(kdtree* curtree,
17299 : ae_int_t n,
17300 : ae_int_t nx,
17301 : ae_int_t ny,
17302 : ae_int_t nodeoffset,
17303 : ae_int_t nodesbase,
17304 : ae_int_t splitsbase,
17305 : ae_int_t cwbase,
17306 : /* Integer */ ae_vector* localnodes,
17307 : ae_int_t* localnodessize,
17308 : /* Real */ ae_vector* localsplits,
17309 : ae_int_t* localsplitssize,
17310 : /* Real */ ae_vector* localcw,
17311 : ae_int_t* localcwsize,
17312 : /* Real */ ae_matrix* xybuf,
17313 : ae_state *_state);
17314 : static void rbfv2_partialcalcrec(rbfv2model* s,
17315 : rbfv2calcbuffer* buf,
17316 : ae_int_t rootidx,
17317 : double invr2,
17318 : double queryr2,
17319 : /* Real */ ae_vector* x,
17320 : /* Real */ ae_vector* y,
17321 : ae_state *_state);
17322 : static void rbfv2_partialrowcalcrec(rbfv2model* s,
17323 : rbfv2calcbuffer* buf,
17324 : ae_int_t rootidx,
17325 : double invr2,
17326 : double rquery2,
17327 : double rfar2,
17328 : /* Real */ ae_vector* cx,
17329 : /* Real */ ae_vector* rx,
17330 : /* Boolean */ ae_vector* rf,
17331 : ae_int_t rowsize,
17332 : /* Real */ ae_vector* ry,
17333 : ae_state *_state);
17334 : static void rbfv2_preparepartialquery(/* Real */ ae_vector* x,
17335 : /* Real */ ae_vector* kdboxmin,
17336 : /* Real */ ae_vector* kdboxmax,
17337 : ae_int_t nx,
17338 : rbfv2calcbuffer* buf,
17339 : ae_int_t* cnt,
17340 : ae_state *_state);
17341 : static void rbfv2_partialqueryrec(/* Integer */ ae_vector* kdnodes,
17342 : /* Real */ ae_vector* kdsplits,
17343 : /* Real */ ae_vector* cw,
17344 : ae_int_t nx,
17345 : ae_int_t ny,
17346 : rbfv2calcbuffer* buf,
17347 : ae_int_t rootidx,
17348 : double queryr2,
17349 : /* Real */ ae_vector* x,
17350 : /* Real */ ae_vector* r2,
17351 : /* Integer */ ae_vector* offs,
17352 : ae_int_t* k,
17353 : ae_state *_state);
17354 : static ae_int_t rbfv2_partialcountrec(/* Integer */ ae_vector* kdnodes,
17355 : /* Real */ ae_vector* kdsplits,
17356 : /* Real */ ae_vector* cw,
17357 : ae_int_t nx,
17358 : ae_int_t ny,
17359 : rbfv2calcbuffer* buf,
17360 : ae_int_t rootidx,
17361 : double queryr2,
17362 : /* Real */ ae_vector* x,
17363 : ae_state *_state);
17364 : static void rbfv2_partialunpackrec(/* Integer */ ae_vector* kdnodes,
17365 : /* Real */ ae_vector* kdsplits,
17366 : /* Real */ ae_vector* cw,
17367 : /* Real */ ae_vector* s,
17368 : ae_int_t nx,
17369 : ae_int_t ny,
17370 : ae_int_t rootidx,
17371 : double r,
17372 : /* Real */ ae_matrix* xwr,
17373 : ae_int_t* k,
17374 : ae_state *_state);
17375 : static ae_int_t rbfv2_designmatrixrowsize(/* Integer */ ae_vector* kdnodes,
17376 : /* Real */ ae_vector* kdsplits,
17377 : /* Real */ ae_vector* cw,
17378 : /* Real */ ae_vector* ri,
17379 : /* Integer */ ae_vector* kdroots,
17380 : /* Real */ ae_vector* kdboxmin,
17381 : /* Real */ ae_vector* kdboxmax,
17382 : ae_int_t nx,
17383 : ae_int_t ny,
17384 : ae_int_t nh,
17385 : ae_int_t level,
17386 : double rcoeff,
17387 : /* Real */ ae_vector* x0,
17388 : rbfv2calcbuffer* calcbuf,
17389 : ae_state *_state);
17390 : static void rbfv2_designmatrixgeneraterow(/* Integer */ ae_vector* kdnodes,
17391 : /* Real */ ae_vector* kdsplits,
17392 : /* Real */ ae_vector* cw,
17393 : /* Real */ ae_vector* ri,
17394 : /* Integer */ ae_vector* kdroots,
17395 : /* Real */ ae_vector* kdboxmin,
17396 : /* Real */ ae_vector* kdboxmax,
17397 : /* Integer */ ae_vector* cwrange,
17398 : ae_int_t nx,
17399 : ae_int_t ny,
17400 : ae_int_t nh,
17401 : ae_int_t level,
17402 : ae_int_t bf,
17403 : double rcoeff,
17404 : ae_int_t rowsperpoint,
17405 : double penalty,
17406 : /* Real */ ae_vector* x0,
17407 : rbfv2calcbuffer* calcbuf,
17408 : /* Real */ ae_vector* tmpr2,
17409 : /* Integer */ ae_vector* tmpoffs,
17410 : /* Integer */ ae_vector* rowidx,
17411 : /* Real */ ae_vector* rowval,
17412 : ae_int_t* rowsize,
17413 : ae_state *_state);
17414 : static void rbfv2_zerofill(rbfv2model* s,
17415 : ae_int_t nx,
17416 : ae_int_t ny,
17417 : ae_int_t bf,
17418 : ae_state *_state);
17419 :
17420 :
17421 : #endif
17422 : #if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD)
17423 : static double spline2d_cholreg = 1.0E-12;
17424 : static double spline2d_lambdaregblocklls = 1.0E-6;
17425 : static double spline2d_lambdaregfastddm = 1.0E-4;
17426 : static double spline2d_lambdadecay = 0.5;
17427 : static void spline2d_bicubiccalcderivatives(/* Real */ ae_matrix* a,
17428 : /* Real */ ae_vector* x,
17429 : /* Real */ ae_vector* y,
17430 : ae_int_t m,
17431 : ae_int_t n,
17432 : /* Real */ ae_matrix* dx,
17433 : /* Real */ ae_matrix* dy,
17434 : /* Real */ ae_matrix* dxy,
17435 : ae_state *_state);
17436 : static void spline2d_generatedesignmatrix(/* Real */ ae_vector* xy,
17437 : ae_int_t npoints,
17438 : ae_int_t d,
17439 : ae_int_t kx,
17440 : ae_int_t ky,
17441 : double smoothing,
17442 : double lambdareg,
17443 : spline1dinterpolant* basis1,
17444 : sparsematrix* av,
17445 : sparsematrix* ah,
17446 : ae_int_t* arows,
17447 : ae_state *_state);
17448 : static void spline2d_updatesplinetable(/* Real */ ae_vector* z,
17449 : ae_int_t kx,
17450 : ae_int_t ky,
17451 : ae_int_t d,
17452 : spline1dinterpolant* basis1,
17453 : ae_int_t bfrad,
17454 : /* Real */ ae_vector* ftbl,
17455 : ae_int_t m,
17456 : ae_int_t n,
17457 : ae_int_t scalexy,
17458 : ae_state *_state);
17459 : static void spline2d_fastddmfit(/* Real */ ae_vector* xy,
17460 : ae_int_t npoints,
17461 : ae_int_t d,
17462 : ae_int_t kx,
17463 : ae_int_t ky,
17464 : ae_int_t basecasex,
17465 : ae_int_t basecasey,
17466 : ae_int_t maxcoresize,
17467 : ae_int_t interfacesize,
17468 : ae_int_t nlayers,
17469 : double smoothing,
17470 : ae_int_t lsqrcnt,
17471 : spline1dinterpolant* basis1,
17472 : spline2dinterpolant* spline,
17473 : spline2dfitreport* rep,
17474 : double tss,
17475 : ae_state *_state);
17476 : static void spline2d_fastddmfitlayer(/* Real */ ae_vector* xy,
17477 : ae_int_t d,
17478 : ae_int_t scalexy,
17479 : /* Integer */ ae_vector* xyindex,
17480 : ae_int_t basecasex,
17481 : ae_int_t tilex0,
17482 : ae_int_t tilex1,
17483 : ae_int_t tilescountx,
17484 : ae_int_t basecasey,
17485 : ae_int_t tiley0,
17486 : ae_int_t tiley1,
17487 : ae_int_t tilescounty,
17488 : ae_int_t maxcoresize,
17489 : ae_int_t interfacesize,
17490 : ae_int_t lsqrcnt,
17491 : double lambdareg,
17492 : spline1dinterpolant* basis1,
17493 : ae_shared_pool* pool,
17494 : spline2dinterpolant* spline,
17495 : ae_state *_state);
17496 : ae_bool _trypexec_spline2d_fastddmfitlayer(/* Real */ ae_vector* xy,
17497 : ae_int_t d,
17498 : ae_int_t scalexy,
17499 : /* Integer */ ae_vector* xyindex,
17500 : ae_int_t basecasex,
17501 : ae_int_t tilex0,
17502 : ae_int_t tilex1,
17503 : ae_int_t tilescountx,
17504 : ae_int_t basecasey,
17505 : ae_int_t tiley0,
17506 : ae_int_t tiley1,
17507 : ae_int_t tilescounty,
17508 : ae_int_t maxcoresize,
17509 : ae_int_t interfacesize,
17510 : ae_int_t lsqrcnt,
17511 : double lambdareg,
17512 : spline1dinterpolant* basis1,
17513 : ae_shared_pool* pool,
17514 : spline2dinterpolant* spline, ae_state *_state);
17515 : static void spline2d_blockllsfit(spline2dxdesignmatrix* xdesign,
17516 : ae_int_t lsqrcnt,
17517 : /* Real */ ae_vector* z,
17518 : spline2dfitreport* rep,
17519 : double tss,
17520 : spline2dblockllsbuf* buf,
17521 : ae_state *_state);
17522 : static void spline2d_naivellsfit(sparsematrix* av,
17523 : sparsematrix* ah,
17524 : ae_int_t arows,
17525 : /* Real */ ae_vector* xy,
17526 : ae_int_t kx,
17527 : ae_int_t ky,
17528 : ae_int_t npoints,
17529 : ae_int_t d,
17530 : ae_int_t lsqrcnt,
17531 : /* Real */ ae_vector* z,
17532 : spline2dfitreport* rep,
17533 : double tss,
17534 : ae_state *_state);
17535 : static ae_int_t spline2d_getcelloffset(ae_int_t kx,
17536 : ae_int_t ky,
17537 : ae_int_t blockbandwidth,
17538 : ae_int_t i,
17539 : ae_int_t j,
17540 : ae_state *_state);
17541 : static void spline2d_copycellto(ae_int_t kx,
17542 : ae_int_t ky,
17543 : ae_int_t blockbandwidth,
17544 : /* Real */ ae_matrix* blockata,
17545 : ae_int_t i,
17546 : ae_int_t j,
17547 : /* Real */ ae_matrix* dst,
17548 : ae_int_t dst0,
17549 : ae_int_t dst1,
17550 : ae_state *_state);
17551 : static void spline2d_flushtozerocell(ae_int_t kx,
17552 : ae_int_t ky,
17553 : ae_int_t blockbandwidth,
17554 : /* Real */ ae_matrix* blockata,
17555 : ae_int_t i,
17556 : ae_int_t j,
17557 : double eps,
17558 : ae_state *_state);
17559 : static void spline2d_blockllsgenerateata(sparsematrix* ah,
17560 : ae_int_t ky0,
17561 : ae_int_t ky1,
17562 : ae_int_t kx,
17563 : ae_int_t ky,
17564 : /* Real */ ae_matrix* blockata,
17565 : sreal* mxata,
17566 : ae_state *_state);
17567 : ae_bool _trypexec_spline2d_blockllsgenerateata(sparsematrix* ah,
17568 : ae_int_t ky0,
17569 : ae_int_t ky1,
17570 : ae_int_t kx,
17571 : ae_int_t ky,
17572 : /* Real */ ae_matrix* blockata,
17573 : sreal* mxata, ae_state *_state);
17574 : static ae_bool spline2d_blockllscholesky(/* Real */ ae_matrix* blockata,
17575 : ae_int_t kx,
17576 : ae_int_t ky,
17577 : /* Real */ ae_matrix* trsmbuf2,
17578 : /* Real */ ae_matrix* cholbuf2,
17579 : /* Real */ ae_vector* cholbuf1,
17580 : ae_state *_state);
17581 : static void spline2d_blockllstrsv(/* Real */ ae_matrix* blockata,
17582 : ae_int_t kx,
17583 : ae_int_t ky,
17584 : ae_bool transu,
17585 : /* Real */ ae_vector* b,
17586 : ae_state *_state);
17587 : static void spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy,
17588 : /* Real */ ae_vector* yraw,
17589 : ae_int_t npoints,
17590 : ae_int_t d,
17591 : ae_int_t scalexy,
17592 : spline2dinterpolant* spline,
17593 : ae_state *_state);
17594 : ae_bool _trypexec_spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy,
17595 : /* Real */ ae_vector* yraw,
17596 : ae_int_t npoints,
17597 : ae_int_t d,
17598 : ae_int_t scalexy,
17599 : spline2dinterpolant* spline, ae_state *_state);
17600 : static void spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy,
17601 : /* Real */ ae_vector* yraw,
17602 : ae_int_t pt0,
17603 : ae_int_t pt1,
17604 : ae_int_t chunksize,
17605 : ae_int_t d,
17606 : ae_int_t scalexy,
17607 : spline2dinterpolant* spline,
17608 : ae_shared_pool* pool,
17609 : ae_state *_state);
17610 : ae_bool _trypexec_spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy,
17611 : /* Real */ ae_vector* yraw,
17612 : ae_int_t pt0,
17613 : ae_int_t pt1,
17614 : ae_int_t chunksize,
17615 : ae_int_t d,
17616 : ae_int_t scalexy,
17617 : spline2dinterpolant* spline,
17618 : ae_shared_pool* pool, ae_state *_state);
17619 : static void spline2d_reorderdatasetandbuildindex(/* Real */ ae_vector* xy,
17620 : ae_int_t npoints,
17621 : ae_int_t d,
17622 : /* Real */ ae_vector* shadow,
17623 : ae_int_t ns,
17624 : ae_int_t kx,
17625 : ae_int_t ky,
17626 : /* Integer */ ae_vector* xyindex,
17627 : /* Integer */ ae_vector* bufi,
17628 : ae_state *_state);
17629 : static void spline2d_rescaledatasetandrefineindex(/* Real */ ae_vector* xy,
17630 : ae_int_t npoints,
17631 : ae_int_t d,
17632 : /* Real */ ae_vector* shadow,
17633 : ae_int_t ns,
17634 : ae_int_t kx,
17635 : ae_int_t ky,
17636 : /* Integer */ ae_vector* xyindex,
17637 : /* Integer */ ae_vector* bufi,
17638 : ae_state *_state);
17639 : static void spline2d_expandindexrows(/* Real */ ae_vector* xy,
17640 : ae_int_t d,
17641 : /* Real */ ae_vector* shadow,
17642 : ae_int_t ns,
17643 : /* Integer */ ae_vector* cidx,
17644 : ae_int_t pt0,
17645 : ae_int_t pt1,
17646 : /* Integer */ ae_vector* xyindexprev,
17647 : ae_int_t row0,
17648 : ae_int_t row1,
17649 : /* Integer */ ae_vector* xyindexnew,
17650 : ae_int_t kxnew,
17651 : ae_int_t kynew,
17652 : ae_bool rootcall,
17653 : ae_state *_state);
17654 : ae_bool _trypexec_spline2d_expandindexrows(/* Real */ ae_vector* xy,
17655 : ae_int_t d,
17656 : /* Real */ ae_vector* shadow,
17657 : ae_int_t ns,
17658 : /* Integer */ ae_vector* cidx,
17659 : ae_int_t pt0,
17660 : ae_int_t pt1,
17661 : /* Integer */ ae_vector* xyindexprev,
17662 : ae_int_t row0,
17663 : ae_int_t row1,
17664 : /* Integer */ ae_vector* xyindexnew,
17665 : ae_int_t kxnew,
17666 : ae_int_t kynew,
17667 : ae_bool rootcall, ae_state *_state);
17668 : static void spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy,
17669 : ae_int_t d,
17670 : /* Real */ ae_vector* shadow,
17671 : ae_int_t ns,
17672 : /* Integer */ ae_vector* cidx,
17673 : ae_int_t pt0,
17674 : ae_int_t pt1,
17675 : /* Integer */ ae_vector* xyindex,
17676 : ae_int_t idx0,
17677 : ae_int_t idx1,
17678 : ae_bool rootcall,
17679 : ae_state *_state);
17680 : ae_bool _trypexec_spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy,
17681 : ae_int_t d,
17682 : /* Real */ ae_vector* shadow,
17683 : ae_int_t ns,
17684 : /* Integer */ ae_vector* cidx,
17685 : ae_int_t pt0,
17686 : ae_int_t pt1,
17687 : /* Integer */ ae_vector* xyindex,
17688 : ae_int_t idx0,
17689 : ae_int_t idx1,
17690 : ae_bool rootcall, ae_state *_state);
17691 : static void spline2d_xdesigngenerate(/* Real */ ae_vector* xy,
17692 : /* Integer */ ae_vector* xyindex,
17693 : ae_int_t kx0,
17694 : ae_int_t kx1,
17695 : ae_int_t kxtotal,
17696 : ae_int_t ky0,
17697 : ae_int_t ky1,
17698 : ae_int_t kytotal,
17699 : ae_int_t d,
17700 : double lambdareg,
17701 : double lambdans,
17702 : spline1dinterpolant* basis1,
17703 : spline2dxdesignmatrix* a,
17704 : ae_state *_state);
17705 : static void spline2d_xdesignmv(spline2dxdesignmatrix* a,
17706 : /* Real */ ae_vector* x,
17707 : /* Real */ ae_vector* y,
17708 : ae_state *_state);
17709 : static void spline2d_xdesignmtv(spline2dxdesignmatrix* a,
17710 : /* Real */ ae_vector* x,
17711 : /* Real */ ae_vector* y,
17712 : ae_state *_state);
17713 : static void spline2d_xdesignblockata(spline2dxdesignmatrix* a,
17714 : /* Real */ ae_matrix* blockata,
17715 : double* mxata,
17716 : ae_state *_state);
17717 :
17718 :
17719 : #endif
17720 : #if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD)
17721 : static ae_int_t rbfv1_mxnx = 3;
17722 : static double rbfv1_rbffarradius = 6;
17723 : static double rbfv1_rbfnearradius = 2.1;
17724 : static double rbfv1_rbfmlradius = 3;
17725 : static double rbfv1_minbasecasecost = 100000;
17726 : static ae_bool rbfv1_rbfv1buildlinearmodel(/* Real */ ae_matrix* x,
17727 : /* Real */ ae_matrix* y,
17728 : ae_int_t n,
17729 : ae_int_t ny,
17730 : ae_int_t modeltype,
17731 : /* Real */ ae_matrix* v,
17732 : ae_state *_state);
17733 : static void rbfv1_buildrbfmodellsqr(/* Real */ ae_matrix* x,
17734 : /* Real */ ae_matrix* y,
17735 : /* Real */ ae_matrix* xc,
17736 : /* Real */ ae_vector* r,
17737 : ae_int_t n,
17738 : ae_int_t nc,
17739 : ae_int_t ny,
17740 : kdtree* pointstree,
17741 : kdtree* centerstree,
17742 : double epsort,
17743 : double epserr,
17744 : ae_int_t maxits,
17745 : ae_int_t* gnnz,
17746 : ae_int_t* snnz,
17747 : /* Real */ ae_matrix* w,
17748 : ae_int_t* info,
17749 : ae_int_t* iterationscount,
17750 : ae_int_t* nmv,
17751 : ae_state *_state);
17752 : static void rbfv1_buildrbfmlayersmodellsqr(/* Real */ ae_matrix* x,
17753 : /* Real */ ae_matrix* y,
17754 : /* Real */ ae_matrix* xc,
17755 : double rval,
17756 : /* Real */ ae_vector* r,
17757 : ae_int_t n,
17758 : ae_int_t* nc,
17759 : ae_int_t ny,
17760 : ae_int_t nlayers,
17761 : kdtree* centerstree,
17762 : double epsort,
17763 : double epserr,
17764 : ae_int_t maxits,
17765 : double lambdav,
17766 : ae_int_t* annz,
17767 : /* Real */ ae_matrix* w,
17768 : ae_int_t* info,
17769 : ae_int_t* iterationscount,
17770 : ae_int_t* nmv,
17771 : ae_state *_state);
17772 :
17773 :
17774 : #endif
17775 : #if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD)
17776 : static double rbf_eps = 1.0E-6;
17777 : static double rbf_rbffarradius = 6;
17778 : static ae_int_t rbf_rbffirstversion = 0;
17779 : static ae_int_t rbf_rbfversion2 = 2;
17780 : static void rbf_rbfpreparenonserializablefields(rbfmodel* s,
17781 : ae_state *_state);
17782 : static void rbf_initializev1(ae_int_t nx,
17783 : ae_int_t ny,
17784 : rbfv1model* s,
17785 : ae_state *_state);
17786 : static void rbf_initializev2(ae_int_t nx,
17787 : ae_int_t ny,
17788 : rbfv2model* s,
17789 : ae_state *_state);
17790 : static void rbf_clearreportfields(rbfreport* rep, ae_state *_state);
17791 :
17792 :
17793 : #endif
17794 : #if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD)
17795 :
17796 :
17797 : #endif
17798 :
17799 : #if defined(AE_COMPILE_IDW) || !defined(AE_PARTIAL_BUILD)
17800 :
17801 :
17802 : /*************************************************************************
17803 : This function creates buffer structure which can be used to perform
17804 : parallel IDW model evaluations (with one IDW model instance being
17805 : used from multiple threads, as long as different threads use different
17806 : instances of buffer).
17807 :
17808 : This buffer object can be used with idwtscalcbuf() function (here "ts"
17809 : stands for "thread-safe", "buf" is a suffix which denotes function which
17810 : reuses previously allocated output space).
17811 :
17812 : How to use it:
17813 : * create IDW model structure or load it from file
17814 : * call idwcreatecalcbuffer(), once per thread working with IDW model (you
17815 : should call this function only AFTER model initialization, see below for
17816 : more information)
17817 : * call idwtscalcbuf() from different threads, with each thread working
17818 : with its own copy of buffer object.
17819 :
17820 : INPUT PARAMETERS
17821 : S - IDW model
17822 :
17823 : OUTPUT PARAMETERS
17824 : Buf - external buffer.
17825 :
17826 :
17827 : IMPORTANT: buffer object should be used only with IDW model object which
17828 : was used to initialize buffer. Any attempt to use buffer with
17829 : different object is dangerous - you may get memory violation
17830 : error because sizes of internal arrays do not fit to dimensions
17831 : of the IDW structure.
17832 :
17833 : IMPORTANT: you should call this function only for model which was built
17834 : with model builder (or unserialized from file). Sizes of some
17835 : internal structures are determined only after model is built,
17836 : so buffer object created before model construction stage will
17837 : be useless (and any attempt to use it will result in exception).
17838 :
17839 : -- ALGLIB --
17840 : Copyright 22.10.2018 by Sergey Bochkanov
17841 : *************************************************************************/
17842 0 : void idwcreatecalcbuffer(idwmodel* s,
17843 : idwcalcbuffer* buf,
17844 : ae_state *_state)
17845 : {
17846 :
17847 0 : _idwcalcbuffer_clear(buf);
17848 :
17849 0 : ae_assert(s->nx>=1, "IDWCreateCalcBuffer: integrity check failed", _state);
17850 0 : ae_assert(s->ny>=1, "IDWCreateCalcBuffer: integrity check failed", _state);
17851 0 : ae_assert(s->nlayers>=0, "IDWCreateCalcBuffer: integrity check failed", _state);
17852 0 : ae_assert(s->algotype>=0, "IDWCreateCalcBuffer: integrity check failed", _state);
17853 0 : if( s->nlayers>=1&&s->algotype!=0 )
17854 : {
17855 0 : kdtreecreaterequestbuffer(&s->tree, &buf->requestbuffer, _state);
17856 : }
17857 0 : rvectorsetlengthatleast(&buf->x, s->nx, _state);
17858 0 : rvectorsetlengthatleast(&buf->y, s->ny, _state);
17859 0 : rvectorsetlengthatleast(&buf->tsyw, s->ny*ae_maxint(s->nlayers, 1, _state), _state);
17860 0 : rvectorsetlengthatleast(&buf->tsw, ae_maxint(s->nlayers, 1, _state), _state);
17861 0 : }
17862 :
17863 :
17864 : /*************************************************************************
17865 : This subroutine creates builder object used to generate IDW model from
17866 : irregularly sampled (scattered) dataset. Multidimensional scalar/vector-
17867 : -valued are supported.
17868 :
17869 : Builder object is used to fit model to data as follows:
17870 : * builder object is created with idwbuildercreate() function
17871 : * dataset is added with idwbuildersetpoints() function
17872 : * one of the modern IDW algorithms is chosen with either:
17873 : * idwbuildersetalgomstab() - Multilayer STABilized algorithm (interpolation)
17874 : Alternatively, one of the textbook algorithms can be chosen (not recommended):
17875 : * idwbuildersetalgotextbookshepard() - textbook Shepard algorithm
17876 : * idwbuildersetalgotextbookmodshepard()-textbook modified Shepard algorithm
17877 : * finally, model construction is performed with idwfit() function.
17878 :
17879 : ! COMMERCIAL EDITION OF ALGLIB:
17880 : !
17881 : ! Commercial Edition of ALGLIB includes following important improvements
17882 : ! of this function:
17883 : ! * high-performance native backend with same C# interface (C# version)
17884 : ! * multithreading support (C++ and C# versions)
17885 : !
17886 : ! We recommend you to read 'Working with commercial version' section of
17887 : ! ALGLIB Reference Manual in order to find out how to use performance-
17888 : ! related features provided by commercial edition of ALGLIB.
17889 :
17890 : INPUT PARAMETERS:
17891 : NX - dimensionality of the argument, NX>=1
17892 : NY - dimensionality of the function being modeled, NY>=1;
17893 : NY=1 corresponds to classic scalar function, NY>=1 corresponds
17894 : to vector-valued function.
17895 :
17896 : OUTPUT PARAMETERS:
17897 : State- builder object
17898 :
17899 : -- ALGLIB PROJECT --
17900 : Copyright 22.10.2018 by Bochkanov Sergey
17901 : *************************************************************************/
17902 0 : void idwbuildercreate(ae_int_t nx,
17903 : ae_int_t ny,
17904 : idwbuilder* state,
17905 : ae_state *_state)
17906 : {
17907 :
17908 0 : _idwbuilder_clear(state);
17909 :
17910 0 : ae_assert(nx>=1, "IDWBuilderCreate: NX<=0", _state);
17911 0 : ae_assert(ny>=1, "IDWBuilderCreate: NY<=0", _state);
17912 :
17913 : /*
17914 : * We choose reasonable defaults for the algorithm:
17915 : * * MSTAB algorithm
17916 : * * 12 layers
17917 : * * default radius
17918 : * * default Lambda0
17919 : */
17920 0 : state->algotype = 2;
17921 0 : state->priortermtype = 2;
17922 0 : rvectorsetlengthatleast(&state->priortermval, ny, _state);
17923 0 : state->nlayers = idw_defaultnlayers;
17924 0 : state->r0 = (double)(0);
17925 0 : state->rdecay = 0.5;
17926 0 : state->lambda0 = idw_defaultlambda0;
17927 0 : state->lambdalast = (double)(0);
17928 0 : state->lambdadecay = 1.0;
17929 :
17930 : /*
17931 : * Other parameters, not used but initialized
17932 : */
17933 0 : state->shepardp = (double)(0);
17934 :
17935 : /*
17936 : * Initial dataset is empty
17937 : */
17938 0 : state->npoints = 0;
17939 0 : state->nx = nx;
17940 0 : state->ny = ny;
17941 0 : }
17942 :
17943 :
17944 : /*************************************************************************
17945 : This function changes number of layers used by IDW-MSTAB algorithm.
17946 :
17947 : The more layers you have, the finer details can be reproduced with IDW
17948 : model. The less layers you have, the less memory and CPU time is consumed
17949 : by the model.
17950 :
17951 : Memory consumption grows linearly with layers count, running time grows
17952 : sub-linearly.
17953 :
17954 : The default number of layers is 16, which allows you to reproduce details
17955 : at distance down to SRad/65536. You will rarely need to change it.
17956 :
17957 : INPUT PARAMETERS:
17958 : State - builder object
17959 : NLayers - NLayers>=1, the number of layers used by the model.
17960 :
17961 : -- ALGLIB --
17962 : Copyright 22.10.2018 by Bochkanov Sergey
17963 : *************************************************************************/
17964 0 : void idwbuildersetnlayers(idwbuilder* state,
17965 : ae_int_t nlayers,
17966 : ae_state *_state)
17967 : {
17968 :
17969 :
17970 0 : ae_assert(nlayers>=1, "IDWBuilderSetNLayers: N<1", _state);
17971 0 : state->nlayers = nlayers;
17972 0 : }
17973 :
17974 :
17975 : /*************************************************************************
17976 : This function adds dataset to the builder object.
17977 :
17978 : This function overrides results of the previous calls, i.e. multiple calls
17979 : of this function will result in only the last set being added.
17980 :
17981 : INPUT PARAMETERS:
17982 : State - builder object
17983 : XY - points, array[N,NX+NY]. One row corresponds to one point
17984 : in the dataset. First NX elements are coordinates, next
17985 : NY elements are function values. Array may be larger than
17986 : specified, in this case only leading [N,NX+NY] elements
17987 : will be used.
17988 : N - number of points in the dataset, N>=0.
17989 :
17990 : -- ALGLIB --
17991 : Copyright 22.10.2018 by Bochkanov Sergey
17992 : *************************************************************************/
17993 0 : void idwbuildersetpoints(idwbuilder* state,
17994 : /* Real */ ae_matrix* xy,
17995 : ae_int_t n,
17996 : ae_state *_state)
17997 : {
17998 : ae_int_t i;
17999 : ae_int_t j;
18000 : ae_int_t ew;
18001 :
18002 :
18003 0 : ae_assert(n>=0, "IDWBuilderSetPoints: N<0", _state);
18004 0 : ae_assert(xy->rows>=n, "IDWBuilderSetPoints: Rows(XY)<N", _state);
18005 0 : ae_assert(n==0||xy->cols>=state->nx+state->ny, "IDWBuilderSetPoints: Cols(XY)<NX+NY", _state);
18006 0 : ae_assert(apservisfinitematrix(xy, n, state->nx+state->ny, _state), "IDWBuilderSetPoints: XY contains infinite or NaN values!", _state);
18007 0 : state->npoints = n;
18008 0 : ew = state->nx+state->ny;
18009 0 : rvectorsetlengthatleast(&state->xy, n*ew, _state);
18010 0 : for(i=0; i<=n-1; i++)
18011 : {
18012 0 : for(j=0; j<=ew-1; j++)
18013 : {
18014 0 : state->xy.ptr.p_double[i*ew+j] = xy->ptr.pp_double[i][j];
18015 : }
18016 : }
18017 0 : }
18018 :
18019 :
18020 : /*************************************************************************
18021 : This function sets IDW model construction algorithm to the Multilayer
18022 : Stabilized IDW method (IDW-MSTAB), a latest incarnation of the inverse
18023 : distance weighting interpolation which fixes shortcomings of the original
18024 : and modified Shepard's variants.
18025 :
18026 : The distinctive features of IDW-MSTAB are:
18027 : 1) exact interpolation is pursued (as opposed to fitting and noise
18028 : suppression)
18029 : 2) improved robustness when compared with that of other algorithms:
18030 : * MSTAB shows almost no strange fitting artifacts like ripples and
18031 : sharp spikes (unlike N-dimensional splines and HRBFs)
18032 : * MSTAB does not return function values far from the interval spanned
18033 : by the dataset; say, if all your points have |f|<=1, you can be sure
18034 : that model value won't deviate too much from [-1,+1]
18035 : 3) good model construction time competing with that of HRBFs and bicubic
18036 : splines
18037 : 4) ability to work with any number of dimensions, starting from NX=1
18038 :
18039 : The drawbacks of IDW-MSTAB (and all IDW algorithms in general) are:
18040 : 1) dependence of the model evaluation time on the search radius
18041 : 2) bad extrapolation properties, models built by this method are usually
18042 : conservative in their predictions
18043 :
18044 : Thus, IDW-MSTAB is a good "default" option if you want to perform
18045 : scattered multidimensional interpolation. Although it has its drawbacks,
18046 : it is easy to use and robust, which makes it a good first step.
18047 :
18048 :
18049 : INPUT PARAMETERS:
18050 : State - builder object
18051 : SRad - initial search radius, SRad>0 is required. A model value
18052 : is obtained by "smart" averaging of the dataset points
18053 : within search radius.
18054 :
18055 : NOTE 1: IDW interpolation can correctly handle ANY dataset, including
18056 : datasets with non-distinct points. In case non-distinct points are
18057 : found, an average value for this point will be calculated.
18058 :
18059 : NOTE 2: the memory requirements for model storage are O(NPoints*NLayers).
18060 : The model construction needs twice as much memory as model storage.
18061 :
18062 : NOTE 3: by default 16 IDW layers are built which is enough for most cases.
18063 : You can change this parameter with idwbuildersetnlayers() method.
18064 : Larger values may be necessary if you need to reproduce extrafine
18065 : details at distances smaller than SRad/65536. Smaller value may
18066 : be necessary if you have to save memory and computing time, and
18067 : ready to sacrifice some model quality.
18068 :
18069 :
18070 : ALGORITHM DESCRIPTION
18071 :
18072 : ALGLIB implementation of IDW is somewhat similar to the modified Shepard's
18073 : method (one with search radius R) but overcomes several of its drawbacks,
18074 : namely:
18075 : 1) a tendency to show stepwise behavior for uniform datasets
18076 : 2) a tendency to show terrible interpolation properties for highly
18077 : nonuniform datasets which often arise in geospatial tasks
18078 : (function values are densely sampled across multiple separated
18079 : "tracks")
18080 :
18081 : IDW-MSTAB method performs several passes over dataset and builds a sequence
18082 : of progressively refined IDW models (layers), which starts from one with
18083 : largest search radius SRad and continues to smaller search radii until
18084 : required number of layers is built. Highest layers reproduce global
18085 : behavior of the target function at larger distances whilst lower layers
18086 : reproduce fine details at smaller distances.
18087 :
18088 : Each layer is an IDW model built with following modifications:
18089 : * weights go to zero when distance approach to the current search radius
18090 : * an additional regularizing term is added to the distance: w=1/(d^2+lambda)
18091 : * an additional fictional term with unit weight and zero function value is
18092 : added in order to promote continuity properties at the isolated and
18093 : boundary points
18094 :
18095 : By default, 16 layers is built, which is enough for most cases. You can
18096 : change this parameter with idwbuildersetnlayers() method.
18097 :
18098 : -- ALGLIB --
18099 : Copyright 22.10.2018 by Bochkanov Sergey
18100 : *************************************************************************/
18101 0 : void idwbuildersetalgomstab(idwbuilder* state,
18102 : double srad,
18103 : ae_state *_state)
18104 : {
18105 :
18106 :
18107 0 : ae_assert(ae_isfinite(srad, _state), "IDWBuilderSetAlgoMSTAB: SRad is not finite", _state);
18108 0 : ae_assert(ae_fp_greater(srad,(double)(0)), "IDWBuilderSetAlgoMSTAB: SRad<=0", _state);
18109 :
18110 : /*
18111 : * Set algorithm
18112 : */
18113 0 : state->algotype = 2;
18114 :
18115 : /*
18116 : * Set options
18117 : */
18118 0 : state->r0 = srad;
18119 0 : state->rdecay = 0.5;
18120 0 : state->lambda0 = idw_defaultlambda0;
18121 0 : state->lambdalast = (double)(0);
18122 0 : state->lambdadecay = 1.0;
18123 0 : }
18124 :
18125 :
18126 : /*************************************************************************
18127 : This function sets IDW model construction algorithm to the textbook
18128 : Shepard's algorithm with custom (user-specified) power parameter.
18129 :
18130 : IMPORTANT: we do NOT recommend using textbook IDW algorithms because they
18131 : have terrible interpolation properties. Use MSTAB in all cases.
18132 :
18133 : INPUT PARAMETERS:
18134 : State - builder object
18135 : P - power parameter, P>0; good value to start with is 2.0
18136 :
18137 : NOTE 1: IDW interpolation can correctly handle ANY dataset, including
18138 : datasets with non-distinct points. In case non-distinct points are
18139 : found, an average value for this point will be calculated.
18140 :
18141 : -- ALGLIB --
18142 : Copyright 22.10.2018 by Bochkanov Sergey
18143 : *************************************************************************/
18144 0 : void idwbuildersetalgotextbookshepard(idwbuilder* state,
18145 : double p,
18146 : ae_state *_state)
18147 : {
18148 :
18149 :
18150 0 : ae_assert(ae_isfinite(p, _state), "IDWBuilderSetAlgoShepard: P is not finite", _state);
18151 0 : ae_assert(ae_fp_greater(p,(double)(0)), "IDWBuilderSetAlgoShepard: P<=0", _state);
18152 :
18153 : /*
18154 : * Set algorithm and options
18155 : */
18156 0 : state->algotype = 0;
18157 0 : state->shepardp = p;
18158 0 : }
18159 :
18160 :
18161 : /*************************************************************************
18162 : This function sets IDW model construction algorithm to the 'textbook'
18163 : modified Shepard's algorithm with user-specified search radius.
18164 :
18165 : IMPORTANT: we do NOT recommend using textbook IDW algorithms because they
18166 : have terrible interpolation properties. Use MSTAB in all cases.
18167 :
18168 : INPUT PARAMETERS:
18169 : State - builder object
18170 : R - search radius
18171 :
18172 : NOTE 1: IDW interpolation can correctly handle ANY dataset, including
18173 : datasets with non-distinct points. In case non-distinct points are
18174 : found, an average value for this point will be calculated.
18175 :
18176 : -- ALGLIB --
18177 : Copyright 22.10.2018 by Bochkanov Sergey
18178 : *************************************************************************/
18179 0 : void idwbuildersetalgotextbookmodshepard(idwbuilder* state,
18180 : double r,
18181 : ae_state *_state)
18182 : {
18183 :
18184 :
18185 0 : ae_assert(ae_isfinite(r, _state), "IDWBuilderSetAlgoModShepard: R is not finite", _state);
18186 0 : ae_assert(ae_fp_greater(r,(double)(0)), "IDWBuilderSetAlgoModShepard: R<=0", _state);
18187 :
18188 : /*
18189 : * Set algorithm and options
18190 : */
18191 0 : state->algotype = 1;
18192 0 : state->r0 = r;
18193 0 : }
18194 :
18195 :
18196 : /*************************************************************************
18197 : This function sets prior term (model value at infinity) as user-specified
18198 : value.
18199 :
18200 : INPUT PARAMETERS:
18201 : S - spline builder
18202 : V - value for user-defined prior
18203 :
18204 : NOTE: for vector-valued models all components of the prior are set to same
18205 : user-specified value
18206 :
18207 : -- ALGLIB --
18208 : Copyright 29.10.2018 by Bochkanov Sergey
18209 : *************************************************************************/
18210 0 : void idwbuildersetuserterm(idwbuilder* state, double v, ae_state *_state)
18211 : {
18212 : ae_int_t j;
18213 :
18214 :
18215 0 : ae_assert(ae_isfinite(v, _state), "IDWBuilderSetUserTerm: infinite/NAN value passed", _state);
18216 0 : state->priortermtype = 0;
18217 0 : for(j=0; j<=state->ny-1; j++)
18218 : {
18219 0 : state->priortermval.ptr.p_double[j] = v;
18220 : }
18221 0 : }
18222 :
18223 :
18224 : /*************************************************************************
18225 : This function sets constant prior term (model value at infinity).
18226 :
18227 : Constant prior term is determined as mean value over dataset.
18228 :
18229 : INPUT PARAMETERS:
18230 : S - spline builder
18231 :
18232 : -- ALGLIB --
18233 : Copyright 29.10.2018 by Bochkanov Sergey
18234 : *************************************************************************/
18235 0 : void idwbuildersetconstterm(idwbuilder* state, ae_state *_state)
18236 : {
18237 :
18238 :
18239 0 : state->priortermtype = 2;
18240 0 : }
18241 :
18242 :
18243 : /*************************************************************************
18244 : This function sets zero prior term (model value at infinity).
18245 :
18246 : INPUT PARAMETERS:
18247 : S - spline builder
18248 :
18249 : -- ALGLIB --
18250 : Copyright 29.10.2018 by Bochkanov Sergey
18251 : *************************************************************************/
18252 0 : void idwbuildersetzeroterm(idwbuilder* state, ae_state *_state)
18253 : {
18254 :
18255 :
18256 0 : state->priortermtype = 3;
18257 0 : }
18258 :
18259 :
18260 : /*************************************************************************
18261 : IDW interpolation: scalar target, 1-dimensional argument
18262 :
18263 : NOTE: this function modifies internal temporaries of the IDW model, thus
18264 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
18265 : evaluation from the multiple threads, use idwtscalcbuf() with per-
18266 : thread buffer object.
18267 :
18268 : INPUT PARAMETERS:
18269 : S - IDW interpolant built with IDW builder
18270 : X0 - argument value
18271 :
18272 : Result:
18273 : IDW interpolant S(X0)
18274 :
18275 : -- ALGLIB --
18276 : Copyright 22.10.2018 by Bochkanov Sergey
18277 : *************************************************************************/
18278 0 : double idwcalc1(idwmodel* s, double x0, ae_state *_state)
18279 : {
18280 : double result;
18281 :
18282 :
18283 0 : ae_assert(s->nx==1, "IDWCalc1: S.NX<>1", _state);
18284 0 : ae_assert(s->ny==1, "IDWCalc1: S.NY<>1", _state);
18285 0 : ae_assert(ae_isfinite(x0, _state), "IDWCalc1: X0 is INF or NAN", _state);
18286 0 : s->buffer.x.ptr.p_double[0] = x0;
18287 0 : idwtscalcbuf(s, &s->buffer, &s->buffer.x, &s->buffer.y, _state);
18288 0 : result = s->buffer.y.ptr.p_double[0];
18289 0 : return result;
18290 : }
18291 :
18292 :
18293 : /*************************************************************************
18294 : IDW interpolation: scalar target, 2-dimensional argument
18295 :
18296 : NOTE: this function modifies internal temporaries of the IDW model, thus
18297 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
18298 : evaluation from the multiple threads, use idwtscalcbuf() with per-
18299 : thread buffer object.
18300 :
18301 : INPUT PARAMETERS:
18302 : S - IDW interpolant built with IDW builder
18303 : X0, X1 - argument value
18304 :
18305 : Result:
18306 : IDW interpolant S(X0,X1)
18307 :
18308 : -- ALGLIB --
18309 : Copyright 22.10.2018 by Bochkanov Sergey
18310 : *************************************************************************/
18311 0 : double idwcalc2(idwmodel* s, double x0, double x1, ae_state *_state)
18312 : {
18313 : double result;
18314 :
18315 :
18316 0 : ae_assert(s->nx==2, "IDWCalc2: S.NX<>2", _state);
18317 0 : ae_assert(s->ny==1, "IDWCalc2: S.NY<>1", _state);
18318 0 : ae_assert(ae_isfinite(x0, _state), "IDWCalc2: X0 is INF or NAN", _state);
18319 0 : ae_assert(ae_isfinite(x1, _state), "IDWCalc2: X1 is INF or NAN", _state);
18320 0 : s->buffer.x.ptr.p_double[0] = x0;
18321 0 : s->buffer.x.ptr.p_double[1] = x1;
18322 0 : idwtscalcbuf(s, &s->buffer, &s->buffer.x, &s->buffer.y, _state);
18323 0 : result = s->buffer.y.ptr.p_double[0];
18324 0 : return result;
18325 : }
18326 :
18327 :
18328 : /*************************************************************************
18329 : IDW interpolation: scalar target, 3-dimensional argument
18330 :
18331 : NOTE: this function modifies internal temporaries of the IDW model, thus
18332 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
18333 : evaluation from the multiple threads, use idwtscalcbuf() with per-
18334 : thread buffer object.
18335 :
18336 : INPUT PARAMETERS:
18337 : S - IDW interpolant built with IDW builder
18338 : X0,X1,X2- argument value
18339 :
18340 : Result:
18341 : IDW interpolant S(X0,X1,X2)
18342 :
18343 : -- ALGLIB --
18344 : Copyright 22.10.2018 by Bochkanov Sergey
18345 : *************************************************************************/
18346 0 : double idwcalc3(idwmodel* s,
18347 : double x0,
18348 : double x1,
18349 : double x2,
18350 : ae_state *_state)
18351 : {
18352 : double result;
18353 :
18354 :
18355 0 : ae_assert(s->nx==3, "IDWCalc3: S.NX<>3", _state);
18356 0 : ae_assert(s->ny==1, "IDWCalc3: S.NY<>1", _state);
18357 0 : ae_assert(ae_isfinite(x0, _state), "IDWCalc3: X0 is INF or NAN", _state);
18358 0 : ae_assert(ae_isfinite(x1, _state), "IDWCalc3: X1 is INF or NAN", _state);
18359 0 : ae_assert(ae_isfinite(x2, _state), "IDWCalc3: X2 is INF or NAN", _state);
18360 0 : s->buffer.x.ptr.p_double[0] = x0;
18361 0 : s->buffer.x.ptr.p_double[1] = x1;
18362 0 : s->buffer.x.ptr.p_double[2] = x2;
18363 0 : idwtscalcbuf(s, &s->buffer, &s->buffer.x, &s->buffer.y, _state);
18364 0 : result = s->buffer.y.ptr.p_double[0];
18365 0 : return result;
18366 : }
18367 :
18368 :
18369 : /*************************************************************************
18370 : This function calculates values of the IDW model at the given point.
18371 :
18372 : This is general function which can be used for arbitrary NX (dimension of
18373 : the space of arguments) and NY (dimension of the function itself). However
18374 : when you have NY=1 you may find more convenient to use idwcalc1(),
18375 : idwcalc2() or idwcalc3().
18376 :
18377 : NOTE: this function modifies internal temporaries of the IDW model, thus
18378 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
18379 : evaluation from the multiple threads, use idwtscalcbuf() with per-
18380 : thread buffer object.
18381 :
18382 : INPUT PARAMETERS:
18383 : S - IDW model
18384 : X - coordinates, array[NX]. X may have more than NX elements,
18385 : in this case only leading NX will be used.
18386 :
18387 : OUTPUT PARAMETERS:
18388 : Y - function value, array[NY]. Y is out-parameter and will be
18389 : reallocated after call to this function. In case you want
18390 : to reuse previously allocated Y, you may use idwcalcbuf(),
18391 : which reallocates Y only when it is too small.
18392 :
18393 : -- ALGLIB --
18394 : Copyright 22.10.2018 by Bochkanov Sergey
18395 : *************************************************************************/
18396 0 : void idwcalc(idwmodel* s,
18397 : /* Real */ ae_vector* x,
18398 : /* Real */ ae_vector* y,
18399 : ae_state *_state)
18400 : {
18401 :
18402 0 : ae_vector_clear(y);
18403 :
18404 0 : idwtscalcbuf(s, &s->buffer, x, y, _state);
18405 0 : }
18406 :
18407 :
18408 : /*************************************************************************
18409 : This function calculates values of the IDW model at the given point.
18410 :
18411 : Same as idwcalc(), but does not reallocate Y when in is large enough to
18412 : store function values.
18413 :
18414 : NOTE: this function modifies internal temporaries of the IDW model, thus
18415 : IT IS NOT THREAD-SAFE! If you want to perform parallel model
18416 : evaluation from the multiple threads, use idwtscalcbuf() with per-
18417 : thread buffer object.
18418 :
18419 : INPUT PARAMETERS:
18420 : S - IDW model
18421 : X - coordinates, array[NX]. X may have more than NX elements,
18422 : in this case only leading NX will be used.
18423 : Y - possibly preallocated array
18424 :
18425 : OUTPUT PARAMETERS:
18426 : Y - function value, array[NY]. Y is not reallocated when it
18427 : is larger than NY.
18428 :
18429 : -- ALGLIB --
18430 : Copyright 22.10.2018 by Bochkanov Sergey
18431 : *************************************************************************/
18432 0 : void idwcalcbuf(idwmodel* s,
18433 : /* Real */ ae_vector* x,
18434 : /* Real */ ae_vector* y,
18435 : ae_state *_state)
18436 : {
18437 :
18438 :
18439 0 : idwtscalcbuf(s, &s->buffer, x, y, _state);
18440 0 : }
18441 :
18442 :
18443 : /*************************************************************************
18444 : This function calculates values of the IDW model at the given point, using
18445 : external buffer object (internal temporaries of IDW model are not
18446 : modified).
18447 :
18448 : This function allows to use same IDW model object in different threads,
18449 : assuming that different threads use different instances of the buffer
18450 : structure.
18451 :
18452 : INPUT PARAMETERS:
18453 : S - IDW model, may be shared between different threads
18454 : Buf - buffer object created for this particular instance of IDW
18455 : model with idwcreatecalcbuffer().
18456 : X - coordinates, array[NX]. X may have more than NX elements,
18457 : in this case only leading NX will be used.
18458 : Y - possibly preallocated array
18459 :
18460 : OUTPUT PARAMETERS:
18461 : Y - function value, array[NY]. Y is not reallocated when it
18462 : is larger than NY.
18463 :
18464 : -- ALGLIB --
18465 : Copyright 13.12.2011 by Bochkanov Sergey
18466 : *************************************************************************/
18467 0 : void idwtscalcbuf(idwmodel* s,
18468 : idwcalcbuffer* buf,
18469 : /* Real */ ae_vector* x,
18470 : /* Real */ ae_vector* y,
18471 : ae_state *_state)
18472 : {
18473 : ae_int_t i;
18474 : ae_int_t j;
18475 : ae_int_t ew;
18476 : ae_int_t k;
18477 : ae_int_t layeridx;
18478 : ae_int_t nx;
18479 : ae_int_t ny;
18480 : ae_int_t npoints;
18481 : double v;
18482 : double vv;
18483 : double f;
18484 : double p;
18485 : double r;
18486 : double eps;
18487 : double lambdacur;
18488 : double lambdadecay;
18489 : double invrdecay;
18490 : double invr;
18491 : ae_bool fastcalcpossible;
18492 : double wf0;
18493 : double ws0;
18494 : double wf1;
18495 : double ws1;
18496 :
18497 :
18498 0 : nx = s->nx;
18499 0 : ny = s->ny;
18500 0 : ae_assert(x->cnt>=nx, "IDWTsCalcBuf: Length(X)<NX", _state);
18501 0 : ae_assert(isfinitevector(x, nx, _state), "IDWTsCalcBuf: X contains infinite or NaN values", _state);
18502 :
18503 : /*
18504 : * Avoid spurious compiler warnings
18505 : */
18506 0 : wf0 = (double)(0);
18507 0 : ws0 = (double)(0);
18508 0 : wf1 = (double)(0);
18509 0 : ws1 = (double)(0);
18510 :
18511 : /*
18512 : * Allocate output
18513 : */
18514 0 : if( y->cnt<ny )
18515 : {
18516 0 : ae_vector_set_length(y, ny, _state);
18517 : }
18518 :
18519 : /*
18520 : * Quick exit for NLayers=0 (no dataset)
18521 : */
18522 0 : if( s->nlayers==0 )
18523 : {
18524 0 : for(j=0; j<=ny-1; j++)
18525 : {
18526 0 : y->ptr.p_double[j] = s->globalprior.ptr.p_double[j];
18527 : }
18528 0 : return;
18529 : }
18530 :
18531 : /*
18532 : * Textbook Shepard's method
18533 : */
18534 0 : if( s->algotype==0 )
18535 : {
18536 0 : npoints = s->npoints;
18537 0 : ae_assert(npoints>0, "IDWTsCalcBuf: integrity check failed", _state);
18538 0 : eps = 1.0E-50;
18539 0 : ew = nx+ny;
18540 0 : p = s->shepardp;
18541 0 : for(j=0; j<=ny-1; j++)
18542 : {
18543 0 : y->ptr.p_double[j] = (double)(0);
18544 0 : buf->tsyw.ptr.p_double[j] = eps;
18545 : }
18546 0 : for(i=0; i<=npoints-1; i++)
18547 : {
18548 :
18549 : /*
18550 : * Compute squared distance
18551 : */
18552 0 : v = (double)(0);
18553 0 : for(j=0; j<=nx-1; j++)
18554 : {
18555 0 : vv = s->shepardxy.ptr.p_double[i*ew+j]-x->ptr.p_double[j];
18556 0 : v = v+vv*vv;
18557 : }
18558 :
18559 : /*
18560 : * Compute weight (with small regularizing addition)
18561 : */
18562 0 : v = ae_pow(v, p*0.5, _state);
18563 0 : v = 1/(eps+v);
18564 :
18565 : /*
18566 : * Accumulate
18567 : */
18568 0 : for(j=0; j<=ny-1; j++)
18569 : {
18570 0 : y->ptr.p_double[j] = y->ptr.p_double[j]+v*s->shepardxy.ptr.p_double[i*ew+nx+j];
18571 0 : buf->tsyw.ptr.p_double[j] = buf->tsyw.ptr.p_double[j]+v;
18572 : }
18573 : }
18574 0 : for(j=0; j<=ny-1; j++)
18575 : {
18576 0 : y->ptr.p_double[j] = y->ptr.p_double[j]/buf->tsyw.ptr.p_double[j]+s->globalprior.ptr.p_double[j];
18577 : }
18578 0 : return;
18579 : }
18580 :
18581 : /*
18582 : * Textbook modified Shepard's method
18583 : */
18584 0 : if( s->algotype==1 )
18585 : {
18586 0 : eps = 1.0E-50;
18587 0 : r = s->r0;
18588 0 : for(j=0; j<=ny-1; j++)
18589 : {
18590 0 : y->ptr.p_double[j] = (double)(0);
18591 0 : buf->tsyw.ptr.p_double[j] = eps;
18592 : }
18593 0 : k = kdtreetsqueryrnn(&s->tree, &buf->requestbuffer, x, r, ae_true, _state);
18594 0 : kdtreetsqueryresultsxy(&s->tree, &buf->requestbuffer, &buf->tsxy, _state);
18595 0 : kdtreetsqueryresultsdistances(&s->tree, &buf->requestbuffer, &buf->tsdist, _state);
18596 0 : for(i=0; i<=k-1; i++)
18597 : {
18598 0 : v = buf->tsdist.ptr.p_double[i];
18599 0 : v = (r-v)/(r*v+eps);
18600 0 : v = v*v;
18601 0 : for(j=0; j<=ny-1; j++)
18602 : {
18603 0 : y->ptr.p_double[j] = y->ptr.p_double[j]+v*buf->tsxy.ptr.pp_double[i][nx+j];
18604 0 : buf->tsyw.ptr.p_double[j] = buf->tsyw.ptr.p_double[j]+v;
18605 : }
18606 : }
18607 0 : for(j=0; j<=ny-1; j++)
18608 : {
18609 0 : y->ptr.p_double[j] = y->ptr.p_double[j]/buf->tsyw.ptr.p_double[j]+s->globalprior.ptr.p_double[j];
18610 : }
18611 0 : return;
18612 : }
18613 :
18614 : /*
18615 : * MSTAB
18616 : */
18617 0 : if( s->algotype==2 )
18618 : {
18619 0 : ae_assert(ae_fp_eq(idw_w0,(double)(1)), "IDWTsCalcBuf: unexpected W0, integrity check failed", _state);
18620 0 : invrdecay = 1/s->rdecay;
18621 0 : invr = 1/s->r0;
18622 0 : lambdadecay = s->lambdadecay;
18623 0 : fastcalcpossible = (ny==1&&s->nlayers>=3)&&ae_fp_eq(lambdadecay,(double)(1));
18624 0 : if( fastcalcpossible )
18625 : {
18626 :
18627 : /*
18628 : * Important special case, NY=1, no lambda-decay,
18629 : * we can perform optimized fast evaluation
18630 : */
18631 0 : wf0 = (double)(0);
18632 0 : ws0 = idw_w0;
18633 0 : wf1 = (double)(0);
18634 0 : ws1 = idw_w0;
18635 0 : for(j=0; j<=s->nlayers-1; j++)
18636 : {
18637 0 : buf->tsyw.ptr.p_double[j] = (double)(0);
18638 0 : buf->tsw.ptr.p_double[j] = idw_w0;
18639 : }
18640 : }
18641 : else
18642 : {
18643 :
18644 : /*
18645 : * Setup variables for generic evaluation path
18646 : */
18647 0 : for(j=0; j<=ny*s->nlayers-1; j++)
18648 : {
18649 0 : buf->tsyw.ptr.p_double[j] = (double)(0);
18650 : }
18651 0 : for(j=0; j<=s->nlayers-1; j++)
18652 : {
18653 0 : buf->tsw.ptr.p_double[j] = idw_w0;
18654 : }
18655 : }
18656 0 : k = kdtreetsqueryrnnu(&s->tree, &buf->requestbuffer, x, s->r0, ae_true, _state);
18657 0 : kdtreetsqueryresultsxy(&s->tree, &buf->requestbuffer, &buf->tsxy, _state);
18658 0 : kdtreetsqueryresultsdistances(&s->tree, &buf->requestbuffer, &buf->tsdist, _state);
18659 0 : for(i=0; i<=k-1; i++)
18660 : {
18661 0 : lambdacur = s->lambda0;
18662 0 : vv = buf->tsdist.ptr.p_double[i]*invr;
18663 0 : if( fastcalcpossible )
18664 : {
18665 :
18666 : /*
18667 : * Important special case, fast evaluation possible
18668 : */
18669 0 : v = vv*vv;
18670 0 : v = (1-v)*(1-v)/(v+lambdacur);
18671 0 : f = buf->tsxy.ptr.pp_double[i][nx+0];
18672 0 : wf0 = wf0+v*f;
18673 0 : ws0 = ws0+v;
18674 0 : vv = vv*invrdecay;
18675 0 : if( vv>=1.0 )
18676 : {
18677 0 : continue;
18678 : }
18679 0 : v = vv*vv;
18680 0 : v = (1-v)*(1-v)/(v+lambdacur);
18681 0 : f = buf->tsxy.ptr.pp_double[i][nx+1];
18682 0 : wf1 = wf1+v*f;
18683 0 : ws1 = ws1+v;
18684 0 : vv = vv*invrdecay;
18685 0 : if( vv>=1.0 )
18686 : {
18687 0 : continue;
18688 : }
18689 0 : for(layeridx=2; layeridx<=s->nlayers-1; layeridx++)
18690 : {
18691 0 : if( layeridx==s->nlayers-1 )
18692 : {
18693 0 : lambdacur = s->lambdalast;
18694 : }
18695 0 : v = vv*vv;
18696 0 : v = (1-v)*(1-v)/(v+lambdacur);
18697 0 : f = buf->tsxy.ptr.pp_double[i][nx+layeridx];
18698 0 : buf->tsyw.ptr.p_double[layeridx] = buf->tsyw.ptr.p_double[layeridx]+v*f;
18699 0 : buf->tsw.ptr.p_double[layeridx] = buf->tsw.ptr.p_double[layeridx]+v;
18700 0 : vv = vv*invrdecay;
18701 0 : if( vv>=1.0 )
18702 : {
18703 0 : break;
18704 : }
18705 : }
18706 : }
18707 : else
18708 : {
18709 :
18710 : /*
18711 : * General case
18712 : */
18713 0 : for(layeridx=0; layeridx<=s->nlayers-1; layeridx++)
18714 : {
18715 0 : if( layeridx==s->nlayers-1 )
18716 : {
18717 0 : lambdacur = s->lambdalast;
18718 : }
18719 0 : if( vv>=1.0 )
18720 : {
18721 0 : break;
18722 : }
18723 0 : v = vv*vv;
18724 0 : v = (1-v)*(1-v)/(v+lambdacur);
18725 0 : for(j=0; j<=ny-1; j++)
18726 : {
18727 0 : f = buf->tsxy.ptr.pp_double[i][nx+layeridx*ny+j];
18728 0 : buf->tsyw.ptr.p_double[layeridx*ny+j] = buf->tsyw.ptr.p_double[layeridx*ny+j]+v*f;
18729 : }
18730 0 : buf->tsw.ptr.p_double[layeridx] = buf->tsw.ptr.p_double[layeridx]+v;
18731 0 : lambdacur = lambdacur*lambdadecay;
18732 0 : vv = vv*invrdecay;
18733 : }
18734 : }
18735 : }
18736 0 : if( fastcalcpossible )
18737 : {
18738 :
18739 : /*
18740 : * Important special case, finalize evaluations
18741 : */
18742 0 : buf->tsyw.ptr.p_double[0] = wf0;
18743 0 : buf->tsw.ptr.p_double[0] = ws0;
18744 0 : buf->tsyw.ptr.p_double[1] = wf1;
18745 0 : buf->tsw.ptr.p_double[1] = ws1;
18746 : }
18747 0 : for(j=0; j<=ny-1; j++)
18748 : {
18749 0 : y->ptr.p_double[j] = s->globalprior.ptr.p_double[j];
18750 : }
18751 0 : for(layeridx=0; layeridx<=s->nlayers-1; layeridx++)
18752 : {
18753 0 : for(j=0; j<=ny-1; j++)
18754 : {
18755 0 : y->ptr.p_double[j] = y->ptr.p_double[j]+buf->tsyw.ptr.p_double[layeridx*ny+j]/buf->tsw.ptr.p_double[layeridx];
18756 : }
18757 : }
18758 0 : return;
18759 : }
18760 :
18761 : /*
18762 : *
18763 : */
18764 0 : ae_assert(ae_false, "IDWTsCalcBuf: unexpected AlgoType", _state);
18765 : }
18766 :
18767 :
18768 : /*************************************************************************
18769 : This function fits IDW model to the dataset using current IDW construction
18770 : algorithm. A model being built and fitting report are returned.
18771 :
18772 : INPUT PARAMETERS:
18773 : State - builder object
18774 :
18775 : OUTPUT PARAMETERS:
18776 : Model - an IDW model built with current algorithm
18777 : Rep - model fitting report, fields of this structure contain
18778 : information about average fitting errors.
18779 :
18780 : NOTE: although IDW-MSTAB algorithm is an interpolation method, i.e. it
18781 : tries to fit the model exactly, it can handle datasets with non-
18782 : distinct points which can not be fit exactly; in such cases least-
18783 : squares fitting is performed.
18784 :
18785 : -- ALGLIB --
18786 : Copyright 22.10.2018 by Bochkanov Sergey
18787 : *************************************************************************/
18788 0 : void idwfit(idwbuilder* state,
18789 : idwmodel* model,
18790 : idwreport* rep,
18791 : ae_state *_state)
18792 : {
18793 : ae_int_t i;
18794 : ae_int_t i0;
18795 : ae_int_t j;
18796 : ae_int_t k;
18797 : ae_int_t layeridx;
18798 : ae_int_t srcidx;
18799 : double v;
18800 : double vv;
18801 : ae_int_t npoints;
18802 : ae_int_t nx;
18803 : ae_int_t ny;
18804 : double rcur;
18805 : double lambdacur;
18806 : double rss;
18807 : double tss;
18808 :
18809 0 : _idwmodel_clear(model);
18810 0 : _idwreport_clear(rep);
18811 :
18812 0 : nx = state->nx;
18813 0 : ny = state->ny;
18814 0 : npoints = state->npoints;
18815 :
18816 : /*
18817 : * Clear report fields
18818 : */
18819 0 : rep->rmserror = (double)(0);
18820 0 : rep->avgerror = (double)(0);
18821 0 : rep->maxerror = (double)(0);
18822 0 : rep->r2 = 1.0;
18823 :
18824 : /*
18825 : * Quick exit for empty dataset
18826 : */
18827 0 : if( state->npoints==0 )
18828 : {
18829 0 : model->nx = nx;
18830 0 : model->ny = ny;
18831 0 : ae_vector_set_length(&model->globalprior, ny, _state);
18832 0 : for(i=0; i<=ny-1; i++)
18833 : {
18834 0 : model->globalprior.ptr.p_double[i] = (double)(0);
18835 : }
18836 0 : model->algotype = 0;
18837 0 : model->nlayers = 0;
18838 0 : model->r0 = (double)(1);
18839 0 : model->rdecay = 0.5;
18840 0 : model->lambda0 = (double)(0);
18841 0 : model->lambdalast = (double)(0);
18842 0 : model->lambdadecay = (double)(1);
18843 0 : model->shepardp = (double)(2);
18844 0 : model->npoints = 0;
18845 0 : idwcreatecalcbuffer(model, &model->buffer, _state);
18846 0 : return;
18847 : }
18848 :
18849 : /*
18850 : * Compute temporaries which will be required later:
18851 : * * global mean
18852 : */
18853 0 : ae_assert(state->npoints>0, "IDWFit: integrity check failed", _state);
18854 0 : rvectorsetlengthatleast(&state->tmpmean, ny, _state);
18855 0 : for(j=0; j<=ny-1; j++)
18856 : {
18857 0 : state->tmpmean.ptr.p_double[j] = (double)(0);
18858 : }
18859 0 : for(i=0; i<=npoints-1; i++)
18860 : {
18861 0 : for(j=0; j<=ny-1; j++)
18862 : {
18863 0 : state->tmpmean.ptr.p_double[j] = state->tmpmean.ptr.p_double[j]+state->xy.ptr.p_double[i*(nx+ny)+nx+j];
18864 : }
18865 : }
18866 0 : for(j=0; j<=ny-1; j++)
18867 : {
18868 0 : state->tmpmean.ptr.p_double[j] = state->tmpmean.ptr.p_double[j]/npoints;
18869 : }
18870 :
18871 : /*
18872 : * Compute global prior
18873 : *
18874 : * NOTE: for original Shepard's method it is always mean value
18875 : */
18876 0 : rvectorsetlengthatleast(&model->globalprior, ny, _state);
18877 0 : for(j=0; j<=ny-1; j++)
18878 : {
18879 0 : model->globalprior.ptr.p_double[j] = state->tmpmean.ptr.p_double[j];
18880 : }
18881 0 : if( state->algotype!=0 )
18882 : {
18883 :
18884 : /*
18885 : * Algorithm is set to one of the "advanced" versions with search
18886 : * radius which can handle non-mean prior term
18887 : */
18888 0 : if( state->priortermtype==0 )
18889 : {
18890 :
18891 : /*
18892 : * User-specified prior
18893 : */
18894 0 : for(j=0; j<=ny-1; j++)
18895 : {
18896 0 : model->globalprior.ptr.p_double[j] = state->priortermval.ptr.p_double[j];
18897 : }
18898 : }
18899 0 : if( state->priortermtype==3 )
18900 : {
18901 :
18902 : /*
18903 : * Zero prior
18904 : */
18905 0 : for(j=0; j<=ny-1; j++)
18906 : {
18907 0 : model->globalprior.ptr.p_double[j] = (double)(0);
18908 : }
18909 : }
18910 : }
18911 :
18912 : /*
18913 : * Textbook Shepard
18914 : */
18915 0 : if( state->algotype==0 )
18916 : {
18917 :
18918 : /*
18919 : * Initialize model
18920 : */
18921 0 : model->algotype = 0;
18922 0 : model->nx = nx;
18923 0 : model->ny = ny;
18924 0 : model->nlayers = 1;
18925 0 : model->r0 = (double)(1);
18926 0 : model->rdecay = 0.5;
18927 0 : model->lambda0 = (double)(0);
18928 0 : model->lambdalast = (double)(0);
18929 0 : model->lambdadecay = (double)(1);
18930 0 : model->shepardp = state->shepardp;
18931 :
18932 : /*
18933 : * Copy dataset
18934 : */
18935 0 : rvectorsetlengthatleast(&model->shepardxy, npoints*(nx+ny), _state);
18936 0 : for(i=0; i<=npoints-1; i++)
18937 : {
18938 0 : for(j=0; j<=nx-1; j++)
18939 : {
18940 0 : model->shepardxy.ptr.p_double[i*(nx+ny)+j] = state->xy.ptr.p_double[i*(nx+ny)+j];
18941 : }
18942 0 : for(j=0; j<=ny-1; j++)
18943 : {
18944 0 : model->shepardxy.ptr.p_double[i*(nx+ny)+nx+j] = state->xy.ptr.p_double[i*(nx+ny)+nx+j]-model->globalprior.ptr.p_double[j];
18945 : }
18946 : }
18947 0 : model->npoints = npoints;
18948 :
18949 : /*
18950 : * Prepare internal buffer
18951 : * Evaluate report fields
18952 : */
18953 0 : idwcreatecalcbuffer(model, &model->buffer, _state);
18954 0 : idw_errormetricsviacalc(state, model, rep, _state);
18955 0 : return;
18956 : }
18957 :
18958 : /*
18959 : * Textbook modified Shepard's method
18960 : */
18961 0 : if( state->algotype==1 )
18962 : {
18963 :
18964 : /*
18965 : * Initialize model
18966 : */
18967 0 : model->algotype = 1;
18968 0 : model->nx = nx;
18969 0 : model->ny = ny;
18970 0 : model->nlayers = 1;
18971 0 : model->r0 = state->r0;
18972 0 : model->rdecay = (double)(1);
18973 0 : model->lambda0 = (double)(0);
18974 0 : model->lambdalast = (double)(0);
18975 0 : model->lambdadecay = (double)(1);
18976 0 : model->shepardp = (double)(0);
18977 :
18978 : /*
18979 : * Build kd-tree search structure
18980 : */
18981 0 : rmatrixsetlengthatleast(&state->tmpxy, npoints, nx+ny, _state);
18982 0 : for(i=0; i<=npoints-1; i++)
18983 : {
18984 0 : for(j=0; j<=nx-1; j++)
18985 : {
18986 0 : state->tmpxy.ptr.pp_double[i][j] = state->xy.ptr.p_double[i*(nx+ny)+j];
18987 : }
18988 0 : for(j=0; j<=ny-1; j++)
18989 : {
18990 0 : state->tmpxy.ptr.pp_double[i][nx+j] = state->xy.ptr.p_double[i*(nx+ny)+nx+j]-model->globalprior.ptr.p_double[j];
18991 : }
18992 : }
18993 0 : kdtreebuild(&state->tmpxy, npoints, nx, ny, 2, &model->tree, _state);
18994 :
18995 : /*
18996 : * Prepare internal buffer
18997 : * Evaluate report fields
18998 : */
18999 0 : idwcreatecalcbuffer(model, &model->buffer, _state);
19000 0 : idw_errormetricsviacalc(state, model, rep, _state);
19001 0 : return;
19002 : }
19003 :
19004 : /*
19005 : * MSTAB algorithm
19006 : */
19007 0 : if( state->algotype==2 )
19008 : {
19009 0 : ae_assert(state->nlayers>=1, "IDWFit: integrity check failed", _state);
19010 :
19011 : /*
19012 : * Initialize model
19013 : */
19014 0 : model->algotype = 2;
19015 0 : model->nx = nx;
19016 0 : model->ny = ny;
19017 0 : model->nlayers = state->nlayers;
19018 0 : model->r0 = state->r0;
19019 0 : model->rdecay = 0.5;
19020 0 : model->lambda0 = state->lambda0;
19021 0 : model->lambdadecay = 1.0;
19022 0 : model->lambdalast = idw_meps;
19023 0 : model->shepardp = (double)(0);
19024 :
19025 : /*
19026 : * Build kd-tree search structure,
19027 : * prepare input residuals for the first layer of the model
19028 : */
19029 0 : rmatrixsetlengthatleast(&state->tmpxy, npoints, nx, _state);
19030 0 : rmatrixsetlengthatleast(&state->tmplayers, npoints, nx+ny*(state->nlayers+1), _state);
19031 0 : ivectorsetlengthatleast(&state->tmptags, npoints, _state);
19032 0 : for(i=0; i<=npoints-1; i++)
19033 : {
19034 0 : for(j=0; j<=nx-1; j++)
19035 : {
19036 0 : v = state->xy.ptr.p_double[i*(nx+ny)+j];
19037 0 : state->tmpxy.ptr.pp_double[i][j] = v;
19038 0 : state->tmplayers.ptr.pp_double[i][j] = v;
19039 : }
19040 0 : state->tmptags.ptr.p_int[i] = i;
19041 0 : for(j=0; j<=ny-1; j++)
19042 : {
19043 0 : state->tmplayers.ptr.pp_double[i][nx+j] = state->xy.ptr.p_double[i*(nx+ny)+nx+j]-model->globalprior.ptr.p_double[j];
19044 : }
19045 : }
19046 0 : kdtreebuildtagged(&state->tmpxy, &state->tmptags, npoints, nx, 0, 2, &state->tmptree, _state);
19047 :
19048 : /*
19049 : * Iteratively build layer by layer
19050 : */
19051 0 : rvectorsetlengthatleast(&state->tmpx, nx, _state);
19052 0 : rvectorsetlengthatleast(&state->tmpwy, ny, _state);
19053 0 : rvectorsetlengthatleast(&state->tmpw, ny, _state);
19054 0 : for(layeridx=0; layeridx<=state->nlayers-1; layeridx++)
19055 : {
19056 :
19057 : /*
19058 : * Determine layer metrics
19059 : */
19060 0 : rcur = model->r0*ae_pow(model->rdecay, (double)(layeridx), _state);
19061 0 : lambdacur = model->lambda0*ae_pow(model->lambdadecay, (double)(layeridx), _state);
19062 0 : if( layeridx==state->nlayers-1 )
19063 : {
19064 0 : lambdacur = model->lambdalast;
19065 : }
19066 :
19067 : /*
19068 : * For each point compute residual from fitting with current layer
19069 : */
19070 0 : for(i=0; i<=npoints-1; i++)
19071 : {
19072 0 : for(j=0; j<=nx-1; j++)
19073 : {
19074 0 : state->tmpx.ptr.p_double[j] = state->tmplayers.ptr.pp_double[i][j];
19075 : }
19076 0 : k = kdtreequeryrnn(&state->tmptree, &state->tmpx, rcur, ae_true, _state);
19077 0 : kdtreequeryresultstags(&state->tmptree, &state->tmptags, _state);
19078 0 : kdtreequeryresultsdistances(&state->tmptree, &state->tmpdist, _state);
19079 0 : for(j=0; j<=ny-1; j++)
19080 : {
19081 0 : state->tmpwy.ptr.p_double[j] = (double)(0);
19082 0 : state->tmpw.ptr.p_double[j] = idw_w0;
19083 : }
19084 0 : for(i0=0; i0<=k-1; i0++)
19085 : {
19086 0 : vv = state->tmpdist.ptr.p_double[i0]/rcur;
19087 0 : vv = vv*vv;
19088 0 : v = (1-vv)*(1-vv)/(vv+lambdacur);
19089 0 : srcidx = state->tmptags.ptr.p_int[i0];
19090 0 : for(j=0; j<=ny-1; j++)
19091 : {
19092 0 : state->tmpwy.ptr.p_double[j] = state->tmpwy.ptr.p_double[j]+v*state->tmplayers.ptr.pp_double[srcidx][nx+layeridx*ny+j];
19093 0 : state->tmpw.ptr.p_double[j] = state->tmpw.ptr.p_double[j]+v;
19094 : }
19095 : }
19096 0 : for(j=0; j<=ny-1; j++)
19097 : {
19098 0 : v = state->tmplayers.ptr.pp_double[i][nx+layeridx*ny+j];
19099 0 : state->tmplayers.ptr.pp_double[i][nx+(layeridx+1)*ny+j] = v-state->tmpwy.ptr.p_double[j]/state->tmpw.ptr.p_double[j];
19100 : }
19101 : }
19102 : }
19103 0 : kdtreebuild(&state->tmplayers, npoints, nx, ny*state->nlayers, 2, &model->tree, _state);
19104 :
19105 : /*
19106 : * Evaluate report fields
19107 : */
19108 0 : rep->rmserror = (double)(0);
19109 0 : rep->avgerror = (double)(0);
19110 0 : rep->maxerror = (double)(0);
19111 0 : rss = (double)(0);
19112 0 : tss = (double)(0);
19113 0 : for(i=0; i<=npoints-1; i++)
19114 : {
19115 0 : for(j=0; j<=ny-1; j++)
19116 : {
19117 0 : v = ae_fabs(state->tmplayers.ptr.pp_double[i][nx+state->nlayers*ny+j], _state);
19118 0 : rep->rmserror = rep->rmserror+v*v;
19119 0 : rep->avgerror = rep->avgerror+v;
19120 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state);
19121 0 : rss = rss+v*v;
19122 0 : tss = tss+ae_sqr(state->xy.ptr.p_double[i*(nx+ny)+nx+j]-state->tmpmean.ptr.p_double[j], _state);
19123 : }
19124 : }
19125 0 : rep->rmserror = ae_sqrt(rep->rmserror/(npoints*ny), _state);
19126 0 : rep->avgerror = rep->avgerror/(npoints*ny);
19127 0 : rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state);
19128 :
19129 : /*
19130 : * Prepare internal buffer
19131 : */
19132 0 : idwcreatecalcbuffer(model, &model->buffer, _state);
19133 0 : return;
19134 : }
19135 :
19136 : /*
19137 : * Unknown algorithm
19138 : */
19139 0 : ae_assert(ae_false, "IDWFit: integrity check failed, unexpected algorithm", _state);
19140 : }
19141 :
19142 :
19143 : /*************************************************************************
19144 : Serializer: allocation
19145 :
19146 : -- ALGLIB --
19147 : Copyright 28.02.2018 by Bochkanov Sergey
19148 : *************************************************************************/
19149 0 : void idwalloc(ae_serializer* s, idwmodel* model, ae_state *_state)
19150 : {
19151 : ae_bool processed;
19152 :
19153 :
19154 :
19155 : /*
19156 : * Header
19157 : */
19158 0 : ae_serializer_alloc_entry(s);
19159 :
19160 : /*
19161 : * Algorithm type and fields which are set for all algorithms
19162 : */
19163 0 : ae_serializer_alloc_entry(s);
19164 0 : ae_serializer_alloc_entry(s);
19165 0 : ae_serializer_alloc_entry(s);
19166 0 : allocrealarray(s, &model->globalprior, -1, _state);
19167 0 : ae_serializer_alloc_entry(s);
19168 0 : ae_serializer_alloc_entry(s);
19169 0 : ae_serializer_alloc_entry(s);
19170 0 : ae_serializer_alloc_entry(s);
19171 0 : ae_serializer_alloc_entry(s);
19172 0 : ae_serializer_alloc_entry(s);
19173 0 : ae_serializer_alloc_entry(s);
19174 :
19175 : /*
19176 : * Algorithm-specific fields
19177 : */
19178 0 : processed = ae_false;
19179 0 : if( model->algotype==0 )
19180 : {
19181 0 : ae_serializer_alloc_entry(s);
19182 0 : allocrealarray(s, &model->shepardxy, -1, _state);
19183 0 : processed = ae_true;
19184 : }
19185 0 : if( model->algotype>0 )
19186 : {
19187 0 : kdtreealloc(s, &model->tree, _state);
19188 0 : processed = ae_true;
19189 : }
19190 0 : ae_assert(processed, "IDW: integrity check failed during serialization", _state);
19191 0 : }
19192 :
19193 :
19194 : /*************************************************************************
19195 : Serializer: serialization
19196 :
19197 : -- ALGLIB --
19198 : Copyright 28.02.2018 by Bochkanov Sergey
19199 : *************************************************************************/
19200 0 : void idwserialize(ae_serializer* s, idwmodel* model, ae_state *_state)
19201 : {
19202 : ae_bool processed;
19203 :
19204 :
19205 :
19206 : /*
19207 : * Header
19208 : */
19209 0 : ae_serializer_serialize_int(s, getidwserializationcode(_state), _state);
19210 :
19211 : /*
19212 : * Algorithm type and fields which are set for all algorithms
19213 : */
19214 0 : ae_serializer_serialize_int(s, model->algotype, _state);
19215 0 : ae_serializer_serialize_int(s, model->nx, _state);
19216 0 : ae_serializer_serialize_int(s, model->ny, _state);
19217 0 : serializerealarray(s, &model->globalprior, -1, _state);
19218 0 : ae_serializer_serialize_int(s, model->nlayers, _state);
19219 0 : ae_serializer_serialize_double(s, model->r0, _state);
19220 0 : ae_serializer_serialize_double(s, model->rdecay, _state);
19221 0 : ae_serializer_serialize_double(s, model->lambda0, _state);
19222 0 : ae_serializer_serialize_double(s, model->lambdalast, _state);
19223 0 : ae_serializer_serialize_double(s, model->lambdadecay, _state);
19224 0 : ae_serializer_serialize_double(s, model->shepardp, _state);
19225 :
19226 : /*
19227 : * Algorithm-specific fields
19228 : */
19229 0 : processed = ae_false;
19230 0 : if( model->algotype==0 )
19231 : {
19232 0 : ae_serializer_serialize_int(s, model->npoints, _state);
19233 0 : serializerealarray(s, &model->shepardxy, -1, _state);
19234 0 : processed = ae_true;
19235 : }
19236 0 : if( model->algotype>0 )
19237 : {
19238 0 : kdtreeserialize(s, &model->tree, _state);
19239 0 : processed = ae_true;
19240 : }
19241 0 : ae_assert(processed, "IDW: integrity check failed during serialization", _state);
19242 0 : }
19243 :
19244 :
19245 : /*************************************************************************
19246 : Serializer: unserialization
19247 :
19248 : -- ALGLIB --
19249 : Copyright 28.02.2018 by Bochkanov Sergey
19250 : *************************************************************************/
19251 0 : void idwunserialize(ae_serializer* s, idwmodel* model, ae_state *_state)
19252 : {
19253 : ae_bool processed;
19254 : ae_int_t scode;
19255 :
19256 0 : _idwmodel_clear(model);
19257 :
19258 :
19259 : /*
19260 : * Header
19261 : */
19262 0 : ae_serializer_unserialize_int(s, &scode, _state);
19263 0 : ae_assert(scode==getidwserializationcode(_state), "IDWUnserialize: stream header corrupted", _state);
19264 :
19265 : /*
19266 : * Algorithm type and fields which are set for all algorithms
19267 : */
19268 0 : ae_serializer_unserialize_int(s, &model->algotype, _state);
19269 0 : ae_serializer_unserialize_int(s, &model->nx, _state);
19270 0 : ae_serializer_unserialize_int(s, &model->ny, _state);
19271 0 : unserializerealarray(s, &model->globalprior, _state);
19272 0 : ae_serializer_unserialize_int(s, &model->nlayers, _state);
19273 0 : ae_serializer_unserialize_double(s, &model->r0, _state);
19274 0 : ae_serializer_unserialize_double(s, &model->rdecay, _state);
19275 0 : ae_serializer_unserialize_double(s, &model->lambda0, _state);
19276 0 : ae_serializer_unserialize_double(s, &model->lambdalast, _state);
19277 0 : ae_serializer_unserialize_double(s, &model->lambdadecay, _state);
19278 0 : ae_serializer_unserialize_double(s, &model->shepardp, _state);
19279 :
19280 : /*
19281 : * Algorithm-specific fields
19282 : */
19283 0 : processed = ae_false;
19284 0 : if( model->algotype==0 )
19285 : {
19286 0 : ae_serializer_unserialize_int(s, &model->npoints, _state);
19287 0 : unserializerealarray(s, &model->shepardxy, _state);
19288 0 : processed = ae_true;
19289 : }
19290 0 : if( model->algotype>0 )
19291 : {
19292 0 : kdtreeunserialize(s, &model->tree, _state);
19293 0 : processed = ae_true;
19294 : }
19295 0 : ae_assert(processed, "IDW: integrity check failed during serialization", _state);
19296 :
19297 : /*
19298 : * Temporary buffers
19299 : */
19300 0 : idwcreatecalcbuffer(model, &model->buffer, _state);
19301 0 : }
19302 :
19303 :
19304 : /*************************************************************************
19305 : This function evaluates error metrics for the model using IDWTsCalcBuf()
19306 : to calculate model at each point.
19307 :
19308 : NOTE: modern IDW algorithms (MSTAB, MSMOOTH) can generate residuals during
19309 : model construction, so they do not need this function in order to
19310 : evaluate error metrics.
19311 :
19312 : Following fields of Rep are filled:
19313 : * rep.rmserror
19314 : * rep.avgerror
19315 : * rep.maxerror
19316 : * rep.r2
19317 :
19318 : -- ALGLIB --
19319 : Copyright 22.10.2018 by Bochkanov Sergey
19320 : *************************************************************************/
19321 0 : static void idw_errormetricsviacalc(idwbuilder* state,
19322 : idwmodel* model,
19323 : idwreport* rep,
19324 : ae_state *_state)
19325 : {
19326 : ae_int_t npoints;
19327 : ae_int_t nx;
19328 : ae_int_t ny;
19329 : ae_int_t i;
19330 : ae_int_t j;
19331 : double v;
19332 : double vv;
19333 : double rss;
19334 : double tss;
19335 :
19336 :
19337 0 : npoints = state->npoints;
19338 0 : nx = state->nx;
19339 0 : ny = state->ny;
19340 0 : if( npoints==0 )
19341 : {
19342 0 : rep->rmserror = (double)(0);
19343 0 : rep->avgerror = (double)(0);
19344 0 : rep->maxerror = (double)(0);
19345 0 : rep->r2 = (double)(1);
19346 0 : return;
19347 : }
19348 0 : rep->rmserror = (double)(0);
19349 0 : rep->avgerror = (double)(0);
19350 0 : rep->maxerror = (double)(0);
19351 0 : rss = (double)(0);
19352 0 : tss = (double)(0);
19353 0 : for(i=0; i<=npoints-1; i++)
19354 : {
19355 0 : for(j=0; j<=nx-1; j++)
19356 : {
19357 0 : model->buffer.x.ptr.p_double[j] = state->xy.ptr.p_double[i*(nx+ny)+j];
19358 : }
19359 0 : idwtscalcbuf(model, &model->buffer, &model->buffer.x, &model->buffer.y, _state);
19360 0 : for(j=0; j<=ny-1; j++)
19361 : {
19362 0 : vv = state->xy.ptr.p_double[i*(nx+ny)+nx+j];
19363 0 : v = ae_fabs(vv-model->buffer.y.ptr.p_double[j], _state);
19364 0 : rep->rmserror = rep->rmserror+v*v;
19365 0 : rep->avgerror = rep->avgerror+v;
19366 0 : rep->maxerror = ae_maxreal(rep->maxerror, v, _state);
19367 0 : rss = rss+v*v;
19368 0 : tss = tss+ae_sqr(vv-state->tmpmean.ptr.p_double[j], _state);
19369 : }
19370 : }
19371 0 : rep->rmserror = ae_sqrt(rep->rmserror/(npoints*ny), _state);
19372 0 : rep->avgerror = rep->avgerror/(npoints*ny);
19373 0 : rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state);
19374 : }
19375 :
19376 :
19377 0 : void _idwcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic)
19378 : {
19379 0 : idwcalcbuffer *p = (idwcalcbuffer*)_p;
19380 0 : ae_touch_ptr((void*)p);
19381 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
19382 0 : ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic);
19383 0 : ae_vector_init(&p->tsyw, 0, DT_REAL, _state, make_automatic);
19384 0 : ae_vector_init(&p->tsw, 0, DT_REAL, _state, make_automatic);
19385 0 : ae_matrix_init(&p->tsxy, 0, 0, DT_REAL, _state, make_automatic);
19386 0 : ae_vector_init(&p->tsdist, 0, DT_REAL, _state, make_automatic);
19387 0 : _kdtreerequestbuffer_init(&p->requestbuffer, _state, make_automatic);
19388 0 : }
19389 :
19390 :
19391 0 : void _idwcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
19392 : {
19393 0 : idwcalcbuffer *dst = (idwcalcbuffer*)_dst;
19394 0 : idwcalcbuffer *src = (idwcalcbuffer*)_src;
19395 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
19396 0 : ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic);
19397 0 : ae_vector_init_copy(&dst->tsyw, &src->tsyw, _state, make_automatic);
19398 0 : ae_vector_init_copy(&dst->tsw, &src->tsw, _state, make_automatic);
19399 0 : ae_matrix_init_copy(&dst->tsxy, &src->tsxy, _state, make_automatic);
19400 0 : ae_vector_init_copy(&dst->tsdist, &src->tsdist, _state, make_automatic);
19401 0 : _kdtreerequestbuffer_init_copy(&dst->requestbuffer, &src->requestbuffer, _state, make_automatic);
19402 0 : }
19403 :
19404 :
19405 0 : void _idwcalcbuffer_clear(void* _p)
19406 : {
19407 0 : idwcalcbuffer *p = (idwcalcbuffer*)_p;
19408 0 : ae_touch_ptr((void*)p);
19409 0 : ae_vector_clear(&p->x);
19410 0 : ae_vector_clear(&p->y);
19411 0 : ae_vector_clear(&p->tsyw);
19412 0 : ae_vector_clear(&p->tsw);
19413 0 : ae_matrix_clear(&p->tsxy);
19414 0 : ae_vector_clear(&p->tsdist);
19415 0 : _kdtreerequestbuffer_clear(&p->requestbuffer);
19416 0 : }
19417 :
19418 :
19419 0 : void _idwcalcbuffer_destroy(void* _p)
19420 : {
19421 0 : idwcalcbuffer *p = (idwcalcbuffer*)_p;
19422 0 : ae_touch_ptr((void*)p);
19423 0 : ae_vector_destroy(&p->x);
19424 0 : ae_vector_destroy(&p->y);
19425 0 : ae_vector_destroy(&p->tsyw);
19426 0 : ae_vector_destroy(&p->tsw);
19427 0 : ae_matrix_destroy(&p->tsxy);
19428 0 : ae_vector_destroy(&p->tsdist);
19429 0 : _kdtreerequestbuffer_destroy(&p->requestbuffer);
19430 0 : }
19431 :
19432 :
19433 0 : void _idwmodel_init(void* _p, ae_state *_state, ae_bool make_automatic)
19434 : {
19435 0 : idwmodel *p = (idwmodel*)_p;
19436 0 : ae_touch_ptr((void*)p);
19437 0 : ae_vector_init(&p->globalprior, 0, DT_REAL, _state, make_automatic);
19438 0 : _kdtree_init(&p->tree, _state, make_automatic);
19439 0 : ae_vector_init(&p->shepardxy, 0, DT_REAL, _state, make_automatic);
19440 0 : _idwcalcbuffer_init(&p->buffer, _state, make_automatic);
19441 0 : }
19442 :
19443 :
19444 0 : void _idwmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
19445 : {
19446 0 : idwmodel *dst = (idwmodel*)_dst;
19447 0 : idwmodel *src = (idwmodel*)_src;
19448 0 : dst->nx = src->nx;
19449 0 : dst->ny = src->ny;
19450 0 : ae_vector_init_copy(&dst->globalprior, &src->globalprior, _state, make_automatic);
19451 0 : dst->algotype = src->algotype;
19452 0 : dst->nlayers = src->nlayers;
19453 0 : dst->r0 = src->r0;
19454 0 : dst->rdecay = src->rdecay;
19455 0 : dst->lambda0 = src->lambda0;
19456 0 : dst->lambdalast = src->lambdalast;
19457 0 : dst->lambdadecay = src->lambdadecay;
19458 0 : dst->shepardp = src->shepardp;
19459 0 : _kdtree_init_copy(&dst->tree, &src->tree, _state, make_automatic);
19460 0 : dst->npoints = src->npoints;
19461 0 : ae_vector_init_copy(&dst->shepardxy, &src->shepardxy, _state, make_automatic);
19462 0 : _idwcalcbuffer_init_copy(&dst->buffer, &src->buffer, _state, make_automatic);
19463 0 : }
19464 :
19465 :
19466 0 : void _idwmodel_clear(void* _p)
19467 : {
19468 0 : idwmodel *p = (idwmodel*)_p;
19469 0 : ae_touch_ptr((void*)p);
19470 0 : ae_vector_clear(&p->globalprior);
19471 0 : _kdtree_clear(&p->tree);
19472 0 : ae_vector_clear(&p->shepardxy);
19473 0 : _idwcalcbuffer_clear(&p->buffer);
19474 0 : }
19475 :
19476 :
19477 0 : void _idwmodel_destroy(void* _p)
19478 : {
19479 0 : idwmodel *p = (idwmodel*)_p;
19480 0 : ae_touch_ptr((void*)p);
19481 0 : ae_vector_destroy(&p->globalprior);
19482 0 : _kdtree_destroy(&p->tree);
19483 0 : ae_vector_destroy(&p->shepardxy);
19484 0 : _idwcalcbuffer_destroy(&p->buffer);
19485 0 : }
19486 :
19487 :
19488 0 : void _idwbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic)
19489 : {
19490 0 : idwbuilder *p = (idwbuilder*)_p;
19491 0 : ae_touch_ptr((void*)p);
19492 0 : ae_vector_init(&p->priortermval, 0, DT_REAL, _state, make_automatic);
19493 0 : ae_vector_init(&p->xy, 0, DT_REAL, _state, make_automatic);
19494 0 : ae_matrix_init(&p->tmpxy, 0, 0, DT_REAL, _state, make_automatic);
19495 0 : ae_matrix_init(&p->tmplayers, 0, 0, DT_REAL, _state, make_automatic);
19496 0 : ae_vector_init(&p->tmptags, 0, DT_INT, _state, make_automatic);
19497 0 : ae_vector_init(&p->tmpdist, 0, DT_REAL, _state, make_automatic);
19498 0 : ae_vector_init(&p->tmpx, 0, DT_REAL, _state, make_automatic);
19499 0 : ae_vector_init(&p->tmpwy, 0, DT_REAL, _state, make_automatic);
19500 0 : ae_vector_init(&p->tmpw, 0, DT_REAL, _state, make_automatic);
19501 0 : _kdtree_init(&p->tmptree, _state, make_automatic);
19502 0 : ae_vector_init(&p->tmpmean, 0, DT_REAL, _state, make_automatic);
19503 0 : }
19504 :
19505 :
19506 0 : void _idwbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
19507 : {
19508 0 : idwbuilder *dst = (idwbuilder*)_dst;
19509 0 : idwbuilder *src = (idwbuilder*)_src;
19510 0 : dst->priortermtype = src->priortermtype;
19511 0 : ae_vector_init_copy(&dst->priortermval, &src->priortermval, _state, make_automatic);
19512 0 : dst->algotype = src->algotype;
19513 0 : dst->nlayers = src->nlayers;
19514 0 : dst->r0 = src->r0;
19515 0 : dst->rdecay = src->rdecay;
19516 0 : dst->lambda0 = src->lambda0;
19517 0 : dst->lambdalast = src->lambdalast;
19518 0 : dst->lambdadecay = src->lambdadecay;
19519 0 : dst->shepardp = src->shepardp;
19520 0 : ae_vector_init_copy(&dst->xy, &src->xy, _state, make_automatic);
19521 0 : dst->npoints = src->npoints;
19522 0 : dst->nx = src->nx;
19523 0 : dst->ny = src->ny;
19524 0 : ae_matrix_init_copy(&dst->tmpxy, &src->tmpxy, _state, make_automatic);
19525 0 : ae_matrix_init_copy(&dst->tmplayers, &src->tmplayers, _state, make_automatic);
19526 0 : ae_vector_init_copy(&dst->tmptags, &src->tmptags, _state, make_automatic);
19527 0 : ae_vector_init_copy(&dst->tmpdist, &src->tmpdist, _state, make_automatic);
19528 0 : ae_vector_init_copy(&dst->tmpx, &src->tmpx, _state, make_automatic);
19529 0 : ae_vector_init_copy(&dst->tmpwy, &src->tmpwy, _state, make_automatic);
19530 0 : ae_vector_init_copy(&dst->tmpw, &src->tmpw, _state, make_automatic);
19531 0 : _kdtree_init_copy(&dst->tmptree, &src->tmptree, _state, make_automatic);
19532 0 : ae_vector_init_copy(&dst->tmpmean, &src->tmpmean, _state, make_automatic);
19533 0 : }
19534 :
19535 :
19536 0 : void _idwbuilder_clear(void* _p)
19537 : {
19538 0 : idwbuilder *p = (idwbuilder*)_p;
19539 0 : ae_touch_ptr((void*)p);
19540 0 : ae_vector_clear(&p->priortermval);
19541 0 : ae_vector_clear(&p->xy);
19542 0 : ae_matrix_clear(&p->tmpxy);
19543 0 : ae_matrix_clear(&p->tmplayers);
19544 0 : ae_vector_clear(&p->tmptags);
19545 0 : ae_vector_clear(&p->tmpdist);
19546 0 : ae_vector_clear(&p->tmpx);
19547 0 : ae_vector_clear(&p->tmpwy);
19548 0 : ae_vector_clear(&p->tmpw);
19549 0 : _kdtree_clear(&p->tmptree);
19550 0 : ae_vector_clear(&p->tmpmean);
19551 0 : }
19552 :
19553 :
19554 0 : void _idwbuilder_destroy(void* _p)
19555 : {
19556 0 : idwbuilder *p = (idwbuilder*)_p;
19557 0 : ae_touch_ptr((void*)p);
19558 0 : ae_vector_destroy(&p->priortermval);
19559 0 : ae_vector_destroy(&p->xy);
19560 0 : ae_matrix_destroy(&p->tmpxy);
19561 0 : ae_matrix_destroy(&p->tmplayers);
19562 0 : ae_vector_destroy(&p->tmptags);
19563 0 : ae_vector_destroy(&p->tmpdist);
19564 0 : ae_vector_destroy(&p->tmpx);
19565 0 : ae_vector_destroy(&p->tmpwy);
19566 0 : ae_vector_destroy(&p->tmpw);
19567 0 : _kdtree_destroy(&p->tmptree);
19568 0 : ae_vector_destroy(&p->tmpmean);
19569 0 : }
19570 :
19571 :
19572 0 : void _idwreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
19573 : {
19574 0 : idwreport *p = (idwreport*)_p;
19575 0 : ae_touch_ptr((void*)p);
19576 0 : }
19577 :
19578 :
19579 0 : void _idwreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
19580 : {
19581 0 : idwreport *dst = (idwreport*)_dst;
19582 0 : idwreport *src = (idwreport*)_src;
19583 0 : dst->rmserror = src->rmserror;
19584 0 : dst->avgerror = src->avgerror;
19585 0 : dst->maxerror = src->maxerror;
19586 0 : dst->r2 = src->r2;
19587 0 : }
19588 :
19589 :
19590 0 : void _idwreport_clear(void* _p)
19591 : {
19592 0 : idwreport *p = (idwreport*)_p;
19593 0 : ae_touch_ptr((void*)p);
19594 0 : }
19595 :
19596 :
19597 0 : void _idwreport_destroy(void* _p)
19598 : {
19599 0 : idwreport *p = (idwreport*)_p;
19600 0 : ae_touch_ptr((void*)p);
19601 0 : }
19602 :
19603 :
19604 : #endif
19605 : #if defined(AE_COMPILE_RATINT) || !defined(AE_PARTIAL_BUILD)
19606 :
19607 :
19608 : /*************************************************************************
19609 : Rational interpolation using barycentric formula
19610 :
19611 : F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
19612 :
19613 : Input parameters:
19614 : B - barycentric interpolant built with one of model building
19615 : subroutines.
19616 : T - interpolation point
19617 :
19618 : Result:
19619 : barycentric interpolant F(t)
19620 :
19621 : -- ALGLIB --
19622 : Copyright 17.08.2009 by Bochkanov Sergey
19623 : *************************************************************************/
19624 0 : double barycentriccalc(barycentricinterpolant* b,
19625 : double t,
19626 : ae_state *_state)
19627 : {
19628 : double s1;
19629 : double s2;
19630 : double s;
19631 : double v;
19632 : ae_int_t i;
19633 : double result;
19634 :
19635 :
19636 0 : ae_assert(!ae_isinf(t, _state), "BarycentricCalc: infinite T!", _state);
19637 :
19638 : /*
19639 : * special case: NaN
19640 : */
19641 0 : if( ae_isnan(t, _state) )
19642 : {
19643 0 : result = _state->v_nan;
19644 0 : return result;
19645 : }
19646 :
19647 : /*
19648 : * special case: N=1
19649 : */
19650 0 : if( b->n==1 )
19651 : {
19652 0 : result = b->sy*b->y.ptr.p_double[0];
19653 0 : return result;
19654 : }
19655 :
19656 : /*
19657 : * Here we assume that task is normalized, i.e.:
19658 : * 1. abs(Y[i])<=1
19659 : * 2. abs(W[i])<=1
19660 : * 3. X[] is ordered
19661 : */
19662 0 : s = ae_fabs(t-b->x.ptr.p_double[0], _state);
19663 0 : for(i=0; i<=b->n-1; i++)
19664 : {
19665 0 : v = b->x.ptr.p_double[i];
19666 0 : if( ae_fp_eq(v,t) )
19667 : {
19668 0 : result = b->sy*b->y.ptr.p_double[i];
19669 0 : return result;
19670 : }
19671 0 : v = ae_fabs(t-v, _state);
19672 0 : if( ae_fp_less(v,s) )
19673 : {
19674 0 : s = v;
19675 : }
19676 : }
19677 0 : s1 = (double)(0);
19678 0 : s2 = (double)(0);
19679 0 : for(i=0; i<=b->n-1; i++)
19680 : {
19681 0 : v = s/(t-b->x.ptr.p_double[i]);
19682 0 : v = v*b->w.ptr.p_double[i];
19683 0 : s1 = s1+v*b->y.ptr.p_double[i];
19684 0 : s2 = s2+v;
19685 : }
19686 0 : result = b->sy*s1/s2;
19687 0 : return result;
19688 : }
19689 :
19690 :
19691 : /*************************************************************************
19692 : Differentiation of barycentric interpolant: first derivative.
19693 :
19694 : Algorithm used in this subroutine is very robust and should not fail until
19695 : provided with values too close to MaxRealNumber (usually MaxRealNumber/N
19696 : or greater will overflow).
19697 :
19698 : INPUT PARAMETERS:
19699 : B - barycentric interpolant built with one of model building
19700 : subroutines.
19701 : T - interpolation point
19702 :
19703 : OUTPUT PARAMETERS:
19704 : F - barycentric interpolant at T
19705 : DF - first derivative
19706 :
19707 : NOTE
19708 :
19709 :
19710 : -- ALGLIB --
19711 : Copyright 17.08.2009 by Bochkanov Sergey
19712 : *************************************************************************/
19713 0 : void barycentricdiff1(barycentricinterpolant* b,
19714 : double t,
19715 : double* f,
19716 : double* df,
19717 : ae_state *_state)
19718 : {
19719 : double v;
19720 : double vv;
19721 : ae_int_t i;
19722 : ae_int_t k;
19723 : double n0;
19724 : double n1;
19725 : double d0;
19726 : double d1;
19727 : double s0;
19728 : double s1;
19729 : double xk;
19730 : double xi;
19731 : double xmin;
19732 : double xmax;
19733 : double xscale1;
19734 : double xoffs1;
19735 : double xscale2;
19736 : double xoffs2;
19737 : double xprev;
19738 :
19739 0 : *f = 0;
19740 0 : *df = 0;
19741 :
19742 0 : ae_assert(!ae_isinf(t, _state), "BarycentricDiff1: infinite T!", _state);
19743 :
19744 : /*
19745 : * special case: NaN
19746 : */
19747 0 : if( ae_isnan(t, _state) )
19748 : {
19749 0 : *f = _state->v_nan;
19750 0 : *df = _state->v_nan;
19751 0 : return;
19752 : }
19753 :
19754 : /*
19755 : * special case: N=1
19756 : */
19757 0 : if( b->n==1 )
19758 : {
19759 0 : *f = b->sy*b->y.ptr.p_double[0];
19760 0 : *df = (double)(0);
19761 0 : return;
19762 : }
19763 0 : if( ae_fp_eq(b->sy,(double)(0)) )
19764 : {
19765 0 : *f = (double)(0);
19766 0 : *df = (double)(0);
19767 0 : return;
19768 : }
19769 0 : ae_assert(ae_fp_greater(b->sy,(double)(0)), "BarycentricDiff1: internal error", _state);
19770 :
19771 : /*
19772 : * We assume than N>1 and B.SY>0. Find:
19773 : * 1. pivot point (X[i] closest to T)
19774 : * 2. width of interval containing X[i]
19775 : */
19776 0 : v = ae_fabs(b->x.ptr.p_double[0]-t, _state);
19777 0 : k = 0;
19778 0 : xmin = b->x.ptr.p_double[0];
19779 0 : xmax = b->x.ptr.p_double[0];
19780 0 : for(i=1; i<=b->n-1; i++)
19781 : {
19782 0 : vv = b->x.ptr.p_double[i];
19783 0 : if( ae_fp_less(ae_fabs(vv-t, _state),v) )
19784 : {
19785 0 : v = ae_fabs(vv-t, _state);
19786 0 : k = i;
19787 : }
19788 0 : xmin = ae_minreal(xmin, vv, _state);
19789 0 : xmax = ae_maxreal(xmax, vv, _state);
19790 : }
19791 :
19792 : /*
19793 : * pivot point found, calculate dNumerator and dDenominator
19794 : */
19795 0 : xscale1 = 1/(xmax-xmin);
19796 0 : xoffs1 = -xmin/(xmax-xmin)+1;
19797 0 : xscale2 = (double)(2);
19798 0 : xoffs2 = (double)(-3);
19799 0 : t = t*xscale1+xoffs1;
19800 0 : t = t*xscale2+xoffs2;
19801 0 : xk = b->x.ptr.p_double[k];
19802 0 : xk = xk*xscale1+xoffs1;
19803 0 : xk = xk*xscale2+xoffs2;
19804 0 : v = t-xk;
19805 0 : n0 = (double)(0);
19806 0 : n1 = (double)(0);
19807 0 : d0 = (double)(0);
19808 0 : d1 = (double)(0);
19809 0 : xprev = (double)(-2);
19810 0 : for(i=0; i<=b->n-1; i++)
19811 : {
19812 0 : xi = b->x.ptr.p_double[i];
19813 0 : xi = xi*xscale1+xoffs1;
19814 0 : xi = xi*xscale2+xoffs2;
19815 0 : ae_assert(ae_fp_greater(xi,xprev), "BarycentricDiff1: points are too close!", _state);
19816 0 : xprev = xi;
19817 0 : if( i!=k )
19818 : {
19819 0 : vv = ae_sqr(t-xi, _state);
19820 0 : s0 = (t-xk)/(t-xi);
19821 0 : s1 = (xk-xi)/vv;
19822 : }
19823 : else
19824 : {
19825 0 : s0 = (double)(1);
19826 0 : s1 = (double)(0);
19827 : }
19828 0 : vv = b->w.ptr.p_double[i]*b->y.ptr.p_double[i];
19829 0 : n0 = n0+s0*vv;
19830 0 : n1 = n1+s1*vv;
19831 0 : vv = b->w.ptr.p_double[i];
19832 0 : d0 = d0+s0*vv;
19833 0 : d1 = d1+s1*vv;
19834 : }
19835 0 : *f = b->sy*n0/d0;
19836 0 : *df = (n1*d0-n0*d1)/ae_sqr(d0, _state);
19837 0 : if( ae_fp_neq(*df,(double)(0)) )
19838 : {
19839 0 : *df = ae_sign(*df, _state)*ae_exp(ae_log(ae_fabs(*df, _state), _state)+ae_log(b->sy, _state)+ae_log(xscale1, _state)+ae_log(xscale2, _state), _state);
19840 : }
19841 : }
19842 :
19843 :
19844 : /*************************************************************************
19845 : Differentiation of barycentric interpolant: first/second derivatives.
19846 :
19847 : INPUT PARAMETERS:
19848 : B - barycentric interpolant built with one of model building
19849 : subroutines.
19850 : T - interpolation point
19851 :
19852 : OUTPUT PARAMETERS:
19853 : F - barycentric interpolant at T
19854 : DF - first derivative
19855 : D2F - second derivative
19856 :
19857 : NOTE: this algorithm may fail due to overflow/underflor if used on data
19858 : whose values are close to MaxRealNumber or MinRealNumber. Use more robust
19859 : BarycentricDiff1() subroutine in such cases.
19860 :
19861 :
19862 : -- ALGLIB --
19863 : Copyright 17.08.2009 by Bochkanov Sergey
19864 : *************************************************************************/
19865 0 : void barycentricdiff2(barycentricinterpolant* b,
19866 : double t,
19867 : double* f,
19868 : double* df,
19869 : double* d2f,
19870 : ae_state *_state)
19871 : {
19872 : double v;
19873 : double vv;
19874 : ae_int_t i;
19875 : ae_int_t k;
19876 : double n0;
19877 : double n1;
19878 : double n2;
19879 : double d0;
19880 : double d1;
19881 : double d2;
19882 : double s0;
19883 : double s1;
19884 : double s2;
19885 : double xk;
19886 : double xi;
19887 :
19888 0 : *f = 0;
19889 0 : *df = 0;
19890 0 : *d2f = 0;
19891 :
19892 0 : ae_assert(!ae_isinf(t, _state), "BarycentricDiff1: infinite T!", _state);
19893 :
19894 : /*
19895 : * special case: NaN
19896 : */
19897 0 : if( ae_isnan(t, _state) )
19898 : {
19899 0 : *f = _state->v_nan;
19900 0 : *df = _state->v_nan;
19901 0 : *d2f = _state->v_nan;
19902 0 : return;
19903 : }
19904 :
19905 : /*
19906 : * special case: N=1
19907 : */
19908 0 : if( b->n==1 )
19909 : {
19910 0 : *f = b->sy*b->y.ptr.p_double[0];
19911 0 : *df = (double)(0);
19912 0 : *d2f = (double)(0);
19913 0 : return;
19914 : }
19915 0 : if( ae_fp_eq(b->sy,(double)(0)) )
19916 : {
19917 0 : *f = (double)(0);
19918 0 : *df = (double)(0);
19919 0 : *d2f = (double)(0);
19920 0 : return;
19921 : }
19922 :
19923 : /*
19924 : * We assume than N>1 and B.SY>0. Find:
19925 : * 1. pivot point (X[i] closest to T)
19926 : * 2. width of interval containing X[i]
19927 : */
19928 0 : ae_assert(ae_fp_greater(b->sy,(double)(0)), "BarycentricDiff: internal error", _state);
19929 0 : *f = (double)(0);
19930 0 : *df = (double)(0);
19931 0 : *d2f = (double)(0);
19932 0 : v = ae_fabs(b->x.ptr.p_double[0]-t, _state);
19933 0 : k = 0;
19934 0 : for(i=1; i<=b->n-1; i++)
19935 : {
19936 0 : vv = b->x.ptr.p_double[i];
19937 0 : if( ae_fp_less(ae_fabs(vv-t, _state),v) )
19938 : {
19939 0 : v = ae_fabs(vv-t, _state);
19940 0 : k = i;
19941 : }
19942 : }
19943 :
19944 : /*
19945 : * pivot point found, calculate dNumerator and dDenominator
19946 : */
19947 0 : xk = b->x.ptr.p_double[k];
19948 0 : v = t-xk;
19949 0 : n0 = (double)(0);
19950 0 : n1 = (double)(0);
19951 0 : n2 = (double)(0);
19952 0 : d0 = (double)(0);
19953 0 : d1 = (double)(0);
19954 0 : d2 = (double)(0);
19955 0 : for(i=0; i<=b->n-1; i++)
19956 : {
19957 0 : if( i!=k )
19958 : {
19959 0 : xi = b->x.ptr.p_double[i];
19960 0 : vv = ae_sqr(t-xi, _state);
19961 0 : s0 = (t-xk)/(t-xi);
19962 0 : s1 = (xk-xi)/vv;
19963 0 : s2 = -2*(xk-xi)/(vv*(t-xi));
19964 : }
19965 : else
19966 : {
19967 0 : s0 = (double)(1);
19968 0 : s1 = (double)(0);
19969 0 : s2 = (double)(0);
19970 : }
19971 0 : vv = b->w.ptr.p_double[i]*b->y.ptr.p_double[i];
19972 0 : n0 = n0+s0*vv;
19973 0 : n1 = n1+s1*vv;
19974 0 : n2 = n2+s2*vv;
19975 0 : vv = b->w.ptr.p_double[i];
19976 0 : d0 = d0+s0*vv;
19977 0 : d1 = d1+s1*vv;
19978 0 : d2 = d2+s2*vv;
19979 : }
19980 0 : *f = b->sy*n0/d0;
19981 0 : *df = b->sy*(n1*d0-n0*d1)/ae_sqr(d0, _state);
19982 0 : *d2f = b->sy*((n2*d0-n0*d2)*ae_sqr(d0, _state)-(n1*d0-n0*d1)*2*d0*d1)/ae_sqr(ae_sqr(d0, _state), _state);
19983 : }
19984 :
19985 :
19986 : /*************************************************************************
19987 : This subroutine performs linear transformation of the argument.
19988 :
19989 : INPUT PARAMETERS:
19990 : B - rational interpolant in barycentric form
19991 : CA, CB - transformation coefficients: x = CA*t + CB
19992 :
19993 : OUTPUT PARAMETERS:
19994 : B - transformed interpolant with X replaced by T
19995 :
19996 : -- ALGLIB PROJECT --
19997 : Copyright 19.08.2009 by Bochkanov Sergey
19998 : *************************************************************************/
19999 0 : void barycentriclintransx(barycentricinterpolant* b,
20000 : double ca,
20001 : double cb,
20002 : ae_state *_state)
20003 : {
20004 : ae_int_t i;
20005 : ae_int_t j;
20006 : double v;
20007 :
20008 :
20009 :
20010 : /*
20011 : * special case, replace by constant F(CB)
20012 : */
20013 0 : if( ae_fp_eq(ca,(double)(0)) )
20014 : {
20015 0 : b->sy = barycentriccalc(b, cb, _state);
20016 0 : v = (double)(1);
20017 0 : for(i=0; i<=b->n-1; i++)
20018 : {
20019 0 : b->y.ptr.p_double[i] = (double)(1);
20020 0 : b->w.ptr.p_double[i] = v;
20021 0 : v = -v;
20022 : }
20023 0 : return;
20024 : }
20025 :
20026 : /*
20027 : * general case: CA<>0
20028 : */
20029 0 : for(i=0; i<=b->n-1; i++)
20030 : {
20031 0 : b->x.ptr.p_double[i] = (b->x.ptr.p_double[i]-cb)/ca;
20032 : }
20033 0 : if( ae_fp_less(ca,(double)(0)) )
20034 : {
20035 0 : for(i=0; i<=b->n-1; i++)
20036 : {
20037 0 : if( i<b->n-1-i )
20038 : {
20039 0 : j = b->n-1-i;
20040 0 : v = b->x.ptr.p_double[i];
20041 0 : b->x.ptr.p_double[i] = b->x.ptr.p_double[j];
20042 0 : b->x.ptr.p_double[j] = v;
20043 0 : v = b->y.ptr.p_double[i];
20044 0 : b->y.ptr.p_double[i] = b->y.ptr.p_double[j];
20045 0 : b->y.ptr.p_double[j] = v;
20046 0 : v = b->w.ptr.p_double[i];
20047 0 : b->w.ptr.p_double[i] = b->w.ptr.p_double[j];
20048 0 : b->w.ptr.p_double[j] = v;
20049 : }
20050 : else
20051 : {
20052 0 : break;
20053 : }
20054 : }
20055 : }
20056 : }
20057 :
20058 :
20059 : /*************************************************************************
20060 : This subroutine performs linear transformation of the barycentric
20061 : interpolant.
20062 :
20063 : INPUT PARAMETERS:
20064 : B - rational interpolant in barycentric form
20065 : CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB
20066 :
20067 : OUTPUT PARAMETERS:
20068 : B - transformed interpolant
20069 :
20070 : -- ALGLIB PROJECT --
20071 : Copyright 19.08.2009 by Bochkanov Sergey
20072 : *************************************************************************/
20073 0 : void barycentriclintransy(barycentricinterpolant* b,
20074 : double ca,
20075 : double cb,
20076 : ae_state *_state)
20077 : {
20078 : ae_int_t i;
20079 : double v;
20080 :
20081 :
20082 0 : for(i=0; i<=b->n-1; i++)
20083 : {
20084 0 : b->y.ptr.p_double[i] = ca*b->sy*b->y.ptr.p_double[i]+cb;
20085 : }
20086 0 : b->sy = (double)(0);
20087 0 : for(i=0; i<=b->n-1; i++)
20088 : {
20089 0 : b->sy = ae_maxreal(b->sy, ae_fabs(b->y.ptr.p_double[i], _state), _state);
20090 : }
20091 0 : if( ae_fp_greater(b->sy,(double)(0)) )
20092 : {
20093 0 : v = 1/b->sy;
20094 0 : ae_v_muld(&b->y.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
20095 : }
20096 0 : }
20097 :
20098 :
20099 : /*************************************************************************
20100 : Extracts X/Y/W arrays from rational interpolant
20101 :
20102 : INPUT PARAMETERS:
20103 : B - barycentric interpolant
20104 :
20105 : OUTPUT PARAMETERS:
20106 : N - nodes count, N>0
20107 : X - interpolation nodes, array[0..N-1]
20108 : F - function values, array[0..N-1]
20109 : W - barycentric weights, array[0..N-1]
20110 :
20111 : -- ALGLIB --
20112 : Copyright 17.08.2009 by Bochkanov Sergey
20113 : *************************************************************************/
20114 0 : void barycentricunpack(barycentricinterpolant* b,
20115 : ae_int_t* n,
20116 : /* Real */ ae_vector* x,
20117 : /* Real */ ae_vector* y,
20118 : /* Real */ ae_vector* w,
20119 : ae_state *_state)
20120 : {
20121 : double v;
20122 :
20123 0 : *n = 0;
20124 0 : ae_vector_clear(x);
20125 0 : ae_vector_clear(y);
20126 0 : ae_vector_clear(w);
20127 :
20128 0 : *n = b->n;
20129 0 : ae_vector_set_length(x, *n, _state);
20130 0 : ae_vector_set_length(y, *n, _state);
20131 0 : ae_vector_set_length(w, *n, _state);
20132 0 : v = b->sy;
20133 0 : ae_v_move(&x->ptr.p_double[0], 1, &b->x.ptr.p_double[0], 1, ae_v_len(0,*n-1));
20134 0 : ae_v_moved(&y->ptr.p_double[0], 1, &b->y.ptr.p_double[0], 1, ae_v_len(0,*n-1), v);
20135 0 : ae_v_move(&w->ptr.p_double[0], 1, &b->w.ptr.p_double[0], 1, ae_v_len(0,*n-1));
20136 0 : }
20137 :
20138 :
20139 : /*************************************************************************
20140 : Rational interpolant from X/Y/W arrays
20141 :
20142 : F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
20143 :
20144 : INPUT PARAMETERS:
20145 : X - interpolation nodes, array[0..N-1]
20146 : F - function values, array[0..N-1]
20147 : W - barycentric weights, array[0..N-1]
20148 : N - nodes count, N>0
20149 :
20150 : OUTPUT PARAMETERS:
20151 : B - barycentric interpolant built from (X, Y, W)
20152 :
20153 : -- ALGLIB --
20154 : Copyright 17.08.2009 by Bochkanov Sergey
20155 : *************************************************************************/
20156 0 : void barycentricbuildxyw(/* Real */ ae_vector* x,
20157 : /* Real */ ae_vector* y,
20158 : /* Real */ ae_vector* w,
20159 : ae_int_t n,
20160 : barycentricinterpolant* b,
20161 : ae_state *_state)
20162 : {
20163 :
20164 0 : _barycentricinterpolant_clear(b);
20165 :
20166 0 : ae_assert(n>0, "BarycentricBuildXYW: incorrect N!", _state);
20167 :
20168 : /*
20169 : * fill X/Y/W
20170 : */
20171 0 : ae_vector_set_length(&b->x, n, _state);
20172 0 : ae_vector_set_length(&b->y, n, _state);
20173 0 : ae_vector_set_length(&b->w, n, _state);
20174 0 : ae_v_move(&b->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
20175 0 : ae_v_move(&b->y.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
20176 0 : ae_v_move(&b->w.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
20177 0 : b->n = n;
20178 :
20179 : /*
20180 : * Normalize
20181 : */
20182 0 : ratint_barycentricnormalize(b, _state);
20183 0 : }
20184 :
20185 :
20186 : /*************************************************************************
20187 : Rational interpolant without poles
20188 :
20189 : The subroutine constructs the rational interpolating function without real
20190 : poles (see 'Barycentric rational interpolation with no poles and high
20191 : rates of approximation', Michael S. Floater. and Kai Hormann, for more
20192 : information on this subject).
20193 :
20194 : Input parameters:
20195 : X - interpolation nodes, array[0..N-1].
20196 : Y - function values, array[0..N-1].
20197 : N - number of nodes, N>0.
20198 : D - order of the interpolation scheme, 0 <= D <= N-1.
20199 : D<0 will cause an error.
20200 : D>=N it will be replaced with D=N-1.
20201 : if you don't know what D to choose, use small value about 3-5.
20202 :
20203 : Output parameters:
20204 : B - barycentric interpolant.
20205 :
20206 : Note:
20207 : this algorithm always succeeds and calculates the weights with close
20208 : to machine precision.
20209 :
20210 : -- ALGLIB PROJECT --
20211 : Copyright 17.06.2007 by Bochkanov Sergey
20212 : *************************************************************************/
20213 0 : void barycentricbuildfloaterhormann(/* Real */ ae_vector* x,
20214 : /* Real */ ae_vector* y,
20215 : ae_int_t n,
20216 : ae_int_t d,
20217 : barycentricinterpolant* b,
20218 : ae_state *_state)
20219 : {
20220 : ae_frame _frame_block;
20221 : double s0;
20222 : double s;
20223 : double v;
20224 : ae_int_t i;
20225 : ae_int_t j;
20226 : ae_int_t k;
20227 : ae_vector perm;
20228 : ae_vector wtemp;
20229 : ae_vector sortrbuf;
20230 : ae_vector sortrbuf2;
20231 :
20232 0 : ae_frame_make(_state, &_frame_block);
20233 0 : memset(&perm, 0, sizeof(perm));
20234 0 : memset(&wtemp, 0, sizeof(wtemp));
20235 0 : memset(&sortrbuf, 0, sizeof(sortrbuf));
20236 0 : memset(&sortrbuf2, 0, sizeof(sortrbuf2));
20237 0 : _barycentricinterpolant_clear(b);
20238 0 : ae_vector_init(&perm, 0, DT_INT, _state, ae_true);
20239 0 : ae_vector_init(&wtemp, 0, DT_REAL, _state, ae_true);
20240 0 : ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true);
20241 0 : ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true);
20242 :
20243 0 : ae_assert(n>0, "BarycentricFloaterHormann: N<=0!", _state);
20244 0 : ae_assert(d>=0, "BarycentricFloaterHormann: incorrect D!", _state);
20245 :
20246 : /*
20247 : * Prepare
20248 : */
20249 0 : if( d>n-1 )
20250 : {
20251 0 : d = n-1;
20252 : }
20253 0 : b->n = n;
20254 :
20255 : /*
20256 : * special case: N=1
20257 : */
20258 0 : if( n==1 )
20259 : {
20260 0 : ae_vector_set_length(&b->x, n, _state);
20261 0 : ae_vector_set_length(&b->y, n, _state);
20262 0 : ae_vector_set_length(&b->w, n, _state);
20263 0 : b->x.ptr.p_double[0] = x->ptr.p_double[0];
20264 0 : b->y.ptr.p_double[0] = y->ptr.p_double[0];
20265 0 : b->w.ptr.p_double[0] = (double)(1);
20266 0 : ratint_barycentricnormalize(b, _state);
20267 0 : ae_frame_leave(_state);
20268 0 : return;
20269 : }
20270 :
20271 : /*
20272 : * Fill X/Y
20273 : */
20274 0 : ae_vector_set_length(&b->x, n, _state);
20275 0 : ae_vector_set_length(&b->y, n, _state);
20276 0 : ae_v_move(&b->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
20277 0 : ae_v_move(&b->y.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
20278 0 : tagsortfastr(&b->x, &b->y, &sortrbuf, &sortrbuf2, n, _state);
20279 :
20280 : /*
20281 : * Calculate Wk
20282 : */
20283 0 : ae_vector_set_length(&b->w, n, _state);
20284 0 : s0 = (double)(1);
20285 0 : for(k=1; k<=d; k++)
20286 : {
20287 0 : s0 = -s0;
20288 : }
20289 0 : for(k=0; k<=n-1; k++)
20290 : {
20291 :
20292 : /*
20293 : * Wk
20294 : */
20295 0 : s = (double)(0);
20296 0 : for(i=ae_maxint(k-d, 0, _state); i<=ae_minint(k, n-1-d, _state); i++)
20297 : {
20298 0 : v = (double)(1);
20299 0 : for(j=i; j<=i+d; j++)
20300 : {
20301 0 : if( j!=k )
20302 : {
20303 0 : v = v/ae_fabs(b->x.ptr.p_double[k]-b->x.ptr.p_double[j], _state);
20304 : }
20305 : }
20306 0 : s = s+v;
20307 : }
20308 0 : b->w.ptr.p_double[k] = s0*s;
20309 :
20310 : /*
20311 : * Next S0
20312 : */
20313 0 : s0 = -s0;
20314 : }
20315 :
20316 : /*
20317 : * Normalize
20318 : */
20319 0 : ratint_barycentricnormalize(b, _state);
20320 0 : ae_frame_leave(_state);
20321 : }
20322 :
20323 :
20324 : /*************************************************************************
20325 : Copying of the barycentric interpolant (for internal use only)
20326 :
20327 : INPUT PARAMETERS:
20328 : B - barycentric interpolant
20329 :
20330 : OUTPUT PARAMETERS:
20331 : B2 - copy(B1)
20332 :
20333 : -- ALGLIB --
20334 : Copyright 17.08.2009 by Bochkanov Sergey
20335 : *************************************************************************/
20336 0 : void barycentriccopy(barycentricinterpolant* b,
20337 : barycentricinterpolant* b2,
20338 : ae_state *_state)
20339 : {
20340 :
20341 0 : _barycentricinterpolant_clear(b2);
20342 :
20343 0 : b2->n = b->n;
20344 0 : b2->sy = b->sy;
20345 0 : ae_vector_set_length(&b2->x, b2->n, _state);
20346 0 : ae_vector_set_length(&b2->y, b2->n, _state);
20347 0 : ae_vector_set_length(&b2->w, b2->n, _state);
20348 0 : ae_v_move(&b2->x.ptr.p_double[0], 1, &b->x.ptr.p_double[0], 1, ae_v_len(0,b2->n-1));
20349 0 : ae_v_move(&b2->y.ptr.p_double[0], 1, &b->y.ptr.p_double[0], 1, ae_v_len(0,b2->n-1));
20350 0 : ae_v_move(&b2->w.ptr.p_double[0], 1, &b->w.ptr.p_double[0], 1, ae_v_len(0,b2->n-1));
20351 0 : }
20352 :
20353 :
20354 : /*************************************************************************
20355 : Normalization of barycentric interpolant:
20356 : * B.N, B.X, B.Y and B.W are initialized
20357 : * B.SY is NOT initialized
20358 : * Y[] is normalized, scaling coefficient is stored in B.SY
20359 : * W[] is normalized, no scaling coefficient is stored
20360 : * X[] is sorted
20361 :
20362 : Internal subroutine.
20363 : *************************************************************************/
20364 0 : static void ratint_barycentricnormalize(barycentricinterpolant* b,
20365 : ae_state *_state)
20366 : {
20367 : ae_frame _frame_block;
20368 : ae_vector p1;
20369 : ae_vector p2;
20370 : ae_int_t i;
20371 : ae_int_t j;
20372 : ae_int_t j2;
20373 : double v;
20374 :
20375 0 : ae_frame_make(_state, &_frame_block);
20376 0 : memset(&p1, 0, sizeof(p1));
20377 0 : memset(&p2, 0, sizeof(p2));
20378 0 : ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
20379 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
20380 :
20381 :
20382 : /*
20383 : * Normalize task: |Y|<=1, |W|<=1, sort X[]
20384 : */
20385 0 : b->sy = (double)(0);
20386 0 : for(i=0; i<=b->n-1; i++)
20387 : {
20388 0 : b->sy = ae_maxreal(b->sy, ae_fabs(b->y.ptr.p_double[i], _state), _state);
20389 : }
20390 0 : if( ae_fp_greater(b->sy,(double)(0))&&ae_fp_greater(ae_fabs(b->sy-1, _state),10*ae_machineepsilon) )
20391 : {
20392 0 : v = 1/b->sy;
20393 0 : ae_v_muld(&b->y.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
20394 : }
20395 0 : v = (double)(0);
20396 0 : for(i=0; i<=b->n-1; i++)
20397 : {
20398 0 : v = ae_maxreal(v, ae_fabs(b->w.ptr.p_double[i], _state), _state);
20399 : }
20400 0 : if( ae_fp_greater(v,(double)(0))&&ae_fp_greater(ae_fabs(v-1, _state),10*ae_machineepsilon) )
20401 : {
20402 0 : v = 1/v;
20403 0 : ae_v_muld(&b->w.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
20404 : }
20405 0 : for(i=0; i<=b->n-2; i++)
20406 : {
20407 0 : if( ae_fp_less(b->x.ptr.p_double[i+1],b->x.ptr.p_double[i]) )
20408 : {
20409 0 : tagsort(&b->x, b->n, &p1, &p2, _state);
20410 0 : for(j=0; j<=b->n-1; j++)
20411 : {
20412 0 : j2 = p2.ptr.p_int[j];
20413 0 : v = b->y.ptr.p_double[j];
20414 0 : b->y.ptr.p_double[j] = b->y.ptr.p_double[j2];
20415 0 : b->y.ptr.p_double[j2] = v;
20416 0 : v = b->w.ptr.p_double[j];
20417 0 : b->w.ptr.p_double[j] = b->w.ptr.p_double[j2];
20418 0 : b->w.ptr.p_double[j2] = v;
20419 : }
20420 0 : break;
20421 : }
20422 : }
20423 0 : ae_frame_leave(_state);
20424 0 : }
20425 :
20426 :
20427 0 : void _barycentricinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
20428 : {
20429 0 : barycentricinterpolant *p = (barycentricinterpolant*)_p;
20430 0 : ae_touch_ptr((void*)p);
20431 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
20432 0 : ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic);
20433 0 : ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic);
20434 0 : }
20435 :
20436 :
20437 0 : void _barycentricinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
20438 : {
20439 0 : barycentricinterpolant *dst = (barycentricinterpolant*)_dst;
20440 0 : barycentricinterpolant *src = (barycentricinterpolant*)_src;
20441 0 : dst->n = src->n;
20442 0 : dst->sy = src->sy;
20443 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
20444 0 : ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic);
20445 0 : ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic);
20446 0 : }
20447 :
20448 :
20449 0 : void _barycentricinterpolant_clear(void* _p)
20450 : {
20451 0 : barycentricinterpolant *p = (barycentricinterpolant*)_p;
20452 0 : ae_touch_ptr((void*)p);
20453 0 : ae_vector_clear(&p->x);
20454 0 : ae_vector_clear(&p->y);
20455 0 : ae_vector_clear(&p->w);
20456 0 : }
20457 :
20458 :
20459 0 : void _barycentricinterpolant_destroy(void* _p)
20460 : {
20461 0 : barycentricinterpolant *p = (barycentricinterpolant*)_p;
20462 0 : ae_touch_ptr((void*)p);
20463 0 : ae_vector_destroy(&p->x);
20464 0 : ae_vector_destroy(&p->y);
20465 0 : ae_vector_destroy(&p->w);
20466 0 : }
20467 :
20468 :
20469 : #endif
20470 : #if defined(AE_COMPILE_FITSPHERE) || !defined(AE_PARTIAL_BUILD)
20471 :
20472 :
20473 : /*************************************************************************
20474 : Fits least squares (LS) circle (or NX-dimensional sphere) to data (a set
20475 : of points in NX-dimensional space).
20476 :
20477 : Least squares circle minimizes sum of squared deviations between distances
20478 : from points to the center and some "candidate" radius, which is also
20479 : fitted to the data.
20480 :
20481 : INPUT PARAMETERS:
20482 : XY - array[NPoints,NX] (or larger), contains dataset.
20483 : One row = one point in NX-dimensional space.
20484 : NPoints - dataset size, NPoints>0
20485 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
20486 :
20487 : OUTPUT PARAMETERS:
20488 : CX - central point for a sphere
20489 : R - radius
20490 :
20491 : -- ALGLIB --
20492 : Copyright 07.05.2018 by Bochkanov Sergey
20493 : *************************************************************************/
20494 0 : void fitspherels(/* Real */ ae_matrix* xy,
20495 : ae_int_t npoints,
20496 : ae_int_t nx,
20497 : /* Real */ ae_vector* cx,
20498 : double* r,
20499 : ae_state *_state)
20500 : {
20501 : double dummy;
20502 :
20503 0 : ae_vector_clear(cx);
20504 0 : *r = 0;
20505 :
20506 0 : fitspherex(xy, npoints, nx, 0, 0.0, 0, 0.0, cx, &dummy, r, _state);
20507 0 : }
20508 :
20509 :
20510 : /*************************************************************************
20511 : Fits minimum circumscribed (MC) circle (or NX-dimensional sphere) to data
20512 : (a set of points in NX-dimensional space).
20513 :
20514 : INPUT PARAMETERS:
20515 : XY - array[NPoints,NX] (or larger), contains dataset.
20516 : One row = one point in NX-dimensional space.
20517 : NPoints - dataset size, NPoints>0
20518 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
20519 :
20520 : OUTPUT PARAMETERS:
20521 : CX - central point for a sphere
20522 : RHi - radius
20523 :
20524 : NOTE: this function is an easy-to-use wrapper around more powerful "expert"
20525 : function fitspherex().
20526 :
20527 : This wrapper is optimized for ease of use and stability - at the
20528 : cost of somewhat lower performance (we have to use very tight
20529 : stopping criteria for inner optimizer because we want to make sure
20530 : that it will converge on any dataset).
20531 :
20532 : If you are ready to experiment with settings of "expert" function,
20533 : you can achieve ~2-4x speedup over standard "bulletproof" settings.
20534 :
20535 :
20536 : -- ALGLIB --
20537 : Copyright 14.04.2017 by Bochkanov Sergey
20538 : *************************************************************************/
20539 0 : void fitspheremc(/* Real */ ae_matrix* xy,
20540 : ae_int_t npoints,
20541 : ae_int_t nx,
20542 : /* Real */ ae_vector* cx,
20543 : double* rhi,
20544 : ae_state *_state)
20545 : {
20546 : double dummy;
20547 :
20548 0 : ae_vector_clear(cx);
20549 0 : *rhi = 0;
20550 :
20551 0 : fitspherex(xy, npoints, nx, 1, 0.0, 0, 0.0, cx, &dummy, rhi, _state);
20552 0 : }
20553 :
20554 :
20555 : /*************************************************************************
20556 : Fits maximum inscribed circle (or NX-dimensional sphere) to data (a set of
20557 : points in NX-dimensional space).
20558 :
20559 : INPUT PARAMETERS:
20560 : XY - array[NPoints,NX] (or larger), contains dataset.
20561 : One row = one point in NX-dimensional space.
20562 : NPoints - dataset size, NPoints>0
20563 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
20564 :
20565 : OUTPUT PARAMETERS:
20566 : CX - central point for a sphere
20567 : RLo - radius
20568 :
20569 : NOTE: this function is an easy-to-use wrapper around more powerful "expert"
20570 : function fitspherex().
20571 :
20572 : This wrapper is optimized for ease of use and stability - at the
20573 : cost of somewhat lower performance (we have to use very tight
20574 : stopping criteria for inner optimizer because we want to make sure
20575 : that it will converge on any dataset).
20576 :
20577 : If you are ready to experiment with settings of "expert" function,
20578 : you can achieve ~2-4x speedup over standard "bulletproof" settings.
20579 :
20580 :
20581 : -- ALGLIB --
20582 : Copyright 14.04.2017 by Bochkanov Sergey
20583 : *************************************************************************/
20584 0 : void fitspheremi(/* Real */ ae_matrix* xy,
20585 : ae_int_t npoints,
20586 : ae_int_t nx,
20587 : /* Real */ ae_vector* cx,
20588 : double* rlo,
20589 : ae_state *_state)
20590 : {
20591 : double dummy;
20592 :
20593 0 : ae_vector_clear(cx);
20594 0 : *rlo = 0;
20595 :
20596 0 : fitspherex(xy, npoints, nx, 2, 0.0, 0, 0.0, cx, rlo, &dummy, _state);
20597 0 : }
20598 :
20599 :
20600 : /*************************************************************************
20601 : Fits minimum zone circle (or NX-dimensional sphere) to data (a set of
20602 : points in NX-dimensional space).
20603 :
20604 : INPUT PARAMETERS:
20605 : XY - array[NPoints,NX] (or larger), contains dataset.
20606 : One row = one point in NX-dimensional space.
20607 : NPoints - dataset size, NPoints>0
20608 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
20609 :
20610 : OUTPUT PARAMETERS:
20611 : CX - central point for a sphere
20612 : RLo - radius of inscribed circle
20613 : RHo - radius of circumscribed circle
20614 :
20615 : NOTE: this function is an easy-to-use wrapper around more powerful "expert"
20616 : function fitspherex().
20617 :
20618 : This wrapper is optimized for ease of use and stability - at the
20619 : cost of somewhat lower performance (we have to use very tight
20620 : stopping criteria for inner optimizer because we want to make sure
20621 : that it will converge on any dataset).
20622 :
20623 : If you are ready to experiment with settings of "expert" function,
20624 : you can achieve ~2-4x speedup over standard "bulletproof" settings.
20625 :
20626 :
20627 : -- ALGLIB --
20628 : Copyright 14.04.2017 by Bochkanov Sergey
20629 : *************************************************************************/
20630 0 : void fitspheremz(/* Real */ ae_matrix* xy,
20631 : ae_int_t npoints,
20632 : ae_int_t nx,
20633 : /* Real */ ae_vector* cx,
20634 : double* rlo,
20635 : double* rhi,
20636 : ae_state *_state)
20637 : {
20638 :
20639 0 : ae_vector_clear(cx);
20640 0 : *rlo = 0;
20641 0 : *rhi = 0;
20642 :
20643 0 : fitspherex(xy, npoints, nx, 3, 0.0, 0, 0.0, cx, rlo, rhi, _state);
20644 0 : }
20645 :
20646 :
20647 : /*************************************************************************
20648 : Fitting minimum circumscribed, maximum inscribed or minimum zone circles
20649 : (or NX-dimensional spheres) to data (a set of points in NX-dimensional
20650 : space).
20651 :
20652 : This is expert function which allows to tweak many parameters of
20653 : underlying nonlinear solver:
20654 : * stopping criteria for inner iterations
20655 : * number of outer iterations
20656 : * penalty coefficient used to handle nonlinear constraints (we convert
20657 : unconstrained nonsmooth optimization problem ivolving max() and/or min()
20658 : operations to quadratically constrained smooth one).
20659 :
20660 : You may tweak all these parameters or only some of them, leaving other
20661 : ones at their default state - just specify zero value, and solver will
20662 : fill it with appropriate default one.
20663 :
20664 : These comments also include some discussion of approach used to handle
20665 : such unusual fitting problem, its stability, drawbacks of alternative
20666 : methods, and convergence properties.
20667 :
20668 : INPUT PARAMETERS:
20669 : XY - array[NPoints,NX] (or larger), contains dataset.
20670 : One row = one point in NX-dimensional space.
20671 : NPoints - dataset size, NPoints>0
20672 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
20673 : ProblemType-used to encode problem type:
20674 : * 0 for least squares circle
20675 : * 1 for minimum circumscribed circle/sphere fitting (MC)
20676 : * 2 for maximum inscribed circle/sphere fitting (MI)
20677 : * 3 for minimum zone circle fitting (difference between
20678 : Rhi and Rlo is minimized), denoted as MZ
20679 : EpsX - stopping condition for NLC optimizer:
20680 : * must be non-negative
20681 : * use 0 to choose default value (1.0E-12 is used by default)
20682 : * you may specify larger values, up to 1.0E-6, if you want
20683 : to speed-up solver; NLC solver performs several
20684 : preconditioned outer iterations, so final result
20685 : typically has precision much better than EpsX.
20686 : AULIts - number of outer iterations performed by NLC optimizer:
20687 : * must be non-negative
20688 : * use 0 to choose default value (20 is used by default)
20689 : * you may specify values smaller than 20 if you want to
20690 : speed up solver; 10 often results in good combination of
20691 : precision and speed; sometimes you may get good results
20692 : with just 6 outer iterations.
20693 : Ignored for ProblemType=0.
20694 : Penalty - penalty coefficient for NLC optimizer:
20695 : * must be non-negative
20696 : * use 0 to choose default value (1.0E6 in current version)
20697 : * it should be really large, 1.0E6...1.0E7 is a good value
20698 : to start from;
20699 : * generally, default value is good enough
20700 : Ignored for ProblemType=0.
20701 :
20702 : OUTPUT PARAMETERS:
20703 : CX - central point for a sphere
20704 : RLo - radius:
20705 : * for ProblemType=2,3, radius of the inscribed sphere
20706 : * for ProblemType=0 - radius of the least squares sphere
20707 : * for ProblemType=1 - zero
20708 : RHo - radius:
20709 : * for ProblemType=1,3, radius of the circumscribed sphere
20710 : * for ProblemType=0 - radius of the least squares sphere
20711 : * for ProblemType=2 - zero
20712 :
20713 : NOTE: ON THE UNIQUENESS OF SOLUTIONS
20714 :
20715 : ALGLIB provides solution to several related circle fitting problems: MC
20716 : (minimum circumscribed), MI (maximum inscribed) and MZ (minimum zone)
20717 : fitting, LS (least squares) fitting.
20718 :
20719 : It is important to note that among these problems only MC and LS are
20720 : convex and have unique solution independently from starting point.
20721 :
20722 : As for MI, it may (or may not, depending on dataset properties) have
20723 : multiple solutions, and it always has one degenerate solution C=infinity
20724 : which corresponds to infinitely large radius. Thus, there are no guarantees
20725 : that solution to MI returned by this solver will be the best one (and no
20726 : one can provide you with such guarantee because problem is NP-hard). The
20727 : only guarantee you have is that this solution is locally optimal, i.e. it
20728 : can not be improved by infinitesimally small tweaks in the parameters.
20729 :
20730 : It is also possible to "run away" to infinity when started from bad
20731 : initial point located outside of point cloud (or when point cloud does not
20732 : span entire circumference/surface of the sphere).
20733 :
20734 : Finally, MZ (minimum zone circle) stands somewhere between MC and MI in
20735 : stability. It is somewhat regularized by "circumscribed" term of the merit
20736 : function; however, solutions to MZ may be non-unique, and in some unlucky
20737 : cases it is also possible to "run away to infinity".
20738 :
20739 :
20740 : NOTE: ON THE NONLINEARLY CONSTRAINED PROGRAMMING APPROACH
20741 :
20742 : The problem formulation for MC (minimum circumscribed circle; for the
20743 : sake of simplicity we omit MZ and MI here) is:
20744 :
20745 : [ [ ]2 ]
20746 : min [ max [ XY[i]-C ] ]
20747 : C [ i [ ] ]
20748 :
20749 : i.e. it is unconstrained nonsmooth optimization problem of finding "best"
20750 : central point, with radius R being unambiguously determined from C. In
20751 : order to move away from non-smoothness we use following reformulation:
20752 :
20753 : [ ] [ ]2
20754 : min [ R ] subject to R>=0, [ XY[i]-C ] <= R^2
20755 : C,R [ ] [ ]
20756 :
20757 : i.e. it becomes smooth quadratically constrained optimization problem with
20758 : linear target function. Such problem statement is 100% equivalent to the
20759 : original nonsmooth one, but much easier to approach. We solve it with
20760 : MinNLC solver provided by ALGLIB.
20761 :
20762 :
20763 : NOTE: ON INSTABILITY OF SEQUENTIAL LINEARIZATION APPROACH
20764 :
20765 : ALGLIB has nonlinearly constrained solver which proved to be stable on
20766 : such problems. However, some authors proposed to linearize constraints in
20767 : the vicinity of current approximation (Ci,Ri) and to get next approximate
20768 : solution (Ci+1,Ri+1) as solution to linear programming problem. Obviously,
20769 : LP problems are easier than nonlinearly constrained ones.
20770 :
20771 : Indeed, such approach to MC/MI/MZ resulted in ~10-20x increase in
20772 : performance (when compared with NLC solver). However, it turned out that
20773 : in some cases linearized model fails to predict correct direction for next
20774 : step and tells us that we converged to solution even when we are still 2-4
20775 : digits of precision away from it.
20776 :
20777 : It is important that it is not failure of LP solver - it is failure of the
20778 : linear model; even when solved exactly, it fails to handle subtle
20779 : nonlinearities which arise near the solution. We validated it by comparing
20780 : results returned by ALGLIB linear solver with that of MATLAB.
20781 :
20782 : In our experiments with linearization:
20783 : * MC failed most often, at both realistic and synthetic datasets
20784 : * MI sometimes failed, but sometimes succeeded
20785 : * MZ often succeeded; our guess is that presence of two independent sets
20786 : of constraints (one set for Rlo and another one for Rhi) and two terms
20787 : in the target function (Rlo and Rhi) regularizes task, so when linear
20788 : model fails to handle nonlinearities from Rlo, it uses Rhi as a hint
20789 : (and vice versa).
20790 :
20791 : Because linearization approach failed to achieve stable results, we do not
20792 : include it in ALGLIB.
20793 :
20794 :
20795 : -- ALGLIB --
20796 : Copyright 14.04.2017 by Bochkanov Sergey
20797 : *************************************************************************/
20798 0 : void fitspherex(/* Real */ ae_matrix* xy,
20799 : ae_int_t npoints,
20800 : ae_int_t nx,
20801 : ae_int_t problemtype,
20802 : double epsx,
20803 : ae_int_t aulits,
20804 : double penalty,
20805 : /* Real */ ae_vector* cx,
20806 : double* rlo,
20807 : double* rhi,
20808 : ae_state *_state)
20809 : {
20810 : ae_frame _frame_block;
20811 : fitsphereinternalreport rep;
20812 :
20813 0 : ae_frame_make(_state, &_frame_block);
20814 0 : memset(&rep, 0, sizeof(rep));
20815 0 : ae_vector_clear(cx);
20816 0 : *rlo = 0;
20817 0 : *rhi = 0;
20818 0 : _fitsphereinternalreport_init(&rep, _state, ae_true);
20819 :
20820 0 : ae_assert(ae_isfinite(penalty, _state)&&ae_fp_greater_eq(penalty,(double)(0)), "FitSphereX: Penalty<0 or is not finite", _state);
20821 0 : ae_assert(ae_isfinite(epsx, _state)&&ae_fp_greater_eq(epsx,(double)(0)), "FitSphereX: EpsX<0 or is not finite", _state);
20822 0 : ae_assert(aulits>=0, "FitSphereX: AULIts<0", _state);
20823 0 : fitsphereinternal(xy, npoints, nx, problemtype, 0, epsx, aulits, penalty, cx, rlo, rhi, &rep, _state);
20824 0 : ae_frame_leave(_state);
20825 0 : }
20826 :
20827 :
20828 : /*************************************************************************
20829 : Fitting minimum circumscribed, maximum inscribed or minimum zone circles
20830 : (or NX-dimensional spheres) to data (a set of points in NX-dimensional
20831 : space).
20832 :
20833 : Internal computational function.
20834 :
20835 : INPUT PARAMETERS:
20836 : XY - array[NPoints,NX] (or larger), contains dataset.
20837 : One row = one point in NX-dimensional space.
20838 : NPoints - dataset size, NPoints>0
20839 : NX - space dimensionality, NX>0 (1, 2, 3, 4, 5 and so on)
20840 : ProblemType-used to encode problem type:
20841 : * 0 for least squares circle
20842 : * 1 for minimum circumscribed circle/sphere fitting (MC)
20843 : * 2 for maximum inscribed circle/sphere fitting (MI)
20844 : * 3 for minimum zone circle fitting (difference between
20845 : Rhi and Rlo is minimized), denoted as MZ
20846 : SolverType- solver to use:
20847 : * 0 use best solver available (1 in current version)
20848 : * 1 use nonlinearly constrained optimization approach, AUL
20849 : (it is roughly 10-20 times slower than SPC-LIN, but
20850 : much more stable)
20851 : * 2 use special fast IMPRECISE solver, SPC-LIN sequential
20852 : linearization approach; SPC-LIN is fast, but sometimes
20853 : fails to converge with more than 3 digits of precision;
20854 : see comments below.
20855 : NOT RECOMMENDED UNLESS YOU REALLY NEED HIGH PERFORMANCE
20856 : AT THE COST OF SOME PRECISION.
20857 : * 3 use nonlinearly constrained optimization approach, SLP
20858 : (most robust one, but somewhat slower than AUL)
20859 : Ignored for ProblemType=0.
20860 : EpsX - stopping criteria for SLP and NLC optimizers:
20861 : * must be non-negative
20862 : * use 0 to choose default value (1.0E-12 is used by default)
20863 : * if you use SLP solver, you should use default values
20864 : * if you use NLC solver, you may specify larger values, up
20865 : to 1.0E-6, if you want to speed-up solver; NLC solver
20866 : performs several preconditioned outer iterations, so final
20867 : result typically has precision much better than EpsX.
20868 : AULIts - number of iterations performed by NLC optimizer:
20869 : * must be non-negative
20870 : * use 0 to choose default value (20 is used by default)
20871 : * you may specify values smaller than 20 if you want to
20872 : speed up solver; 10 often results in good combination of
20873 : precision and speed
20874 : Ignored for ProblemType=0.
20875 : Penalty - penalty coefficient for NLC optimizer (ignored for SLP):
20876 : * must be non-negative
20877 : * use 0 to choose default value (1.0E6 in current version)
20878 : * it should be really large, 1.0E6...1.0E7 is a good value
20879 : to start from;
20880 : * generally, default value is good enough
20881 : * ignored by SLP optimizer
20882 : Ignored for ProblemType=0.
20883 :
20884 : OUTPUT PARAMETERS:
20885 : CX - central point for a sphere
20886 : RLo - radius:
20887 : * for ProblemType=2,3, radius of the inscribed sphere
20888 : * for ProblemType=0 - radius of the least squares sphere
20889 : * for ProblemType=1 - zero
20890 : RHo - radius:
20891 : * for ProblemType=1,3, radius of the circumscribed sphere
20892 : * for ProblemType=0 - radius of the least squares sphere
20893 : * for ProblemType=2 - zero
20894 :
20895 : -- ALGLIB --
20896 : Copyright 14.04.2017 by Bochkanov Sergey
20897 : *************************************************************************/
20898 0 : void fitsphereinternal(/* Real */ ae_matrix* xy,
20899 : ae_int_t npoints,
20900 : ae_int_t nx,
20901 : ae_int_t problemtype,
20902 : ae_int_t solvertype,
20903 : double epsx,
20904 : ae_int_t aulits,
20905 : double penalty,
20906 : /* Real */ ae_vector* cx,
20907 : double* rlo,
20908 : double* rhi,
20909 : fitsphereinternalreport* rep,
20910 : ae_state *_state)
20911 : {
20912 : ae_frame _frame_block;
20913 : ae_int_t i;
20914 : ae_int_t j;
20915 : double v;
20916 : double vv;
20917 : ae_int_t cpr;
20918 : ae_bool userlo;
20919 : ae_bool userhi;
20920 : double vlo;
20921 : double vhi;
20922 : ae_vector vmin;
20923 : ae_vector vmax;
20924 : double spread;
20925 : ae_vector pcr;
20926 : ae_vector scr;
20927 : ae_vector bl;
20928 : ae_vector bu;
20929 : ae_int_t suboffset;
20930 : ae_int_t dstrow;
20931 : minnlcstate nlcstate;
20932 : minnlcreport nlcrep;
20933 : ae_matrix cmatrix;
20934 : ae_vector ct;
20935 : ae_int_t outeridx;
20936 : ae_int_t maxouterits;
20937 : ae_int_t maxits;
20938 : double safeguard;
20939 : double bi;
20940 : minbleicstate blcstate;
20941 : minbleicreport blcrep;
20942 : ae_vector prevc;
20943 : minlmstate lmstate;
20944 : minlmreport lmrep;
20945 :
20946 0 : ae_frame_make(_state, &_frame_block);
20947 0 : memset(&vmin, 0, sizeof(vmin));
20948 0 : memset(&vmax, 0, sizeof(vmax));
20949 0 : memset(&pcr, 0, sizeof(pcr));
20950 0 : memset(&scr, 0, sizeof(scr));
20951 0 : memset(&bl, 0, sizeof(bl));
20952 0 : memset(&bu, 0, sizeof(bu));
20953 0 : memset(&nlcstate, 0, sizeof(nlcstate));
20954 0 : memset(&nlcrep, 0, sizeof(nlcrep));
20955 0 : memset(&cmatrix, 0, sizeof(cmatrix));
20956 0 : memset(&ct, 0, sizeof(ct));
20957 0 : memset(&blcstate, 0, sizeof(blcstate));
20958 0 : memset(&blcrep, 0, sizeof(blcrep));
20959 0 : memset(&prevc, 0, sizeof(prevc));
20960 0 : memset(&lmstate, 0, sizeof(lmstate));
20961 0 : memset(&lmrep, 0, sizeof(lmrep));
20962 0 : ae_vector_clear(cx);
20963 0 : *rlo = 0;
20964 0 : *rhi = 0;
20965 0 : _fitsphereinternalreport_clear(rep);
20966 0 : ae_vector_init(&vmin, 0, DT_REAL, _state, ae_true);
20967 0 : ae_vector_init(&vmax, 0, DT_REAL, _state, ae_true);
20968 0 : ae_vector_init(&pcr, 0, DT_REAL, _state, ae_true);
20969 0 : ae_vector_init(&scr, 0, DT_REAL, _state, ae_true);
20970 0 : ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
20971 0 : ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
20972 0 : _minnlcstate_init(&nlcstate, _state, ae_true);
20973 0 : _minnlcreport_init(&nlcrep, _state, ae_true);
20974 0 : ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true);
20975 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
20976 0 : _minbleicstate_init(&blcstate, _state, ae_true);
20977 0 : _minbleicreport_init(&blcrep, _state, ae_true);
20978 0 : ae_vector_init(&prevc, 0, DT_REAL, _state, ae_true);
20979 0 : _minlmstate_init(&lmstate, _state, ae_true);
20980 0 : _minlmreport_init(&lmrep, _state, ae_true);
20981 :
20982 :
20983 : /*
20984 : * Check input parameters
20985 : */
20986 0 : ae_assert(npoints>0, "FitSphereX: NPoints<=0", _state);
20987 0 : ae_assert(nx>0, "FitSphereX: NX<=0", _state);
20988 0 : ae_assert(apservisfinitematrix(xy, npoints, nx, _state), "FitSphereX: XY contains infinite or NAN values", _state);
20989 0 : ae_assert(problemtype>=0&&problemtype<=3, "FitSphereX: ProblemType is neither 0, 1, 2 or 3", _state);
20990 0 : ae_assert(solvertype>=0&&solvertype<=3, "FitSphereX: ProblemType is neither 1, 2 or 3", _state);
20991 0 : ae_assert(ae_isfinite(penalty, _state)&&ae_fp_greater_eq(penalty,(double)(0)), "FitSphereX: Penalty<0 or is not finite", _state);
20992 0 : ae_assert(ae_isfinite(epsx, _state)&&ae_fp_greater_eq(epsx,(double)(0)), "FitSphereX: EpsX<0 or is not finite", _state);
20993 0 : ae_assert(aulits>=0, "FitSphereX: AULIts<0", _state);
20994 0 : if( solvertype==0 )
20995 : {
20996 0 : solvertype = 1;
20997 : }
20998 0 : if( ae_fp_eq(penalty,(double)(0)) )
20999 : {
21000 0 : penalty = 1.0E6;
21001 : }
21002 0 : if( ae_fp_eq(epsx,(double)(0)) )
21003 : {
21004 0 : epsx = 1.0E-12;
21005 : }
21006 0 : if( aulits==0 )
21007 : {
21008 0 : aulits = 20;
21009 : }
21010 0 : safeguard = (double)(10);
21011 0 : maxouterits = 10;
21012 0 : maxits = 10000;
21013 0 : rep->nfev = 0;
21014 0 : rep->iterationscount = 0;
21015 :
21016 : /*
21017 : * Determine initial values, initial estimates and spread of the points
21018 : */
21019 0 : ae_vector_set_length(&vmin, nx, _state);
21020 0 : ae_vector_set_length(&vmax, nx, _state);
21021 0 : ae_vector_set_length(cx, nx, _state);
21022 0 : for(j=0; j<=nx-1; j++)
21023 : {
21024 0 : vmin.ptr.p_double[j] = xy->ptr.pp_double[0][j];
21025 0 : vmax.ptr.p_double[j] = xy->ptr.pp_double[0][j];
21026 0 : cx->ptr.p_double[j] = (double)(0);
21027 : }
21028 0 : for(i=0; i<=npoints-1; i++)
21029 : {
21030 0 : for(j=0; j<=nx-1; j++)
21031 : {
21032 0 : cx->ptr.p_double[j] = cx->ptr.p_double[j]+xy->ptr.pp_double[i][j];
21033 0 : vmin.ptr.p_double[j] = ae_minreal(vmin.ptr.p_double[j], xy->ptr.pp_double[i][j], _state);
21034 0 : vmax.ptr.p_double[j] = ae_maxreal(vmax.ptr.p_double[j], xy->ptr.pp_double[i][j], _state);
21035 : }
21036 : }
21037 0 : spread = (double)(0);
21038 0 : for(j=0; j<=nx-1; j++)
21039 : {
21040 0 : cx->ptr.p_double[j] = cx->ptr.p_double[j]/npoints;
21041 0 : spread = ae_maxreal(spread, vmax.ptr.p_double[j]-vmin.ptr.p_double[j], _state);
21042 : }
21043 0 : *rlo = ae_maxrealnumber;
21044 0 : *rhi = (double)(0);
21045 0 : for(i=0; i<=npoints-1; i++)
21046 : {
21047 0 : v = (double)(0);
21048 0 : for(j=0; j<=nx-1; j++)
21049 : {
21050 0 : v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state);
21051 : }
21052 0 : v = ae_sqrt(v, _state);
21053 0 : *rhi = ae_maxreal(*rhi, v, _state);
21054 0 : *rlo = ae_minreal(*rlo, v, _state);
21055 : }
21056 :
21057 : /*
21058 : * Handle degenerate case of zero spread
21059 : */
21060 0 : if( ae_fp_eq(spread,(double)(0)) )
21061 : {
21062 0 : for(j=0; j<=nx-1; j++)
21063 : {
21064 0 : cx->ptr.p_double[j] = vmin.ptr.p_double[j];
21065 : }
21066 0 : *rhi = (double)(0);
21067 0 : *rlo = (double)(0);
21068 0 : ae_frame_leave(_state);
21069 0 : return;
21070 : }
21071 :
21072 : /*
21073 : * Prepare initial point for optimizer, scale vector and box constraints
21074 : */
21075 0 : ae_vector_set_length(&pcr, nx+2, _state);
21076 0 : ae_vector_set_length(&scr, nx+2, _state);
21077 0 : ae_vector_set_length(&bl, nx+2, _state);
21078 0 : ae_vector_set_length(&bu, nx+2, _state);
21079 0 : for(j=0; j<=nx-1; j++)
21080 : {
21081 0 : pcr.ptr.p_double[j] = cx->ptr.p_double[j];
21082 0 : scr.ptr.p_double[j] = 0.1*spread;
21083 0 : bl.ptr.p_double[j] = cx->ptr.p_double[j]-safeguard*spread;
21084 0 : bu.ptr.p_double[j] = cx->ptr.p_double[j]+safeguard*spread;
21085 : }
21086 0 : pcr.ptr.p_double[nx+0] = *rlo;
21087 0 : pcr.ptr.p_double[nx+1] = *rhi;
21088 0 : scr.ptr.p_double[nx+0] = 0.5*spread;
21089 0 : scr.ptr.p_double[nx+1] = 0.5*spread;
21090 0 : bl.ptr.p_double[nx+0] = (double)(0);
21091 0 : bl.ptr.p_double[nx+1] = (double)(0);
21092 0 : bu.ptr.p_double[nx+0] = safeguard*(*rhi);
21093 0 : bu.ptr.p_double[nx+1] = safeguard*(*rhi);
21094 :
21095 : /*
21096 : * First branch: least squares fitting vs MI/MC/MZ fitting
21097 : */
21098 0 : if( problemtype==0 )
21099 : {
21100 :
21101 : /*
21102 : * Solve problem with Levenberg-Marquardt algorithm
21103 : */
21104 0 : pcr.ptr.p_double[nx] = *rhi;
21105 0 : minlmcreatevj(nx+1, npoints, &pcr, &lmstate, _state);
21106 0 : minlmsetscale(&lmstate, &scr, _state);
21107 0 : minlmsetbc(&lmstate, &bl, &bu, _state);
21108 0 : minlmsetcond(&lmstate, epsx, maxits, _state);
21109 0 : while(minlmiteration(&lmstate, _state))
21110 : {
21111 0 : if( lmstate.needfij||lmstate.needfi )
21112 : {
21113 0 : inc(&rep->nfev, _state);
21114 0 : for(i=0; i<=npoints-1; i++)
21115 : {
21116 0 : v = (double)(0);
21117 0 : for(j=0; j<=nx-1; j++)
21118 : {
21119 0 : v = v+ae_sqr(lmstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j], _state);
21120 : }
21121 0 : lmstate.fi.ptr.p_double[i] = ae_sqrt(v, _state)-lmstate.x.ptr.p_double[nx];
21122 0 : if( lmstate.needfij )
21123 : {
21124 0 : for(j=0; j<=nx-1; j++)
21125 : {
21126 0 : lmstate.j.ptr.pp_double[i][j] = 0.5/(1.0E-9*spread+ae_sqrt(v, _state))*2*(lmstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j]);
21127 : }
21128 0 : lmstate.j.ptr.pp_double[i][nx] = (double)(-1);
21129 : }
21130 : }
21131 0 : continue;
21132 : }
21133 0 : ae_assert(ae_false, "Assertion failed", _state);
21134 : }
21135 0 : minlmresults(&lmstate, &pcr, &lmrep, _state);
21136 0 : ae_assert(lmrep.terminationtype>0, "FitSphereX: unexpected failure of LM solver", _state);
21137 0 : rep->iterationscount = rep->iterationscount+lmrep.iterationscount;
21138 :
21139 : /*
21140 : * Offload center coordinates from PCR to CX,
21141 : * re-calculate exact value of RLo/RHi using CX.
21142 : */
21143 0 : for(j=0; j<=nx-1; j++)
21144 : {
21145 0 : cx->ptr.p_double[j] = pcr.ptr.p_double[j];
21146 : }
21147 0 : vv = (double)(0);
21148 0 : for(i=0; i<=npoints-1; i++)
21149 : {
21150 0 : v = (double)(0);
21151 0 : for(j=0; j<=nx-1; j++)
21152 : {
21153 0 : v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state);
21154 : }
21155 0 : v = ae_sqrt(v, _state);
21156 0 : vv = vv+v/npoints;
21157 : }
21158 0 : *rlo = vv;
21159 0 : *rhi = vv;
21160 : }
21161 : else
21162 : {
21163 :
21164 : /*
21165 : * MI, MC, MZ fitting.
21166 : * Prepare problem metrics
21167 : */
21168 0 : userlo = problemtype==2||problemtype==3;
21169 0 : userhi = problemtype==1||problemtype==3;
21170 0 : if( userlo&&userhi )
21171 : {
21172 0 : cpr = 2;
21173 : }
21174 : else
21175 : {
21176 0 : cpr = 1;
21177 : }
21178 0 : if( userlo )
21179 : {
21180 0 : vlo = (double)(1);
21181 : }
21182 : else
21183 : {
21184 0 : vlo = (double)(0);
21185 : }
21186 0 : if( userhi )
21187 : {
21188 0 : vhi = (double)(1);
21189 : }
21190 : else
21191 : {
21192 0 : vhi = (double)(0);
21193 : }
21194 :
21195 : /*
21196 : * Solve with NLC solver; problem is treated as general nonlinearly constrained
21197 : * programming, with augmented Lagrangian solver or SLP being used.
21198 : */
21199 0 : if( solvertype==1||solvertype==3 )
21200 : {
21201 0 : minnlccreate(nx+2, &pcr, &nlcstate, _state);
21202 0 : minnlcsetscale(&nlcstate, &scr, _state);
21203 0 : minnlcsetbc(&nlcstate, &bl, &bu, _state);
21204 0 : minnlcsetnlc(&nlcstate, 0, cpr*npoints, _state);
21205 0 : minnlcsetcond(&nlcstate, epsx, maxits, _state);
21206 0 : minnlcsetprecexactrobust(&nlcstate, 5, _state);
21207 0 : minnlcsetstpmax(&nlcstate, 0.1, _state);
21208 0 : if( solvertype==1 )
21209 : {
21210 0 : minnlcsetalgoaul(&nlcstate, penalty, aulits, _state);
21211 : }
21212 : else
21213 : {
21214 0 : minnlcsetalgoslp(&nlcstate, _state);
21215 : }
21216 0 : minnlcrestartfrom(&nlcstate, &pcr, _state);
21217 0 : while(minnlciteration(&nlcstate, _state))
21218 : {
21219 0 : if( nlcstate.needfij )
21220 : {
21221 0 : inc(&rep->nfev, _state);
21222 0 : nlcstate.fi.ptr.p_double[0] = vhi*nlcstate.x.ptr.p_double[nx+1]-vlo*nlcstate.x.ptr.p_double[nx+0];
21223 0 : for(j=0; j<=nx-1; j++)
21224 : {
21225 0 : nlcstate.j.ptr.pp_double[0][j] = (double)(0);
21226 : }
21227 0 : nlcstate.j.ptr.pp_double[0][nx+0] = -1*vlo;
21228 0 : nlcstate.j.ptr.pp_double[0][nx+1] = 1*vhi;
21229 0 : for(i=0; i<=npoints-1; i++)
21230 : {
21231 0 : suboffset = 0;
21232 0 : if( userhi )
21233 : {
21234 0 : dstrow = 1+cpr*i+suboffset;
21235 0 : v = (double)(0);
21236 0 : for(j=0; j<=nx-1; j++)
21237 : {
21238 0 : vv = nlcstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j];
21239 0 : v = v+vv*vv;
21240 0 : nlcstate.j.ptr.pp_double[dstrow][j] = 2*vv;
21241 : }
21242 0 : vv = nlcstate.x.ptr.p_double[nx+1];
21243 0 : v = v-vv*vv;
21244 0 : nlcstate.j.ptr.pp_double[dstrow][nx+0] = (double)(0);
21245 0 : nlcstate.j.ptr.pp_double[dstrow][nx+1] = -2*vv;
21246 0 : nlcstate.fi.ptr.p_double[dstrow] = v;
21247 0 : inc(&suboffset, _state);
21248 : }
21249 0 : if( userlo )
21250 : {
21251 0 : dstrow = 1+cpr*i+suboffset;
21252 0 : v = (double)(0);
21253 0 : for(j=0; j<=nx-1; j++)
21254 : {
21255 0 : vv = nlcstate.x.ptr.p_double[j]-xy->ptr.pp_double[i][j];
21256 0 : v = v-vv*vv;
21257 0 : nlcstate.j.ptr.pp_double[dstrow][j] = -2*vv;
21258 : }
21259 0 : vv = nlcstate.x.ptr.p_double[nx+0];
21260 0 : v = v+vv*vv;
21261 0 : nlcstate.j.ptr.pp_double[dstrow][nx+0] = 2*vv;
21262 0 : nlcstate.j.ptr.pp_double[dstrow][nx+1] = (double)(0);
21263 0 : nlcstate.fi.ptr.p_double[dstrow] = v;
21264 0 : inc(&suboffset, _state);
21265 : }
21266 0 : ae_assert(suboffset==cpr, "Assertion failed", _state);
21267 : }
21268 0 : continue;
21269 : }
21270 0 : ae_assert(ae_false, "Assertion failed", _state);
21271 : }
21272 0 : minnlcresults(&nlcstate, &pcr, &nlcrep, _state);
21273 0 : ae_assert(nlcrep.terminationtype>0, "FitSphereX: unexpected failure of NLC solver", _state);
21274 0 : rep->iterationscount = rep->iterationscount+nlcrep.iterationscount;
21275 :
21276 : /*
21277 : * Offload center coordinates from PCR to CX,
21278 : * re-calculate exact value of RLo/RHi using CX.
21279 : */
21280 0 : for(j=0; j<=nx-1; j++)
21281 : {
21282 0 : cx->ptr.p_double[j] = pcr.ptr.p_double[j];
21283 : }
21284 0 : *rlo = ae_maxrealnumber;
21285 0 : *rhi = (double)(0);
21286 0 : for(i=0; i<=npoints-1; i++)
21287 : {
21288 0 : v = (double)(0);
21289 0 : for(j=0; j<=nx-1; j++)
21290 : {
21291 0 : v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state);
21292 : }
21293 0 : v = ae_sqrt(v, _state);
21294 0 : *rhi = ae_maxreal(*rhi, v, _state);
21295 0 : *rlo = ae_minreal(*rlo, v, _state);
21296 : }
21297 0 : if( !userlo )
21298 : {
21299 0 : *rlo = (double)(0);
21300 : }
21301 0 : if( !userhi )
21302 : {
21303 0 : *rhi = (double)(0);
21304 : }
21305 0 : ae_frame_leave(_state);
21306 0 : return;
21307 : }
21308 :
21309 : /*
21310 : * Solve problem with SLP (sequential LP) approach; this approach
21311 : * is much faster than NLP, but often fails for MI and MC (for MZ
21312 : * it performs well enough).
21313 : *
21314 : * REFERENCE: "On a sequential linear programming approach to finding
21315 : * the smallest circumscribed, largest inscribed, and minimum
21316 : * zone circle or sphere", Helmuth Spath and G.A.Watson
21317 : */
21318 0 : if( solvertype==2 )
21319 : {
21320 0 : ae_matrix_set_length(&cmatrix, cpr*npoints, nx+3, _state);
21321 0 : ae_vector_set_length(&ct, cpr*npoints, _state);
21322 0 : ae_vector_set_length(&prevc, nx, _state);
21323 0 : minbleiccreate(nx+2, &pcr, &blcstate, _state);
21324 0 : minbleicsetscale(&blcstate, &scr, _state);
21325 0 : minbleicsetbc(&blcstate, &bl, &bu, _state);
21326 0 : minbleicsetcond(&blcstate, (double)(0), (double)(0), epsx, maxits, _state);
21327 0 : for(outeridx=0; outeridx<=maxouterits-1; outeridx++)
21328 : {
21329 :
21330 : /*
21331 : * Prepare initial point for algorithm; center coordinates at
21332 : * PCR are used to calculate RLo/RHi and update PCR with them.
21333 : */
21334 0 : *rlo = ae_maxrealnumber;
21335 0 : *rhi = (double)(0);
21336 0 : for(i=0; i<=npoints-1; i++)
21337 : {
21338 0 : v = (double)(0);
21339 0 : for(j=0; j<=nx-1; j++)
21340 : {
21341 0 : v = v+ae_sqr(xy->ptr.pp_double[i][j]-pcr.ptr.p_double[j], _state);
21342 : }
21343 0 : v = ae_sqrt(v, _state);
21344 0 : *rhi = ae_maxreal(*rhi, v, _state);
21345 0 : *rlo = ae_minreal(*rlo, v, _state);
21346 : }
21347 0 : pcr.ptr.p_double[nx+0] = *rlo*0.99999;
21348 0 : pcr.ptr.p_double[nx+1] = *rhi/0.99999;
21349 :
21350 : /*
21351 : * Generate matrix of linear constraints
21352 : */
21353 0 : for(i=0; i<=npoints-1; i++)
21354 : {
21355 0 : v = (double)(0);
21356 0 : for(j=0; j<=nx-1; j++)
21357 : {
21358 0 : v = v+ae_sqr(xy->ptr.pp_double[i][j], _state);
21359 : }
21360 0 : bi = -v/2;
21361 0 : suboffset = 0;
21362 0 : if( userhi )
21363 : {
21364 0 : dstrow = cpr*i+suboffset;
21365 0 : for(j=0; j<=nx-1; j++)
21366 : {
21367 0 : cmatrix.ptr.pp_double[dstrow][j] = pcr.ptr.p_double[j]/2-xy->ptr.pp_double[i][j];
21368 : }
21369 0 : cmatrix.ptr.pp_double[dstrow][nx+0] = (double)(0);
21370 0 : cmatrix.ptr.pp_double[dstrow][nx+1] = -*rhi/2;
21371 0 : cmatrix.ptr.pp_double[dstrow][nx+2] = bi;
21372 0 : ct.ptr.p_int[dstrow] = -1;
21373 0 : inc(&suboffset, _state);
21374 : }
21375 0 : if( userlo )
21376 : {
21377 0 : dstrow = cpr*i+suboffset;
21378 0 : for(j=0; j<=nx-1; j++)
21379 : {
21380 0 : cmatrix.ptr.pp_double[dstrow][j] = -(pcr.ptr.p_double[j]/2-xy->ptr.pp_double[i][j]);
21381 : }
21382 0 : cmatrix.ptr.pp_double[dstrow][nx+0] = *rlo/2;
21383 0 : cmatrix.ptr.pp_double[dstrow][nx+1] = (double)(0);
21384 0 : cmatrix.ptr.pp_double[dstrow][nx+2] = -bi;
21385 0 : ct.ptr.p_int[dstrow] = -1;
21386 0 : inc(&suboffset, _state);
21387 : }
21388 0 : ae_assert(suboffset==cpr, "Assertion failed", _state);
21389 : }
21390 :
21391 : /*
21392 : * Solve LP subproblem with MinBLEIC
21393 : */
21394 0 : for(j=0; j<=nx-1; j++)
21395 : {
21396 0 : prevc.ptr.p_double[j] = pcr.ptr.p_double[j];
21397 : }
21398 0 : minbleicsetlc(&blcstate, &cmatrix, &ct, cpr*npoints, _state);
21399 0 : minbleicrestartfrom(&blcstate, &pcr, _state);
21400 0 : while(minbleiciteration(&blcstate, _state))
21401 : {
21402 0 : if( blcstate.needfg )
21403 : {
21404 0 : inc(&rep->nfev, _state);
21405 0 : blcstate.f = vhi*blcstate.x.ptr.p_double[nx+1]-vlo*blcstate.x.ptr.p_double[nx+0];
21406 0 : for(j=0; j<=nx-1; j++)
21407 : {
21408 0 : blcstate.g.ptr.p_double[j] = (double)(0);
21409 : }
21410 0 : blcstate.g.ptr.p_double[nx+0] = -1*vlo;
21411 0 : blcstate.g.ptr.p_double[nx+1] = 1*vhi;
21412 0 : continue;
21413 : }
21414 : }
21415 0 : minbleicresults(&blcstate, &pcr, &blcrep, _state);
21416 0 : ae_assert(blcrep.terminationtype>0, "FitSphereX: unexpected failure of BLEIC solver", _state);
21417 0 : rep->iterationscount = rep->iterationscount+blcrep.iterationscount;
21418 :
21419 : /*
21420 : * Terminate iterations early if we converged
21421 : */
21422 0 : v = (double)(0);
21423 0 : for(j=0; j<=nx-1; j++)
21424 : {
21425 0 : v = v+ae_sqr(prevc.ptr.p_double[j]-pcr.ptr.p_double[j], _state);
21426 : }
21427 0 : v = ae_sqrt(v, _state);
21428 0 : if( ae_fp_less_eq(v,epsx) )
21429 : {
21430 0 : break;
21431 : }
21432 : }
21433 :
21434 : /*
21435 : * Offload center coordinates from PCR to CX,
21436 : * re-calculate exact value of RLo/RHi using CX.
21437 : */
21438 0 : for(j=0; j<=nx-1; j++)
21439 : {
21440 0 : cx->ptr.p_double[j] = pcr.ptr.p_double[j];
21441 : }
21442 0 : *rlo = ae_maxrealnumber;
21443 0 : *rhi = (double)(0);
21444 0 : for(i=0; i<=npoints-1; i++)
21445 : {
21446 0 : v = (double)(0);
21447 0 : for(j=0; j<=nx-1; j++)
21448 : {
21449 0 : v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state);
21450 : }
21451 0 : v = ae_sqrt(v, _state);
21452 0 : *rhi = ae_maxreal(*rhi, v, _state);
21453 0 : *rlo = ae_minreal(*rlo, v, _state);
21454 : }
21455 0 : if( !userlo )
21456 : {
21457 0 : *rlo = (double)(0);
21458 : }
21459 0 : if( !userhi )
21460 : {
21461 0 : *rhi = (double)(0);
21462 : }
21463 0 : ae_frame_leave(_state);
21464 0 : return;
21465 : }
21466 :
21467 : /*
21468 : * Oooops...!
21469 : */
21470 0 : ae_assert(ae_false, "FitSphereX: integrity check failed", _state);
21471 : }
21472 0 : ae_frame_leave(_state);
21473 : }
21474 :
21475 :
21476 0 : void _fitsphereinternalreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
21477 : {
21478 0 : fitsphereinternalreport *p = (fitsphereinternalreport*)_p;
21479 0 : ae_touch_ptr((void*)p);
21480 0 : }
21481 :
21482 :
21483 0 : void _fitsphereinternalreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
21484 : {
21485 0 : fitsphereinternalreport *dst = (fitsphereinternalreport*)_dst;
21486 0 : fitsphereinternalreport *src = (fitsphereinternalreport*)_src;
21487 0 : dst->nfev = src->nfev;
21488 0 : dst->iterationscount = src->iterationscount;
21489 0 : }
21490 :
21491 :
21492 0 : void _fitsphereinternalreport_clear(void* _p)
21493 : {
21494 0 : fitsphereinternalreport *p = (fitsphereinternalreport*)_p;
21495 0 : ae_touch_ptr((void*)p);
21496 0 : }
21497 :
21498 :
21499 0 : void _fitsphereinternalreport_destroy(void* _p)
21500 : {
21501 0 : fitsphereinternalreport *p = (fitsphereinternalreport*)_p;
21502 0 : ae_touch_ptr((void*)p);
21503 0 : }
21504 :
21505 :
21506 : #endif
21507 : #if defined(AE_COMPILE_INTFITSERV) || !defined(AE_PARTIAL_BUILD)
21508 :
21509 :
21510 : /*************************************************************************
21511 : Internal subroutine: automatic scaling for LLS tasks.
21512 : NEVER CALL IT DIRECTLY!
21513 :
21514 : Maps abscissas to [-1,1], standartizes ordinates and correspondingly scales
21515 : constraints. It also scales weights so that max(W[i])=1
21516 :
21517 : Transformations performed:
21518 : * X, XC [XA,XB] => [-1,+1]
21519 : transformation makes min(X)=-1, max(X)=+1
21520 :
21521 : * Y [SA,SB] => [0,1]
21522 : transformation makes mean(Y)=0, stddev(Y)=1
21523 :
21524 : * YC transformed accordingly to SA, SB, DC[I]
21525 :
21526 : -- ALGLIB PROJECT --
21527 : Copyright 08.09.2009 by Bochkanov Sergey
21528 : *************************************************************************/
21529 0 : void lsfitscalexy(/* Real */ ae_vector* x,
21530 : /* Real */ ae_vector* y,
21531 : /* Real */ ae_vector* w,
21532 : ae_int_t n,
21533 : /* Real */ ae_vector* xc,
21534 : /* Real */ ae_vector* yc,
21535 : /* Integer */ ae_vector* dc,
21536 : ae_int_t k,
21537 : double* xa,
21538 : double* xb,
21539 : double* sa,
21540 : double* sb,
21541 : /* Real */ ae_vector* xoriginal,
21542 : /* Real */ ae_vector* yoriginal,
21543 : ae_state *_state)
21544 : {
21545 : double xmin;
21546 : double xmax;
21547 : ae_int_t i;
21548 : double mx;
21549 :
21550 0 : *xa = 0;
21551 0 : *xb = 0;
21552 0 : *sa = 0;
21553 0 : *sb = 0;
21554 0 : ae_vector_clear(xoriginal);
21555 0 : ae_vector_clear(yoriginal);
21556 :
21557 0 : ae_assert(n>=1, "LSFitScaleXY: incorrect N", _state);
21558 0 : ae_assert(k>=0, "LSFitScaleXY: incorrect K", _state);
21559 0 : xmin = x->ptr.p_double[0];
21560 0 : xmax = x->ptr.p_double[0];
21561 0 : for(i=1; i<=n-1; i++)
21562 : {
21563 0 : xmin = ae_minreal(xmin, x->ptr.p_double[i], _state);
21564 0 : xmax = ae_maxreal(xmax, x->ptr.p_double[i], _state);
21565 : }
21566 0 : for(i=0; i<=k-1; i++)
21567 : {
21568 0 : xmin = ae_minreal(xmin, xc->ptr.p_double[i], _state);
21569 0 : xmax = ae_maxreal(xmax, xc->ptr.p_double[i], _state);
21570 : }
21571 0 : if( ae_fp_eq(xmin,xmax) )
21572 : {
21573 0 : if( ae_fp_eq(xmin,(double)(0)) )
21574 : {
21575 0 : xmin = (double)(-1);
21576 0 : xmax = (double)(1);
21577 : }
21578 : else
21579 : {
21580 0 : if( ae_fp_greater(xmin,(double)(0)) )
21581 : {
21582 0 : xmin = 0.5*xmin;
21583 : }
21584 : else
21585 : {
21586 0 : xmax = 0.5*xmax;
21587 : }
21588 : }
21589 : }
21590 0 : ae_vector_set_length(xoriginal, n, _state);
21591 0 : ae_v_move(&xoriginal->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
21592 0 : *xa = xmin;
21593 0 : *xb = xmax;
21594 0 : for(i=0; i<=n-1; i++)
21595 : {
21596 0 : x->ptr.p_double[i] = 2*(x->ptr.p_double[i]-0.5*(*xa+(*xb)))/(*xb-(*xa));
21597 : }
21598 0 : for(i=0; i<=k-1; i++)
21599 : {
21600 0 : ae_assert(dc->ptr.p_int[i]>=0, "LSFitScaleXY: internal error!", _state);
21601 0 : xc->ptr.p_double[i] = 2*(xc->ptr.p_double[i]-0.5*(*xa+(*xb)))/(*xb-(*xa));
21602 0 : yc->ptr.p_double[i] = yc->ptr.p_double[i]*ae_pow(0.5*(*xb-(*xa)), (double)(dc->ptr.p_int[i]), _state);
21603 : }
21604 0 : ae_vector_set_length(yoriginal, n, _state);
21605 0 : ae_v_move(&yoriginal->ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
21606 0 : *sa = (double)(0);
21607 0 : for(i=0; i<=n-1; i++)
21608 : {
21609 0 : *sa = *sa+y->ptr.p_double[i];
21610 : }
21611 0 : *sa = *sa/n;
21612 0 : *sb = (double)(0);
21613 0 : for(i=0; i<=n-1; i++)
21614 : {
21615 0 : *sb = *sb+ae_sqr(y->ptr.p_double[i]-(*sa), _state);
21616 : }
21617 0 : *sb = ae_sqrt(*sb/n, _state)+(*sa);
21618 0 : if( ae_fp_eq(*sb,*sa) )
21619 : {
21620 0 : *sb = 2*(*sa);
21621 : }
21622 0 : if( ae_fp_eq(*sb,*sa) )
21623 : {
21624 0 : *sb = *sa+1;
21625 : }
21626 0 : for(i=0; i<=n-1; i++)
21627 : {
21628 0 : y->ptr.p_double[i] = (y->ptr.p_double[i]-(*sa))/(*sb-(*sa));
21629 : }
21630 0 : for(i=0; i<=k-1; i++)
21631 : {
21632 0 : if( dc->ptr.p_int[i]==0 )
21633 : {
21634 0 : yc->ptr.p_double[i] = (yc->ptr.p_double[i]-(*sa))/(*sb-(*sa));
21635 : }
21636 : else
21637 : {
21638 0 : yc->ptr.p_double[i] = yc->ptr.p_double[i]/(*sb-(*sa));
21639 : }
21640 : }
21641 0 : mx = (double)(0);
21642 0 : for(i=0; i<=n-1; i++)
21643 : {
21644 0 : mx = ae_maxreal(mx, ae_fabs(w->ptr.p_double[i], _state), _state);
21645 : }
21646 0 : if( ae_fp_neq(mx,(double)(0)) )
21647 : {
21648 0 : for(i=0; i<=n-1; i++)
21649 : {
21650 0 : w->ptr.p_double[i] = w->ptr.p_double[i]/mx;
21651 : }
21652 : }
21653 0 : }
21654 :
21655 :
21656 0 : void buildpriorterm(/* Real */ ae_matrix* xy,
21657 : ae_int_t n,
21658 : ae_int_t nx,
21659 : ae_int_t ny,
21660 : ae_int_t modeltype,
21661 : double priorval,
21662 : /* Real */ ae_matrix* v,
21663 : ae_state *_state)
21664 : {
21665 : ae_frame _frame_block;
21666 : ae_int_t i;
21667 : ae_int_t j;
21668 : ae_int_t j0;
21669 : ae_int_t j1;
21670 : double rj;
21671 : ae_matrix araw;
21672 : ae_matrix amod;
21673 : ae_matrix braw;
21674 : ae_vector tmp0;
21675 : double lambdareg;
21676 : ae_int_t rfsits;
21677 :
21678 0 : ae_frame_make(_state, &_frame_block);
21679 0 : memset(&araw, 0, sizeof(araw));
21680 0 : memset(&amod, 0, sizeof(amod));
21681 0 : memset(&braw, 0, sizeof(braw));
21682 0 : memset(&tmp0, 0, sizeof(tmp0));
21683 0 : ae_matrix_clear(v);
21684 0 : ae_matrix_init(&araw, 0, 0, DT_REAL, _state, ae_true);
21685 0 : ae_matrix_init(&amod, 0, 0, DT_REAL, _state, ae_true);
21686 0 : ae_matrix_init(&braw, 0, 0, DT_REAL, _state, ae_true);
21687 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
21688 :
21689 0 : ae_assert(n>=0, "BuildPriorTerm: N<0", _state);
21690 0 : ae_assert(nx>0, "BuildPriorTerm: NX<=0", _state);
21691 0 : ae_assert(ny>0, "BuildPriorTerm: NY<=0", _state);
21692 0 : ae_matrix_set_length(v, ny, nx+1, _state);
21693 0 : for(i=0; i<=v->rows-1; i++)
21694 : {
21695 0 : for(j=0; j<=v->cols-1; j++)
21696 : {
21697 0 : v->ptr.pp_double[i][j] = (double)(0);
21698 : }
21699 : }
21700 0 : if( n==0 )
21701 : {
21702 0 : if( modeltype==0 )
21703 : {
21704 0 : for(i=0; i<=ny-1; i++)
21705 : {
21706 0 : v->ptr.pp_double[i][nx] = priorval;
21707 : }
21708 0 : ae_frame_leave(_state);
21709 0 : return;
21710 : }
21711 0 : if( modeltype==1 )
21712 : {
21713 0 : ae_frame_leave(_state);
21714 0 : return;
21715 : }
21716 0 : if( modeltype==2 )
21717 : {
21718 0 : ae_frame_leave(_state);
21719 0 : return;
21720 : }
21721 0 : if( modeltype==3 )
21722 : {
21723 0 : ae_frame_leave(_state);
21724 0 : return;
21725 : }
21726 0 : ae_assert(ae_false, "BuildPriorTerm: unexpected model type", _state);
21727 : }
21728 0 : if( modeltype==0 )
21729 : {
21730 0 : for(i=0; i<=ny-1; i++)
21731 : {
21732 0 : v->ptr.pp_double[i][nx] = priorval;
21733 : }
21734 0 : for(i=0; i<=n-1; i++)
21735 : {
21736 0 : for(j=0; j<=ny-1; j++)
21737 : {
21738 0 : xy->ptr.pp_double[i][nx+j] = xy->ptr.pp_double[i][nx+j]-priorval;
21739 : }
21740 : }
21741 0 : ae_frame_leave(_state);
21742 0 : return;
21743 : }
21744 0 : if( modeltype==2 )
21745 : {
21746 0 : for(i=0; i<=n-1; i++)
21747 : {
21748 0 : for(j=0; j<=ny-1; j++)
21749 : {
21750 0 : v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]+xy->ptr.pp_double[i][nx+j];
21751 : }
21752 : }
21753 0 : for(j=0; j<=ny-1; j++)
21754 : {
21755 0 : v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]/coalesce((double)(n), (double)(1), _state);
21756 : }
21757 0 : for(i=0; i<=n-1; i++)
21758 : {
21759 0 : for(j=0; j<=ny-1; j++)
21760 : {
21761 0 : xy->ptr.pp_double[i][nx+j] = xy->ptr.pp_double[i][nx+j]-v->ptr.pp_double[j][nx];
21762 : }
21763 : }
21764 0 : ae_frame_leave(_state);
21765 0 : return;
21766 : }
21767 0 : if( modeltype==3 )
21768 : {
21769 0 : ae_frame_leave(_state);
21770 0 : return;
21771 : }
21772 0 : ae_assert(modeltype==1, "BuildPriorTerm: unexpected model type", _state);
21773 0 : lambdareg = 0.0;
21774 0 : ae_matrix_set_length(&araw, nx+1, nx+1, _state);
21775 0 : ae_matrix_set_length(&braw, nx+1, ny, _state);
21776 0 : ae_vector_set_length(&tmp0, nx+1, _state);
21777 0 : ae_matrix_set_length(&amod, nx+1, nx+1, _state);
21778 0 : for(i=0; i<=nx; i++)
21779 : {
21780 0 : for(j=0; j<=nx; j++)
21781 : {
21782 0 : araw.ptr.pp_double[i][j] = (double)(0);
21783 : }
21784 : }
21785 0 : for(i=0; i<=n-1; i++)
21786 : {
21787 0 : for(j=0; j<=nx-1; j++)
21788 : {
21789 0 : tmp0.ptr.p_double[j] = xy->ptr.pp_double[i][j];
21790 : }
21791 0 : tmp0.ptr.p_double[nx] = 1.0;
21792 0 : for(j0=0; j0<=nx; j0++)
21793 : {
21794 0 : for(j1=0; j1<=nx; j1++)
21795 : {
21796 0 : araw.ptr.pp_double[j0][j1] = araw.ptr.pp_double[j0][j1]+tmp0.ptr.p_double[j0]*tmp0.ptr.p_double[j1];
21797 : }
21798 : }
21799 : }
21800 0 : for(rfsits=1; rfsits<=3; rfsits++)
21801 : {
21802 0 : for(i=0; i<=nx; i++)
21803 : {
21804 0 : for(j=0; j<=ny-1; j++)
21805 : {
21806 0 : braw.ptr.pp_double[i][j] = (double)(0);
21807 : }
21808 : }
21809 0 : for(i=0; i<=n-1; i++)
21810 : {
21811 0 : for(j=0; j<=nx-1; j++)
21812 : {
21813 0 : tmp0.ptr.p_double[j] = xy->ptr.pp_double[i][j];
21814 : }
21815 0 : tmp0.ptr.p_double[nx] = 1.0;
21816 0 : for(j=0; j<=ny-1; j++)
21817 : {
21818 0 : rj = xy->ptr.pp_double[i][nx+j];
21819 0 : for(j0=0; j0<=nx; j0++)
21820 : {
21821 0 : rj = rj-tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0];
21822 : }
21823 0 : for(j0=0; j0<=nx; j0++)
21824 : {
21825 0 : braw.ptr.pp_double[j0][j] = braw.ptr.pp_double[j0][j]+rj*tmp0.ptr.p_double[j0];
21826 : }
21827 : }
21828 : }
21829 : for(;;)
21830 : {
21831 0 : for(i=0; i<=nx; i++)
21832 : {
21833 0 : for(j=0; j<=nx; j++)
21834 : {
21835 0 : amod.ptr.pp_double[i][j] = araw.ptr.pp_double[i][j];
21836 : }
21837 0 : amod.ptr.pp_double[i][i] = amod.ptr.pp_double[i][i]+lambdareg*coalesce(amod.ptr.pp_double[i][i], (double)(1), _state);
21838 : }
21839 0 : if( spdmatrixcholesky(&amod, nx+1, ae_true, _state) )
21840 : {
21841 0 : break;
21842 : }
21843 0 : lambdareg = coalesce(10*lambdareg, 1.0E-12, _state);
21844 : }
21845 0 : rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 1, &braw, 0, 0, _state);
21846 0 : rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 0, &braw, 0, 0, _state);
21847 0 : for(i=0; i<=nx; i++)
21848 : {
21849 0 : for(j=0; j<=ny-1; j++)
21850 : {
21851 0 : v->ptr.pp_double[j][i] = v->ptr.pp_double[j][i]+braw.ptr.pp_double[i][j];
21852 : }
21853 : }
21854 : }
21855 0 : for(i=0; i<=n-1; i++)
21856 : {
21857 0 : for(j=0; j<=nx-1; j++)
21858 : {
21859 0 : tmp0.ptr.p_double[j] = xy->ptr.pp_double[i][j];
21860 : }
21861 0 : tmp0.ptr.p_double[nx] = 1.0;
21862 0 : for(j=0; j<=ny-1; j++)
21863 : {
21864 0 : rj = 0.0;
21865 0 : for(j0=0; j0<=nx; j0++)
21866 : {
21867 0 : rj = rj+tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0];
21868 : }
21869 0 : xy->ptr.pp_double[i][nx+j] = xy->ptr.pp_double[i][nx+j]-rj;
21870 : }
21871 : }
21872 0 : ae_frame_leave(_state);
21873 : }
21874 :
21875 :
21876 0 : void buildpriorterm1(/* Real */ ae_vector* xy1,
21877 : ae_int_t n,
21878 : ae_int_t nx,
21879 : ae_int_t ny,
21880 : ae_int_t modeltype,
21881 : double priorval,
21882 : /* Real */ ae_matrix* v,
21883 : ae_state *_state)
21884 : {
21885 : ae_frame _frame_block;
21886 : ae_int_t i;
21887 : ae_int_t j;
21888 : ae_int_t j0;
21889 : ae_int_t j1;
21890 : ae_int_t ew;
21891 : double rj;
21892 : ae_matrix araw;
21893 : ae_matrix amod;
21894 : ae_matrix braw;
21895 : ae_vector tmp0;
21896 : double lambdareg;
21897 : ae_int_t rfsits;
21898 :
21899 0 : ae_frame_make(_state, &_frame_block);
21900 0 : memset(&araw, 0, sizeof(araw));
21901 0 : memset(&amod, 0, sizeof(amod));
21902 0 : memset(&braw, 0, sizeof(braw));
21903 0 : memset(&tmp0, 0, sizeof(tmp0));
21904 0 : ae_matrix_clear(v);
21905 0 : ae_matrix_init(&araw, 0, 0, DT_REAL, _state, ae_true);
21906 0 : ae_matrix_init(&amod, 0, 0, DT_REAL, _state, ae_true);
21907 0 : ae_matrix_init(&braw, 0, 0, DT_REAL, _state, ae_true);
21908 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
21909 :
21910 0 : ae_assert(n>=0, "BuildPriorTerm: N<0", _state);
21911 0 : ae_assert(nx>0, "BuildPriorTerm: NX<=0", _state);
21912 0 : ae_assert(ny>0, "BuildPriorTerm: NY<=0", _state);
21913 0 : ew = nx+ny;
21914 0 : ae_matrix_set_length(v, ny, nx+1, _state);
21915 0 : for(i=0; i<=v->rows-1; i++)
21916 : {
21917 0 : for(j=0; j<=v->cols-1; j++)
21918 : {
21919 0 : v->ptr.pp_double[i][j] = (double)(0);
21920 : }
21921 : }
21922 0 : if( n==0 )
21923 : {
21924 0 : if( modeltype==0 )
21925 : {
21926 0 : for(i=0; i<=ny-1; i++)
21927 : {
21928 0 : v->ptr.pp_double[i][nx] = priorval;
21929 : }
21930 0 : ae_frame_leave(_state);
21931 0 : return;
21932 : }
21933 0 : if( modeltype==1 )
21934 : {
21935 0 : ae_frame_leave(_state);
21936 0 : return;
21937 : }
21938 0 : if( modeltype==2 )
21939 : {
21940 0 : ae_frame_leave(_state);
21941 0 : return;
21942 : }
21943 0 : if( modeltype==3 )
21944 : {
21945 0 : ae_frame_leave(_state);
21946 0 : return;
21947 : }
21948 0 : ae_assert(ae_false, "BuildPriorTerm: unexpected model type", _state);
21949 : }
21950 0 : if( modeltype==0 )
21951 : {
21952 0 : for(i=0; i<=ny-1; i++)
21953 : {
21954 0 : v->ptr.pp_double[i][nx] = priorval;
21955 : }
21956 0 : for(i=0; i<=n-1; i++)
21957 : {
21958 0 : for(j=0; j<=ny-1; j++)
21959 : {
21960 0 : xy1->ptr.p_double[i*ew+nx+j] = xy1->ptr.p_double[i*ew+nx+j]-priorval;
21961 : }
21962 : }
21963 0 : ae_frame_leave(_state);
21964 0 : return;
21965 : }
21966 0 : if( modeltype==2 )
21967 : {
21968 0 : for(i=0; i<=n-1; i++)
21969 : {
21970 0 : for(j=0; j<=ny-1; j++)
21971 : {
21972 0 : v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]+xy1->ptr.p_double[i*ew+nx+j];
21973 : }
21974 : }
21975 0 : for(j=0; j<=ny-1; j++)
21976 : {
21977 0 : v->ptr.pp_double[j][nx] = v->ptr.pp_double[j][nx]/coalesce((double)(n), (double)(1), _state);
21978 : }
21979 0 : for(i=0; i<=n-1; i++)
21980 : {
21981 0 : for(j=0; j<=ny-1; j++)
21982 : {
21983 0 : xy1->ptr.p_double[i*ew+nx+j] = xy1->ptr.p_double[i*ew+nx+j]-v->ptr.pp_double[j][nx];
21984 : }
21985 : }
21986 0 : ae_frame_leave(_state);
21987 0 : return;
21988 : }
21989 0 : if( modeltype==3 )
21990 : {
21991 0 : ae_frame_leave(_state);
21992 0 : return;
21993 : }
21994 0 : ae_assert(modeltype==1, "BuildPriorTerm: unexpected model type", _state);
21995 0 : lambdareg = 0.0;
21996 0 : ae_matrix_set_length(&araw, nx+1, nx+1, _state);
21997 0 : ae_matrix_set_length(&braw, nx+1, ny, _state);
21998 0 : ae_vector_set_length(&tmp0, nx+1, _state);
21999 0 : ae_matrix_set_length(&amod, nx+1, nx+1, _state);
22000 0 : for(i=0; i<=nx; i++)
22001 : {
22002 0 : for(j=0; j<=nx; j++)
22003 : {
22004 0 : araw.ptr.pp_double[i][j] = (double)(0);
22005 : }
22006 : }
22007 0 : for(i=0; i<=n-1; i++)
22008 : {
22009 0 : for(j=0; j<=nx-1; j++)
22010 : {
22011 0 : tmp0.ptr.p_double[j] = xy1->ptr.p_double[i*ew+j];
22012 : }
22013 0 : tmp0.ptr.p_double[nx] = 1.0;
22014 0 : for(j0=0; j0<=nx; j0++)
22015 : {
22016 0 : for(j1=0; j1<=nx; j1++)
22017 : {
22018 0 : araw.ptr.pp_double[j0][j1] = araw.ptr.pp_double[j0][j1]+tmp0.ptr.p_double[j0]*tmp0.ptr.p_double[j1];
22019 : }
22020 : }
22021 : }
22022 0 : for(rfsits=1; rfsits<=3; rfsits++)
22023 : {
22024 0 : for(i=0; i<=nx; i++)
22025 : {
22026 0 : for(j=0; j<=ny-1; j++)
22027 : {
22028 0 : braw.ptr.pp_double[i][j] = (double)(0);
22029 : }
22030 : }
22031 0 : for(i=0; i<=n-1; i++)
22032 : {
22033 0 : for(j=0; j<=nx-1; j++)
22034 : {
22035 0 : tmp0.ptr.p_double[j] = xy1->ptr.p_double[i*ew+j];
22036 : }
22037 0 : tmp0.ptr.p_double[nx] = 1.0;
22038 0 : for(j=0; j<=ny-1; j++)
22039 : {
22040 0 : rj = xy1->ptr.p_double[i*ew+nx+j];
22041 0 : for(j0=0; j0<=nx; j0++)
22042 : {
22043 0 : rj = rj-tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0];
22044 : }
22045 0 : for(j0=0; j0<=nx; j0++)
22046 : {
22047 0 : braw.ptr.pp_double[j0][j] = braw.ptr.pp_double[j0][j]+rj*tmp0.ptr.p_double[j0];
22048 : }
22049 : }
22050 : }
22051 : for(;;)
22052 : {
22053 0 : for(i=0; i<=nx; i++)
22054 : {
22055 0 : for(j=0; j<=nx; j++)
22056 : {
22057 0 : amod.ptr.pp_double[i][j] = araw.ptr.pp_double[i][j];
22058 : }
22059 0 : amod.ptr.pp_double[i][i] = amod.ptr.pp_double[i][i]+lambdareg*coalesce(amod.ptr.pp_double[i][i], (double)(1), _state);
22060 : }
22061 0 : if( spdmatrixcholesky(&amod, nx+1, ae_true, _state) )
22062 : {
22063 0 : break;
22064 : }
22065 0 : lambdareg = coalesce(10*lambdareg, 1.0E-12, _state);
22066 : }
22067 0 : rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 1, &braw, 0, 0, _state);
22068 0 : rmatrixlefttrsm(nx+1, ny, &amod, 0, 0, ae_true, ae_false, 0, &braw, 0, 0, _state);
22069 0 : for(i=0; i<=nx; i++)
22070 : {
22071 0 : for(j=0; j<=ny-1; j++)
22072 : {
22073 0 : v->ptr.pp_double[j][i] = v->ptr.pp_double[j][i]+braw.ptr.pp_double[i][j];
22074 : }
22075 : }
22076 : }
22077 0 : for(i=0; i<=n-1; i++)
22078 : {
22079 0 : for(j=0; j<=nx-1; j++)
22080 : {
22081 0 : tmp0.ptr.p_double[j] = xy1->ptr.p_double[i*ew+j];
22082 : }
22083 0 : tmp0.ptr.p_double[nx] = 1.0;
22084 0 : for(j=0; j<=ny-1; j++)
22085 : {
22086 0 : rj = 0.0;
22087 0 : for(j0=0; j0<=nx; j0++)
22088 : {
22089 0 : rj = rj+tmp0.ptr.p_double[j0]*v->ptr.pp_double[j][j0];
22090 : }
22091 0 : xy1->ptr.p_double[i*ew+nx+j] = xy1->ptr.p_double[i*ew+nx+j]-rj;
22092 : }
22093 : }
22094 0 : ae_frame_leave(_state);
22095 : }
22096 :
22097 :
22098 : #endif
22099 : #if defined(AE_COMPILE_SPLINE1D) || !defined(AE_PARTIAL_BUILD)
22100 :
22101 :
22102 : /*************************************************************************
22103 : This subroutine builds linear spline interpolant
22104 :
22105 : INPUT PARAMETERS:
22106 : X - spline nodes, array[0..N-1]
22107 : Y - function values, array[0..N-1]
22108 : N - points count (optional):
22109 : * N>=2
22110 : * if given, only first N points are used to build spline
22111 : * if not given, automatically detected from X/Y sizes
22112 : (len(X) must be equal to len(Y))
22113 :
22114 : OUTPUT PARAMETERS:
22115 : C - spline interpolant
22116 :
22117 :
22118 : ORDER OF POINTS
22119 :
22120 : Subroutine automatically sorts points, so caller may pass unsorted array.
22121 :
22122 : -- ALGLIB PROJECT --
22123 : Copyright 24.06.2007 by Bochkanov Sergey
22124 : *************************************************************************/
22125 0 : void spline1dbuildlinear(/* Real */ ae_vector* x,
22126 : /* Real */ ae_vector* y,
22127 : ae_int_t n,
22128 : spline1dinterpolant* c,
22129 : ae_state *_state)
22130 : {
22131 : ae_frame _frame_block;
22132 : ae_vector _x;
22133 : ae_vector _y;
22134 : ae_int_t i;
22135 :
22136 0 : ae_frame_make(_state, &_frame_block);
22137 0 : memset(&_x, 0, sizeof(_x));
22138 0 : memset(&_y, 0, sizeof(_y));
22139 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
22140 0 : x = &_x;
22141 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
22142 0 : y = &_y;
22143 0 : _spline1dinterpolant_clear(c);
22144 :
22145 0 : ae_assert(n>1, "Spline1DBuildLinear: N<2!", _state);
22146 0 : ae_assert(x->cnt>=n, "Spline1DBuildLinear: Length(X)<N!", _state);
22147 0 : ae_assert(y->cnt>=n, "Spline1DBuildLinear: Length(Y)<N!", _state);
22148 :
22149 : /*
22150 : * check and sort points
22151 : */
22152 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DBuildLinear: X contains infinite or NAN values!", _state);
22153 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DBuildLinear: Y contains infinite or NAN values!", _state);
22154 0 : spline1d_heapsortpoints(x, y, n, _state);
22155 0 : ae_assert(aredistinct(x, n, _state), "Spline1DBuildLinear: at least two consequent points are too close!", _state);
22156 :
22157 : /*
22158 : * Build
22159 : */
22160 0 : c->periodic = ae_false;
22161 0 : c->n = n;
22162 0 : c->k = 3;
22163 0 : c->continuity = 0;
22164 0 : ae_vector_set_length(&c->x, n, _state);
22165 0 : ae_vector_set_length(&c->c, 4*(n-1)+2, _state);
22166 0 : for(i=0; i<=n-1; i++)
22167 : {
22168 0 : c->x.ptr.p_double[i] = x->ptr.p_double[i];
22169 : }
22170 0 : for(i=0; i<=n-2; i++)
22171 : {
22172 0 : c->c.ptr.p_double[4*i+0] = y->ptr.p_double[i];
22173 0 : c->c.ptr.p_double[4*i+1] = (y->ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i]);
22174 0 : c->c.ptr.p_double[4*i+2] = (double)(0);
22175 0 : c->c.ptr.p_double[4*i+3] = (double)(0);
22176 : }
22177 0 : c->c.ptr.p_double[4*(n-1)+0] = y->ptr.p_double[n-1];
22178 0 : c->c.ptr.p_double[4*(n-1)+1] = c->c.ptr.p_double[4*(n-2)+1];
22179 0 : ae_frame_leave(_state);
22180 0 : }
22181 :
22182 :
22183 : /*************************************************************************
22184 : This subroutine builds cubic spline interpolant.
22185 :
22186 : INPUT PARAMETERS:
22187 : X - spline nodes, array[0..N-1].
22188 : Y - function values, array[0..N-1].
22189 :
22190 : OPTIONAL PARAMETERS:
22191 : N - points count:
22192 : * N>=2
22193 : * if given, only first N points are used to build spline
22194 : * if not given, automatically detected from X/Y sizes
22195 : (len(X) must be equal to len(Y))
22196 : BoundLType - boundary condition type for the left boundary
22197 : BoundL - left boundary condition (first or second derivative,
22198 : depending on the BoundLType)
22199 : BoundRType - boundary condition type for the right boundary
22200 : BoundR - right boundary condition (first or second derivative,
22201 : depending on the BoundRType)
22202 :
22203 : OUTPUT PARAMETERS:
22204 : C - spline interpolant
22205 :
22206 : ORDER OF POINTS
22207 :
22208 : Subroutine automatically sorts points, so caller may pass unsorted array.
22209 :
22210 : SETTING BOUNDARY VALUES:
22211 :
22212 : The BoundLType/BoundRType parameters can have the following values:
22213 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
22214 : In this case:
22215 : * both BoundLType and BoundRType must be equal to -1.
22216 : * BoundL/BoundR are ignored
22217 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
22218 : * 0, which corresponds to the parabolically terminated spline
22219 : (BoundL and/or BoundR are ignored).
22220 : * 1, which corresponds to the first derivative boundary condition
22221 : * 2, which corresponds to the second derivative boundary condition
22222 : * by default, BoundType=0 is used
22223 :
22224 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
22225 :
22226 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
22227 : However, this subroutine doesn't require you to specify equal values for
22228 : the first and last points - it automatically forces them to be equal by
22229 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
22230 : Y[last_point]. However it is recommended to pass consistent values of Y[],
22231 : i.e. to make Y[first_point]=Y[last_point].
22232 :
22233 : -- ALGLIB PROJECT --
22234 : Copyright 23.06.2007 by Bochkanov Sergey
22235 : *************************************************************************/
22236 0 : void spline1dbuildcubic(/* Real */ ae_vector* x,
22237 : /* Real */ ae_vector* y,
22238 : ae_int_t n,
22239 : ae_int_t boundltype,
22240 : double boundl,
22241 : ae_int_t boundrtype,
22242 : double boundr,
22243 : spline1dinterpolant* c,
22244 : ae_state *_state)
22245 : {
22246 : ae_frame _frame_block;
22247 : ae_vector _x;
22248 : ae_vector _y;
22249 : ae_vector a1;
22250 : ae_vector a2;
22251 : ae_vector a3;
22252 : ae_vector b;
22253 : ae_vector dt;
22254 : ae_vector d;
22255 : ae_vector p;
22256 : ae_int_t ylen;
22257 :
22258 0 : ae_frame_make(_state, &_frame_block);
22259 0 : memset(&_x, 0, sizeof(_x));
22260 0 : memset(&_y, 0, sizeof(_y));
22261 0 : memset(&a1, 0, sizeof(a1));
22262 0 : memset(&a2, 0, sizeof(a2));
22263 0 : memset(&a3, 0, sizeof(a3));
22264 0 : memset(&b, 0, sizeof(b));
22265 0 : memset(&dt, 0, sizeof(dt));
22266 0 : memset(&d, 0, sizeof(d));
22267 0 : memset(&p, 0, sizeof(p));
22268 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
22269 0 : x = &_x;
22270 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
22271 0 : y = &_y;
22272 0 : _spline1dinterpolant_clear(c);
22273 0 : ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
22274 0 : ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
22275 0 : ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
22276 0 : ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
22277 0 : ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
22278 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
22279 0 : ae_vector_init(&p, 0, DT_INT, _state, ae_true);
22280 :
22281 :
22282 : /*
22283 : * check correctness of boundary conditions
22284 : */
22285 0 : ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DBuildCubic: incorrect BoundLType!", _state);
22286 0 : ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DBuildCubic: incorrect BoundRType!", _state);
22287 0 : ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DBuildCubic: incorrect BoundLType/BoundRType!", _state);
22288 0 : if( boundltype==1||boundltype==2 )
22289 : {
22290 0 : ae_assert(ae_isfinite(boundl, _state), "Spline1DBuildCubic: BoundL is infinite or NAN!", _state);
22291 : }
22292 0 : if( boundrtype==1||boundrtype==2 )
22293 : {
22294 0 : ae_assert(ae_isfinite(boundr, _state), "Spline1DBuildCubic: BoundR is infinite or NAN!", _state);
22295 : }
22296 :
22297 : /*
22298 : * check lengths of arguments
22299 : */
22300 0 : ae_assert(n>=2, "Spline1DBuildCubic: N<2!", _state);
22301 0 : ae_assert(x->cnt>=n, "Spline1DBuildCubic: Length(X)<N!", _state);
22302 0 : ae_assert(y->cnt>=n, "Spline1DBuildCubic: Length(Y)<N!", _state);
22303 :
22304 : /*
22305 : * check and sort points
22306 : */
22307 0 : ylen = n;
22308 0 : if( boundltype==-1 )
22309 : {
22310 0 : ylen = n-1;
22311 : }
22312 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DBuildCubic: X contains infinite or NAN values!", _state);
22313 0 : ae_assert(isfinitevector(y, ylen, _state), "Spline1DBuildCubic: Y contains infinite or NAN values!", _state);
22314 0 : spline1d_heapsortppoints(x, y, &p, n, _state);
22315 0 : ae_assert(aredistinct(x, n, _state), "Spline1DBuildCubic: at least two consequent points are too close!", _state);
22316 :
22317 : /*
22318 : * Now we've checked and preordered everything,
22319 : * so we can call internal function to calculate derivatives,
22320 : * and then build Hermite spline using these derivatives
22321 : */
22322 0 : if( boundltype==-1||boundrtype==-1 )
22323 : {
22324 0 : y->ptr.p_double[n-1] = y->ptr.p_double[0];
22325 : }
22326 0 : spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
22327 0 : spline1dbuildhermite(x, y, &d, n, c, _state);
22328 0 : c->periodic = boundltype==-1||boundrtype==-1;
22329 0 : c->continuity = 2;
22330 0 : ae_frame_leave(_state);
22331 0 : }
22332 :
22333 :
22334 : /*************************************************************************
22335 : This function solves following problem: given table y[] of function values
22336 : at nodes x[], it calculates and returns table of function derivatives d[]
22337 : (calculated at the same nodes x[]).
22338 :
22339 : This function yields same result as Spline1DBuildCubic() call followed by
22340 : sequence of Spline1DDiff() calls, but it can be several times faster when
22341 : called for ordered X[] and X2[].
22342 :
22343 : INPUT PARAMETERS:
22344 : X - spline nodes
22345 : Y - function values
22346 :
22347 : OPTIONAL PARAMETERS:
22348 : N - points count:
22349 : * N>=2
22350 : * if given, only first N points are used
22351 : * if not given, automatically detected from X/Y sizes
22352 : (len(X) must be equal to len(Y))
22353 : BoundLType - boundary condition type for the left boundary
22354 : BoundL - left boundary condition (first or second derivative,
22355 : depending on the BoundLType)
22356 : BoundRType - boundary condition type for the right boundary
22357 : BoundR - right boundary condition (first or second derivative,
22358 : depending on the BoundRType)
22359 :
22360 : OUTPUT PARAMETERS:
22361 : D - derivative values at X[]
22362 :
22363 : ORDER OF POINTS
22364 :
22365 : Subroutine automatically sorts points, so caller may pass unsorted array.
22366 : Derivative values are correctly reordered on return, so D[I] is always
22367 : equal to S'(X[I]) independently of points order.
22368 :
22369 : SETTING BOUNDARY VALUES:
22370 :
22371 : The BoundLType/BoundRType parameters can have the following values:
22372 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
22373 : In this case:
22374 : * both BoundLType and BoundRType must be equal to -1.
22375 : * BoundL/BoundR are ignored
22376 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
22377 : * 0, which corresponds to the parabolically terminated spline
22378 : (BoundL and/or BoundR are ignored).
22379 : * 1, which corresponds to the first derivative boundary condition
22380 : * 2, which corresponds to the second derivative boundary condition
22381 : * by default, BoundType=0 is used
22382 :
22383 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
22384 :
22385 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
22386 : However, this subroutine doesn't require you to specify equal values for
22387 : the first and last points - it automatically forces them to be equal by
22388 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
22389 : Y[last_point]. However it is recommended to pass consistent values of Y[],
22390 : i.e. to make Y[first_point]=Y[last_point].
22391 :
22392 : -- ALGLIB PROJECT --
22393 : Copyright 03.09.2010 by Bochkanov Sergey
22394 : *************************************************************************/
22395 0 : void spline1dgriddiffcubic(/* Real */ ae_vector* x,
22396 : /* Real */ ae_vector* y,
22397 : ae_int_t n,
22398 : ae_int_t boundltype,
22399 : double boundl,
22400 : ae_int_t boundrtype,
22401 : double boundr,
22402 : /* Real */ ae_vector* d,
22403 : ae_state *_state)
22404 : {
22405 : ae_frame _frame_block;
22406 : ae_vector _x;
22407 : ae_vector _y;
22408 : ae_vector a1;
22409 : ae_vector a2;
22410 : ae_vector a3;
22411 : ae_vector b;
22412 : ae_vector dt;
22413 : ae_vector p;
22414 : ae_int_t i;
22415 : ae_int_t ylen;
22416 :
22417 0 : ae_frame_make(_state, &_frame_block);
22418 0 : memset(&_x, 0, sizeof(_x));
22419 0 : memset(&_y, 0, sizeof(_y));
22420 0 : memset(&a1, 0, sizeof(a1));
22421 0 : memset(&a2, 0, sizeof(a2));
22422 0 : memset(&a3, 0, sizeof(a3));
22423 0 : memset(&b, 0, sizeof(b));
22424 0 : memset(&dt, 0, sizeof(dt));
22425 0 : memset(&p, 0, sizeof(p));
22426 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
22427 0 : x = &_x;
22428 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
22429 0 : y = &_y;
22430 0 : ae_vector_clear(d);
22431 0 : ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
22432 0 : ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
22433 0 : ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
22434 0 : ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
22435 0 : ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
22436 0 : ae_vector_init(&p, 0, DT_INT, _state, ae_true);
22437 :
22438 :
22439 : /*
22440 : * check correctness of boundary conditions
22441 : */
22442 0 : ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DGridDiffCubic: incorrect BoundLType!", _state);
22443 0 : ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DGridDiffCubic: incorrect BoundRType!", _state);
22444 0 : ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DGridDiffCubic: incorrect BoundLType/BoundRType!", _state);
22445 0 : if( boundltype==1||boundltype==2 )
22446 : {
22447 0 : ae_assert(ae_isfinite(boundl, _state), "Spline1DGridDiffCubic: BoundL is infinite or NAN!", _state);
22448 : }
22449 0 : if( boundrtype==1||boundrtype==2 )
22450 : {
22451 0 : ae_assert(ae_isfinite(boundr, _state), "Spline1DGridDiffCubic: BoundR is infinite or NAN!", _state);
22452 : }
22453 :
22454 : /*
22455 : * check lengths of arguments
22456 : */
22457 0 : ae_assert(n>=2, "Spline1DGridDiffCubic: N<2!", _state);
22458 0 : ae_assert(x->cnt>=n, "Spline1DGridDiffCubic: Length(X)<N!", _state);
22459 0 : ae_assert(y->cnt>=n, "Spline1DGridDiffCubic: Length(Y)<N!", _state);
22460 :
22461 : /*
22462 : * check and sort points
22463 : */
22464 0 : ylen = n;
22465 0 : if( boundltype==-1 )
22466 : {
22467 0 : ylen = n-1;
22468 : }
22469 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DGridDiffCubic: X contains infinite or NAN values!", _state);
22470 0 : ae_assert(isfinitevector(y, ylen, _state), "Spline1DGridDiffCubic: Y contains infinite or NAN values!", _state);
22471 0 : spline1d_heapsortppoints(x, y, &p, n, _state);
22472 0 : ae_assert(aredistinct(x, n, _state), "Spline1DGridDiffCubic: at least two consequent points are too close!", _state);
22473 :
22474 : /*
22475 : * Now we've checked and preordered everything,
22476 : * so we can call internal function.
22477 : */
22478 0 : spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, d, &a1, &a2, &a3, &b, &dt, _state);
22479 :
22480 : /*
22481 : * Remember that HeapSortPPoints() call?
22482 : * Now we have to reorder them back.
22483 : */
22484 0 : if( dt.cnt<n )
22485 : {
22486 0 : ae_vector_set_length(&dt, n, _state);
22487 : }
22488 0 : for(i=0; i<=n-1; i++)
22489 : {
22490 0 : dt.ptr.p_double[p.ptr.p_int[i]] = d->ptr.p_double[i];
22491 : }
22492 0 : ae_v_move(&d->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1));
22493 0 : ae_frame_leave(_state);
22494 0 : }
22495 :
22496 :
22497 : /*************************************************************************
22498 : This function solves following problem: given table y[] of function values
22499 : at nodes x[], it calculates and returns tables of first and second
22500 : function derivatives d1[] and d2[] (calculated at the same nodes x[]).
22501 :
22502 : This function yields same result as Spline1DBuildCubic() call followed by
22503 : sequence of Spline1DDiff() calls, but it can be several times faster when
22504 : called for ordered X[] and X2[].
22505 :
22506 : INPUT PARAMETERS:
22507 : X - spline nodes
22508 : Y - function values
22509 :
22510 : OPTIONAL PARAMETERS:
22511 : N - points count:
22512 : * N>=2
22513 : * if given, only first N points are used
22514 : * if not given, automatically detected from X/Y sizes
22515 : (len(X) must be equal to len(Y))
22516 : BoundLType - boundary condition type for the left boundary
22517 : BoundL - left boundary condition (first or second derivative,
22518 : depending on the BoundLType)
22519 : BoundRType - boundary condition type for the right boundary
22520 : BoundR - right boundary condition (first or second derivative,
22521 : depending on the BoundRType)
22522 :
22523 : OUTPUT PARAMETERS:
22524 : D1 - S' values at X[]
22525 : D2 - S'' values at X[]
22526 :
22527 : ORDER OF POINTS
22528 :
22529 : Subroutine automatically sorts points, so caller may pass unsorted array.
22530 : Derivative values are correctly reordered on return, so D[I] is always
22531 : equal to S'(X[I]) independently of points order.
22532 :
22533 : SETTING BOUNDARY VALUES:
22534 :
22535 : The BoundLType/BoundRType parameters can have the following values:
22536 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
22537 : In this case:
22538 : * both BoundLType and BoundRType must be equal to -1.
22539 : * BoundL/BoundR are ignored
22540 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
22541 : * 0, which corresponds to the parabolically terminated spline
22542 : (BoundL and/or BoundR are ignored).
22543 : * 1, which corresponds to the first derivative boundary condition
22544 : * 2, which corresponds to the second derivative boundary condition
22545 : * by default, BoundType=0 is used
22546 :
22547 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
22548 :
22549 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
22550 : However, this subroutine doesn't require you to specify equal values for
22551 : the first and last points - it automatically forces them to be equal by
22552 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
22553 : Y[last_point]. However it is recommended to pass consistent values of Y[],
22554 : i.e. to make Y[first_point]=Y[last_point].
22555 :
22556 : -- ALGLIB PROJECT --
22557 : Copyright 03.09.2010 by Bochkanov Sergey
22558 : *************************************************************************/
22559 0 : void spline1dgriddiff2cubic(/* Real */ ae_vector* x,
22560 : /* Real */ ae_vector* y,
22561 : ae_int_t n,
22562 : ae_int_t boundltype,
22563 : double boundl,
22564 : ae_int_t boundrtype,
22565 : double boundr,
22566 : /* Real */ ae_vector* d1,
22567 : /* Real */ ae_vector* d2,
22568 : ae_state *_state)
22569 : {
22570 : ae_frame _frame_block;
22571 : ae_vector _x;
22572 : ae_vector _y;
22573 : ae_vector a1;
22574 : ae_vector a2;
22575 : ae_vector a3;
22576 : ae_vector b;
22577 : ae_vector dt;
22578 : ae_vector p;
22579 : ae_int_t i;
22580 : ae_int_t ylen;
22581 : double delta;
22582 : double delta2;
22583 : double delta3;
22584 : double s2;
22585 : double s3;
22586 :
22587 0 : ae_frame_make(_state, &_frame_block);
22588 0 : memset(&_x, 0, sizeof(_x));
22589 0 : memset(&_y, 0, sizeof(_y));
22590 0 : memset(&a1, 0, sizeof(a1));
22591 0 : memset(&a2, 0, sizeof(a2));
22592 0 : memset(&a3, 0, sizeof(a3));
22593 0 : memset(&b, 0, sizeof(b));
22594 0 : memset(&dt, 0, sizeof(dt));
22595 0 : memset(&p, 0, sizeof(p));
22596 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
22597 0 : x = &_x;
22598 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
22599 0 : y = &_y;
22600 0 : ae_vector_clear(d1);
22601 0 : ae_vector_clear(d2);
22602 0 : ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
22603 0 : ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
22604 0 : ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
22605 0 : ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
22606 0 : ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
22607 0 : ae_vector_init(&p, 0, DT_INT, _state, ae_true);
22608 :
22609 :
22610 : /*
22611 : * check correctness of boundary conditions
22612 : */
22613 0 : ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DGridDiff2Cubic: incorrect BoundLType!", _state);
22614 0 : ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DGridDiff2Cubic: incorrect BoundRType!", _state);
22615 0 : ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DGridDiff2Cubic: incorrect BoundLType/BoundRType!", _state);
22616 0 : if( boundltype==1||boundltype==2 )
22617 : {
22618 0 : ae_assert(ae_isfinite(boundl, _state), "Spline1DGridDiff2Cubic: BoundL is infinite or NAN!", _state);
22619 : }
22620 0 : if( boundrtype==1||boundrtype==2 )
22621 : {
22622 0 : ae_assert(ae_isfinite(boundr, _state), "Spline1DGridDiff2Cubic: BoundR is infinite or NAN!", _state);
22623 : }
22624 :
22625 : /*
22626 : * check lengths of arguments
22627 : */
22628 0 : ae_assert(n>=2, "Spline1DGridDiff2Cubic: N<2!", _state);
22629 0 : ae_assert(x->cnt>=n, "Spline1DGridDiff2Cubic: Length(X)<N!", _state);
22630 0 : ae_assert(y->cnt>=n, "Spline1DGridDiff2Cubic: Length(Y)<N!", _state);
22631 :
22632 : /*
22633 : * check and sort points
22634 : */
22635 0 : ylen = n;
22636 0 : if( boundltype==-1 )
22637 : {
22638 0 : ylen = n-1;
22639 : }
22640 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DGridDiff2Cubic: X contains infinite or NAN values!", _state);
22641 0 : ae_assert(isfinitevector(y, ylen, _state), "Spline1DGridDiff2Cubic: Y contains infinite or NAN values!", _state);
22642 0 : spline1d_heapsortppoints(x, y, &p, n, _state);
22643 0 : ae_assert(aredistinct(x, n, _state), "Spline1DGridDiff2Cubic: at least two consequent points are too close!", _state);
22644 :
22645 : /*
22646 : * Now we've checked and preordered everything,
22647 : * so we can call internal function.
22648 : *
22649 : * After this call we will calculate second derivatives
22650 : * (manually, by converting to the power basis)
22651 : */
22652 0 : spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, d1, &a1, &a2, &a3, &b, &dt, _state);
22653 0 : ae_vector_set_length(d2, n, _state);
22654 0 : delta = (double)(0);
22655 0 : s2 = (double)(0);
22656 0 : s3 = (double)(0);
22657 0 : for(i=0; i<=n-2; i++)
22658 : {
22659 :
22660 : /*
22661 : * We convert from Hermite basis to the power basis.
22662 : * Si is coefficient before x^i.
22663 : *
22664 : * Inside this cycle we need just S2,
22665 : * because we calculate S'' exactly at spline node,
22666 : * (only x^2 matters at x=0), but after iterations
22667 : * will be over, we will need other coefficients
22668 : * to calculate spline value at the last node.
22669 : */
22670 0 : delta = x->ptr.p_double[i+1]-x->ptr.p_double[i];
22671 0 : delta2 = ae_sqr(delta, _state);
22672 0 : delta3 = delta*delta2;
22673 0 : s2 = (3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])-2*d1->ptr.p_double[i]*delta-d1->ptr.p_double[i+1]*delta)/delta2;
22674 0 : s3 = (2*(y->ptr.p_double[i]-y->ptr.p_double[i+1])+d1->ptr.p_double[i]*delta+d1->ptr.p_double[i+1]*delta)/delta3;
22675 0 : d2->ptr.p_double[i] = 2*s2;
22676 : }
22677 0 : d2->ptr.p_double[n-1] = 2*s2+6*s3*delta;
22678 :
22679 : /*
22680 : * Remember that HeapSortPPoints() call?
22681 : * Now we have to reorder them back.
22682 : */
22683 0 : if( dt.cnt<n )
22684 : {
22685 0 : ae_vector_set_length(&dt, n, _state);
22686 : }
22687 0 : for(i=0; i<=n-1; i++)
22688 : {
22689 0 : dt.ptr.p_double[p.ptr.p_int[i]] = d1->ptr.p_double[i];
22690 : }
22691 0 : ae_v_move(&d1->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1));
22692 0 : for(i=0; i<=n-1; i++)
22693 : {
22694 0 : dt.ptr.p_double[p.ptr.p_int[i]] = d2->ptr.p_double[i];
22695 : }
22696 0 : ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1));
22697 0 : ae_frame_leave(_state);
22698 0 : }
22699 :
22700 :
22701 : /*************************************************************************
22702 : This function solves following problem: given table y[] of function values
22703 : at old nodes x[] and new nodes x2[], it calculates and returns table of
22704 : function values y2[] (calculated at x2[]).
22705 :
22706 : This function yields same result as Spline1DBuildCubic() call followed by
22707 : sequence of Spline1DDiff() calls, but it can be several times faster when
22708 : called for ordered X[] and X2[].
22709 :
22710 : INPUT PARAMETERS:
22711 : X - old spline nodes
22712 : Y - function values
22713 : X2 - new spline nodes
22714 :
22715 : OPTIONAL PARAMETERS:
22716 : N - points count:
22717 : * N>=2
22718 : * if given, only first N points from X/Y are used
22719 : * if not given, automatically detected from X/Y sizes
22720 : (len(X) must be equal to len(Y))
22721 : BoundLType - boundary condition type for the left boundary
22722 : BoundL - left boundary condition (first or second derivative,
22723 : depending on the BoundLType)
22724 : BoundRType - boundary condition type for the right boundary
22725 : BoundR - right boundary condition (first or second derivative,
22726 : depending on the BoundRType)
22727 : N2 - new points count:
22728 : * N2>=2
22729 : * if given, only first N2 points from X2 are used
22730 : * if not given, automatically detected from X2 size
22731 :
22732 : OUTPUT PARAMETERS:
22733 : F2 - function values at X2[]
22734 :
22735 : ORDER OF POINTS
22736 :
22737 : Subroutine automatically sorts points, so caller may pass unsorted array.
22738 : Function values are correctly reordered on return, so F2[I] is always
22739 : equal to S(X2[I]) independently of points order.
22740 :
22741 : SETTING BOUNDARY VALUES:
22742 :
22743 : The BoundLType/BoundRType parameters can have the following values:
22744 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
22745 : In this case:
22746 : * both BoundLType and BoundRType must be equal to -1.
22747 : * BoundL/BoundR are ignored
22748 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
22749 : * 0, which corresponds to the parabolically terminated spline
22750 : (BoundL and/or BoundR are ignored).
22751 : * 1, which corresponds to the first derivative boundary condition
22752 : * 2, which corresponds to the second derivative boundary condition
22753 : * by default, BoundType=0 is used
22754 :
22755 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
22756 :
22757 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
22758 : However, this subroutine doesn't require you to specify equal values for
22759 : the first and last points - it automatically forces them to be equal by
22760 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
22761 : Y[last_point]. However it is recommended to pass consistent values of Y[],
22762 : i.e. to make Y[first_point]=Y[last_point].
22763 :
22764 : -- ALGLIB PROJECT --
22765 : Copyright 03.09.2010 by Bochkanov Sergey
22766 : *************************************************************************/
22767 0 : void spline1dconvcubic(/* Real */ ae_vector* x,
22768 : /* Real */ ae_vector* y,
22769 : ae_int_t n,
22770 : ae_int_t boundltype,
22771 : double boundl,
22772 : ae_int_t boundrtype,
22773 : double boundr,
22774 : /* Real */ ae_vector* x2,
22775 : ae_int_t n2,
22776 : /* Real */ ae_vector* y2,
22777 : ae_state *_state)
22778 : {
22779 : ae_frame _frame_block;
22780 : ae_vector _x;
22781 : ae_vector _y;
22782 : ae_vector _x2;
22783 : ae_vector a1;
22784 : ae_vector a2;
22785 : ae_vector a3;
22786 : ae_vector b;
22787 : ae_vector d;
22788 : ae_vector dt;
22789 : ae_vector d1;
22790 : ae_vector d2;
22791 : ae_vector p;
22792 : ae_vector p2;
22793 : ae_int_t i;
22794 : ae_int_t ylen;
22795 : double t;
22796 : double t2;
22797 :
22798 0 : ae_frame_make(_state, &_frame_block);
22799 0 : memset(&_x, 0, sizeof(_x));
22800 0 : memset(&_y, 0, sizeof(_y));
22801 0 : memset(&_x2, 0, sizeof(_x2));
22802 0 : memset(&a1, 0, sizeof(a1));
22803 0 : memset(&a2, 0, sizeof(a2));
22804 0 : memset(&a3, 0, sizeof(a3));
22805 0 : memset(&b, 0, sizeof(b));
22806 0 : memset(&d, 0, sizeof(d));
22807 0 : memset(&dt, 0, sizeof(dt));
22808 0 : memset(&d1, 0, sizeof(d1));
22809 0 : memset(&d2, 0, sizeof(d2));
22810 0 : memset(&p, 0, sizeof(p));
22811 0 : memset(&p2, 0, sizeof(p2));
22812 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
22813 0 : x = &_x;
22814 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
22815 0 : y = &_y;
22816 0 : ae_vector_init_copy(&_x2, x2, _state, ae_true);
22817 0 : x2 = &_x2;
22818 0 : ae_vector_clear(y2);
22819 0 : ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
22820 0 : ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
22821 0 : ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
22822 0 : ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
22823 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
22824 0 : ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
22825 0 : ae_vector_init(&d1, 0, DT_REAL, _state, ae_true);
22826 0 : ae_vector_init(&d2, 0, DT_REAL, _state, ae_true);
22827 0 : ae_vector_init(&p, 0, DT_INT, _state, ae_true);
22828 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
22829 :
22830 :
22831 : /*
22832 : * check correctness of boundary conditions
22833 : */
22834 0 : ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvCubic: incorrect BoundLType!", _state);
22835 0 : ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvCubic: incorrect BoundRType!", _state);
22836 0 : ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvCubic: incorrect BoundLType/BoundRType!", _state);
22837 0 : if( boundltype==1||boundltype==2 )
22838 : {
22839 0 : ae_assert(ae_isfinite(boundl, _state), "Spline1DConvCubic: BoundL is infinite or NAN!", _state);
22840 : }
22841 0 : if( boundrtype==1||boundrtype==2 )
22842 : {
22843 0 : ae_assert(ae_isfinite(boundr, _state), "Spline1DConvCubic: BoundR is infinite or NAN!", _state);
22844 : }
22845 :
22846 : /*
22847 : * check lengths of arguments
22848 : */
22849 0 : ae_assert(n>=2, "Spline1DConvCubic: N<2!", _state);
22850 0 : ae_assert(x->cnt>=n, "Spline1DConvCubic: Length(X)<N!", _state);
22851 0 : ae_assert(y->cnt>=n, "Spline1DConvCubic: Length(Y)<N!", _state);
22852 0 : ae_assert(n2>=2, "Spline1DConvCubic: N2<2!", _state);
22853 0 : ae_assert(x2->cnt>=n2, "Spline1DConvCubic: Length(X2)<N2!", _state);
22854 :
22855 : /*
22856 : * check and sort X/Y
22857 : */
22858 0 : ylen = n;
22859 0 : if( boundltype==-1 )
22860 : {
22861 0 : ylen = n-1;
22862 : }
22863 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DConvCubic: X contains infinite or NAN values!", _state);
22864 0 : ae_assert(isfinitevector(y, ylen, _state), "Spline1DConvCubic: Y contains infinite or NAN values!", _state);
22865 0 : ae_assert(isfinitevector(x2, n2, _state), "Spline1DConvCubic: X2 contains infinite or NAN values!", _state);
22866 0 : spline1d_heapsortppoints(x, y, &p, n, _state);
22867 0 : ae_assert(aredistinct(x, n, _state), "Spline1DConvCubic: at least two consequent points are too close!", _state);
22868 :
22869 : /*
22870 : * set up DT (we will need it below)
22871 : */
22872 0 : ae_vector_set_length(&dt, ae_maxint(n, n2, _state), _state);
22873 :
22874 : /*
22875 : * sort X2:
22876 : * * use fake array DT because HeapSortPPoints() needs both integer AND real arrays
22877 : * * if we have periodic problem, wrap points
22878 : * * sort them, store permutation at P2
22879 : */
22880 0 : if( boundrtype==-1&&boundltype==-1 )
22881 : {
22882 0 : for(i=0; i<=n2-1; i++)
22883 : {
22884 0 : t = x2->ptr.p_double[i];
22885 0 : apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state);
22886 0 : x2->ptr.p_double[i] = t;
22887 : }
22888 : }
22889 0 : spline1d_heapsortppoints(x2, &dt, &p2, n2, _state);
22890 :
22891 : /*
22892 : * Now we've checked and preordered everything, so we:
22893 : * * call internal GridDiff() function to get Hermite form of spline
22894 : * * convert using internal Conv() function
22895 : * * convert Y2 back to original order
22896 : */
22897 0 : spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
22898 0 : spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, &d1, ae_false, &d2, ae_false, _state);
22899 0 : ae_assert(dt.cnt>=n2, "Spline1DConvCubic: internal error!", _state);
22900 0 : for(i=0; i<=n2-1; i++)
22901 : {
22902 0 : dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i];
22903 : }
22904 0 : ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
22905 0 : ae_frame_leave(_state);
22906 0 : }
22907 :
22908 :
22909 : /*************************************************************************
22910 : This function solves following problem: given table y[] of function values
22911 : at old nodes x[] and new nodes x2[], it calculates and returns table of
22912 : function values y2[] and derivatives d2[] (calculated at x2[]).
22913 :
22914 : This function yields same result as Spline1DBuildCubic() call followed by
22915 : sequence of Spline1DDiff() calls, but it can be several times faster when
22916 : called for ordered X[] and X2[].
22917 :
22918 : INPUT PARAMETERS:
22919 : X - old spline nodes
22920 : Y - function values
22921 : X2 - new spline nodes
22922 :
22923 : OPTIONAL PARAMETERS:
22924 : N - points count:
22925 : * N>=2
22926 : * if given, only first N points from X/Y are used
22927 : * if not given, automatically detected from X/Y sizes
22928 : (len(X) must be equal to len(Y))
22929 : BoundLType - boundary condition type for the left boundary
22930 : BoundL - left boundary condition (first or second derivative,
22931 : depending on the BoundLType)
22932 : BoundRType - boundary condition type for the right boundary
22933 : BoundR - right boundary condition (first or second derivative,
22934 : depending on the BoundRType)
22935 : N2 - new points count:
22936 : * N2>=2
22937 : * if given, only first N2 points from X2 are used
22938 : * if not given, automatically detected from X2 size
22939 :
22940 : OUTPUT PARAMETERS:
22941 : F2 - function values at X2[]
22942 : D2 - first derivatives at X2[]
22943 :
22944 : ORDER OF POINTS
22945 :
22946 : Subroutine automatically sorts points, so caller may pass unsorted array.
22947 : Function values are correctly reordered on return, so F2[I] is always
22948 : equal to S(X2[I]) independently of points order.
22949 :
22950 : SETTING BOUNDARY VALUES:
22951 :
22952 : The BoundLType/BoundRType parameters can have the following values:
22953 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
22954 : In this case:
22955 : * both BoundLType and BoundRType must be equal to -1.
22956 : * BoundL/BoundR are ignored
22957 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
22958 : * 0, which corresponds to the parabolically terminated spline
22959 : (BoundL and/or BoundR are ignored).
22960 : * 1, which corresponds to the first derivative boundary condition
22961 : * 2, which corresponds to the second derivative boundary condition
22962 : * by default, BoundType=0 is used
22963 :
22964 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
22965 :
22966 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
22967 : However, this subroutine doesn't require you to specify equal values for
22968 : the first and last points - it automatically forces them to be equal by
22969 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
22970 : Y[last_point]. However it is recommended to pass consistent values of Y[],
22971 : i.e. to make Y[first_point]=Y[last_point].
22972 :
22973 : -- ALGLIB PROJECT --
22974 : Copyright 03.09.2010 by Bochkanov Sergey
22975 : *************************************************************************/
22976 0 : void spline1dconvdiffcubic(/* Real */ ae_vector* x,
22977 : /* Real */ ae_vector* y,
22978 : ae_int_t n,
22979 : ae_int_t boundltype,
22980 : double boundl,
22981 : ae_int_t boundrtype,
22982 : double boundr,
22983 : /* Real */ ae_vector* x2,
22984 : ae_int_t n2,
22985 : /* Real */ ae_vector* y2,
22986 : /* Real */ ae_vector* d2,
22987 : ae_state *_state)
22988 : {
22989 : ae_frame _frame_block;
22990 : ae_vector _x;
22991 : ae_vector _y;
22992 : ae_vector _x2;
22993 : ae_vector a1;
22994 : ae_vector a2;
22995 : ae_vector a3;
22996 : ae_vector b;
22997 : ae_vector d;
22998 : ae_vector dt;
22999 : ae_vector rt1;
23000 : ae_vector p;
23001 : ae_vector p2;
23002 : ae_int_t i;
23003 : ae_int_t ylen;
23004 : double t;
23005 : double t2;
23006 :
23007 0 : ae_frame_make(_state, &_frame_block);
23008 0 : memset(&_x, 0, sizeof(_x));
23009 0 : memset(&_y, 0, sizeof(_y));
23010 0 : memset(&_x2, 0, sizeof(_x2));
23011 0 : memset(&a1, 0, sizeof(a1));
23012 0 : memset(&a2, 0, sizeof(a2));
23013 0 : memset(&a3, 0, sizeof(a3));
23014 0 : memset(&b, 0, sizeof(b));
23015 0 : memset(&d, 0, sizeof(d));
23016 0 : memset(&dt, 0, sizeof(dt));
23017 0 : memset(&rt1, 0, sizeof(rt1));
23018 0 : memset(&p, 0, sizeof(p));
23019 0 : memset(&p2, 0, sizeof(p2));
23020 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
23021 0 : x = &_x;
23022 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
23023 0 : y = &_y;
23024 0 : ae_vector_init_copy(&_x2, x2, _state, ae_true);
23025 0 : x2 = &_x2;
23026 0 : ae_vector_clear(y2);
23027 0 : ae_vector_clear(d2);
23028 0 : ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
23029 0 : ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
23030 0 : ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
23031 0 : ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
23032 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
23033 0 : ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
23034 0 : ae_vector_init(&rt1, 0, DT_REAL, _state, ae_true);
23035 0 : ae_vector_init(&p, 0, DT_INT, _state, ae_true);
23036 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
23037 :
23038 :
23039 : /*
23040 : * check correctness of boundary conditions
23041 : */
23042 0 : ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvDiffCubic: incorrect BoundLType!", _state);
23043 0 : ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvDiffCubic: incorrect BoundRType!", _state);
23044 0 : ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvDiffCubic: incorrect BoundLType/BoundRType!", _state);
23045 0 : if( boundltype==1||boundltype==2 )
23046 : {
23047 0 : ae_assert(ae_isfinite(boundl, _state), "Spline1DConvDiffCubic: BoundL is infinite or NAN!", _state);
23048 : }
23049 0 : if( boundrtype==1||boundrtype==2 )
23050 : {
23051 0 : ae_assert(ae_isfinite(boundr, _state), "Spline1DConvDiffCubic: BoundR is infinite or NAN!", _state);
23052 : }
23053 :
23054 : /*
23055 : * check lengths of arguments
23056 : */
23057 0 : ae_assert(n>=2, "Spline1DConvDiffCubic: N<2!", _state);
23058 0 : ae_assert(x->cnt>=n, "Spline1DConvDiffCubic: Length(X)<N!", _state);
23059 0 : ae_assert(y->cnt>=n, "Spline1DConvDiffCubic: Length(Y)<N!", _state);
23060 0 : ae_assert(n2>=2, "Spline1DConvDiffCubic: N2<2!", _state);
23061 0 : ae_assert(x2->cnt>=n2, "Spline1DConvDiffCubic: Length(X2)<N2!", _state);
23062 :
23063 : /*
23064 : * check and sort X/Y
23065 : */
23066 0 : ylen = n;
23067 0 : if( boundltype==-1 )
23068 : {
23069 0 : ylen = n-1;
23070 : }
23071 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DConvDiffCubic: X contains infinite or NAN values!", _state);
23072 0 : ae_assert(isfinitevector(y, ylen, _state), "Spline1DConvDiffCubic: Y contains infinite or NAN values!", _state);
23073 0 : ae_assert(isfinitevector(x2, n2, _state), "Spline1DConvDiffCubic: X2 contains infinite or NAN values!", _state);
23074 0 : spline1d_heapsortppoints(x, y, &p, n, _state);
23075 0 : ae_assert(aredistinct(x, n, _state), "Spline1DConvDiffCubic: at least two consequent points are too close!", _state);
23076 :
23077 : /*
23078 : * set up DT (we will need it below)
23079 : */
23080 0 : ae_vector_set_length(&dt, ae_maxint(n, n2, _state), _state);
23081 :
23082 : /*
23083 : * sort X2:
23084 : * * use fake array DT because HeapSortPPoints() needs both integer AND real arrays
23085 : * * if we have periodic problem, wrap points
23086 : * * sort them, store permutation at P2
23087 : */
23088 0 : if( boundrtype==-1&&boundltype==-1 )
23089 : {
23090 0 : for(i=0; i<=n2-1; i++)
23091 : {
23092 0 : t = x2->ptr.p_double[i];
23093 0 : apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state);
23094 0 : x2->ptr.p_double[i] = t;
23095 : }
23096 : }
23097 0 : spline1d_heapsortppoints(x2, &dt, &p2, n2, _state);
23098 :
23099 : /*
23100 : * Now we've checked and preordered everything, so we:
23101 : * * call internal GridDiff() function to get Hermite form of spline
23102 : * * convert using internal Conv() function
23103 : * * convert Y2 back to original order
23104 : */
23105 0 : spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
23106 0 : spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, d2, ae_true, &rt1, ae_false, _state);
23107 0 : ae_assert(dt.cnt>=n2, "Spline1DConvDiffCubic: internal error!", _state);
23108 0 : for(i=0; i<=n2-1; i++)
23109 : {
23110 0 : dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i];
23111 : }
23112 0 : ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
23113 0 : for(i=0; i<=n2-1; i++)
23114 : {
23115 0 : dt.ptr.p_double[p2.ptr.p_int[i]] = d2->ptr.p_double[i];
23116 : }
23117 0 : ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
23118 0 : ae_frame_leave(_state);
23119 0 : }
23120 :
23121 :
23122 : /*************************************************************************
23123 : This function solves following problem: given table y[] of function values
23124 : at old nodes x[] and new nodes x2[], it calculates and returns table of
23125 : function values y2[], first and second derivatives d2[] and dd2[]
23126 : (calculated at x2[]).
23127 :
23128 : This function yields same result as Spline1DBuildCubic() call followed by
23129 : sequence of Spline1DDiff() calls, but it can be several times faster when
23130 : called for ordered X[] and X2[].
23131 :
23132 : INPUT PARAMETERS:
23133 : X - old spline nodes
23134 : Y - function values
23135 : X2 - new spline nodes
23136 :
23137 : OPTIONAL PARAMETERS:
23138 : N - points count:
23139 : * N>=2
23140 : * if given, only first N points from X/Y are used
23141 : * if not given, automatically detected from X/Y sizes
23142 : (len(X) must be equal to len(Y))
23143 : BoundLType - boundary condition type for the left boundary
23144 : BoundL - left boundary condition (first or second derivative,
23145 : depending on the BoundLType)
23146 : BoundRType - boundary condition type for the right boundary
23147 : BoundR - right boundary condition (first or second derivative,
23148 : depending on the BoundRType)
23149 : N2 - new points count:
23150 : * N2>=2
23151 : * if given, only first N2 points from X2 are used
23152 : * if not given, automatically detected from X2 size
23153 :
23154 : OUTPUT PARAMETERS:
23155 : F2 - function values at X2[]
23156 : D2 - first derivatives at X2[]
23157 : DD2 - second derivatives at X2[]
23158 :
23159 : ORDER OF POINTS
23160 :
23161 : Subroutine automatically sorts points, so caller may pass unsorted array.
23162 : Function values are correctly reordered on return, so F2[I] is always
23163 : equal to S(X2[I]) independently of points order.
23164 :
23165 : SETTING BOUNDARY VALUES:
23166 :
23167 : The BoundLType/BoundRType parameters can have the following values:
23168 : * -1, which corresonds to the periodic (cyclic) boundary conditions.
23169 : In this case:
23170 : * both BoundLType and BoundRType must be equal to -1.
23171 : * BoundL/BoundR are ignored
23172 : * Y[last] is ignored (it is assumed to be equal to Y[first]).
23173 : * 0, which corresponds to the parabolically terminated spline
23174 : (BoundL and/or BoundR are ignored).
23175 : * 1, which corresponds to the first derivative boundary condition
23176 : * 2, which corresponds to the second derivative boundary condition
23177 : * by default, BoundType=0 is used
23178 :
23179 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
23180 :
23181 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
23182 : However, this subroutine doesn't require you to specify equal values for
23183 : the first and last points - it automatically forces them to be equal by
23184 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
23185 : Y[last_point]. However it is recommended to pass consistent values of Y[],
23186 : i.e. to make Y[first_point]=Y[last_point].
23187 :
23188 : -- ALGLIB PROJECT --
23189 : Copyright 03.09.2010 by Bochkanov Sergey
23190 : *************************************************************************/
23191 0 : void spline1dconvdiff2cubic(/* Real */ ae_vector* x,
23192 : /* Real */ ae_vector* y,
23193 : ae_int_t n,
23194 : ae_int_t boundltype,
23195 : double boundl,
23196 : ae_int_t boundrtype,
23197 : double boundr,
23198 : /* Real */ ae_vector* x2,
23199 : ae_int_t n2,
23200 : /* Real */ ae_vector* y2,
23201 : /* Real */ ae_vector* d2,
23202 : /* Real */ ae_vector* dd2,
23203 : ae_state *_state)
23204 : {
23205 : ae_frame _frame_block;
23206 : ae_vector _x;
23207 : ae_vector _y;
23208 : ae_vector _x2;
23209 : ae_vector a1;
23210 : ae_vector a2;
23211 : ae_vector a3;
23212 : ae_vector b;
23213 : ae_vector d;
23214 : ae_vector dt;
23215 : ae_vector p;
23216 : ae_vector p2;
23217 : ae_int_t i;
23218 : ae_int_t ylen;
23219 : double t;
23220 : double t2;
23221 :
23222 0 : ae_frame_make(_state, &_frame_block);
23223 0 : memset(&_x, 0, sizeof(_x));
23224 0 : memset(&_y, 0, sizeof(_y));
23225 0 : memset(&_x2, 0, sizeof(_x2));
23226 0 : memset(&a1, 0, sizeof(a1));
23227 0 : memset(&a2, 0, sizeof(a2));
23228 0 : memset(&a3, 0, sizeof(a3));
23229 0 : memset(&b, 0, sizeof(b));
23230 0 : memset(&d, 0, sizeof(d));
23231 0 : memset(&dt, 0, sizeof(dt));
23232 0 : memset(&p, 0, sizeof(p));
23233 0 : memset(&p2, 0, sizeof(p2));
23234 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
23235 0 : x = &_x;
23236 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
23237 0 : y = &_y;
23238 0 : ae_vector_init_copy(&_x2, x2, _state, ae_true);
23239 0 : x2 = &_x2;
23240 0 : ae_vector_clear(y2);
23241 0 : ae_vector_clear(d2);
23242 0 : ae_vector_clear(dd2);
23243 0 : ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
23244 0 : ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
23245 0 : ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
23246 0 : ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
23247 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
23248 0 : ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
23249 0 : ae_vector_init(&p, 0, DT_INT, _state, ae_true);
23250 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
23251 :
23252 :
23253 : /*
23254 : * check correctness of boundary conditions
23255 : */
23256 0 : ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvDiff2Cubic: incorrect BoundLType!", _state);
23257 0 : ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvDiff2Cubic: incorrect BoundRType!", _state);
23258 0 : ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvDiff2Cubic: incorrect BoundLType/BoundRType!", _state);
23259 0 : if( boundltype==1||boundltype==2 )
23260 : {
23261 0 : ae_assert(ae_isfinite(boundl, _state), "Spline1DConvDiff2Cubic: BoundL is infinite or NAN!", _state);
23262 : }
23263 0 : if( boundrtype==1||boundrtype==2 )
23264 : {
23265 0 : ae_assert(ae_isfinite(boundr, _state), "Spline1DConvDiff2Cubic: BoundR is infinite or NAN!", _state);
23266 : }
23267 :
23268 : /*
23269 : * check lengths of arguments
23270 : */
23271 0 : ae_assert(n>=2, "Spline1DConvDiff2Cubic: N<2!", _state);
23272 0 : ae_assert(x->cnt>=n, "Spline1DConvDiff2Cubic: Length(X)<N!", _state);
23273 0 : ae_assert(y->cnt>=n, "Spline1DConvDiff2Cubic: Length(Y)<N!", _state);
23274 0 : ae_assert(n2>=2, "Spline1DConvDiff2Cubic: N2<2!", _state);
23275 0 : ae_assert(x2->cnt>=n2, "Spline1DConvDiff2Cubic: Length(X2)<N2!", _state);
23276 :
23277 : /*
23278 : * check and sort X/Y
23279 : */
23280 0 : ylen = n;
23281 0 : if( boundltype==-1 )
23282 : {
23283 0 : ylen = n-1;
23284 : }
23285 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DConvDiff2Cubic: X contains infinite or NAN values!", _state);
23286 0 : ae_assert(isfinitevector(y, ylen, _state), "Spline1DConvDiff2Cubic: Y contains infinite or NAN values!", _state);
23287 0 : ae_assert(isfinitevector(x2, n2, _state), "Spline1DConvDiff2Cubic: X2 contains infinite or NAN values!", _state);
23288 0 : spline1d_heapsortppoints(x, y, &p, n, _state);
23289 0 : ae_assert(aredistinct(x, n, _state), "Spline1DConvDiff2Cubic: at least two consequent points are too close!", _state);
23290 :
23291 : /*
23292 : * set up DT (we will need it below)
23293 : */
23294 0 : ae_vector_set_length(&dt, ae_maxint(n, n2, _state), _state);
23295 :
23296 : /*
23297 : * sort X2:
23298 : * * use fake array DT because HeapSortPPoints() needs both integer AND real arrays
23299 : * * if we have periodic problem, wrap points
23300 : * * sort them, store permutation at P2
23301 : */
23302 0 : if( boundrtype==-1&&boundltype==-1 )
23303 : {
23304 0 : for(i=0; i<=n2-1; i++)
23305 : {
23306 0 : t = x2->ptr.p_double[i];
23307 0 : apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state);
23308 0 : x2->ptr.p_double[i] = t;
23309 : }
23310 : }
23311 0 : spline1d_heapsortppoints(x2, &dt, &p2, n2, _state);
23312 :
23313 : /*
23314 : * Now we've checked and preordered everything, so we:
23315 : * * call internal GridDiff() function to get Hermite form of spline
23316 : * * convert using internal Conv() function
23317 : * * convert Y2 back to original order
23318 : */
23319 0 : spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
23320 0 : spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, d2, ae_true, dd2, ae_true, _state);
23321 0 : ae_assert(dt.cnt>=n2, "Spline1DConvDiff2Cubic: internal error!", _state);
23322 0 : for(i=0; i<=n2-1; i++)
23323 : {
23324 0 : dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i];
23325 : }
23326 0 : ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
23327 0 : for(i=0; i<=n2-1; i++)
23328 : {
23329 0 : dt.ptr.p_double[p2.ptr.p_int[i]] = d2->ptr.p_double[i];
23330 : }
23331 0 : ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
23332 0 : for(i=0; i<=n2-1; i++)
23333 : {
23334 0 : dt.ptr.p_double[p2.ptr.p_int[i]] = dd2->ptr.p_double[i];
23335 : }
23336 0 : ae_v_move(&dd2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
23337 0 : ae_frame_leave(_state);
23338 0 : }
23339 :
23340 :
23341 : /*************************************************************************
23342 : This subroutine builds Catmull-Rom spline interpolant.
23343 :
23344 : INPUT PARAMETERS:
23345 : X - spline nodes, array[0..N-1].
23346 : Y - function values, array[0..N-1].
23347 :
23348 : OPTIONAL PARAMETERS:
23349 : N - points count:
23350 : * N>=2
23351 : * if given, only first N points are used to build spline
23352 : * if not given, automatically detected from X/Y sizes
23353 : (len(X) must be equal to len(Y))
23354 : BoundType - boundary condition type:
23355 : * -1 for periodic boundary condition
23356 : * 0 for parabolically terminated spline (default)
23357 : Tension - tension parameter:
23358 : * tension=0 corresponds to classic Catmull-Rom spline (default)
23359 : * 0<tension<1 corresponds to more general form - cardinal spline
23360 :
23361 : OUTPUT PARAMETERS:
23362 : C - spline interpolant
23363 :
23364 :
23365 : ORDER OF POINTS
23366 :
23367 : Subroutine automatically sorts points, so caller may pass unsorted array.
23368 :
23369 : PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
23370 :
23371 : Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
23372 : However, this subroutine doesn't require you to specify equal values for
23373 : the first and last points - it automatically forces them to be equal by
23374 : copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
23375 : Y[last_point]. However it is recommended to pass consistent values of Y[],
23376 : i.e. to make Y[first_point]=Y[last_point].
23377 :
23378 : -- ALGLIB PROJECT --
23379 : Copyright 23.06.2007 by Bochkanov Sergey
23380 : *************************************************************************/
23381 0 : void spline1dbuildcatmullrom(/* Real */ ae_vector* x,
23382 : /* Real */ ae_vector* y,
23383 : ae_int_t n,
23384 : ae_int_t boundtype,
23385 : double tension,
23386 : spline1dinterpolant* c,
23387 : ae_state *_state)
23388 : {
23389 : ae_frame _frame_block;
23390 : ae_vector _x;
23391 : ae_vector _y;
23392 : ae_vector d;
23393 : ae_int_t i;
23394 :
23395 0 : ae_frame_make(_state, &_frame_block);
23396 0 : memset(&_x, 0, sizeof(_x));
23397 0 : memset(&_y, 0, sizeof(_y));
23398 0 : memset(&d, 0, sizeof(d));
23399 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
23400 0 : x = &_x;
23401 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
23402 0 : y = &_y;
23403 0 : _spline1dinterpolant_clear(c);
23404 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
23405 :
23406 0 : ae_assert(n>=2, "Spline1DBuildCatmullRom: N<2!", _state);
23407 0 : ae_assert(boundtype==-1||boundtype==0, "Spline1DBuildCatmullRom: incorrect BoundType!", _state);
23408 0 : ae_assert(ae_fp_greater_eq(tension,(double)(0)), "Spline1DBuildCatmullRom: Tension<0!", _state);
23409 0 : ae_assert(ae_fp_less_eq(tension,(double)(1)), "Spline1DBuildCatmullRom: Tension>1!", _state);
23410 0 : ae_assert(x->cnt>=n, "Spline1DBuildCatmullRom: Length(X)<N!", _state);
23411 0 : ae_assert(y->cnt>=n, "Spline1DBuildCatmullRom: Length(Y)<N!", _state);
23412 :
23413 : /*
23414 : * check and sort points
23415 : */
23416 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DBuildCatmullRom: X contains infinite or NAN values!", _state);
23417 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DBuildCatmullRom: Y contains infinite or NAN values!", _state);
23418 0 : spline1d_heapsortpoints(x, y, n, _state);
23419 0 : ae_assert(aredistinct(x, n, _state), "Spline1DBuildCatmullRom: at least two consequent points are too close!", _state);
23420 :
23421 : /*
23422 : * Special cases:
23423 : * * N=2, parabolic terminated boundary condition on both ends
23424 : * * N=2, periodic boundary condition
23425 : */
23426 0 : if( n==2&&boundtype==0 )
23427 : {
23428 :
23429 : /*
23430 : * Just linear spline
23431 : */
23432 0 : spline1dbuildlinear(x, y, n, c, _state);
23433 0 : ae_frame_leave(_state);
23434 0 : return;
23435 : }
23436 0 : if( n==2&&boundtype==-1 )
23437 : {
23438 :
23439 : /*
23440 : * Same as cubic spline with periodic conditions
23441 : */
23442 0 : spline1dbuildcubic(x, y, n, -1, 0.0, -1, 0.0, c, _state);
23443 0 : ae_frame_leave(_state);
23444 0 : return;
23445 : }
23446 :
23447 : /*
23448 : * Periodic or non-periodic boundary conditions
23449 : */
23450 0 : if( boundtype==-1 )
23451 : {
23452 :
23453 : /*
23454 : * Periodic boundary conditions
23455 : */
23456 0 : y->ptr.p_double[n-1] = y->ptr.p_double[0];
23457 0 : ae_vector_set_length(&d, n, _state);
23458 0 : d.ptr.p_double[0] = (y->ptr.p_double[1]-y->ptr.p_double[n-2])/(2*(x->ptr.p_double[1]-x->ptr.p_double[0]+x->ptr.p_double[n-1]-x->ptr.p_double[n-2]));
23459 0 : for(i=1; i<=n-2; i++)
23460 : {
23461 0 : d.ptr.p_double[i] = (1-tension)*(y->ptr.p_double[i+1]-y->ptr.p_double[i-1])/(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]);
23462 : }
23463 0 : d.ptr.p_double[n-1] = d.ptr.p_double[0];
23464 :
23465 : /*
23466 : * Now problem is reduced to the cubic Hermite spline
23467 : */
23468 0 : spline1dbuildhermite(x, y, &d, n, c, _state);
23469 0 : c->periodic = ae_true;
23470 : }
23471 : else
23472 : {
23473 :
23474 : /*
23475 : * Non-periodic boundary conditions
23476 : */
23477 0 : ae_vector_set_length(&d, n, _state);
23478 0 : for(i=1; i<=n-2; i++)
23479 : {
23480 0 : d.ptr.p_double[i] = (1-tension)*(y->ptr.p_double[i+1]-y->ptr.p_double[i-1])/(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]);
23481 : }
23482 0 : d.ptr.p_double[0] = 2*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0])-d.ptr.p_double[1];
23483 0 : d.ptr.p_double[n-1] = 2*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2])-d.ptr.p_double[n-2];
23484 :
23485 : /*
23486 : * Now problem is reduced to the cubic Hermite spline
23487 : */
23488 0 : spline1dbuildhermite(x, y, &d, n, c, _state);
23489 : }
23490 0 : ae_frame_leave(_state);
23491 : }
23492 :
23493 :
23494 : /*************************************************************************
23495 : This subroutine builds Hermite spline interpolant.
23496 :
23497 : INPUT PARAMETERS:
23498 : X - spline nodes, array[0..N-1]
23499 : Y - function values, array[0..N-1]
23500 : D - derivatives, array[0..N-1]
23501 : N - points count (optional):
23502 : * N>=2
23503 : * if given, only first N points are used to build spline
23504 : * if not given, automatically detected from X/Y sizes
23505 : (len(X) must be equal to len(Y))
23506 :
23507 : OUTPUT PARAMETERS:
23508 : C - spline interpolant.
23509 :
23510 :
23511 : ORDER OF POINTS
23512 :
23513 : Subroutine automatically sorts points, so caller may pass unsorted array.
23514 :
23515 : -- ALGLIB PROJECT --
23516 : Copyright 23.06.2007 by Bochkanov Sergey
23517 : *************************************************************************/
23518 0 : void spline1dbuildhermite(/* Real */ ae_vector* x,
23519 : /* Real */ ae_vector* y,
23520 : /* Real */ ae_vector* d,
23521 : ae_int_t n,
23522 : spline1dinterpolant* c,
23523 : ae_state *_state)
23524 : {
23525 : ae_frame _frame_block;
23526 : ae_vector _x;
23527 : ae_vector _y;
23528 : ae_vector _d;
23529 : ae_int_t i;
23530 : double delta;
23531 : double delta2;
23532 : double delta3;
23533 :
23534 0 : ae_frame_make(_state, &_frame_block);
23535 0 : memset(&_x, 0, sizeof(_x));
23536 0 : memset(&_y, 0, sizeof(_y));
23537 0 : memset(&_d, 0, sizeof(_d));
23538 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
23539 0 : x = &_x;
23540 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
23541 0 : y = &_y;
23542 0 : ae_vector_init_copy(&_d, d, _state, ae_true);
23543 0 : d = &_d;
23544 0 : _spline1dinterpolant_clear(c);
23545 :
23546 0 : ae_assert(n>=2, "Spline1DBuildHermite: N<2!", _state);
23547 0 : ae_assert(x->cnt>=n, "Spline1DBuildHermite: Length(X)<N!", _state);
23548 0 : ae_assert(y->cnt>=n, "Spline1DBuildHermite: Length(Y)<N!", _state);
23549 0 : ae_assert(d->cnt>=n, "Spline1DBuildHermite: Length(D)<N!", _state);
23550 :
23551 : /*
23552 : * check and sort points
23553 : */
23554 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DBuildHermite: X contains infinite or NAN values!", _state);
23555 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DBuildHermite: Y contains infinite or NAN values!", _state);
23556 0 : ae_assert(isfinitevector(d, n, _state), "Spline1DBuildHermite: D contains infinite or NAN values!", _state);
23557 0 : heapsortdpoints(x, y, d, n, _state);
23558 0 : ae_assert(aredistinct(x, n, _state), "Spline1DBuildHermite: at least two consequent points are too close!", _state);
23559 :
23560 : /*
23561 : * Build
23562 : */
23563 0 : ae_vector_set_length(&c->x, n, _state);
23564 0 : ae_vector_set_length(&c->c, 4*(n-1)+2, _state);
23565 0 : c->periodic = ae_false;
23566 0 : c->k = 3;
23567 0 : c->n = n;
23568 0 : c->continuity = 1;
23569 0 : for(i=0; i<=n-1; i++)
23570 : {
23571 0 : c->x.ptr.p_double[i] = x->ptr.p_double[i];
23572 : }
23573 0 : for(i=0; i<=n-2; i++)
23574 : {
23575 0 : delta = x->ptr.p_double[i+1]-x->ptr.p_double[i];
23576 0 : delta2 = ae_sqr(delta, _state);
23577 0 : delta3 = delta*delta2;
23578 0 : c->c.ptr.p_double[4*i+0] = y->ptr.p_double[i];
23579 0 : c->c.ptr.p_double[4*i+1] = d->ptr.p_double[i];
23580 0 : c->c.ptr.p_double[4*i+2] = (3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])-2*d->ptr.p_double[i]*delta-d->ptr.p_double[i+1]*delta)/delta2;
23581 0 : c->c.ptr.p_double[4*i+3] = (2*(y->ptr.p_double[i]-y->ptr.p_double[i+1])+d->ptr.p_double[i]*delta+d->ptr.p_double[i+1]*delta)/delta3;
23582 : }
23583 0 : c->c.ptr.p_double[4*(n-1)+0] = y->ptr.p_double[n-1];
23584 0 : c->c.ptr.p_double[4*(n-1)+1] = d->ptr.p_double[n-1];
23585 0 : ae_frame_leave(_state);
23586 0 : }
23587 :
23588 :
23589 : /*************************************************************************
23590 : This subroutine builds Akima spline interpolant
23591 :
23592 : INPUT PARAMETERS:
23593 : X - spline nodes, array[0..N-1]
23594 : Y - function values, array[0..N-1]
23595 : N - points count (optional):
23596 : * N>=2
23597 : * if given, only first N points are used to build spline
23598 : * if not given, automatically detected from X/Y sizes
23599 : (len(X) must be equal to len(Y))
23600 :
23601 : OUTPUT PARAMETERS:
23602 : C - spline interpolant
23603 :
23604 :
23605 : ORDER OF POINTS
23606 :
23607 : Subroutine automatically sorts points, so caller may pass unsorted array.
23608 :
23609 : -- ALGLIB PROJECT --
23610 : Copyright 24.06.2007 by Bochkanov Sergey
23611 : *************************************************************************/
23612 0 : void spline1dbuildakima(/* Real */ ae_vector* x,
23613 : /* Real */ ae_vector* y,
23614 : ae_int_t n,
23615 : spline1dinterpolant* c,
23616 : ae_state *_state)
23617 : {
23618 : ae_frame _frame_block;
23619 : ae_vector _x;
23620 : ae_vector _y;
23621 : ae_int_t i;
23622 : ae_vector d;
23623 : ae_vector w;
23624 : ae_vector diff;
23625 :
23626 0 : ae_frame_make(_state, &_frame_block);
23627 0 : memset(&_x, 0, sizeof(_x));
23628 0 : memset(&_y, 0, sizeof(_y));
23629 0 : memset(&d, 0, sizeof(d));
23630 0 : memset(&w, 0, sizeof(w));
23631 0 : memset(&diff, 0, sizeof(diff));
23632 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
23633 0 : x = &_x;
23634 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
23635 0 : y = &_y;
23636 0 : _spline1dinterpolant_clear(c);
23637 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
23638 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
23639 0 : ae_vector_init(&diff, 0, DT_REAL, _state, ae_true);
23640 :
23641 0 : ae_assert(n>=2, "Spline1DBuildAkima: N<2!", _state);
23642 0 : ae_assert(x->cnt>=n, "Spline1DBuildAkima: Length(X)<N!", _state);
23643 0 : ae_assert(y->cnt>=n, "Spline1DBuildAkima: Length(Y)<N!", _state);
23644 :
23645 : /*
23646 : * check and sort points
23647 : */
23648 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DBuildAkima: X contains infinite or NAN values!", _state);
23649 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DBuildAkima: Y contains infinite or NAN values!", _state);
23650 0 : spline1d_heapsortpoints(x, y, n, _state);
23651 0 : ae_assert(aredistinct(x, n, _state), "Spline1DBuildAkima: at least two consequent points are too close!", _state);
23652 :
23653 : /*
23654 : * Handle special cases: N=2, N=3, N=4
23655 : */
23656 0 : if( n<=4 )
23657 : {
23658 0 : spline1dbuildcubic(x, y, n, 0, 0.0, 0, 0.0, c, _state);
23659 0 : ae_frame_leave(_state);
23660 0 : return;
23661 : }
23662 :
23663 : /*
23664 : * Prepare W (weights), Diff (divided differences)
23665 : */
23666 0 : ae_vector_set_length(&w, n-1, _state);
23667 0 : ae_vector_set_length(&diff, n-1, _state);
23668 0 : for(i=0; i<=n-2; i++)
23669 : {
23670 0 : diff.ptr.p_double[i] = (y->ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i]);
23671 : }
23672 0 : for(i=1; i<=n-2; i++)
23673 : {
23674 0 : w.ptr.p_double[i] = ae_fabs(diff.ptr.p_double[i]-diff.ptr.p_double[i-1], _state);
23675 : }
23676 :
23677 : /*
23678 : * Prepare Hermite interpolation scheme
23679 : */
23680 0 : ae_vector_set_length(&d, n, _state);
23681 0 : for(i=2; i<=n-3; i++)
23682 : {
23683 0 : if( ae_fp_neq(ae_fabs(w.ptr.p_double[i-1], _state)+ae_fabs(w.ptr.p_double[i+1], _state),(double)(0)) )
23684 : {
23685 0 : d.ptr.p_double[i] = (w.ptr.p_double[i+1]*diff.ptr.p_double[i-1]+w.ptr.p_double[i-1]*diff.ptr.p_double[i])/(w.ptr.p_double[i+1]+w.ptr.p_double[i-1]);
23686 : }
23687 : else
23688 : {
23689 0 : d.ptr.p_double[i] = ((x->ptr.p_double[i+1]-x->ptr.p_double[i])*diff.ptr.p_double[i-1]+(x->ptr.p_double[i]-x->ptr.p_double[i-1])*diff.ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]);
23690 : }
23691 : }
23692 0 : d.ptr.p_double[0] = spline1d_diffthreepoint(x->ptr.p_double[0], x->ptr.p_double[0], y->ptr.p_double[0], x->ptr.p_double[1], y->ptr.p_double[1], x->ptr.p_double[2], y->ptr.p_double[2], _state);
23693 0 : d.ptr.p_double[1] = spline1d_diffthreepoint(x->ptr.p_double[1], x->ptr.p_double[0], y->ptr.p_double[0], x->ptr.p_double[1], y->ptr.p_double[1], x->ptr.p_double[2], y->ptr.p_double[2], _state);
23694 0 : d.ptr.p_double[n-2] = spline1d_diffthreepoint(x->ptr.p_double[n-2], x->ptr.p_double[n-3], y->ptr.p_double[n-3], x->ptr.p_double[n-2], y->ptr.p_double[n-2], x->ptr.p_double[n-1], y->ptr.p_double[n-1], _state);
23695 0 : d.ptr.p_double[n-1] = spline1d_diffthreepoint(x->ptr.p_double[n-1], x->ptr.p_double[n-3], y->ptr.p_double[n-3], x->ptr.p_double[n-2], y->ptr.p_double[n-2], x->ptr.p_double[n-1], y->ptr.p_double[n-1], _state);
23696 :
23697 : /*
23698 : * Build Akima spline using Hermite interpolation scheme
23699 : */
23700 0 : spline1dbuildhermite(x, y, &d, n, c, _state);
23701 0 : ae_frame_leave(_state);
23702 : }
23703 :
23704 :
23705 : /*************************************************************************
23706 : This subroutine calculates the value of the spline at the given point X.
23707 :
23708 : INPUT PARAMETERS:
23709 : C - spline interpolant
23710 : X - point
23711 :
23712 : Result:
23713 : S(x)
23714 :
23715 : -- ALGLIB PROJECT --
23716 : Copyright 23.06.2007 by Bochkanov Sergey
23717 : *************************************************************************/
23718 0 : double spline1dcalc(spline1dinterpolant* c, double x, ae_state *_state)
23719 : {
23720 : ae_int_t l;
23721 : ae_int_t r;
23722 : ae_int_t m;
23723 : double t;
23724 : double result;
23725 :
23726 :
23727 0 : ae_assert(c->k==3, "Spline1DCalc: internal error", _state);
23728 0 : ae_assert(!ae_isinf(x, _state), "Spline1DCalc: infinite X!", _state);
23729 :
23730 : /*
23731 : * special case: NaN
23732 : */
23733 0 : if( ae_isnan(x, _state) )
23734 : {
23735 0 : result = _state->v_nan;
23736 0 : return result;
23737 : }
23738 :
23739 : /*
23740 : * correct if periodic
23741 : */
23742 0 : if( c->periodic )
23743 : {
23744 0 : apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state);
23745 : }
23746 :
23747 : /*
23748 : * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
23749 : */
23750 0 : l = 0;
23751 0 : r = c->n-2+1;
23752 0 : while(l!=r-1)
23753 : {
23754 0 : m = (l+r)/2;
23755 0 : if( c->x.ptr.p_double[m]>=x )
23756 : {
23757 0 : r = m;
23758 : }
23759 : else
23760 : {
23761 0 : l = m;
23762 : }
23763 : }
23764 :
23765 : /*
23766 : * Interpolation
23767 : */
23768 0 : x = x-c->x.ptr.p_double[l];
23769 0 : m = 4*l;
23770 0 : result = c->c.ptr.p_double[m]+x*(c->c.ptr.p_double[m+1]+x*(c->c.ptr.p_double[m+2]+x*c->c.ptr.p_double[m+3]));
23771 0 : return result;
23772 : }
23773 :
23774 :
23775 : /*************************************************************************
23776 : This subroutine differentiates the spline.
23777 :
23778 : INPUT PARAMETERS:
23779 : C - spline interpolant.
23780 : X - point
23781 :
23782 : Result:
23783 : S - S(x)
23784 : DS - S'(x)
23785 : D2S - S''(x)
23786 :
23787 : -- ALGLIB PROJECT --
23788 : Copyright 24.06.2007 by Bochkanov Sergey
23789 : *************************************************************************/
23790 0 : void spline1ddiff(spline1dinterpolant* c,
23791 : double x,
23792 : double* s,
23793 : double* ds,
23794 : double* d2s,
23795 : ae_state *_state)
23796 : {
23797 : ae_int_t l;
23798 : ae_int_t r;
23799 : ae_int_t m;
23800 : double t;
23801 :
23802 0 : *s = 0;
23803 0 : *ds = 0;
23804 0 : *d2s = 0;
23805 :
23806 0 : ae_assert(c->k==3, "Spline1DDiff: internal error", _state);
23807 0 : ae_assert(!ae_isinf(x, _state), "Spline1DDiff: infinite X!", _state);
23808 :
23809 : /*
23810 : * special case: NaN
23811 : */
23812 0 : if( ae_isnan(x, _state) )
23813 : {
23814 0 : *s = _state->v_nan;
23815 0 : *ds = _state->v_nan;
23816 0 : *d2s = _state->v_nan;
23817 0 : return;
23818 : }
23819 :
23820 : /*
23821 : * correct if periodic
23822 : */
23823 0 : if( c->periodic )
23824 : {
23825 0 : apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state);
23826 : }
23827 :
23828 : /*
23829 : * Binary search
23830 : */
23831 0 : l = 0;
23832 0 : r = c->n-2+1;
23833 0 : while(l!=r-1)
23834 : {
23835 0 : m = (l+r)/2;
23836 0 : if( c->x.ptr.p_double[m]>=x )
23837 : {
23838 0 : r = m;
23839 : }
23840 : else
23841 : {
23842 0 : l = m;
23843 : }
23844 : }
23845 :
23846 : /*
23847 : * Differentiation
23848 : */
23849 0 : x = x-c->x.ptr.p_double[l];
23850 0 : m = 4*l;
23851 0 : *s = c->c.ptr.p_double[m]+x*(c->c.ptr.p_double[m+1]+x*(c->c.ptr.p_double[m+2]+x*c->c.ptr.p_double[m+3]));
23852 0 : *ds = c->c.ptr.p_double[m+1]+2*x*c->c.ptr.p_double[m+2]+3*ae_sqr(x, _state)*c->c.ptr.p_double[m+3];
23853 0 : *d2s = 2*c->c.ptr.p_double[m+2]+6*x*c->c.ptr.p_double[m+3];
23854 : }
23855 :
23856 :
23857 : /*************************************************************************
23858 : This subroutine makes the copy of the spline.
23859 :
23860 : INPUT PARAMETERS:
23861 : C - spline interpolant.
23862 :
23863 : Result:
23864 : CC - spline copy
23865 :
23866 : -- ALGLIB PROJECT --
23867 : Copyright 29.06.2007 by Bochkanov Sergey
23868 : *************************************************************************/
23869 0 : void spline1dcopy(spline1dinterpolant* c,
23870 : spline1dinterpolant* cc,
23871 : ae_state *_state)
23872 : {
23873 : ae_int_t s;
23874 :
23875 0 : _spline1dinterpolant_clear(cc);
23876 :
23877 0 : cc->periodic = c->periodic;
23878 0 : cc->n = c->n;
23879 0 : cc->k = c->k;
23880 0 : cc->continuity = c->continuity;
23881 0 : ae_vector_set_length(&cc->x, cc->n, _state);
23882 0 : ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1));
23883 0 : s = c->c.cnt;
23884 0 : ae_vector_set_length(&cc->c, s, _state);
23885 0 : ae_v_move(&cc->c.ptr.p_double[0], 1, &c->c.ptr.p_double[0], 1, ae_v_len(0,s-1));
23886 0 : }
23887 :
23888 :
23889 : /*************************************************************************
23890 : This subroutine unpacks the spline into the coefficients table.
23891 :
23892 : INPUT PARAMETERS:
23893 : C - spline interpolant.
23894 : X - point
23895 :
23896 : OUTPUT PARAMETERS:
23897 : Tbl - coefficients table, unpacked format, array[0..N-2, 0..5].
23898 : For I = 0...N-2:
23899 : Tbl[I,0] = X[i]
23900 : Tbl[I,1] = X[i+1]
23901 : Tbl[I,2] = C0
23902 : Tbl[I,3] = C1
23903 : Tbl[I,4] = C2
23904 : Tbl[I,5] = C3
23905 : On [x[i], x[i+1]] spline is equals to:
23906 : S(x) = C0 + C1*t + C2*t^2 + C3*t^3
23907 : t = x-x[i]
23908 :
23909 : NOTE:
23910 : You can rebuild spline with Spline1DBuildHermite() function, which
23911 : accepts as inputs function values and derivatives at nodes, which are
23912 : easy to calculate when you have coefficients.
23913 :
23914 : -- ALGLIB PROJECT --
23915 : Copyright 29.06.2007 by Bochkanov Sergey
23916 : *************************************************************************/
23917 0 : void spline1dunpack(spline1dinterpolant* c,
23918 : ae_int_t* n,
23919 : /* Real */ ae_matrix* tbl,
23920 : ae_state *_state)
23921 : {
23922 : ae_int_t i;
23923 : ae_int_t j;
23924 :
23925 0 : *n = 0;
23926 0 : ae_matrix_clear(tbl);
23927 :
23928 0 : ae_matrix_set_length(tbl, c->n-2+1, 2+c->k+1, _state);
23929 0 : *n = c->n;
23930 :
23931 : /*
23932 : * Fill
23933 : */
23934 0 : for(i=0; i<=*n-2; i++)
23935 : {
23936 0 : tbl->ptr.pp_double[i][0] = c->x.ptr.p_double[i];
23937 0 : tbl->ptr.pp_double[i][1] = c->x.ptr.p_double[i+1];
23938 0 : for(j=0; j<=c->k; j++)
23939 : {
23940 0 : tbl->ptr.pp_double[i][2+j] = c->c.ptr.p_double[(c->k+1)*i+j];
23941 : }
23942 : }
23943 0 : }
23944 :
23945 :
23946 : /*************************************************************************
23947 : This subroutine performs linear transformation of the spline argument.
23948 :
23949 : INPUT PARAMETERS:
23950 : C - spline interpolant.
23951 : A, B- transformation coefficients: x = A*t + B
23952 : Result:
23953 : C - transformed spline
23954 :
23955 : -- ALGLIB PROJECT --
23956 : Copyright 30.06.2007 by Bochkanov Sergey
23957 : *************************************************************************/
23958 0 : void spline1dlintransx(spline1dinterpolant* c,
23959 : double a,
23960 : double b,
23961 : ae_state *_state)
23962 : {
23963 : ae_frame _frame_block;
23964 : ae_int_t i;
23965 : ae_int_t n;
23966 : double v;
23967 : double dv;
23968 : double d2v;
23969 : ae_vector x;
23970 : ae_vector y;
23971 : ae_vector d;
23972 : ae_bool isperiodic;
23973 : ae_int_t contval;
23974 :
23975 0 : ae_frame_make(_state, &_frame_block);
23976 0 : memset(&x, 0, sizeof(x));
23977 0 : memset(&y, 0, sizeof(y));
23978 0 : memset(&d, 0, sizeof(d));
23979 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
23980 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
23981 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
23982 :
23983 0 : ae_assert(c->k==3, "Spline1DLinTransX: internal error", _state);
23984 0 : n = c->n;
23985 0 : ae_vector_set_length(&x, n, _state);
23986 0 : ae_vector_set_length(&y, n, _state);
23987 0 : ae_vector_set_length(&d, n, _state);
23988 :
23989 : /*
23990 : * Unpack, X, Y, dY/dX.
23991 : * Scale and pack with Spline1DBuildHermite again.
23992 : */
23993 0 : if( ae_fp_eq(a,(double)(0)) )
23994 : {
23995 :
23996 : /*
23997 : * Special case: A=0
23998 : */
23999 0 : v = spline1dcalc(c, b, _state);
24000 0 : for(i=0; i<=n-1; i++)
24001 : {
24002 0 : x.ptr.p_double[i] = c->x.ptr.p_double[i];
24003 0 : y.ptr.p_double[i] = v;
24004 0 : d.ptr.p_double[i] = 0.0;
24005 : }
24006 : }
24007 : else
24008 : {
24009 :
24010 : /*
24011 : * General case, A<>0
24012 : */
24013 0 : for(i=0; i<=n-1; i++)
24014 : {
24015 0 : x.ptr.p_double[i] = c->x.ptr.p_double[i];
24016 0 : spline1ddiff(c, x.ptr.p_double[i], &v, &dv, &d2v, _state);
24017 0 : x.ptr.p_double[i] = (x.ptr.p_double[i]-b)/a;
24018 0 : y.ptr.p_double[i] = v;
24019 0 : d.ptr.p_double[i] = a*dv;
24020 : }
24021 : }
24022 0 : isperiodic = c->periodic;
24023 0 : contval = c->continuity;
24024 0 : if( contval>0 )
24025 : {
24026 0 : spline1dbuildhermite(&x, &y, &d, n, c, _state);
24027 : }
24028 : else
24029 : {
24030 0 : spline1dbuildlinear(&x, &y, n, c, _state);
24031 : }
24032 0 : c->periodic = isperiodic;
24033 0 : c->continuity = contval;
24034 0 : ae_frame_leave(_state);
24035 0 : }
24036 :
24037 :
24038 : /*************************************************************************
24039 : This subroutine performs linear transformation of the spline.
24040 :
24041 : INPUT PARAMETERS:
24042 : C - spline interpolant.
24043 : A, B- transformation coefficients: S2(x) = A*S(x) + B
24044 : Result:
24045 : C - transformed spline
24046 :
24047 : -- ALGLIB PROJECT --
24048 : Copyright 30.06.2007 by Bochkanov Sergey
24049 : *************************************************************************/
24050 0 : void spline1dlintransy(spline1dinterpolant* c,
24051 : double a,
24052 : double b,
24053 : ae_state *_state)
24054 : {
24055 : ae_int_t i;
24056 : ae_int_t j;
24057 : ae_int_t n;
24058 :
24059 :
24060 0 : ae_assert(c->k==3, "Spline1DLinTransX: internal error", _state);
24061 0 : n = c->n;
24062 0 : for(i=0; i<=n-2; i++)
24063 : {
24064 0 : c->c.ptr.p_double[4*i] = a*c->c.ptr.p_double[4*i]+b;
24065 0 : for(j=1; j<=3; j++)
24066 : {
24067 0 : c->c.ptr.p_double[4*i+j] = a*c->c.ptr.p_double[4*i+j];
24068 : }
24069 : }
24070 0 : c->c.ptr.p_double[4*(n-1)+0] = a*c->c.ptr.p_double[4*(n-1)+0]+b;
24071 0 : c->c.ptr.p_double[4*(n-1)+1] = a*c->c.ptr.p_double[4*(n-1)+1];
24072 0 : }
24073 :
24074 :
24075 : /*************************************************************************
24076 : This subroutine integrates the spline.
24077 :
24078 : INPUT PARAMETERS:
24079 : C - spline interpolant.
24080 : X - right bound of the integration interval [a, x],
24081 : here 'a' denotes min(x[])
24082 : Result:
24083 : integral(S(t)dt,a,x)
24084 :
24085 : -- ALGLIB PROJECT --
24086 : Copyright 23.06.2007 by Bochkanov Sergey
24087 : *************************************************************************/
24088 0 : double spline1dintegrate(spline1dinterpolant* c,
24089 : double x,
24090 : ae_state *_state)
24091 : {
24092 : ae_int_t n;
24093 : ae_int_t i;
24094 : ae_int_t j;
24095 : ae_int_t l;
24096 : ae_int_t r;
24097 : ae_int_t m;
24098 : double w;
24099 : double v;
24100 : double t;
24101 : double intab;
24102 : double additionalterm;
24103 : double result;
24104 :
24105 :
24106 0 : n = c->n;
24107 :
24108 : /*
24109 : * Periodic splines require special treatment. We make
24110 : * following transformation:
24111 : *
24112 : * integral(S(t)dt,A,X) = integral(S(t)dt,A,Z)+AdditionalTerm
24113 : *
24114 : * here X may lie outside of [A,B], Z lies strictly in [A,B],
24115 : * AdditionalTerm is equals to integral(S(t)dt,A,B) times some
24116 : * integer number (may be zero).
24117 : */
24118 0 : if( c->periodic&&(ae_fp_less(x,c->x.ptr.p_double[0])||ae_fp_greater(x,c->x.ptr.p_double[c->n-1])) )
24119 : {
24120 :
24121 : /*
24122 : * compute integral(S(x)dx,A,B)
24123 : */
24124 0 : intab = (double)(0);
24125 0 : for(i=0; i<=c->n-2; i++)
24126 : {
24127 0 : w = c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i];
24128 0 : m = (c->k+1)*i;
24129 0 : intab = intab+c->c.ptr.p_double[m]*w;
24130 0 : v = w;
24131 0 : for(j=1; j<=c->k; j++)
24132 : {
24133 0 : v = v*w;
24134 0 : intab = intab+c->c.ptr.p_double[m+j]*v/(j+1);
24135 : }
24136 : }
24137 :
24138 : /*
24139 : * map X into [A,B]
24140 : */
24141 0 : apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state);
24142 0 : additionalterm = t*intab;
24143 : }
24144 : else
24145 : {
24146 0 : additionalterm = (double)(0);
24147 : }
24148 :
24149 : /*
24150 : * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
24151 : */
24152 0 : l = 0;
24153 0 : r = n-2+1;
24154 0 : while(l!=r-1)
24155 : {
24156 0 : m = (l+r)/2;
24157 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[m],x) )
24158 : {
24159 0 : r = m;
24160 : }
24161 : else
24162 : {
24163 0 : l = m;
24164 : }
24165 : }
24166 :
24167 : /*
24168 : * Integration
24169 : */
24170 0 : result = (double)(0);
24171 0 : for(i=0; i<=l-1; i++)
24172 : {
24173 0 : w = c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i];
24174 0 : m = (c->k+1)*i;
24175 0 : result = result+c->c.ptr.p_double[m]*w;
24176 0 : v = w;
24177 0 : for(j=1; j<=c->k; j++)
24178 : {
24179 0 : v = v*w;
24180 0 : result = result+c->c.ptr.p_double[m+j]*v/(j+1);
24181 : }
24182 : }
24183 0 : w = x-c->x.ptr.p_double[l];
24184 0 : m = (c->k+1)*l;
24185 0 : v = w;
24186 0 : result = result+c->c.ptr.p_double[m]*w;
24187 0 : for(j=1; j<=c->k; j++)
24188 : {
24189 0 : v = v*w;
24190 0 : result = result+c->c.ptr.p_double[m+j]*v/(j+1);
24191 : }
24192 0 : result = result+additionalterm;
24193 0 : return result;
24194 : }
24195 :
24196 :
24197 : /*************************************************************************
24198 : Fitting by smoothing (penalized) cubic spline.
24199 :
24200 : This function approximates N scattered points (some of X[] may be equal to
24201 : each other) by cubic spline with M nodes at equidistant grid spanning
24202 : interval [min(x,xc),max(x,xc)].
24203 :
24204 : The problem is regularized by adding nonlinearity penalty to usual least
24205 : squares penalty function:
24206 :
24207 : MERIT_FUNC = F_LS + F_NL
24208 :
24209 : where F_LS is a least squares error term, and F_NL is a nonlinearity
24210 : penalty which is roughly proportional to LambdaNS*integral{ S''(x)^2*dx }.
24211 : Algorithm applies automatic renormalization of F_NL which makes penalty
24212 : term roughly invariant to scaling of X[] and changes in M.
24213 :
24214 : This function is a new edition of penalized regression spline fitting,
24215 : a fast and compact one which needs much less resources that its previous
24216 : version: just O(maxMN) memory and O(maxMN*log(maxMN)) time.
24217 :
24218 : NOTE: it is OK to run this function with both M<<N and M>>N; say, it is
24219 : possible to process 100 points with 1000-node spline.
24220 :
24221 : INPUT PARAMETERS:
24222 : X - points, array[0..N-1].
24223 : Y - function values, array[0..N-1].
24224 : N - number of points (optional):
24225 : * N>0
24226 : * if given, only first N elements of X/Y are processed
24227 : * if not given, automatically determined from lengths
24228 : M - number of basis functions ( = number_of_nodes), M>=4.
24229 : LambdaNS - LambdaNS>=0, regularization constant passed by user.
24230 : It penalizes nonlinearity in the regression spline.
24231 : Possible values to start from are 0.00001, 0.1, 1
24232 :
24233 : OUTPUT PARAMETERS:
24234 : S - spline interpolant.
24235 : Rep - Following fields are set:
24236 : * RMSError rms error on the (X,Y).
24237 : * AvgError average error on the (X,Y).
24238 : * AvgRelError average relative error on the non-zero Y
24239 : * MaxError maximum error
24240 :
24241 : -- ALGLIB PROJECT --
24242 : Copyright 27.08.2019 by Bochkanov Sergey
24243 : *************************************************************************/
24244 0 : void spline1dfit(/* Real */ ae_vector* x,
24245 : /* Real */ ae_vector* y,
24246 : ae_int_t n,
24247 : ae_int_t m,
24248 : double lambdans,
24249 : spline1dinterpolant* s,
24250 : spline1dfitreport* rep,
24251 : ae_state *_state)
24252 : {
24253 : ae_frame _frame_block;
24254 : ae_vector _x;
24255 : ae_vector _y;
24256 : ae_int_t bfrad;
24257 : double xa;
24258 : double xb;
24259 : ae_int_t i;
24260 : ae_int_t j;
24261 : ae_int_t k;
24262 : ae_int_t k0;
24263 : ae_int_t k1;
24264 : double v;
24265 : double dv;
24266 : double d2v;
24267 : ae_int_t gridexpansion;
24268 : ae_vector xywork;
24269 : ae_matrix vterm;
24270 : ae_vector sx;
24271 : ae_vector sy;
24272 : ae_vector sdy;
24273 : ae_vector tmpx;
24274 : ae_vector tmpy;
24275 : spline1dinterpolant basis1;
24276 : sparsematrix av;
24277 : sparsematrix ah;
24278 : sparsematrix ata;
24279 : ae_vector targets;
24280 : double meany;
24281 : ae_int_t lsqrcnt;
24282 : ae_int_t nrel;
24283 : double rss;
24284 : double tss;
24285 : ae_int_t arows;
24286 : ae_vector tmp0;
24287 : ae_vector tmp1;
24288 : linlsqrstate solver;
24289 : linlsqrreport srep;
24290 : double creg;
24291 : double mxata;
24292 : ae_int_t bw;
24293 : ae_vector nzidx;
24294 : ae_vector nzval;
24295 : ae_int_t nzcnt;
24296 : double scaletargetsby;
24297 : double scalepenaltyby;
24298 :
24299 0 : ae_frame_make(_state, &_frame_block);
24300 0 : memset(&_x, 0, sizeof(_x));
24301 0 : memset(&_y, 0, sizeof(_y));
24302 0 : memset(&xywork, 0, sizeof(xywork));
24303 0 : memset(&vterm, 0, sizeof(vterm));
24304 0 : memset(&sx, 0, sizeof(sx));
24305 0 : memset(&sy, 0, sizeof(sy));
24306 0 : memset(&sdy, 0, sizeof(sdy));
24307 0 : memset(&tmpx, 0, sizeof(tmpx));
24308 0 : memset(&tmpy, 0, sizeof(tmpy));
24309 0 : memset(&basis1, 0, sizeof(basis1));
24310 0 : memset(&av, 0, sizeof(av));
24311 0 : memset(&ah, 0, sizeof(ah));
24312 0 : memset(&ata, 0, sizeof(ata));
24313 0 : memset(&targets, 0, sizeof(targets));
24314 0 : memset(&tmp0, 0, sizeof(tmp0));
24315 0 : memset(&tmp1, 0, sizeof(tmp1));
24316 0 : memset(&solver, 0, sizeof(solver));
24317 0 : memset(&srep, 0, sizeof(srep));
24318 0 : memset(&nzidx, 0, sizeof(nzidx));
24319 0 : memset(&nzval, 0, sizeof(nzval));
24320 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
24321 0 : x = &_x;
24322 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
24323 0 : y = &_y;
24324 0 : _spline1dinterpolant_clear(s);
24325 0 : _spline1dfitreport_clear(rep);
24326 0 : ae_vector_init(&xywork, 0, DT_REAL, _state, ae_true);
24327 0 : ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true);
24328 0 : ae_vector_init(&sx, 0, DT_REAL, _state, ae_true);
24329 0 : ae_vector_init(&sy, 0, DT_REAL, _state, ae_true);
24330 0 : ae_vector_init(&sdy, 0, DT_REAL, _state, ae_true);
24331 0 : ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true);
24332 0 : ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
24333 0 : _spline1dinterpolant_init(&basis1, _state, ae_true);
24334 0 : _sparsematrix_init(&av, _state, ae_true);
24335 0 : _sparsematrix_init(&ah, _state, ae_true);
24336 0 : _sparsematrix_init(&ata, _state, ae_true);
24337 0 : ae_vector_init(&targets, 0, DT_REAL, _state, ae_true);
24338 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
24339 0 : ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
24340 0 : _linlsqrstate_init(&solver, _state, ae_true);
24341 0 : _linlsqrreport_init(&srep, _state, ae_true);
24342 0 : ae_vector_init(&nzidx, 0, DT_INT, _state, ae_true);
24343 0 : ae_vector_init(&nzval, 0, DT_REAL, _state, ae_true);
24344 :
24345 0 : ae_assert(n>=1, "Spline1DFit: N<1!", _state);
24346 0 : ae_assert(m>=1, "Spline1DFit: M<1!", _state);
24347 0 : ae_assert(x->cnt>=n, "Spline1DFit: Length(X)<N!", _state);
24348 0 : ae_assert(y->cnt>=n, "Spline1DFit: Length(Y)<N!", _state);
24349 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DFit: X contains infinite or NAN values!", _state);
24350 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DFit: Y contains infinite or NAN values!", _state);
24351 0 : ae_assert(ae_isfinite(lambdans, _state), "Spline1DFit: LambdaNS is infinite!", _state);
24352 0 : ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "Spline1DFit: LambdaNS<0!", _state);
24353 0 : bfrad = 2;
24354 0 : lsqrcnt = 10;
24355 :
24356 : /*
24357 : * Sort points.
24358 : * Determine actual area size, make sure that XA<XB
24359 : */
24360 0 : tagsortfastr(x, y, &tmpx, &tmpy, n, _state);
24361 0 : xa = x->ptr.p_double[0];
24362 0 : xb = x->ptr.p_double[n-1];
24363 0 : if( ae_fp_eq(xa,xb) )
24364 : {
24365 0 : v = xa;
24366 0 : if( ae_fp_greater_eq(v,(double)(0)) )
24367 : {
24368 0 : xa = v/2-1;
24369 0 : xb = v*2+1;
24370 : }
24371 : else
24372 : {
24373 0 : xa = v*2-1;
24374 0 : xb = v/2+1;
24375 : }
24376 : }
24377 0 : ae_assert(ae_fp_less(xa,xb), "Spline1DFit: integrity error", _state);
24378 :
24379 : /*
24380 : * Perform a grid correction according to current grid expansion size.
24381 : */
24382 0 : m = ae_maxint(m, 4, _state);
24383 0 : gridexpansion = 1;
24384 0 : v = (xb-xa)/m;
24385 0 : xa = xa-v*gridexpansion;
24386 0 : xb = xb+v*gridexpansion;
24387 0 : m = m+2*gridexpansion;
24388 :
24389 : /*
24390 : * Convert X/Y to work representation, remove linear trend (in
24391 : * order to improve condition number).
24392 : *
24393 : * Compute total-sum-of-squares (needed later for R2 coefficient).
24394 : */
24395 0 : ae_vector_set_length(&xywork, 2*n, _state);
24396 0 : for(i=0; i<=n-1; i++)
24397 : {
24398 0 : xywork.ptr.p_double[2*i+0] = (x->ptr.p_double[i]-xa)/(xb-xa);
24399 0 : xywork.ptr.p_double[2*i+1] = y->ptr.p_double[i];
24400 : }
24401 0 : buildpriorterm1(&xywork, n, 1, 1, 1, 0.0, &vterm, _state);
24402 0 : meany = (double)(0);
24403 0 : for(i=0; i<=n-1; i++)
24404 : {
24405 0 : meany = meany+y->ptr.p_double[i];
24406 : }
24407 0 : meany = meany/n;
24408 0 : tss = (double)(0);
24409 0 : for(i=0; i<=n-1; i++)
24410 : {
24411 0 : tss = tss+ae_sqr(y->ptr.p_double[i]-meany, _state);
24412 : }
24413 :
24414 : /*
24415 : * Build 1D compact basis function
24416 : * Generate design matrix AV ("vertical") and its transpose AH ("horizontal").
24417 : */
24418 0 : ae_vector_set_length(&tmpx, 7, _state);
24419 0 : ae_vector_set_length(&tmpy, 7, _state);
24420 0 : tmpx.ptr.p_double[0] = -(double)3/(double)(m-1);
24421 0 : tmpx.ptr.p_double[1] = -(double)2/(double)(m-1);
24422 0 : tmpx.ptr.p_double[2] = -(double)1/(double)(m-1);
24423 0 : tmpx.ptr.p_double[3] = (double)0/(double)(m-1);
24424 0 : tmpx.ptr.p_double[4] = (double)1/(double)(m-1);
24425 0 : tmpx.ptr.p_double[5] = (double)2/(double)(m-1);
24426 0 : tmpx.ptr.p_double[6] = (double)3/(double)(m-1);
24427 0 : tmpy.ptr.p_double[0] = (double)(0);
24428 0 : tmpy.ptr.p_double[1] = (double)(0);
24429 0 : tmpy.ptr.p_double[2] = (double)1/(double)12;
24430 0 : tmpy.ptr.p_double[3] = (double)2/(double)6;
24431 0 : tmpy.ptr.p_double[4] = (double)1/(double)12;
24432 0 : tmpy.ptr.p_double[5] = (double)(0);
24433 0 : tmpy.ptr.p_double[6] = (double)(0);
24434 0 : spline1dbuildcubic(&tmpx, &tmpy, tmpx.cnt, 2, 0.0, 2, 0.0, &basis1, _state);
24435 0 : arows = n+2*m;
24436 0 : sparsecreate(arows, m, 0, &av, _state);
24437 0 : setlengthzero(&targets, arows, _state);
24438 0 : scaletargetsby = 1/ae_sqrt((double)(n), _state);
24439 0 : scalepenaltyby = 1/ae_sqrt((double)(m), _state);
24440 0 : for(i=0; i<=n-1; i++)
24441 : {
24442 :
24443 : /*
24444 : * Generate design matrix row #I which corresponds to I-th dataset point
24445 : */
24446 0 : k = ae_ifloor(boundval(xywork.ptr.p_double[2*i+0]*(m-1), (double)(0), (double)(m-1), _state), _state);
24447 0 : k0 = ae_maxint(k-(bfrad-1), 0, _state);
24448 0 : k1 = ae_minint(k+bfrad, m-1, _state);
24449 0 : for(j=k0; j<=k1; j++)
24450 : {
24451 0 : sparseset(&av, i, j, spline1dcalc(&basis1, xywork.ptr.p_double[2*i+0]-(double)j/(double)(m-1), _state)*scaletargetsby, _state);
24452 : }
24453 0 : targets.ptr.p_double[i] = xywork.ptr.p_double[2*i+1]*scaletargetsby;
24454 : }
24455 0 : for(i=0; i<=m-1; i++)
24456 : {
24457 :
24458 : /*
24459 : * Generate design matrix row #(I+N) which corresponds to nonlinearity penalty at I-th node
24460 : */
24461 0 : k0 = ae_maxint(i-(bfrad-1), 0, _state);
24462 0 : k1 = ae_minint(i+(bfrad-1), m-1, _state);
24463 0 : for(j=k0; j<=k1; j++)
24464 : {
24465 0 : spline1ddiff(&basis1, (double)i/(double)(m-1)-(double)j/(double)(m-1), &v, &dv, &d2v, _state);
24466 0 : sparseset(&av, n+i, j, lambdans*d2v*scalepenaltyby, _state);
24467 : }
24468 : }
24469 0 : for(i=0; i<=m-1; i++)
24470 : {
24471 :
24472 : /*
24473 : * Generate design matrix row #(I+N+M) which corresponds to regularization for I-th coefficient
24474 : */
24475 0 : sparseset(&av, n+m+i, i, spline1d_lambdareg, _state);
24476 : }
24477 0 : sparseconverttocrs(&av, _state);
24478 0 : sparsecopytransposecrs(&av, &ah, _state);
24479 :
24480 : /*
24481 : * Build 7-diagonal (bandwidth=3) normal equations matrix and perform Cholesky
24482 : * decomposition (to be used later as preconditioner for LSQR iterations).
24483 : */
24484 0 : bw = 3;
24485 0 : sparsecreatesksband(m, m, bw, &ata, _state);
24486 0 : mxata = (double)(0);
24487 0 : for(i=0; i<=m-1; i++)
24488 : {
24489 0 : for(j=i; j<=ae_minint(i+bw, m-1, _state); j++)
24490 : {
24491 :
24492 : /*
24493 : * Get pattern of nonzeros in one of the rows (let it be I-th one)
24494 : * and compute dot product only for nonzero entries.
24495 : */
24496 0 : sparsegetcompressedrow(&ah, i, &nzidx, &nzval, &nzcnt, _state);
24497 0 : v = (double)(0);
24498 0 : for(k=0; k<=nzcnt-1; k++)
24499 : {
24500 0 : v = v+sparseget(&ah, i, nzidx.ptr.p_int[k], _state)*sparseget(&ah, j, nzidx.ptr.p_int[k], _state);
24501 : }
24502 :
24503 : /*
24504 : * Update ATA and max(ATA)
24505 : */
24506 0 : sparseset(&ata, i, j, v, _state);
24507 0 : if( i==j )
24508 : {
24509 0 : mxata = ae_maxreal(mxata, ae_fabs(v, _state), _state);
24510 : }
24511 : }
24512 : }
24513 0 : mxata = coalesce(mxata, 1.0, _state);
24514 0 : creg = spline1d_cholreg;
24515 : for(;;)
24516 : {
24517 :
24518 : /*
24519 : * Regularization
24520 : */
24521 0 : for(i=0; i<=m-1; i++)
24522 : {
24523 0 : sparseset(&ata, i, i, sparseget(&ata, i, i, _state)+mxata*creg, _state);
24524 : }
24525 :
24526 : /*
24527 : * Try Cholesky factorization.
24528 : */
24529 0 : if( !sparsecholeskyskyline(&ata, m, ae_true, _state) )
24530 : {
24531 :
24532 : /*
24533 : * Factorization failed, increase regularizer and repeat
24534 : */
24535 0 : creg = coalesce(10*creg, 1.0E-12, _state);
24536 0 : continue;
24537 : }
24538 0 : break;
24539 : }
24540 :
24541 : /*
24542 : * Solve with preconditioned LSQR:
24543 : *
24544 : * use Cholesky factor U of squared design matrix A'*A to
24545 : * transform min|A*x-b| to min|[A*inv(U)]*y-b| with y=U*x.
24546 : *
24547 : * Preconditioned problem is solved with LSQR solver, which
24548 : * gives superior results to normal equations approach. Due
24549 : * to Cholesky preconditioner being utilized we can solve
24550 : * problem in just a few iterations.
24551 : */
24552 0 : rvectorsetlengthatleast(&tmp0, arows, _state);
24553 0 : rvectorsetlengthatleast(&tmp1, m, _state);
24554 0 : linlsqrcreatebuf(arows, m, &solver, _state);
24555 0 : linlsqrsetb(&solver, &targets, _state);
24556 0 : linlsqrsetcond(&solver, 1.0E-14, 1.0E-14, lsqrcnt, _state);
24557 0 : while(linlsqriteration(&solver, _state))
24558 : {
24559 0 : if( solver.needmv )
24560 : {
24561 0 : for(i=0; i<=m-1; i++)
24562 : {
24563 0 : tmp1.ptr.p_double[i] = solver.x.ptr.p_double[i];
24564 : }
24565 :
24566 : /*
24567 : * Use Cholesky factorization of the system matrix
24568 : * as preconditioner: solve TRSV(U,Solver.X)
24569 : */
24570 0 : sparsetrsv(&ata, ae_true, ae_false, 0, &tmp1, _state);
24571 :
24572 : /*
24573 : * After preconditioning is done, multiply by A
24574 : */
24575 0 : sparsemv(&av, &tmp1, &solver.mv, _state);
24576 : }
24577 0 : if( solver.needmtv )
24578 : {
24579 :
24580 : /*
24581 : * Multiply by design matrix A
24582 : */
24583 0 : sparsemtv(&av, &solver.x, &solver.mtv, _state);
24584 :
24585 : /*
24586 : * Multiply by preconditioner: solve TRSV(U',A*Solver.X)
24587 : */
24588 0 : sparsetrsv(&ata, ae_true, ae_false, 1, &solver.mtv, _state);
24589 : }
24590 : }
24591 0 : linlsqrresults(&solver, &tmp1, &srep, _state);
24592 0 : sparsetrsv(&ata, ae_true, ae_false, 0, &tmp1, _state);
24593 :
24594 : /*
24595 : * Generate output spline as a table of spline valued and first
24596 : * derivatives at nodes (used to build Hermite spline)
24597 : */
24598 0 : ae_vector_set_length(&sx, m, _state);
24599 0 : ae_vector_set_length(&sy, m, _state);
24600 0 : ae_vector_set_length(&sdy, m, _state);
24601 0 : for(i=0; i<=m-1; i++)
24602 : {
24603 0 : sx.ptr.p_double[i] = (double)i/(double)(m-1);
24604 0 : sy.ptr.p_double[i] = (double)(0);
24605 0 : sdy.ptr.p_double[i] = (double)(0);
24606 : }
24607 0 : for(i=0; i<=m-1; i++)
24608 : {
24609 0 : k0 = ae_maxint(i-(bfrad-1), 0, _state);
24610 0 : k1 = ae_minint(i+bfrad, m-1, _state);
24611 0 : for(j=k0; j<=k1; j++)
24612 : {
24613 0 : spline1ddiff(&basis1, (double)j/(double)(m-1)-(double)i/(double)(m-1), &v, &dv, &d2v, _state);
24614 0 : sy.ptr.p_double[j] = sy.ptr.p_double[j]+tmp1.ptr.p_double[i]*v;
24615 0 : sdy.ptr.p_double[j] = sdy.ptr.p_double[j]+tmp1.ptr.p_double[i]*dv;
24616 : }
24617 : }
24618 :
24619 : /*
24620 : * Calculate model values
24621 : */
24622 0 : sparsemv(&av, &tmp1, &tmp0, _state);
24623 0 : for(i=0; i<=n-1; i++)
24624 : {
24625 0 : tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/scaletargetsby;
24626 : }
24627 0 : rss = 0.0;
24628 0 : nrel = 0;
24629 0 : rep->rmserror = (double)(0);
24630 0 : rep->maxerror = (double)(0);
24631 0 : rep->avgerror = (double)(0);
24632 0 : rep->avgrelerror = (double)(0);
24633 0 : for(i=0; i<=n-1; i++)
24634 : {
24635 0 : v = xywork.ptr.p_double[2*i+1]-tmp0.ptr.p_double[i];
24636 0 : rss = rss+v*v;
24637 0 : rep->rmserror = rep->rmserror+ae_sqr(v, _state);
24638 0 : rep->avgerror = rep->avgerror+ae_fabs(v, _state);
24639 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state);
24640 0 : if( ae_fp_neq(y->ptr.p_double[i],(double)(0)) )
24641 : {
24642 0 : rep->avgrelerror = rep->avgrelerror+ae_fabs(v/y->ptr.p_double[i], _state);
24643 0 : nrel = nrel+1;
24644 : }
24645 : }
24646 0 : rep->rmserror = ae_sqrt(rep->rmserror/n, _state);
24647 0 : rep->avgerror = rep->avgerror/n;
24648 0 : rep->avgrelerror = rep->avgrelerror/coalesce((double)(nrel), 1.0, _state);
24649 :
24650 : /*
24651 : * Append prior term.
24652 : * Transform spline to original coordinates.
24653 : * Output.
24654 : */
24655 0 : for(i=0; i<=m-1; i++)
24656 : {
24657 0 : sy.ptr.p_double[i] = sy.ptr.p_double[i]+vterm.ptr.pp_double[0][0]*sx.ptr.p_double[i]+vterm.ptr.pp_double[0][1];
24658 0 : sdy.ptr.p_double[i] = sdy.ptr.p_double[i]+vterm.ptr.pp_double[0][0];
24659 : }
24660 0 : for(i=0; i<=m-1; i++)
24661 : {
24662 0 : sx.ptr.p_double[i] = sx.ptr.p_double[i]*(xb-xa)+xa;
24663 0 : sdy.ptr.p_double[i] = sdy.ptr.p_double[i]/(xb-xa);
24664 : }
24665 0 : spline1dbuildhermite(&sx, &sy, &sdy, m, s, _state);
24666 0 : ae_frame_leave(_state);
24667 0 : }
24668 :
24669 :
24670 : /*************************************************************************
24671 : Internal version of Spline1DConvDiff
24672 :
24673 : Converts from Hermite spline given by grid XOld to new grid X2
24674 :
24675 : INPUT PARAMETERS:
24676 : XOld - old grid
24677 : YOld - values at old grid
24678 : DOld - first derivative at old grid
24679 : N - grid size
24680 : X2 - new grid
24681 : N2 - new grid size
24682 : Y - possibly preallocated output array
24683 : (reallocate if too small)
24684 : NeedY - do we need Y?
24685 : D1 - possibly preallocated output array
24686 : (reallocate if too small)
24687 : NeedD1 - do we need D1?
24688 : D2 - possibly preallocated output array
24689 : (reallocate if too small)
24690 : NeedD2 - do we need D1?
24691 :
24692 : OUTPUT ARRAYS:
24693 : Y - values, if needed
24694 : D1 - first derivative, if needed
24695 : D2 - second derivative, if needed
24696 :
24697 : -- ALGLIB PROJECT --
24698 : Copyright 03.09.2010 by Bochkanov Sergey
24699 : *************************************************************************/
24700 0 : void spline1dconvdiffinternal(/* Real */ ae_vector* xold,
24701 : /* Real */ ae_vector* yold,
24702 : /* Real */ ae_vector* dold,
24703 : ae_int_t n,
24704 : /* Real */ ae_vector* x2,
24705 : ae_int_t n2,
24706 : /* Real */ ae_vector* y,
24707 : ae_bool needy,
24708 : /* Real */ ae_vector* d1,
24709 : ae_bool needd1,
24710 : /* Real */ ae_vector* d2,
24711 : ae_bool needd2,
24712 : ae_state *_state)
24713 : {
24714 : ae_int_t intervalindex;
24715 : ae_int_t pointindex;
24716 : ae_bool havetoadvance;
24717 : double c0;
24718 : double c1;
24719 : double c2;
24720 : double c3;
24721 : double a;
24722 : double b;
24723 : double w;
24724 : double w2;
24725 : double w3;
24726 : double fa;
24727 : double fb;
24728 : double da;
24729 : double db;
24730 : double t;
24731 :
24732 :
24733 :
24734 : /*
24735 : * Prepare space
24736 : */
24737 0 : if( needy&&y->cnt<n2 )
24738 : {
24739 0 : ae_vector_set_length(y, n2, _state);
24740 : }
24741 0 : if( needd1&&d1->cnt<n2 )
24742 : {
24743 0 : ae_vector_set_length(d1, n2, _state);
24744 : }
24745 0 : if( needd2&&d2->cnt<n2 )
24746 : {
24747 0 : ae_vector_set_length(d2, n2, _state);
24748 : }
24749 :
24750 : /*
24751 : * These assignments aren't actually needed
24752 : * (variables are initialized in the loop below),
24753 : * but without them compiler will complain about uninitialized locals
24754 : */
24755 0 : c0 = (double)(0);
24756 0 : c1 = (double)(0);
24757 0 : c2 = (double)(0);
24758 0 : c3 = (double)(0);
24759 0 : a = (double)(0);
24760 0 : b = (double)(0);
24761 :
24762 : /*
24763 : * Cycle
24764 : */
24765 0 : intervalindex = -1;
24766 0 : pointindex = 0;
24767 : for(;;)
24768 : {
24769 :
24770 : /*
24771 : * are we ready to exit?
24772 : */
24773 0 : if( pointindex>=n2 )
24774 : {
24775 0 : break;
24776 : }
24777 0 : t = x2->ptr.p_double[pointindex];
24778 :
24779 : /*
24780 : * do we need to advance interval?
24781 : */
24782 0 : havetoadvance = ae_false;
24783 0 : if( intervalindex==-1 )
24784 : {
24785 0 : havetoadvance = ae_true;
24786 : }
24787 : else
24788 : {
24789 0 : if( intervalindex<n-2 )
24790 : {
24791 0 : havetoadvance = ae_fp_greater_eq(t,b);
24792 : }
24793 : }
24794 0 : if( havetoadvance )
24795 : {
24796 0 : intervalindex = intervalindex+1;
24797 0 : a = xold->ptr.p_double[intervalindex];
24798 0 : b = xold->ptr.p_double[intervalindex+1];
24799 0 : w = b-a;
24800 0 : w2 = w*w;
24801 0 : w3 = w*w2;
24802 0 : fa = yold->ptr.p_double[intervalindex];
24803 0 : fb = yold->ptr.p_double[intervalindex+1];
24804 0 : da = dold->ptr.p_double[intervalindex];
24805 0 : db = dold->ptr.p_double[intervalindex+1];
24806 0 : c0 = fa;
24807 0 : c1 = da;
24808 0 : c2 = (3*(fb-fa)-2*da*w-db*w)/w2;
24809 0 : c3 = (2*(fa-fb)+da*w+db*w)/w3;
24810 0 : continue;
24811 : }
24812 :
24813 : /*
24814 : * Calculate spline and its derivatives using power basis
24815 : */
24816 0 : t = t-a;
24817 0 : if( needy )
24818 : {
24819 0 : y->ptr.p_double[pointindex] = c0+t*(c1+t*(c2+t*c3));
24820 : }
24821 0 : if( needd1 )
24822 : {
24823 0 : d1->ptr.p_double[pointindex] = c1+2*t*c2+3*t*t*c3;
24824 : }
24825 0 : if( needd2 )
24826 : {
24827 0 : d2->ptr.p_double[pointindex] = 2*c2+6*t*c3;
24828 : }
24829 0 : pointindex = pointindex+1;
24830 : }
24831 0 : }
24832 :
24833 :
24834 : /*************************************************************************
24835 : This function finds all roots and extrema of the spline S(x) defined at
24836 : [A,B] (interval which contains spline nodes).
24837 :
24838 : It does not extrapolates function, so roots and extrema located outside
24839 : of [A,B] will not be found. It returns all isolated (including multiple)
24840 : roots and extrema.
24841 :
24842 : INPUT PARAMETERS
24843 : C - spline interpolant
24844 :
24845 : OUTPUT PARAMETERS
24846 : R - array[NR], contains roots of the spline.
24847 : In case there is no roots, this array has zero length.
24848 : NR - number of roots, >=0
24849 : DR - is set to True in case there is at least one interval
24850 : where spline is just a zero constant. Such degenerate
24851 : cases are not reported in the R/NR
24852 : E - array[NE], contains extrema (maximums/minimums) of
24853 : the spline. In case there is no extrema, this array
24854 : has zero length.
24855 : ET - array[NE], extrema types:
24856 : * ET[i]>0 in case I-th extrema is a minimum
24857 : * ET[i]<0 in case I-th extrema is a maximum
24858 : NE - number of extrema, >=0
24859 : DE - is set to True in case there is at least one interval
24860 : where spline is a constant. Such degenerate cases are
24861 : not reported in the E/NE.
24862 :
24863 : NOTES:
24864 :
24865 : 1. This function does NOT report following kinds of roots:
24866 : * intervals where function is constantly zero
24867 : * roots which are outside of [A,B] (note: it CAN return A or B)
24868 :
24869 : 2. This function does NOT report following kinds of extrema:
24870 : * intervals where function is a constant
24871 : * extrema which are outside of (A,B) (note: it WON'T return A or B)
24872 :
24873 : -- ALGLIB PROJECT --
24874 : Copyright 26.09.2011 by Bochkanov Sergey
24875 : *************************************************************************/
24876 0 : void spline1drootsandextrema(spline1dinterpolant* c,
24877 : /* Real */ ae_vector* r,
24878 : ae_int_t* nr,
24879 : ae_bool* dr,
24880 : /* Real */ ae_vector* e,
24881 : /* Integer */ ae_vector* et,
24882 : ae_int_t* ne,
24883 : ae_bool* de,
24884 : ae_state *_state)
24885 : {
24886 : ae_frame _frame_block;
24887 : double pl;
24888 : double ml;
24889 : double pll;
24890 : double pr;
24891 : double mr;
24892 : ae_vector tr;
24893 : ae_vector tmpr;
24894 : ae_vector tmpe;
24895 : ae_vector tmpet;
24896 : ae_vector tmpc;
24897 : double x0;
24898 : double x1;
24899 : double x2;
24900 : double ex0;
24901 : double ex1;
24902 : ae_int_t tne;
24903 : ae_int_t tnr;
24904 : ae_int_t i;
24905 : ae_int_t j;
24906 : ae_bool nstep;
24907 :
24908 0 : ae_frame_make(_state, &_frame_block);
24909 0 : memset(&tr, 0, sizeof(tr));
24910 0 : memset(&tmpr, 0, sizeof(tmpr));
24911 0 : memset(&tmpe, 0, sizeof(tmpe));
24912 0 : memset(&tmpet, 0, sizeof(tmpet));
24913 0 : memset(&tmpc, 0, sizeof(tmpc));
24914 0 : ae_vector_clear(r);
24915 0 : *nr = 0;
24916 0 : *dr = ae_false;
24917 0 : ae_vector_clear(e);
24918 0 : ae_vector_clear(et);
24919 0 : *ne = 0;
24920 0 : *de = ae_false;
24921 0 : ae_vector_init(&tr, 0, DT_REAL, _state, ae_true);
24922 0 : ae_vector_init(&tmpr, 0, DT_REAL, _state, ae_true);
24923 0 : ae_vector_init(&tmpe, 0, DT_REAL, _state, ae_true);
24924 0 : ae_vector_init(&tmpet, 0, DT_INT, _state, ae_true);
24925 0 : ae_vector_init(&tmpc, 0, DT_REAL, _state, ae_true);
24926 :
24927 :
24928 : /*
24929 : *exception handling
24930 : */
24931 0 : ae_assert(c->k==3, "Spline1DRootsAndExtrema : incorrect parameter C.K!", _state);
24932 0 : ae_assert(c->continuity>=0, "Spline1DRootsAndExtrema : parameter C.Continuity must not be less than 0!", _state);
24933 :
24934 : /*
24935 : *initialization of variable
24936 : */
24937 0 : *nr = 0;
24938 0 : *ne = 0;
24939 0 : *dr = ae_false;
24940 0 : *de = ae_false;
24941 0 : nstep = ae_true;
24942 :
24943 : /*
24944 : *consider case, when C.Continuty=0
24945 : */
24946 0 : if( c->continuity==0 )
24947 : {
24948 :
24949 : /*
24950 : *allocation for auxiliary arrays
24951 : *'TmpR ' - it stores a time value for roots
24952 : *'TmpE ' - it stores a time value for extremums
24953 : *'TmpET '- it stores a time value for extremums type
24954 : */
24955 0 : rvectorsetlengthatleast(&tmpr, 3*(c->n-1), _state);
24956 0 : rvectorsetlengthatleast(&tmpe, 2*(c->n-1), _state);
24957 0 : ivectorsetlengthatleast(&tmpet, 2*(c->n-1), _state);
24958 :
24959 : /*
24960 : *start calculating
24961 : */
24962 0 : for(i=0; i<=c->n-2; i++)
24963 : {
24964 :
24965 : /*
24966 : *initialization pL, mL, pR, mR
24967 : */
24968 0 : pl = c->c.ptr.p_double[4*i];
24969 0 : ml = c->c.ptr.p_double[4*i+1];
24970 0 : pr = c->c.ptr.p_double[4*(i+1)];
24971 0 : mr = c->c.ptr.p_double[4*i+1]+2*c->c.ptr.p_double[4*i+2]*(c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i])+3*c->c.ptr.p_double[4*i+3]*(c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i])*(c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i]);
24972 :
24973 : /*
24974 : *pre-searching roots and extremums
24975 : */
24976 0 : solvecubicpolinom(pl, ml, pr, mr, c->x.ptr.p_double[i], c->x.ptr.p_double[i+1], &x0, &x1, &x2, &ex0, &ex1, &tnr, &tne, &tr, _state);
24977 0 : *dr = *dr||tnr==-1;
24978 0 : *de = *de||tne==-1;
24979 :
24980 : /*
24981 : *searching of roots
24982 : */
24983 0 : if( tnr==1&&nstep )
24984 : {
24985 :
24986 : /*
24987 : *is there roots?
24988 : */
24989 0 : if( *nr>0 )
24990 : {
24991 :
24992 : /*
24993 : *is a next root equal a previous root?
24994 : *if is't, then write new root
24995 : */
24996 0 : if( ae_fp_neq(x0,tmpr.ptr.p_double[*nr-1]) )
24997 : {
24998 0 : tmpr.ptr.p_double[*nr] = x0;
24999 0 : *nr = *nr+1;
25000 : }
25001 : }
25002 : else
25003 : {
25004 :
25005 : /*
25006 : *write a first root
25007 : */
25008 0 : tmpr.ptr.p_double[*nr] = x0;
25009 0 : *nr = *nr+1;
25010 : }
25011 : }
25012 : else
25013 : {
25014 :
25015 : /*
25016 : *case when function at a segment identically to zero
25017 : *then we have to clear a root, if the one located on a
25018 : *constant segment
25019 : */
25020 0 : if( tnr==-1 )
25021 : {
25022 :
25023 : /*
25024 : *safe state variable as constant
25025 : */
25026 0 : if( nstep )
25027 : {
25028 0 : nstep = ae_false;
25029 : }
25030 :
25031 : /*
25032 : *clear the root, if there is
25033 : */
25034 0 : if( *nr>0 )
25035 : {
25036 0 : if( ae_fp_eq(c->x.ptr.p_double[i],tmpr.ptr.p_double[*nr-1]) )
25037 : {
25038 0 : *nr = *nr-1;
25039 : }
25040 : }
25041 :
25042 : /*
25043 : *change state for 'DR'
25044 : */
25045 0 : if( !*dr )
25046 : {
25047 0 : *dr = ae_true;
25048 : }
25049 : }
25050 : else
25051 : {
25052 0 : nstep = ae_true;
25053 : }
25054 : }
25055 :
25056 : /*
25057 : *searching of extremums
25058 : */
25059 0 : if( i>0 )
25060 : {
25061 0 : pll = c->c.ptr.p_double[4*(i-1)];
25062 :
25063 : /*
25064 : *if pL=pLL or pL=pR then
25065 : */
25066 0 : if( tne==-1 )
25067 : {
25068 0 : if( !*de )
25069 : {
25070 0 : *de = ae_true;
25071 : }
25072 : }
25073 : else
25074 : {
25075 0 : if( ae_fp_greater(pl,pll)&&ae_fp_greater(pl,pr) )
25076 : {
25077 :
25078 : /*
25079 : *maximum
25080 : */
25081 0 : tmpet.ptr.p_int[*ne] = -1;
25082 0 : tmpe.ptr.p_double[*ne] = c->x.ptr.p_double[i];
25083 0 : *ne = *ne+1;
25084 : }
25085 : else
25086 : {
25087 0 : if( ae_fp_less(pl,pll)&&ae_fp_less(pl,pr) )
25088 : {
25089 :
25090 : /*
25091 : *minimum
25092 : */
25093 0 : tmpet.ptr.p_int[*ne] = 1;
25094 0 : tmpe.ptr.p_double[*ne] = c->x.ptr.p_double[i];
25095 0 : *ne = *ne+1;
25096 : }
25097 : }
25098 : }
25099 : }
25100 : }
25101 :
25102 : /*
25103 : *write final result
25104 : */
25105 0 : rvectorsetlengthatleast(r, *nr, _state);
25106 0 : rvectorsetlengthatleast(e, *ne, _state);
25107 0 : ivectorsetlengthatleast(et, *ne, _state);
25108 :
25109 : /*
25110 : *write roots
25111 : */
25112 0 : for(i=0; i<=*nr-1; i++)
25113 : {
25114 0 : r->ptr.p_double[i] = tmpr.ptr.p_double[i];
25115 : }
25116 :
25117 : /*
25118 : *write extremums and their types
25119 : */
25120 0 : for(i=0; i<=*ne-1; i++)
25121 : {
25122 0 : e->ptr.p_double[i] = tmpe.ptr.p_double[i];
25123 0 : et->ptr.p_int[i] = tmpet.ptr.p_int[i];
25124 : }
25125 : }
25126 : else
25127 : {
25128 :
25129 : /*
25130 : *case, when C.Continuity>=1
25131 : *'TmpR ' - it stores a time value for roots
25132 : *'TmpC' - it stores a time value for extremums and
25133 : *their function value (TmpC={EX0,F(EX0), EX1,F(EX1), ..., EXn,F(EXn)};)
25134 : *'TmpE' - it stores a time value for extremums only
25135 : *'TmpET'- it stores a time value for extremums type
25136 : */
25137 0 : rvectorsetlengthatleast(&tmpr, 2*c->n-1, _state);
25138 0 : rvectorsetlengthatleast(&tmpc, 4*c->n, _state);
25139 0 : rvectorsetlengthatleast(&tmpe, 2*c->n, _state);
25140 0 : ivectorsetlengthatleast(&tmpet, 2*c->n, _state);
25141 :
25142 : /*
25143 : *start calculating
25144 : */
25145 0 : for(i=0; i<=c->n-2; i++)
25146 : {
25147 :
25148 : /*
25149 : *we calculate pL,mL, pR,mR as Fi+1(F'i+1) at left border
25150 : */
25151 0 : pl = c->c.ptr.p_double[4*i];
25152 0 : ml = c->c.ptr.p_double[4*i+1];
25153 0 : pr = c->c.ptr.p_double[4*(i+1)];
25154 0 : mr = c->c.ptr.p_double[4*(i+1)+1];
25155 :
25156 : /*
25157 : *calculating roots and extremums at [X[i],X[i+1]]
25158 : */
25159 0 : solvecubicpolinom(pl, ml, pr, mr, c->x.ptr.p_double[i], c->x.ptr.p_double[i+1], &x0, &x1, &x2, &ex0, &ex1, &tnr, &tne, &tr, _state);
25160 :
25161 : /*
25162 : *searching roots
25163 : */
25164 0 : if( tnr>0 )
25165 : {
25166 :
25167 : /*
25168 : *re-init tR
25169 : */
25170 0 : if( tnr>=1 )
25171 : {
25172 0 : tr.ptr.p_double[0] = x0;
25173 : }
25174 0 : if( tnr>=2 )
25175 : {
25176 0 : tr.ptr.p_double[1] = x1;
25177 : }
25178 0 : if( tnr==3 )
25179 : {
25180 0 : tr.ptr.p_double[2] = x2;
25181 : }
25182 :
25183 : /*
25184 : *start root selection
25185 : */
25186 0 : if( *nr>0 )
25187 : {
25188 0 : if( ae_fp_neq(tmpr.ptr.p_double[*nr-1],x0) )
25189 : {
25190 :
25191 : /*
25192 : *previous segment was't constant identical zero
25193 : */
25194 0 : if( nstep )
25195 : {
25196 0 : for(j=0; j<=tnr-1; j++)
25197 : {
25198 0 : tmpr.ptr.p_double[*nr+j] = tr.ptr.p_double[j];
25199 : }
25200 0 : *nr = *nr+tnr;
25201 : }
25202 : else
25203 : {
25204 :
25205 : /*
25206 : *previous segment was constant identical zero
25207 : *and we must ignore [NR+j-1] root
25208 : */
25209 0 : for(j=1; j<=tnr-1; j++)
25210 : {
25211 0 : tmpr.ptr.p_double[*nr+j-1] = tr.ptr.p_double[j];
25212 : }
25213 0 : *nr = *nr+tnr-1;
25214 0 : nstep = ae_true;
25215 : }
25216 : }
25217 : else
25218 : {
25219 0 : for(j=1; j<=tnr-1; j++)
25220 : {
25221 0 : tmpr.ptr.p_double[*nr+j-1] = tr.ptr.p_double[j];
25222 : }
25223 0 : *nr = *nr+tnr-1;
25224 : }
25225 : }
25226 : else
25227 : {
25228 :
25229 : /*
25230 : *write first root
25231 : */
25232 0 : for(j=0; j<=tnr-1; j++)
25233 : {
25234 0 : tmpr.ptr.p_double[*nr+j] = tr.ptr.p_double[j];
25235 : }
25236 0 : *nr = *nr+tnr;
25237 : }
25238 : }
25239 : else
25240 : {
25241 0 : if( tnr==-1 )
25242 : {
25243 :
25244 : /*
25245 : *decrement 'NR' if at previous step was writen a root
25246 : *(previous segment identical zero)
25247 : */
25248 0 : if( *nr>0&&nstep )
25249 : {
25250 0 : *nr = *nr-1;
25251 : }
25252 :
25253 : /*
25254 : *previous segment is't constant
25255 : */
25256 0 : if( nstep )
25257 : {
25258 0 : nstep = ae_false;
25259 : }
25260 :
25261 : /*
25262 : *rewrite 'DR'
25263 : */
25264 0 : if( !*dr )
25265 : {
25266 0 : *dr = ae_true;
25267 : }
25268 : }
25269 : }
25270 :
25271 : /*
25272 : *searching extremums
25273 : *write all term like extremums
25274 : */
25275 0 : if( tne==1 )
25276 : {
25277 0 : if( *ne>0 )
25278 : {
25279 :
25280 : /*
25281 : *just ignore identical extremums
25282 : *because he must be one
25283 : */
25284 0 : if( ae_fp_neq(tmpc.ptr.p_double[*ne-2],ex0) )
25285 : {
25286 0 : tmpc.ptr.p_double[*ne] = ex0;
25287 0 : tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]);
25288 0 : *ne = *ne+2;
25289 : }
25290 : }
25291 : else
25292 : {
25293 :
25294 : /*
25295 : *write first extremum and it function value
25296 : */
25297 0 : tmpc.ptr.p_double[*ne] = ex0;
25298 0 : tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]);
25299 0 : *ne = *ne+2;
25300 : }
25301 : }
25302 : else
25303 : {
25304 0 : if( tne==2 )
25305 : {
25306 0 : if( *ne>0 )
25307 : {
25308 :
25309 : /*
25310 : *ignore identical extremum
25311 : */
25312 0 : if( ae_fp_neq(tmpc.ptr.p_double[*ne-2],ex0) )
25313 : {
25314 0 : tmpc.ptr.p_double[*ne] = ex0;
25315 0 : tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]);
25316 0 : *ne = *ne+2;
25317 : }
25318 : }
25319 : else
25320 : {
25321 :
25322 : /*
25323 : *write first extremum
25324 : */
25325 0 : tmpc.ptr.p_double[*ne] = ex0;
25326 0 : tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i])*(ex0-c->x.ptr.p_double[i]);
25327 0 : *ne = *ne+2;
25328 : }
25329 :
25330 : /*
25331 : *write second extremum
25332 : */
25333 0 : tmpc.ptr.p_double[*ne] = ex1;
25334 0 : tmpc.ptr.p_double[*ne+1] = c->c.ptr.p_double[4*i]+c->c.ptr.p_double[4*i+1]*(ex1-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+2]*(ex1-c->x.ptr.p_double[i])*(ex1-c->x.ptr.p_double[i])+c->c.ptr.p_double[4*i+3]*(ex1-c->x.ptr.p_double[i])*(ex1-c->x.ptr.p_double[i])*(ex1-c->x.ptr.p_double[i]);
25335 0 : *ne = *ne+2;
25336 : }
25337 : else
25338 : {
25339 0 : if( tne==-1 )
25340 : {
25341 0 : if( !*de )
25342 : {
25343 0 : *de = ae_true;
25344 : }
25345 : }
25346 : }
25347 : }
25348 : }
25349 :
25350 : /*
25351 : *checking of arrays
25352 : *get number of extremums (tNe=NE/2)
25353 : *initialize pL as value F0(X[0]) and
25354 : *initialize pR as value Fn-1(X[N])
25355 : */
25356 0 : tne = *ne/2;
25357 0 : *ne = 0;
25358 0 : pl = c->c.ptr.p_double[0];
25359 0 : pr = c->c.ptr.p_double[4*(c->n-1)];
25360 0 : for(i=0; i<=tne-1; i++)
25361 : {
25362 0 : if( i>0&&i<tne-1 )
25363 : {
25364 0 : if( ae_fp_greater(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i-1)+1])&&ae_fp_greater(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i+1)+1]) )
25365 : {
25366 :
25367 : /*
25368 : *maximum
25369 : */
25370 0 : tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
25371 0 : tmpet.ptr.p_int[*ne] = -1;
25372 0 : *ne = *ne+1;
25373 : }
25374 : else
25375 : {
25376 0 : if( ae_fp_less(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i-1)+1])&&ae_fp_less(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i+1)+1]) )
25377 : {
25378 :
25379 : /*
25380 : *minimum
25381 : */
25382 0 : tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
25383 0 : tmpet.ptr.p_int[*ne] = 1;
25384 0 : *ne = *ne+1;
25385 : }
25386 : }
25387 : }
25388 : else
25389 : {
25390 0 : if( i==0 )
25391 : {
25392 0 : if( ae_fp_neq(tmpc.ptr.p_double[2*i],c->x.ptr.p_double[0]) )
25393 : {
25394 0 : if( ae_fp_greater(tmpc.ptr.p_double[2*i+1],pl)&&ae_fp_greater(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i+1)+1]) )
25395 : {
25396 :
25397 : /*
25398 : *maximum
25399 : */
25400 0 : tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
25401 0 : tmpet.ptr.p_int[*ne] = -1;
25402 0 : *ne = *ne+1;
25403 : }
25404 : else
25405 : {
25406 0 : if( ae_fp_less(tmpc.ptr.p_double[2*i+1],pl)&&ae_fp_less(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i+1)+1]) )
25407 : {
25408 :
25409 : /*
25410 : *minimum
25411 : */
25412 0 : tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
25413 0 : tmpet.ptr.p_int[*ne] = 1;
25414 0 : *ne = *ne+1;
25415 : }
25416 : }
25417 : }
25418 : }
25419 : else
25420 : {
25421 0 : if( i==tne-1 )
25422 : {
25423 0 : if( ae_fp_neq(tmpc.ptr.p_double[2*i],c->x.ptr.p_double[c->n-1]) )
25424 : {
25425 0 : if( ae_fp_greater(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i-1)+1])&&ae_fp_greater(tmpc.ptr.p_double[2*i+1],pr) )
25426 : {
25427 :
25428 : /*
25429 : *maximum
25430 : */
25431 0 : tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
25432 0 : tmpet.ptr.p_int[*ne] = -1;
25433 0 : *ne = *ne+1;
25434 : }
25435 : else
25436 : {
25437 0 : if( ae_fp_less(tmpc.ptr.p_double[2*i+1],tmpc.ptr.p_double[2*(i-1)+1])&&ae_fp_less(tmpc.ptr.p_double[2*i+1],pr) )
25438 : {
25439 :
25440 : /*
25441 : *minimum
25442 : */
25443 0 : tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
25444 0 : tmpet.ptr.p_int[*ne] = 1;
25445 0 : *ne = *ne+1;
25446 : }
25447 : }
25448 : }
25449 : }
25450 : }
25451 : }
25452 : }
25453 :
25454 : /*
25455 : *final results
25456 : *allocate R, E, ET
25457 : */
25458 0 : rvectorsetlengthatleast(r, *nr, _state);
25459 0 : rvectorsetlengthatleast(e, *ne, _state);
25460 0 : ivectorsetlengthatleast(et, *ne, _state);
25461 :
25462 : /*
25463 : *write result for extremus and their types
25464 : */
25465 0 : for(i=0; i<=*ne-1; i++)
25466 : {
25467 0 : e->ptr.p_double[i] = tmpe.ptr.p_double[i];
25468 0 : et->ptr.p_int[i] = tmpet.ptr.p_int[i];
25469 : }
25470 :
25471 : /*
25472 : *write result for roots
25473 : */
25474 0 : for(i=0; i<=*nr-1; i++)
25475 : {
25476 0 : r->ptr.p_double[i] = tmpr.ptr.p_double[i];
25477 : }
25478 : }
25479 0 : ae_frame_leave(_state);
25480 0 : }
25481 :
25482 :
25483 : /*************************************************************************
25484 : Internal subroutine. Heap sort.
25485 : *************************************************************************/
25486 0 : void heapsortdpoints(/* Real */ ae_vector* x,
25487 : /* Real */ ae_vector* y,
25488 : /* Real */ ae_vector* d,
25489 : ae_int_t n,
25490 : ae_state *_state)
25491 : {
25492 : ae_frame _frame_block;
25493 : ae_vector rbuf;
25494 : ae_vector ibuf;
25495 : ae_vector rbuf2;
25496 : ae_vector ibuf2;
25497 : ae_int_t i;
25498 :
25499 0 : ae_frame_make(_state, &_frame_block);
25500 0 : memset(&rbuf, 0, sizeof(rbuf));
25501 0 : memset(&ibuf, 0, sizeof(ibuf));
25502 0 : memset(&rbuf2, 0, sizeof(rbuf2));
25503 0 : memset(&ibuf2, 0, sizeof(ibuf2));
25504 0 : ae_vector_init(&rbuf, 0, DT_REAL, _state, ae_true);
25505 0 : ae_vector_init(&ibuf, 0, DT_INT, _state, ae_true);
25506 0 : ae_vector_init(&rbuf2, 0, DT_REAL, _state, ae_true);
25507 0 : ae_vector_init(&ibuf2, 0, DT_INT, _state, ae_true);
25508 :
25509 0 : ae_vector_set_length(&ibuf, n, _state);
25510 0 : ae_vector_set_length(&rbuf, n, _state);
25511 0 : for(i=0; i<=n-1; i++)
25512 : {
25513 0 : ibuf.ptr.p_int[i] = i;
25514 : }
25515 0 : tagsortfasti(x, &ibuf, &rbuf2, &ibuf2, n, _state);
25516 0 : for(i=0; i<=n-1; i++)
25517 : {
25518 0 : rbuf.ptr.p_double[i] = y->ptr.p_double[ibuf.ptr.p_int[i]];
25519 : }
25520 0 : ae_v_move(&y->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1));
25521 0 : for(i=0; i<=n-1; i++)
25522 : {
25523 0 : rbuf.ptr.p_double[i] = d->ptr.p_double[ibuf.ptr.p_int[i]];
25524 : }
25525 0 : ae_v_move(&d->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1));
25526 0 : ae_frame_leave(_state);
25527 0 : }
25528 :
25529 :
25530 : /*************************************************************************
25531 : This procedure search roots of an quadratic equation inside [0;1] and it number of roots.
25532 :
25533 : INPUT PARAMETERS:
25534 : P0 - value of a function at 0
25535 : M0 - value of a derivative at 0
25536 : P1 - value of a function at 1
25537 : M1 - value of a derivative at 1
25538 :
25539 : OUTPUT PARAMETERS:
25540 : X0 - first root of an equation
25541 : X1 - second root of an equation
25542 : NR - number of roots
25543 :
25544 : RESTRICTIONS OF PARAMETERS:
25545 :
25546 : Parameters for this procedure has't to be zero simultaneously. Is expected,
25547 : that input polinom is't degenerate or constant identicaly ZERO.
25548 :
25549 :
25550 : REMARK:
25551 :
25552 : The procedure always fill value for X1 and X2, even if it is't belongs to [0;1].
25553 : But first true root(even if existing one) is in X1.
25554 : Number of roots is NR.
25555 :
25556 : -- ALGLIB PROJECT --
25557 : Copyright 26.09.2011 by Bochkanov Sergey
25558 : *************************************************************************/
25559 0 : void solvepolinom2(double p0,
25560 : double m0,
25561 : double p1,
25562 : double m1,
25563 : double* x0,
25564 : double* x1,
25565 : ae_int_t* nr,
25566 : ae_state *_state)
25567 : {
25568 : double a;
25569 : double b;
25570 : double c;
25571 : double dd;
25572 : double tmp;
25573 : double exf;
25574 : double extr;
25575 :
25576 0 : *x0 = 0;
25577 0 : *x1 = 0;
25578 0 : *nr = 0;
25579 :
25580 :
25581 : /*
25582 : *calculate parameters for equation: A, B and C
25583 : */
25584 0 : a = 6*p0+3*m0-6*p1+3*m1;
25585 0 : b = -6*p0-4*m0+6*p1-2*m1;
25586 0 : c = m0;
25587 :
25588 : /*
25589 : *check case, when A=0
25590 : *we are considering the linear equation
25591 : */
25592 0 : if( ae_fp_eq(a,(double)(0)) )
25593 : {
25594 :
25595 : /*
25596 : *B<>0 and root inside [0;1]
25597 : *one root
25598 : */
25599 0 : if( (ae_fp_neq(b,(double)(0))&&ae_sign(c, _state)*ae_sign(b, _state)<=0)&&ae_fp_greater_eq(ae_fabs(b, _state),ae_fabs(c, _state)) )
25600 : {
25601 0 : *x0 = -c/b;
25602 0 : *nr = 1;
25603 0 : return;
25604 : }
25605 : else
25606 : {
25607 0 : *nr = 0;
25608 0 : return;
25609 : }
25610 : }
25611 :
25612 : /*
25613 : *consider case, when extremumu outside (0;1)
25614 : *exist one root only
25615 : */
25616 0 : if( ae_fp_less_eq(ae_fabs(2*a, _state),ae_fabs(b, _state))||ae_sign(b, _state)*ae_sign(a, _state)>=0 )
25617 : {
25618 0 : if( ae_sign(m0, _state)*ae_sign(m1, _state)>0 )
25619 : {
25620 0 : *nr = 0;
25621 0 : return;
25622 : }
25623 :
25624 : /*
25625 : *consider case, when the one exist
25626 : *same sign of derivative
25627 : */
25628 0 : if( ae_sign(m0, _state)*ae_sign(m1, _state)<0 )
25629 : {
25630 0 : *nr = 1;
25631 0 : extr = -b/(2*a);
25632 0 : dd = b*b-4*a*c;
25633 0 : if( ae_fp_less(dd,(double)(0)) )
25634 : {
25635 0 : return;
25636 : }
25637 0 : *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
25638 0 : *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
25639 0 : if( (ae_fp_greater_eq(extr,(double)(1))&&ae_fp_less_eq(*x1,extr))||(ae_fp_less_eq(extr,(double)(0))&&ae_fp_greater_eq(*x1,extr)) )
25640 : {
25641 0 : *x0 = *x1;
25642 : }
25643 0 : return;
25644 : }
25645 :
25646 : /*
25647 : *consider case, when the one is 0
25648 : */
25649 0 : if( ae_fp_eq(m0,(double)(0)) )
25650 : {
25651 0 : *x0 = (double)(0);
25652 0 : *nr = 1;
25653 0 : return;
25654 : }
25655 0 : if( ae_fp_eq(m1,(double)(0)) )
25656 : {
25657 0 : *x0 = (double)(1);
25658 0 : *nr = 1;
25659 0 : return;
25660 : }
25661 : }
25662 : else
25663 : {
25664 :
25665 : /*
25666 : *consider case, when both of derivatives is 0
25667 : */
25668 0 : if( ae_fp_eq(m0,(double)(0))&&ae_fp_eq(m1,(double)(0)) )
25669 : {
25670 0 : *x0 = (double)(0);
25671 0 : *x1 = (double)(1);
25672 0 : *nr = 2;
25673 0 : return;
25674 : }
25675 :
25676 : /*
25677 : *consider case, when derivative at 0 is 0, and derivative at 1 is't 0
25678 : */
25679 0 : if( ae_fp_eq(m0,(double)(0))&&ae_fp_neq(m1,(double)(0)) )
25680 : {
25681 0 : dd = b*b-4*a*c;
25682 0 : if( ae_fp_less(dd,(double)(0)) )
25683 : {
25684 0 : *x0 = (double)(0);
25685 0 : *nr = 1;
25686 0 : return;
25687 : }
25688 0 : *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
25689 0 : *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
25690 0 : extr = -b/(2*a);
25691 0 : exf = a*extr*extr+b*extr+c;
25692 0 : if( ae_sign(exf, _state)*ae_sign(m1, _state)>0 )
25693 : {
25694 0 : *x0 = (double)(0);
25695 0 : *nr = 1;
25696 0 : return;
25697 : }
25698 : else
25699 : {
25700 0 : if( ae_fp_greater(extr,*x0) )
25701 : {
25702 0 : *x0 = (double)(0);
25703 : }
25704 : else
25705 : {
25706 0 : *x1 = (double)(0);
25707 : }
25708 0 : *nr = 2;
25709 :
25710 : /*
25711 : *roots must placed ascending
25712 : */
25713 0 : if( ae_fp_greater(*x0,*x1) )
25714 : {
25715 0 : tmp = *x0;
25716 0 : *x0 = *x1;
25717 0 : *x1 = tmp;
25718 : }
25719 0 : return;
25720 : }
25721 : }
25722 0 : if( ae_fp_eq(m1,(double)(0))&&ae_fp_neq(m0,(double)(0)) )
25723 : {
25724 0 : dd = b*b-4*a*c;
25725 0 : if( ae_fp_less(dd,(double)(0)) )
25726 : {
25727 0 : *x0 = (double)(1);
25728 0 : *nr = 1;
25729 0 : return;
25730 : }
25731 0 : *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
25732 0 : *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
25733 0 : extr = -b/(2*a);
25734 0 : exf = a*extr*extr+b*extr+c;
25735 0 : if( ae_sign(exf, _state)*ae_sign(m0, _state)>0 )
25736 : {
25737 0 : *x0 = (double)(1);
25738 0 : *nr = 1;
25739 0 : return;
25740 : }
25741 : else
25742 : {
25743 0 : if( ae_fp_less(extr,*x0) )
25744 : {
25745 0 : *x0 = (double)(1);
25746 : }
25747 : else
25748 : {
25749 0 : *x1 = (double)(1);
25750 : }
25751 0 : *nr = 2;
25752 :
25753 : /*
25754 : *roots must placed ascending
25755 : */
25756 0 : if( ae_fp_greater(*x0,*x1) )
25757 : {
25758 0 : tmp = *x0;
25759 0 : *x0 = *x1;
25760 0 : *x1 = tmp;
25761 : }
25762 0 : return;
25763 : }
25764 : }
25765 : else
25766 : {
25767 0 : extr = -b/(2*a);
25768 0 : exf = a*extr*extr+b*extr+c;
25769 0 : if( ae_sign(exf, _state)*ae_sign(m0, _state)>0&&ae_sign(exf, _state)*ae_sign(m1, _state)>0 )
25770 : {
25771 0 : *nr = 0;
25772 0 : return;
25773 : }
25774 0 : dd = b*b-4*a*c;
25775 0 : if( ae_fp_less(dd,(double)(0)) )
25776 : {
25777 0 : *nr = 0;
25778 0 : return;
25779 : }
25780 0 : *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
25781 0 : *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
25782 :
25783 : /*
25784 : *if EXF and m0, EXF and m1 has different signs, then equation has two roots
25785 : */
25786 0 : if( ae_sign(exf, _state)*ae_sign(m0, _state)<0&&ae_sign(exf, _state)*ae_sign(m1, _state)<0 )
25787 : {
25788 0 : *nr = 2;
25789 :
25790 : /*
25791 : *roots must placed ascending
25792 : */
25793 0 : if( ae_fp_greater(*x0,*x1) )
25794 : {
25795 0 : tmp = *x0;
25796 0 : *x0 = *x1;
25797 0 : *x1 = tmp;
25798 : }
25799 0 : return;
25800 : }
25801 : else
25802 : {
25803 0 : *nr = 1;
25804 0 : if( ae_sign(exf, _state)*ae_sign(m0, _state)<0 )
25805 : {
25806 0 : if( ae_fp_less(*x1,extr) )
25807 : {
25808 0 : *x0 = *x1;
25809 : }
25810 0 : return;
25811 : }
25812 0 : if( ae_sign(exf, _state)*ae_sign(m1, _state)<0 )
25813 : {
25814 0 : if( ae_fp_greater(*x1,extr) )
25815 : {
25816 0 : *x0 = *x1;
25817 : }
25818 0 : return;
25819 : }
25820 : }
25821 : }
25822 : }
25823 : }
25824 :
25825 :
25826 : /*************************************************************************
25827 : This procedure search roots of an cubic equation inside [A;B], it number of roots
25828 : and number of extremums.
25829 :
25830 : INPUT PARAMETERS:
25831 : pA - value of a function at A
25832 : mA - value of a derivative at A
25833 : pB - value of a function at B
25834 : mB - value of a derivative at B
25835 : A0 - left border [A0;B0]
25836 : B0 - right border [A0;B0]
25837 :
25838 : OUTPUT PARAMETERS:
25839 : X0 - first root of an equation
25840 : X1 - second root of an equation
25841 : X2 - third root of an equation
25842 : EX0 - first extremum of a function
25843 : EX0 - second extremum of a function
25844 : NR - number of roots
25845 : NR - number of extrmums
25846 :
25847 : RESTRICTIONS OF PARAMETERS:
25848 :
25849 : Length of [A;B] must be positive and is't zero, i.e. A<>B and A<B.
25850 :
25851 :
25852 : REMARK:
25853 :
25854 : If 'NR' is -1 it's mean, than polinom has infiniti roots.
25855 : If 'NE' is -1 it's mean, than polinom has infiniti extremums.
25856 :
25857 : -- ALGLIB PROJECT --
25858 : Copyright 26.09.2011 by Bochkanov Sergey
25859 : *************************************************************************/
25860 0 : void solvecubicpolinom(double pa,
25861 : double ma,
25862 : double pb,
25863 : double mb,
25864 : double a,
25865 : double b,
25866 : double* x0,
25867 : double* x1,
25868 : double* x2,
25869 : double* ex0,
25870 : double* ex1,
25871 : ae_int_t* nr,
25872 : ae_int_t* ne,
25873 : /* Real */ ae_vector* tempdata,
25874 : ae_state *_state)
25875 : {
25876 : ae_int_t i;
25877 : double tmpma;
25878 : double tmpmb;
25879 : double tex0;
25880 : double tex1;
25881 :
25882 0 : *x0 = 0;
25883 0 : *x1 = 0;
25884 0 : *x2 = 0;
25885 0 : *ex0 = 0;
25886 0 : *ex1 = 0;
25887 0 : *nr = 0;
25888 0 : *ne = 0;
25889 :
25890 0 : rvectorsetlengthatleast(tempdata, 3, _state);
25891 :
25892 : /*
25893 : *case, when A>B
25894 : */
25895 0 : ae_assert(ae_fp_less(a,b), "\nSolveCubicPolinom: incorrect borders for [A;B]!\n", _state);
25896 :
25897 : /*
25898 : *case 1
25899 : *function can be identicaly to ZERO
25900 : */
25901 0 : if( ((ae_fp_eq(ma,(double)(0))&&ae_fp_eq(mb,(double)(0)))&&ae_fp_eq(pa,pb))&&ae_fp_eq(pa,(double)(0)) )
25902 : {
25903 0 : *nr = -1;
25904 0 : *ne = -1;
25905 0 : return;
25906 : }
25907 0 : if( (ae_fp_eq(ma,(double)(0))&&ae_fp_eq(mb,(double)(0)))&&ae_fp_eq(pa,pb) )
25908 : {
25909 0 : *nr = 0;
25910 0 : *ne = -1;
25911 0 : return;
25912 : }
25913 0 : tmpma = ma*(b-a);
25914 0 : tmpmb = mb*(b-a);
25915 0 : solvepolinom2(pa, tmpma, pb, tmpmb, ex0, ex1, ne, _state);
25916 0 : *ex0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *ex0, _state);
25917 0 : *ex1 = spline1d_rescaleval((double)(0), (double)(1), a, b, *ex1, _state);
25918 :
25919 : /*
25920 : *case 3.1
25921 : *no extremums at [A;B]
25922 : */
25923 0 : if( *ne==0 )
25924 : {
25925 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), (double)(1), x0, _state);
25926 0 : if( *nr==1 )
25927 : {
25928 0 : *x0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *x0, _state);
25929 : }
25930 0 : return;
25931 : }
25932 :
25933 : /*
25934 : *case 3.2
25935 : *one extremum
25936 : */
25937 0 : if( *ne==1 )
25938 : {
25939 0 : if( ae_fp_eq(*ex0,a)||ae_fp_eq(*ex0,b) )
25940 : {
25941 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), (double)(1), x0, _state);
25942 0 : if( *nr==1 )
25943 : {
25944 0 : *x0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *x0, _state);
25945 : }
25946 0 : return;
25947 : }
25948 : else
25949 : {
25950 0 : *nr = 0;
25951 0 : i = 0;
25952 0 : tex0 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex0, _state);
25953 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex0, x0, _state)+(*nr);
25954 0 : if( *nr>i )
25955 : {
25956 0 : tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex0, a, *ex0, *x0, _state);
25957 0 : i = i+1;
25958 : }
25959 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, (double)(1), x0, _state)+(*nr);
25960 0 : if( *nr>i )
25961 : {
25962 0 : *x0 = spline1d_rescaleval(tex0, (double)(1), *ex0, b, *x0, _state);
25963 0 : if( i>0 )
25964 : {
25965 0 : if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
25966 : {
25967 0 : tempdata->ptr.p_double[i] = *x0;
25968 0 : i = i+1;
25969 : }
25970 : else
25971 : {
25972 0 : *nr = *nr-1;
25973 : }
25974 : }
25975 : else
25976 : {
25977 0 : tempdata->ptr.p_double[i] = *x0;
25978 0 : i = i+1;
25979 : }
25980 : }
25981 0 : if( *nr>0 )
25982 : {
25983 0 : *x0 = tempdata->ptr.p_double[0];
25984 0 : if( *nr>1 )
25985 : {
25986 0 : *x1 = tempdata->ptr.p_double[1];
25987 : }
25988 0 : return;
25989 : }
25990 : }
25991 0 : return;
25992 : }
25993 : else
25994 : {
25995 :
25996 : /*
25997 : *case 3.3
25998 : *two extremums(or more, but it's impossible)
25999 : *
26000 : *
26001 : *case 3.3.0
26002 : *both extremums at the border
26003 : */
26004 0 : if( ae_fp_eq(*ex0,a)&&ae_fp_eq(*ex1,b) )
26005 : {
26006 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), (double)(1), x0, _state);
26007 0 : if( *nr==1 )
26008 : {
26009 0 : *x0 = spline1d_rescaleval((double)(0), (double)(1), a, b, *x0, _state);
26010 : }
26011 0 : return;
26012 : }
26013 0 : if( ae_fp_eq(*ex0,a)&&ae_fp_neq(*ex1,b) )
26014 : {
26015 0 : *nr = 0;
26016 0 : i = 0;
26017 0 : tex1 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex1, _state);
26018 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex1, x0, _state)+(*nr);
26019 0 : if( *nr>i )
26020 : {
26021 0 : tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex1, a, *ex1, *x0, _state);
26022 0 : i = i+1;
26023 : }
26024 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex1, (double)(1), x0, _state)+(*nr);
26025 0 : if( *nr>i )
26026 : {
26027 0 : *x0 = spline1d_rescaleval(tex1, (double)(1), *ex1, b, *x0, _state);
26028 0 : if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
26029 : {
26030 0 : tempdata->ptr.p_double[i] = *x0;
26031 0 : i = i+1;
26032 : }
26033 : else
26034 : {
26035 0 : *nr = *nr-1;
26036 : }
26037 : }
26038 0 : if( *nr>0 )
26039 : {
26040 0 : *x0 = tempdata->ptr.p_double[0];
26041 0 : if( *nr>1 )
26042 : {
26043 0 : *x1 = tempdata->ptr.p_double[1];
26044 : }
26045 0 : return;
26046 : }
26047 : }
26048 0 : if( ae_fp_eq(*ex1,b)&&ae_fp_neq(*ex0,a) )
26049 : {
26050 0 : *nr = 0;
26051 0 : i = 0;
26052 0 : tex0 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex0, _state);
26053 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex0, x0, _state)+(*nr);
26054 0 : if( *nr>i )
26055 : {
26056 0 : tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex0, a, *ex0, *x0, _state);
26057 0 : i = i+1;
26058 : }
26059 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, (double)(1), x0, _state)+(*nr);
26060 0 : if( *nr>i )
26061 : {
26062 0 : *x0 = spline1d_rescaleval(tex0, (double)(1), *ex0, b, *x0, _state);
26063 0 : if( i>0 )
26064 : {
26065 0 : if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
26066 : {
26067 0 : tempdata->ptr.p_double[i] = *x0;
26068 0 : i = i+1;
26069 : }
26070 : else
26071 : {
26072 0 : *nr = *nr-1;
26073 : }
26074 : }
26075 : else
26076 : {
26077 0 : tempdata->ptr.p_double[i] = *x0;
26078 0 : i = i+1;
26079 : }
26080 : }
26081 0 : if( *nr>0 )
26082 : {
26083 0 : *x0 = tempdata->ptr.p_double[0];
26084 0 : if( *nr>1 )
26085 : {
26086 0 : *x1 = tempdata->ptr.p_double[1];
26087 : }
26088 0 : return;
26089 : }
26090 : }
26091 : else
26092 : {
26093 :
26094 : /*
26095 : *case 3.3.2
26096 : *both extremums inside (0;1)
26097 : */
26098 0 : *nr = 0;
26099 0 : i = 0;
26100 0 : tex0 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex0, _state);
26101 0 : tex1 = spline1d_rescaleval(a, b, (double)(0), (double)(1), *ex1, _state);
26102 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, (double)(0), tex0, x0, _state)+(*nr);
26103 0 : if( *nr>i )
26104 : {
26105 0 : tempdata->ptr.p_double[i] = spline1d_rescaleval((double)(0), tex0, a, *ex0, *x0, _state);
26106 0 : i = i+1;
26107 : }
26108 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, tex1, x0, _state)+(*nr);
26109 0 : if( *nr>i )
26110 : {
26111 0 : *x0 = spline1d_rescaleval(tex0, tex1, *ex0, *ex1, *x0, _state);
26112 0 : if( i>0 )
26113 : {
26114 0 : if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
26115 : {
26116 0 : tempdata->ptr.p_double[i] = *x0;
26117 0 : i = i+1;
26118 : }
26119 : else
26120 : {
26121 0 : *nr = *nr-1;
26122 : }
26123 : }
26124 : else
26125 : {
26126 0 : tempdata->ptr.p_double[i] = *x0;
26127 0 : i = i+1;
26128 : }
26129 : }
26130 0 : *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex1, (double)(1), x0, _state)+(*nr);
26131 0 : if( *nr>i )
26132 : {
26133 0 : *x0 = spline1d_rescaleval(tex1, (double)(1), *ex1, b, *x0, _state);
26134 0 : if( i>0 )
26135 : {
26136 0 : if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
26137 : {
26138 0 : tempdata->ptr.p_double[i] = *x0;
26139 0 : i = i+1;
26140 : }
26141 : else
26142 : {
26143 0 : *nr = *nr-1;
26144 : }
26145 : }
26146 : else
26147 : {
26148 0 : tempdata->ptr.p_double[i] = *x0;
26149 0 : i = i+1;
26150 : }
26151 : }
26152 :
26153 : /*
26154 : *write are found roots
26155 : */
26156 0 : if( *nr>0 )
26157 : {
26158 0 : *x0 = tempdata->ptr.p_double[0];
26159 0 : if( *nr>1 )
26160 : {
26161 0 : *x1 = tempdata->ptr.p_double[1];
26162 : }
26163 0 : if( *nr>2 )
26164 : {
26165 0 : *x2 = tempdata->ptr.p_double[2];
26166 : }
26167 0 : return;
26168 : }
26169 : }
26170 : }
26171 : }
26172 :
26173 :
26174 : /*************************************************************************
26175 : Function for searching a root at [A;B] by bisection method and return number of roots
26176 : (0 or 1)
26177 :
26178 : INPUT PARAMETERS:
26179 : pA - value of a function at A
26180 : mA - value of a derivative at A
26181 : pB - value of a function at B
26182 : mB - value of a derivative at B
26183 : A0 - left border [A0;B0]
26184 : B0 - right border [A0;B0]
26185 :
26186 : RESTRICTIONS OF PARAMETERS:
26187 :
26188 : We assume, that B0>A0.
26189 :
26190 :
26191 : REMARK:
26192 :
26193 : Assume, that exist one root only at [A;B], else
26194 : function may be work incorrectly.
26195 : The function dont check value A0,B0!
26196 :
26197 : -- ALGLIB PROJECT --
26198 : Copyright 26.09.2011 by Bochkanov Sergey
26199 : *************************************************************************/
26200 0 : ae_int_t bisectmethod(double pa,
26201 : double ma,
26202 : double pb,
26203 : double mb,
26204 : double a,
26205 : double b,
26206 : double* x,
26207 : ae_state *_state)
26208 : {
26209 : double vacuum;
26210 : double eps;
26211 : double a0;
26212 : double b0;
26213 : double m;
26214 : double lf;
26215 : double rf;
26216 : double mf;
26217 : ae_int_t result;
26218 :
26219 0 : *x = 0;
26220 :
26221 :
26222 : /*
26223 : *accuracy
26224 : */
26225 0 : eps = 1000*(b-a)*ae_machineepsilon;
26226 :
26227 : /*
26228 : *initialization left and right borders
26229 : */
26230 0 : a0 = a;
26231 0 : b0 = b;
26232 :
26233 : /*
26234 : *initialize function value at 'A' and 'B'
26235 : */
26236 0 : spline1d_hermitecalc(pa, ma, pb, mb, a, &lf, &vacuum, _state);
26237 0 : spline1d_hermitecalc(pa, ma, pb, mb, b, &rf, &vacuum, _state);
26238 :
26239 : /*
26240 : *check, that 'A' and 'B' are't roots,
26241 : *and that root exist
26242 : */
26243 0 : if( ae_sign(lf, _state)*ae_sign(rf, _state)>0 )
26244 : {
26245 0 : result = 0;
26246 0 : return result;
26247 : }
26248 : else
26249 : {
26250 0 : if( ae_fp_eq(lf,(double)(0)) )
26251 : {
26252 0 : *x = a;
26253 0 : result = 1;
26254 0 : return result;
26255 : }
26256 : else
26257 : {
26258 0 : if( ae_fp_eq(rf,(double)(0)) )
26259 : {
26260 0 : *x = b;
26261 0 : result = 1;
26262 0 : return result;
26263 : }
26264 : }
26265 : }
26266 :
26267 : /*
26268 : *searching a root
26269 : */
26270 0 : do
26271 : {
26272 0 : m = (b0+a0)/2;
26273 0 : spline1d_hermitecalc(pa, ma, pb, mb, a0, &lf, &vacuum, _state);
26274 0 : spline1d_hermitecalc(pa, ma, pb, mb, b0, &rf, &vacuum, _state);
26275 0 : spline1d_hermitecalc(pa, ma, pb, mb, m, &mf, &vacuum, _state);
26276 0 : if( ae_sign(mf, _state)*ae_sign(lf, _state)<0 )
26277 : {
26278 0 : b0 = m;
26279 : }
26280 : else
26281 : {
26282 0 : if( ae_sign(mf, _state)*ae_sign(rf, _state)<0 )
26283 : {
26284 0 : a0 = m;
26285 : }
26286 : else
26287 : {
26288 0 : if( ae_fp_eq(lf,(double)(0)) )
26289 : {
26290 0 : *x = a0;
26291 0 : result = 1;
26292 0 : return result;
26293 : }
26294 0 : if( ae_fp_eq(rf,(double)(0)) )
26295 : {
26296 0 : *x = b0;
26297 0 : result = 1;
26298 0 : return result;
26299 : }
26300 0 : if( ae_fp_eq(mf,(double)(0)) )
26301 : {
26302 0 : *x = m;
26303 0 : result = 1;
26304 0 : return result;
26305 : }
26306 : }
26307 : }
26308 : }
26309 0 : while(ae_fp_greater_eq(ae_fabs(b0-a0, _state),eps));
26310 0 : *x = m;
26311 0 : result = 1;
26312 0 : return result;
26313 : }
26314 :
26315 :
26316 : /*************************************************************************
26317 : This function builds monotone cubic Hermite interpolant. This interpolant
26318 : is monotonic in [x(0),x(n-1)] and is constant outside of this interval.
26319 :
26320 : In case y[] form non-monotonic sequence, interpolant is piecewise
26321 : monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will
26322 : monotonically grow at [0..2] and monotonically decrease at [2..4].
26323 :
26324 : INPUT PARAMETERS:
26325 : X - spline nodes, array[0..N-1]. Subroutine automatically
26326 : sorts points, so caller may pass unsorted array.
26327 : Y - function values, array[0..N-1]
26328 : N - the number of points(N>=2).
26329 :
26330 : OUTPUT PARAMETERS:
26331 : C - spline interpolant.
26332 :
26333 : -- ALGLIB PROJECT --
26334 : Copyright 21.06.2012 by Bochkanov Sergey
26335 : *************************************************************************/
26336 0 : void spline1dbuildmonotone(/* Real */ ae_vector* x,
26337 : /* Real */ ae_vector* y,
26338 : ae_int_t n,
26339 : spline1dinterpolant* c,
26340 : ae_state *_state)
26341 : {
26342 : ae_frame _frame_block;
26343 : ae_vector _x;
26344 : ae_vector _y;
26345 : ae_vector d;
26346 : ae_vector ex;
26347 : ae_vector ey;
26348 : ae_vector p;
26349 : double delta;
26350 : double alpha;
26351 : double beta;
26352 : ae_int_t tmpn;
26353 : ae_int_t sn;
26354 : double ca;
26355 : double cb;
26356 : double epsilon;
26357 : ae_int_t i;
26358 : ae_int_t j;
26359 :
26360 0 : ae_frame_make(_state, &_frame_block);
26361 0 : memset(&_x, 0, sizeof(_x));
26362 0 : memset(&_y, 0, sizeof(_y));
26363 0 : memset(&d, 0, sizeof(d));
26364 0 : memset(&ex, 0, sizeof(ex));
26365 0 : memset(&ey, 0, sizeof(ey));
26366 0 : memset(&p, 0, sizeof(p));
26367 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
26368 0 : x = &_x;
26369 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
26370 0 : y = &_y;
26371 0 : _spline1dinterpolant_clear(c);
26372 0 : ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
26373 0 : ae_vector_init(&ex, 0, DT_REAL, _state, ae_true);
26374 0 : ae_vector_init(&ey, 0, DT_REAL, _state, ae_true);
26375 0 : ae_vector_init(&p, 0, DT_INT, _state, ae_true);
26376 :
26377 :
26378 : /*
26379 : * Check lengths of arguments
26380 : */
26381 0 : ae_assert(n>=2, "Spline1DBuildMonotone: N<2", _state);
26382 0 : ae_assert(x->cnt>=n, "Spline1DBuildMonotone: Length(X)<N", _state);
26383 0 : ae_assert(y->cnt>=n, "Spline1DBuildMonotone: Length(Y)<N", _state);
26384 :
26385 : /*
26386 : * Check and sort points
26387 : */
26388 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DBuildMonotone: X contains infinite or NAN values", _state);
26389 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DBuildMonotone: Y contains infinite or NAN values", _state);
26390 0 : spline1d_heapsortppoints(x, y, &p, n, _state);
26391 0 : ae_assert(aredistinct(x, n, _state), "Spline1DBuildMonotone: at least two consequent points are too close", _state);
26392 0 : epsilon = ae_machineepsilon;
26393 0 : n = n+2;
26394 0 : ae_vector_set_length(&d, n, _state);
26395 0 : ae_vector_set_length(&ex, n, _state);
26396 0 : ae_vector_set_length(&ey, n, _state);
26397 0 : ex.ptr.p_double[0] = x->ptr.p_double[0]-ae_fabs(x->ptr.p_double[1]-x->ptr.p_double[0], _state);
26398 0 : ex.ptr.p_double[n-1] = x->ptr.p_double[n-3]+ae_fabs(x->ptr.p_double[n-3]-x->ptr.p_double[n-4], _state);
26399 0 : ey.ptr.p_double[0] = y->ptr.p_double[0];
26400 0 : ey.ptr.p_double[n-1] = y->ptr.p_double[n-3];
26401 0 : for(i=1; i<=n-2; i++)
26402 : {
26403 0 : ex.ptr.p_double[i] = x->ptr.p_double[i-1];
26404 0 : ey.ptr.p_double[i] = y->ptr.p_double[i-1];
26405 : }
26406 :
26407 : /*
26408 : * Init sign of the function for first segment
26409 : */
26410 0 : i = 0;
26411 0 : ca = (double)(0);
26412 0 : do
26413 : {
26414 0 : ca = ey.ptr.p_double[i+1]-ey.ptr.p_double[i];
26415 0 : i = i+1;
26416 : }
26417 0 : while(!(ae_fp_neq(ca,(double)(0))||i>n-2));
26418 0 : if( ae_fp_neq(ca,(double)(0)) )
26419 : {
26420 0 : ca = ca/ae_fabs(ca, _state);
26421 : }
26422 0 : i = 0;
26423 0 : while(i<n-1)
26424 : {
26425 :
26426 : /*
26427 : * Partition of the segment [X0;Xn]
26428 : */
26429 0 : tmpn = 1;
26430 0 : for(j=i; j<=n-2; j++)
26431 : {
26432 0 : cb = ey.ptr.p_double[j+1]-ey.ptr.p_double[j];
26433 0 : if( ae_fp_greater_eq(ca*cb,(double)(0)) )
26434 : {
26435 0 : tmpn = tmpn+1;
26436 : }
26437 : else
26438 : {
26439 0 : ca = cb/ae_fabs(cb, _state);
26440 0 : break;
26441 : }
26442 : }
26443 0 : sn = i+tmpn;
26444 0 : ae_assert(tmpn>=2, "Spline1DBuildMonotone: internal error", _state);
26445 :
26446 : /*
26447 : * Calculate derivatives for current segment
26448 : */
26449 0 : d.ptr.p_double[i] = (double)(0);
26450 0 : d.ptr.p_double[sn-1] = (double)(0);
26451 0 : for(j=i+1; j<=sn-2; j++)
26452 : {
26453 0 : d.ptr.p_double[j] = ((ey.ptr.p_double[j]-ey.ptr.p_double[j-1])/(ex.ptr.p_double[j]-ex.ptr.p_double[j-1])+(ey.ptr.p_double[j+1]-ey.ptr.p_double[j])/(ex.ptr.p_double[j+1]-ex.ptr.p_double[j]))/2;
26454 : }
26455 0 : for(j=i; j<=sn-2; j++)
26456 : {
26457 0 : delta = (ey.ptr.p_double[j+1]-ey.ptr.p_double[j])/(ex.ptr.p_double[j+1]-ex.ptr.p_double[j]);
26458 0 : if( ae_fp_less_eq(ae_fabs(delta, _state),epsilon) )
26459 : {
26460 0 : d.ptr.p_double[j] = (double)(0);
26461 0 : d.ptr.p_double[j+1] = (double)(0);
26462 : }
26463 : else
26464 : {
26465 0 : alpha = d.ptr.p_double[j]/delta;
26466 0 : beta = d.ptr.p_double[j+1]/delta;
26467 0 : if( ae_fp_neq(alpha,(double)(0)) )
26468 : {
26469 0 : cb = alpha*ae_sqrt(1+ae_sqr(beta/alpha, _state), _state);
26470 : }
26471 : else
26472 : {
26473 0 : if( ae_fp_neq(beta,(double)(0)) )
26474 : {
26475 0 : cb = beta;
26476 : }
26477 : else
26478 : {
26479 0 : continue;
26480 : }
26481 : }
26482 0 : if( ae_fp_greater(cb,(double)(3)) )
26483 : {
26484 0 : d.ptr.p_double[j] = 3*alpha*delta/cb;
26485 0 : d.ptr.p_double[j+1] = 3*beta*delta/cb;
26486 : }
26487 : }
26488 : }
26489 :
26490 : /*
26491 : * Transition to next segment
26492 : */
26493 0 : i = sn-1;
26494 : }
26495 0 : spline1dbuildhermite(&ex, &ey, &d, n, c, _state);
26496 0 : c->continuity = 2;
26497 0 : ae_frame_leave(_state);
26498 0 : }
26499 :
26500 :
26501 : /*************************************************************************
26502 : Internal version of Spline1DGridDiffCubic.
26503 :
26504 : Accepts pre-ordered X/Y, temporary arrays (which may be preallocated, if
26505 : you want to save time, or not) and output array (which may be preallocated
26506 : too).
26507 :
26508 : Y is passed as var-parameter because we may need to force last element to
26509 : be equal to the first one (if periodic boundary conditions are specified).
26510 :
26511 : -- ALGLIB PROJECT --
26512 : Copyright 03.09.2010 by Bochkanov Sergey
26513 : *************************************************************************/
26514 0 : static void spline1d_spline1dgriddiffcubicinternal(/* Real */ ae_vector* x,
26515 : /* Real */ ae_vector* y,
26516 : ae_int_t n,
26517 : ae_int_t boundltype,
26518 : double boundl,
26519 : ae_int_t boundrtype,
26520 : double boundr,
26521 : /* Real */ ae_vector* d,
26522 : /* Real */ ae_vector* a1,
26523 : /* Real */ ae_vector* a2,
26524 : /* Real */ ae_vector* a3,
26525 : /* Real */ ae_vector* b,
26526 : /* Real */ ae_vector* dt,
26527 : ae_state *_state)
26528 : {
26529 : ae_int_t i;
26530 :
26531 :
26532 :
26533 : /*
26534 : * allocate arrays
26535 : */
26536 0 : if( d->cnt<n )
26537 : {
26538 0 : ae_vector_set_length(d, n, _state);
26539 : }
26540 0 : if( a1->cnt<n )
26541 : {
26542 0 : ae_vector_set_length(a1, n, _state);
26543 : }
26544 0 : if( a2->cnt<n )
26545 : {
26546 0 : ae_vector_set_length(a2, n, _state);
26547 : }
26548 0 : if( a3->cnt<n )
26549 : {
26550 0 : ae_vector_set_length(a3, n, _state);
26551 : }
26552 0 : if( b->cnt<n )
26553 : {
26554 0 : ae_vector_set_length(b, n, _state);
26555 : }
26556 0 : if( dt->cnt<n )
26557 : {
26558 0 : ae_vector_set_length(dt, n, _state);
26559 : }
26560 :
26561 : /*
26562 : * Special cases:
26563 : * * N=2, parabolic terminated boundary condition on both ends
26564 : * * N=2, periodic boundary condition
26565 : */
26566 0 : if( (n==2&&boundltype==0)&&boundrtype==0 )
26567 : {
26568 0 : d->ptr.p_double[0] = (y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0]);
26569 0 : d->ptr.p_double[1] = d->ptr.p_double[0];
26570 0 : return;
26571 : }
26572 0 : if( (n==2&&boundltype==-1)&&boundrtype==-1 )
26573 : {
26574 0 : d->ptr.p_double[0] = (double)(0);
26575 0 : d->ptr.p_double[1] = (double)(0);
26576 0 : return;
26577 : }
26578 :
26579 : /*
26580 : * Periodic and non-periodic boundary conditions are
26581 : * two separate classes
26582 : */
26583 0 : if( boundrtype==-1&&boundltype==-1 )
26584 : {
26585 :
26586 : /*
26587 : * Periodic boundary conditions
26588 : */
26589 0 : y->ptr.p_double[n-1] = y->ptr.p_double[0];
26590 :
26591 : /*
26592 : * Boundary conditions at N-1 points
26593 : * (one point less because last point is the same as first point).
26594 : */
26595 0 : a1->ptr.p_double[0] = x->ptr.p_double[1]-x->ptr.p_double[0];
26596 0 : a2->ptr.p_double[0] = 2*(x->ptr.p_double[1]-x->ptr.p_double[0]+x->ptr.p_double[n-1]-x->ptr.p_double[n-2]);
26597 0 : a3->ptr.p_double[0] = x->ptr.p_double[n-1]-x->ptr.p_double[n-2];
26598 0 : b->ptr.p_double[0] = 3*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2])*(x->ptr.p_double[1]-x->ptr.p_double[0])+3*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0])*(x->ptr.p_double[n-1]-x->ptr.p_double[n-2]);
26599 0 : for(i=1; i<=n-2; i++)
26600 : {
26601 :
26602 : /*
26603 : * Altough last point is [N-2], we use X[N-1] and Y[N-1]
26604 : * (because of periodicity)
26605 : */
26606 0 : a1->ptr.p_double[i] = x->ptr.p_double[i+1]-x->ptr.p_double[i];
26607 0 : a2->ptr.p_double[i] = 2*(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]);
26608 0 : a3->ptr.p_double[i] = x->ptr.p_double[i]-x->ptr.p_double[i-1];
26609 0 : b->ptr.p_double[i] = 3*(y->ptr.p_double[i]-y->ptr.p_double[i-1])/(x->ptr.p_double[i]-x->ptr.p_double[i-1])*(x->ptr.p_double[i+1]-x->ptr.p_double[i])+3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i])*(x->ptr.p_double[i]-x->ptr.p_double[i-1]);
26610 : }
26611 :
26612 : /*
26613 : * Solve, add last point (with index N-1)
26614 : */
26615 0 : spline1d_solvecyclictridiagonal(a1, a2, a3, b, n-1, dt, _state);
26616 0 : ae_v_move(&d->ptr.p_double[0], 1, &dt->ptr.p_double[0], 1, ae_v_len(0,n-2));
26617 0 : d->ptr.p_double[n-1] = d->ptr.p_double[0];
26618 : }
26619 : else
26620 : {
26621 :
26622 : /*
26623 : * Non-periodic boundary condition.
26624 : * Left boundary conditions.
26625 : */
26626 0 : if( boundltype==0 )
26627 : {
26628 0 : a1->ptr.p_double[0] = (double)(0);
26629 0 : a2->ptr.p_double[0] = (double)(1);
26630 0 : a3->ptr.p_double[0] = (double)(1);
26631 0 : b->ptr.p_double[0] = 2*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0]);
26632 : }
26633 0 : if( boundltype==1 )
26634 : {
26635 0 : a1->ptr.p_double[0] = (double)(0);
26636 0 : a2->ptr.p_double[0] = (double)(1);
26637 0 : a3->ptr.p_double[0] = (double)(0);
26638 0 : b->ptr.p_double[0] = boundl;
26639 : }
26640 0 : if( boundltype==2 )
26641 : {
26642 0 : a1->ptr.p_double[0] = (double)(0);
26643 0 : a2->ptr.p_double[0] = (double)(2);
26644 0 : a3->ptr.p_double[0] = (double)(1);
26645 0 : b->ptr.p_double[0] = 3*(y->ptr.p_double[1]-y->ptr.p_double[0])/(x->ptr.p_double[1]-x->ptr.p_double[0])-0.5*boundl*(x->ptr.p_double[1]-x->ptr.p_double[0]);
26646 : }
26647 :
26648 : /*
26649 : * Central conditions
26650 : */
26651 0 : for(i=1; i<=n-2; i++)
26652 : {
26653 0 : a1->ptr.p_double[i] = x->ptr.p_double[i+1]-x->ptr.p_double[i];
26654 0 : a2->ptr.p_double[i] = 2*(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]);
26655 0 : a3->ptr.p_double[i] = x->ptr.p_double[i]-x->ptr.p_double[i-1];
26656 0 : b->ptr.p_double[i] = 3*(y->ptr.p_double[i]-y->ptr.p_double[i-1])/(x->ptr.p_double[i]-x->ptr.p_double[i-1])*(x->ptr.p_double[i+1]-x->ptr.p_double[i])+3*(y->ptr.p_double[i+1]-y->ptr.p_double[i])/(x->ptr.p_double[i+1]-x->ptr.p_double[i])*(x->ptr.p_double[i]-x->ptr.p_double[i-1]);
26657 : }
26658 :
26659 : /*
26660 : * Right boundary conditions
26661 : */
26662 0 : if( boundrtype==0 )
26663 : {
26664 0 : a1->ptr.p_double[n-1] = (double)(1);
26665 0 : a2->ptr.p_double[n-1] = (double)(1);
26666 0 : a3->ptr.p_double[n-1] = (double)(0);
26667 0 : b->ptr.p_double[n-1] = 2*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2]);
26668 : }
26669 0 : if( boundrtype==1 )
26670 : {
26671 0 : a1->ptr.p_double[n-1] = (double)(0);
26672 0 : a2->ptr.p_double[n-1] = (double)(1);
26673 0 : a3->ptr.p_double[n-1] = (double)(0);
26674 0 : b->ptr.p_double[n-1] = boundr;
26675 : }
26676 0 : if( boundrtype==2 )
26677 : {
26678 0 : a1->ptr.p_double[n-1] = (double)(1);
26679 0 : a2->ptr.p_double[n-1] = (double)(2);
26680 0 : a3->ptr.p_double[n-1] = (double)(0);
26681 0 : b->ptr.p_double[n-1] = 3*(y->ptr.p_double[n-1]-y->ptr.p_double[n-2])/(x->ptr.p_double[n-1]-x->ptr.p_double[n-2])+0.5*boundr*(x->ptr.p_double[n-1]-x->ptr.p_double[n-2]);
26682 : }
26683 :
26684 : /*
26685 : * Solve
26686 : */
26687 0 : spline1d_solvetridiagonal(a1, a2, a3, b, n, d, _state);
26688 : }
26689 : }
26690 :
26691 :
26692 : /*************************************************************************
26693 : Internal subroutine. Heap sort.
26694 : *************************************************************************/
26695 0 : static void spline1d_heapsortpoints(/* Real */ ae_vector* x,
26696 : /* Real */ ae_vector* y,
26697 : ae_int_t n,
26698 : ae_state *_state)
26699 : {
26700 : ae_frame _frame_block;
26701 : ae_vector bufx;
26702 : ae_vector bufy;
26703 :
26704 0 : ae_frame_make(_state, &_frame_block);
26705 0 : memset(&bufx, 0, sizeof(bufx));
26706 0 : memset(&bufy, 0, sizeof(bufy));
26707 0 : ae_vector_init(&bufx, 0, DT_REAL, _state, ae_true);
26708 0 : ae_vector_init(&bufy, 0, DT_REAL, _state, ae_true);
26709 :
26710 0 : tagsortfastr(x, y, &bufx, &bufy, n, _state);
26711 0 : ae_frame_leave(_state);
26712 0 : }
26713 :
26714 :
26715 : /*************************************************************************
26716 : Internal subroutine. Heap sort.
26717 :
26718 : Accepts:
26719 : X, Y - points
26720 : P - empty or preallocated array
26721 :
26722 : Returns:
26723 : X, Y - sorted by X
26724 : P - array of permutations; I-th position of output
26725 : arrays X/Y contains (X[P[I]],Y[P[I]])
26726 : *************************************************************************/
26727 0 : static void spline1d_heapsortppoints(/* Real */ ae_vector* x,
26728 : /* Real */ ae_vector* y,
26729 : /* Integer */ ae_vector* p,
26730 : ae_int_t n,
26731 : ae_state *_state)
26732 : {
26733 : ae_frame _frame_block;
26734 : ae_vector rbuf;
26735 : ae_vector ibuf;
26736 : ae_int_t i;
26737 :
26738 0 : ae_frame_make(_state, &_frame_block);
26739 0 : memset(&rbuf, 0, sizeof(rbuf));
26740 0 : memset(&ibuf, 0, sizeof(ibuf));
26741 0 : ae_vector_init(&rbuf, 0, DT_REAL, _state, ae_true);
26742 0 : ae_vector_init(&ibuf, 0, DT_INT, _state, ae_true);
26743 :
26744 0 : if( p->cnt<n )
26745 : {
26746 0 : ae_vector_set_length(p, n, _state);
26747 : }
26748 0 : ae_vector_set_length(&rbuf, n, _state);
26749 0 : for(i=0; i<=n-1; i++)
26750 : {
26751 0 : p->ptr.p_int[i] = i;
26752 : }
26753 0 : tagsortfasti(x, p, &rbuf, &ibuf, n, _state);
26754 0 : for(i=0; i<=n-1; i++)
26755 : {
26756 0 : rbuf.ptr.p_double[i] = y->ptr.p_double[p->ptr.p_int[i]];
26757 : }
26758 0 : ae_v_move(&y->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1));
26759 0 : ae_frame_leave(_state);
26760 0 : }
26761 :
26762 :
26763 : /*************************************************************************
26764 : Internal subroutine. Tridiagonal solver. Solves
26765 :
26766 : ( B[0] C[0]
26767 : ( A[1] B[1] C[1] )
26768 : ( A[2] B[2] C[2] )
26769 : ( .......... ) * X = D
26770 : ( .......... )
26771 : ( A[N-2] B[N-2] C[N-2] )
26772 : ( A[N-1] B[N-1] )
26773 :
26774 : *************************************************************************/
26775 0 : static void spline1d_solvetridiagonal(/* Real */ ae_vector* a,
26776 : /* Real */ ae_vector* b,
26777 : /* Real */ ae_vector* c,
26778 : /* Real */ ae_vector* d,
26779 : ae_int_t n,
26780 : /* Real */ ae_vector* x,
26781 : ae_state *_state)
26782 : {
26783 : ae_frame _frame_block;
26784 : ae_vector _b;
26785 : ae_vector _d;
26786 : ae_int_t k;
26787 : double t;
26788 :
26789 0 : ae_frame_make(_state, &_frame_block);
26790 0 : memset(&_b, 0, sizeof(_b));
26791 0 : memset(&_d, 0, sizeof(_d));
26792 0 : ae_vector_init_copy(&_b, b, _state, ae_true);
26793 0 : b = &_b;
26794 0 : ae_vector_init_copy(&_d, d, _state, ae_true);
26795 0 : d = &_d;
26796 :
26797 0 : if( x->cnt<n )
26798 : {
26799 0 : ae_vector_set_length(x, n, _state);
26800 : }
26801 0 : for(k=1; k<=n-1; k++)
26802 : {
26803 0 : t = a->ptr.p_double[k]/b->ptr.p_double[k-1];
26804 0 : b->ptr.p_double[k] = b->ptr.p_double[k]-t*c->ptr.p_double[k-1];
26805 0 : d->ptr.p_double[k] = d->ptr.p_double[k]-t*d->ptr.p_double[k-1];
26806 : }
26807 0 : x->ptr.p_double[n-1] = d->ptr.p_double[n-1]/b->ptr.p_double[n-1];
26808 0 : for(k=n-2; k>=0; k--)
26809 : {
26810 0 : x->ptr.p_double[k] = (d->ptr.p_double[k]-c->ptr.p_double[k]*x->ptr.p_double[k+1])/b->ptr.p_double[k];
26811 : }
26812 0 : ae_frame_leave(_state);
26813 0 : }
26814 :
26815 :
26816 : /*************************************************************************
26817 : Internal subroutine. Cyclic tridiagonal solver. Solves
26818 :
26819 : ( B[0] C[0] A[0] )
26820 : ( A[1] B[1] C[1] )
26821 : ( A[2] B[2] C[2] )
26822 : ( .......... ) * X = D
26823 : ( .......... )
26824 : ( A[N-2] B[N-2] C[N-2] )
26825 : ( C[N-1] A[N-1] B[N-1] )
26826 : *************************************************************************/
26827 0 : static void spline1d_solvecyclictridiagonal(/* Real */ ae_vector* a,
26828 : /* Real */ ae_vector* b,
26829 : /* Real */ ae_vector* c,
26830 : /* Real */ ae_vector* d,
26831 : ae_int_t n,
26832 : /* Real */ ae_vector* x,
26833 : ae_state *_state)
26834 : {
26835 : ae_frame _frame_block;
26836 : ae_vector _b;
26837 : ae_int_t k;
26838 : double alpha;
26839 : double beta;
26840 : double gamma;
26841 : ae_vector y;
26842 : ae_vector z;
26843 : ae_vector u;
26844 :
26845 0 : ae_frame_make(_state, &_frame_block);
26846 0 : memset(&_b, 0, sizeof(_b));
26847 0 : memset(&y, 0, sizeof(y));
26848 0 : memset(&z, 0, sizeof(z));
26849 0 : memset(&u, 0, sizeof(u));
26850 0 : ae_vector_init_copy(&_b, b, _state, ae_true);
26851 0 : b = &_b;
26852 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
26853 0 : ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
26854 0 : ae_vector_init(&u, 0, DT_REAL, _state, ae_true);
26855 :
26856 0 : if( x->cnt<n )
26857 : {
26858 0 : ae_vector_set_length(x, n, _state);
26859 : }
26860 0 : beta = a->ptr.p_double[0];
26861 0 : alpha = c->ptr.p_double[n-1];
26862 0 : gamma = -b->ptr.p_double[0];
26863 0 : b->ptr.p_double[0] = 2*b->ptr.p_double[0];
26864 0 : b->ptr.p_double[n-1] = b->ptr.p_double[n-1]-alpha*beta/gamma;
26865 0 : ae_vector_set_length(&u, n, _state);
26866 0 : for(k=0; k<=n-1; k++)
26867 : {
26868 0 : u.ptr.p_double[k] = (double)(0);
26869 : }
26870 0 : u.ptr.p_double[0] = gamma;
26871 0 : u.ptr.p_double[n-1] = alpha;
26872 0 : spline1d_solvetridiagonal(a, b, c, d, n, &y, _state);
26873 0 : spline1d_solvetridiagonal(a, b, c, &u, n, &z, _state);
26874 0 : for(k=0; k<=n-1; k++)
26875 : {
26876 0 : x->ptr.p_double[k] = y.ptr.p_double[k]-(y.ptr.p_double[0]+beta/gamma*y.ptr.p_double[n-1])/(1+z.ptr.p_double[0]+beta/gamma*z.ptr.p_double[n-1])*z.ptr.p_double[k];
26877 : }
26878 0 : ae_frame_leave(_state);
26879 0 : }
26880 :
26881 :
26882 : /*************************************************************************
26883 : Internal subroutine. Three-point differentiation
26884 : *************************************************************************/
26885 0 : static double spline1d_diffthreepoint(double t,
26886 : double x0,
26887 : double f0,
26888 : double x1,
26889 : double f1,
26890 : double x2,
26891 : double f2,
26892 : ae_state *_state)
26893 : {
26894 : double a;
26895 : double b;
26896 : double result;
26897 :
26898 :
26899 0 : t = t-x0;
26900 0 : x1 = x1-x0;
26901 0 : x2 = x2-x0;
26902 0 : a = (f2-f0-x2/x1*(f1-f0))/(ae_sqr(x2, _state)-x1*x2);
26903 0 : b = (f1-f0-a*ae_sqr(x1, _state))/x1;
26904 0 : result = 2*a*t+b;
26905 0 : return result;
26906 : }
26907 :
26908 :
26909 : /*************************************************************************
26910 : Procedure for calculating value of a function is providet in the form of
26911 : Hermite polinom
26912 :
26913 : INPUT PARAMETERS:
26914 : P0 - value of a function at 0
26915 : M0 - value of a derivative at 0
26916 : P1 - value of a function at 1
26917 : M1 - value of a derivative at 1
26918 : T - point inside [0;1]
26919 :
26920 : OUTPUT PARAMETERS:
26921 : S - value of a function at T
26922 : B0 - value of a derivative function at T
26923 :
26924 : -- ALGLIB PROJECT --
26925 : Copyright 26.09.2011 by Bochkanov Sergey
26926 : *************************************************************************/
26927 0 : static void spline1d_hermitecalc(double p0,
26928 : double m0,
26929 : double p1,
26930 : double m1,
26931 : double t,
26932 : double* s,
26933 : double* ds,
26934 : ae_state *_state)
26935 : {
26936 :
26937 0 : *s = 0;
26938 0 : *ds = 0;
26939 :
26940 0 : *s = p0*(1+2*t)*(1-t)*(1-t)+m0*t*(1-t)*(1-t)+p1*(3-2*t)*t*t+m1*t*t*(t-1);
26941 0 : *ds = -p0*6*t*(1-t)+m0*(1-t)*(1-3*t)+p1*6*t*(1-t)+m1*t*(3*t-2);
26942 0 : }
26943 :
26944 :
26945 : /*************************************************************************
26946 : Function for mapping from [A0;B0] to [A1;B1]
26947 :
26948 : INPUT PARAMETERS:
26949 : A0 - left border [A0;B0]
26950 : B0 - right border [A0;B0]
26951 : A1 - left border [A1;B1]
26952 : B1 - right border [A1;B1]
26953 : T - value inside [A0;B0]
26954 :
26955 : RESTRICTIONS OF PARAMETERS:
26956 :
26957 : We assume, that B0>A0 and B1>A1. But we chech, that T is inside [A0;B0],
26958 : and if T<A0 then T become A1, if T>B0 then T - B1.
26959 :
26960 : INPUT PARAMETERS:
26961 : A0 - left border for segment [A0;B0] from 'T' is converted to [A1;B1]
26962 : B0 - right border for segment [A0;B0] from 'T' is converted to [A1;B1]
26963 : A1 - left border for segment [A1;B1] to 'T' is converted from [A0;B0]
26964 : B1 - right border for segment [A1;B1] to 'T' is converted from [A0;B0]
26965 : T - the parameter is mapped from [A0;B0] to [A1;B1]
26966 :
26967 : Result:
26968 : is converted value for 'T' from [A0;B0] to [A1;B1]
26969 :
26970 : REMARK:
26971 :
26972 : The function dont check value A0,B0 and A1,B1!
26973 :
26974 : -- ALGLIB PROJECT --
26975 : Copyright 26.09.2011 by Bochkanov Sergey
26976 : *************************************************************************/
26977 0 : static double spline1d_rescaleval(double a0,
26978 : double b0,
26979 : double a1,
26980 : double b1,
26981 : double t,
26982 : ae_state *_state)
26983 : {
26984 : double result;
26985 :
26986 :
26987 :
26988 : /*
26989 : *return left border
26990 : */
26991 0 : if( ae_fp_less_eq(t,a0) )
26992 : {
26993 0 : result = a1;
26994 0 : return result;
26995 : }
26996 :
26997 : /*
26998 : *return right border
26999 : */
27000 0 : if( ae_fp_greater_eq(t,b0) )
27001 : {
27002 0 : result = b1;
27003 0 : return result;
27004 : }
27005 :
27006 : /*
27007 : *return value between left and right borders
27008 : */
27009 0 : result = (b1-a1)*(t-a0)/(b0-a0)+a1;
27010 0 : return result;
27011 : }
27012 :
27013 :
27014 0 : void _spline1dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
27015 : {
27016 0 : spline1dinterpolant *p = (spline1dinterpolant*)_p;
27017 0 : ae_touch_ptr((void*)p);
27018 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
27019 0 : ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic);
27020 0 : }
27021 :
27022 :
27023 0 : void _spline1dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27024 : {
27025 0 : spline1dinterpolant *dst = (spline1dinterpolant*)_dst;
27026 0 : spline1dinterpolant *src = (spline1dinterpolant*)_src;
27027 0 : dst->periodic = src->periodic;
27028 0 : dst->n = src->n;
27029 0 : dst->k = src->k;
27030 0 : dst->continuity = src->continuity;
27031 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
27032 0 : ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic);
27033 0 : }
27034 :
27035 :
27036 0 : void _spline1dinterpolant_clear(void* _p)
27037 : {
27038 0 : spline1dinterpolant *p = (spline1dinterpolant*)_p;
27039 0 : ae_touch_ptr((void*)p);
27040 0 : ae_vector_clear(&p->x);
27041 0 : ae_vector_clear(&p->c);
27042 0 : }
27043 :
27044 :
27045 0 : void _spline1dinterpolant_destroy(void* _p)
27046 : {
27047 0 : spline1dinterpolant *p = (spline1dinterpolant*)_p;
27048 0 : ae_touch_ptr((void*)p);
27049 0 : ae_vector_destroy(&p->x);
27050 0 : ae_vector_destroy(&p->c);
27051 0 : }
27052 :
27053 :
27054 0 : void _spline1dfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
27055 : {
27056 0 : spline1dfitreport *p = (spline1dfitreport*)_p;
27057 0 : ae_touch_ptr((void*)p);
27058 0 : }
27059 :
27060 :
27061 0 : void _spline1dfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27062 : {
27063 0 : spline1dfitreport *dst = (spline1dfitreport*)_dst;
27064 0 : spline1dfitreport *src = (spline1dfitreport*)_src;
27065 0 : dst->taskrcond = src->taskrcond;
27066 0 : dst->rmserror = src->rmserror;
27067 0 : dst->avgerror = src->avgerror;
27068 0 : dst->avgrelerror = src->avgrelerror;
27069 0 : dst->maxerror = src->maxerror;
27070 0 : }
27071 :
27072 :
27073 0 : void _spline1dfitreport_clear(void* _p)
27074 : {
27075 0 : spline1dfitreport *p = (spline1dfitreport*)_p;
27076 0 : ae_touch_ptr((void*)p);
27077 0 : }
27078 :
27079 :
27080 0 : void _spline1dfitreport_destroy(void* _p)
27081 : {
27082 0 : spline1dfitreport *p = (spline1dfitreport*)_p;
27083 0 : ae_touch_ptr((void*)p);
27084 0 : }
27085 :
27086 :
27087 : #endif
27088 : #if defined(AE_COMPILE_PARAMETRIC) || !defined(AE_PARTIAL_BUILD)
27089 :
27090 :
27091 : /*************************************************************************
27092 : This function builds non-periodic 2-dimensional parametric spline which
27093 : starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]).
27094 :
27095 : INPUT PARAMETERS:
27096 : XY - points, array[0..N-1,0..1].
27097 : XY[I,0:1] corresponds to the Ith point.
27098 : Order of points is important!
27099 : N - points count, N>=5 for Akima splines, N>=2 for other types of
27100 : splines.
27101 : ST - spline type:
27102 : * 0 Akima spline
27103 : * 1 parabolically terminated Catmull-Rom spline (Tension=0)
27104 : * 2 parabolically terminated cubic spline
27105 : PT - parameterization type:
27106 : * 0 uniform
27107 : * 1 chord length
27108 : * 2 centripetal
27109 :
27110 : OUTPUT PARAMETERS:
27111 : P - parametric spline interpolant
27112 :
27113 :
27114 : NOTES:
27115 : * this function assumes that there all consequent points are distinct.
27116 : I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
27117 : However, non-consequent points may coincide, i.e. we can have (x0,y0)=
27118 : =(x2,y2).
27119 :
27120 : -- ALGLIB PROJECT --
27121 : Copyright 28.05.2010 by Bochkanov Sergey
27122 : *************************************************************************/
27123 0 : void pspline2build(/* Real */ ae_matrix* xy,
27124 : ae_int_t n,
27125 : ae_int_t st,
27126 : ae_int_t pt,
27127 : pspline2interpolant* p,
27128 : ae_state *_state)
27129 : {
27130 : ae_frame _frame_block;
27131 : ae_matrix _xy;
27132 : ae_vector tmp;
27133 :
27134 0 : ae_frame_make(_state, &_frame_block);
27135 0 : memset(&_xy, 0, sizeof(_xy));
27136 0 : memset(&tmp, 0, sizeof(tmp));
27137 0 : ae_matrix_init_copy(&_xy, xy, _state, ae_true);
27138 0 : xy = &_xy;
27139 0 : _pspline2interpolant_clear(p);
27140 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
27141 :
27142 0 : ae_assert(st>=0&&st<=2, "PSpline2Build: incorrect spline type!", _state);
27143 0 : ae_assert(pt>=0&&pt<=2, "PSpline2Build: incorrect parameterization type!", _state);
27144 0 : if( st==0 )
27145 : {
27146 0 : ae_assert(n>=5, "PSpline2Build: N<5 (minimum value for Akima splines)!", _state);
27147 : }
27148 : else
27149 : {
27150 0 : ae_assert(n>=2, "PSpline2Build: N<2!", _state);
27151 : }
27152 :
27153 : /*
27154 : * Prepare
27155 : */
27156 0 : p->n = n;
27157 0 : p->periodic = ae_false;
27158 0 : ae_vector_set_length(&tmp, n, _state);
27159 :
27160 : /*
27161 : * Build parameterization, check that all parameters are distinct
27162 : */
27163 0 : parametric_pspline2par(xy, n, pt, &p->p, _state);
27164 0 : ae_assert(aredistinct(&p->p, n, _state), "PSpline2Build: consequent points are too close!", _state);
27165 :
27166 : /*
27167 : * Build splines
27168 : */
27169 0 : if( st==0 )
27170 : {
27171 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27172 0 : spline1dbuildakima(&p->p, &tmp, n, &p->x, _state);
27173 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27174 0 : spline1dbuildakima(&p->p, &tmp, n, &p->y, _state);
27175 : }
27176 0 : if( st==1 )
27177 : {
27178 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27179 0 : spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->x, _state);
27180 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27181 0 : spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->y, _state);
27182 : }
27183 0 : if( st==2 )
27184 : {
27185 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27186 0 : spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->x, _state);
27187 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27188 0 : spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->y, _state);
27189 : }
27190 0 : ae_frame_leave(_state);
27191 0 : }
27192 :
27193 :
27194 : /*************************************************************************
27195 : This function builds non-periodic 3-dimensional parametric spline which
27196 : starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]).
27197 :
27198 : Same as PSpline2Build() function, but for 3D, so we won't duplicate its
27199 : description here.
27200 :
27201 : -- ALGLIB PROJECT --
27202 : Copyright 28.05.2010 by Bochkanov Sergey
27203 : *************************************************************************/
27204 0 : void pspline3build(/* Real */ ae_matrix* xy,
27205 : ae_int_t n,
27206 : ae_int_t st,
27207 : ae_int_t pt,
27208 : pspline3interpolant* p,
27209 : ae_state *_state)
27210 : {
27211 : ae_frame _frame_block;
27212 : ae_matrix _xy;
27213 : ae_vector tmp;
27214 :
27215 0 : ae_frame_make(_state, &_frame_block);
27216 0 : memset(&_xy, 0, sizeof(_xy));
27217 0 : memset(&tmp, 0, sizeof(tmp));
27218 0 : ae_matrix_init_copy(&_xy, xy, _state, ae_true);
27219 0 : xy = &_xy;
27220 0 : _pspline3interpolant_clear(p);
27221 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
27222 :
27223 0 : ae_assert(st>=0&&st<=2, "PSpline3Build: incorrect spline type!", _state);
27224 0 : ae_assert(pt>=0&&pt<=2, "PSpline3Build: incorrect parameterization type!", _state);
27225 0 : if( st==0 )
27226 : {
27227 0 : ae_assert(n>=5, "PSpline3Build: N<5 (minimum value for Akima splines)!", _state);
27228 : }
27229 : else
27230 : {
27231 0 : ae_assert(n>=2, "PSpline3Build: N<2!", _state);
27232 : }
27233 :
27234 : /*
27235 : * Prepare
27236 : */
27237 0 : p->n = n;
27238 0 : p->periodic = ae_false;
27239 0 : ae_vector_set_length(&tmp, n, _state);
27240 :
27241 : /*
27242 : * Build parameterization, check that all parameters are distinct
27243 : */
27244 0 : parametric_pspline3par(xy, n, pt, &p->p, _state);
27245 0 : ae_assert(aredistinct(&p->p, n, _state), "PSpline3Build: consequent points are too close!", _state);
27246 :
27247 : /*
27248 : * Build splines
27249 : */
27250 0 : if( st==0 )
27251 : {
27252 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27253 0 : spline1dbuildakima(&p->p, &tmp, n, &p->x, _state);
27254 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27255 0 : spline1dbuildakima(&p->p, &tmp, n, &p->y, _state);
27256 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1));
27257 0 : spline1dbuildakima(&p->p, &tmp, n, &p->z, _state);
27258 : }
27259 0 : if( st==1 )
27260 : {
27261 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27262 0 : spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->x, _state);
27263 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27264 0 : spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->y, _state);
27265 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1));
27266 0 : spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->z, _state);
27267 : }
27268 0 : if( st==2 )
27269 : {
27270 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27271 0 : spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->x, _state);
27272 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27273 0 : spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->y, _state);
27274 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1));
27275 0 : spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->z, _state);
27276 : }
27277 0 : ae_frame_leave(_state);
27278 0 : }
27279 :
27280 :
27281 : /*************************************************************************
27282 : This function builds periodic 2-dimensional parametric spline which
27283 : starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then
27284 : back to (X[0],Y[0]).
27285 :
27286 : INPUT PARAMETERS:
27287 : XY - points, array[0..N-1,0..1].
27288 : XY[I,0:1] corresponds to the Ith point.
27289 : XY[N-1,0:1] must be different from XY[0,0:1].
27290 : Order of points is important!
27291 : N - points count, N>=3 for other types of splines.
27292 : ST - spline type:
27293 : * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions
27294 : * 2 cubic spline with cyclic boundary conditions
27295 : PT - parameterization type:
27296 : * 0 uniform
27297 : * 1 chord length
27298 : * 2 centripetal
27299 :
27300 : OUTPUT PARAMETERS:
27301 : P - parametric spline interpolant
27302 :
27303 :
27304 : NOTES:
27305 : * this function assumes that there all consequent points are distinct.
27306 : I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
27307 : However, non-consequent points may coincide, i.e. we can have (x0,y0)=
27308 : =(x2,y2).
27309 : * last point of sequence is NOT equal to the first point. You shouldn't
27310 : make curve "explicitly periodic" by making them equal.
27311 :
27312 : -- ALGLIB PROJECT --
27313 : Copyright 28.05.2010 by Bochkanov Sergey
27314 : *************************************************************************/
27315 0 : void pspline2buildperiodic(/* Real */ ae_matrix* xy,
27316 : ae_int_t n,
27317 : ae_int_t st,
27318 : ae_int_t pt,
27319 : pspline2interpolant* p,
27320 : ae_state *_state)
27321 : {
27322 : ae_frame _frame_block;
27323 : ae_matrix _xy;
27324 : ae_matrix xyp;
27325 : ae_vector tmp;
27326 :
27327 0 : ae_frame_make(_state, &_frame_block);
27328 0 : memset(&_xy, 0, sizeof(_xy));
27329 0 : memset(&xyp, 0, sizeof(xyp));
27330 0 : memset(&tmp, 0, sizeof(tmp));
27331 0 : ae_matrix_init_copy(&_xy, xy, _state, ae_true);
27332 0 : xy = &_xy;
27333 0 : _pspline2interpolant_clear(p);
27334 0 : ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true);
27335 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
27336 :
27337 0 : ae_assert(st>=1&&st<=2, "PSpline2BuildPeriodic: incorrect spline type!", _state);
27338 0 : ae_assert(pt>=0&&pt<=2, "PSpline2BuildPeriodic: incorrect parameterization type!", _state);
27339 0 : ae_assert(n>=3, "PSpline2BuildPeriodic: N<3!", _state);
27340 :
27341 : /*
27342 : * Prepare
27343 : */
27344 0 : p->n = n;
27345 0 : p->periodic = ae_true;
27346 0 : ae_vector_set_length(&tmp, n+1, _state);
27347 0 : ae_matrix_set_length(&xyp, n+1, 2, _state);
27348 0 : ae_v_move(&xyp.ptr.pp_double[0][0], xyp.stride, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27349 0 : ae_v_move(&xyp.ptr.pp_double[0][1], xyp.stride, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27350 0 : ae_v_move(&xyp.ptr.pp_double[n][0], 1, &xy->ptr.pp_double[0][0], 1, ae_v_len(0,1));
27351 :
27352 : /*
27353 : * Build parameterization, check that all parameters are distinct
27354 : */
27355 0 : parametric_pspline2par(&xyp, n+1, pt, &p->p, _state);
27356 0 : ae_assert(aredistinct(&p->p, n+1, _state), "PSpline2BuildPeriodic: consequent (or first and last) points are too close!", _state);
27357 :
27358 : /*
27359 : * Build splines
27360 : */
27361 0 : if( st==1 )
27362 : {
27363 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
27364 0 : spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->x, _state);
27365 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
27366 0 : spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->y, _state);
27367 : }
27368 0 : if( st==2 )
27369 : {
27370 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
27371 0 : spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->x, _state);
27372 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
27373 0 : spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->y, _state);
27374 : }
27375 0 : ae_frame_leave(_state);
27376 0 : }
27377 :
27378 :
27379 : /*************************************************************************
27380 : This function builds periodic 3-dimensional parametric spline which
27381 : starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1])
27382 : and then back to (X[0],Y[0],Z[0]).
27383 :
27384 : Same as PSpline2Build() function, but for 3D, so we won't duplicate its
27385 : description here.
27386 :
27387 : -- ALGLIB PROJECT --
27388 : Copyright 28.05.2010 by Bochkanov Sergey
27389 : *************************************************************************/
27390 0 : void pspline3buildperiodic(/* Real */ ae_matrix* xy,
27391 : ae_int_t n,
27392 : ae_int_t st,
27393 : ae_int_t pt,
27394 : pspline3interpolant* p,
27395 : ae_state *_state)
27396 : {
27397 : ae_frame _frame_block;
27398 : ae_matrix _xy;
27399 : ae_matrix xyp;
27400 : ae_vector tmp;
27401 :
27402 0 : ae_frame_make(_state, &_frame_block);
27403 0 : memset(&_xy, 0, sizeof(_xy));
27404 0 : memset(&xyp, 0, sizeof(xyp));
27405 0 : memset(&tmp, 0, sizeof(tmp));
27406 0 : ae_matrix_init_copy(&_xy, xy, _state, ae_true);
27407 0 : xy = &_xy;
27408 0 : _pspline3interpolant_clear(p);
27409 0 : ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true);
27410 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
27411 :
27412 0 : ae_assert(st>=1&&st<=2, "PSpline3BuildPeriodic: incorrect spline type!", _state);
27413 0 : ae_assert(pt>=0&&pt<=2, "PSpline3BuildPeriodic: incorrect parameterization type!", _state);
27414 0 : ae_assert(n>=3, "PSpline3BuildPeriodic: N<3!", _state);
27415 :
27416 : /*
27417 : * Prepare
27418 : */
27419 0 : p->n = n;
27420 0 : p->periodic = ae_true;
27421 0 : ae_vector_set_length(&tmp, n+1, _state);
27422 0 : ae_matrix_set_length(&xyp, n+1, 3, _state);
27423 0 : ae_v_move(&xyp.ptr.pp_double[0][0], xyp.stride, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
27424 0 : ae_v_move(&xyp.ptr.pp_double[0][1], xyp.stride, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
27425 0 : ae_v_move(&xyp.ptr.pp_double[0][2], xyp.stride, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1));
27426 0 : ae_v_move(&xyp.ptr.pp_double[n][0], 1, &xy->ptr.pp_double[0][0], 1, ae_v_len(0,2));
27427 :
27428 : /*
27429 : * Build parameterization, check that all parameters are distinct
27430 : */
27431 0 : parametric_pspline3par(&xyp, n+1, pt, &p->p, _state);
27432 0 : ae_assert(aredistinct(&p->p, n+1, _state), "PSplineBuild2Periodic: consequent (or first and last) points are too close!", _state);
27433 :
27434 : /*
27435 : * Build splines
27436 : */
27437 0 : if( st==1 )
27438 : {
27439 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
27440 0 : spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->x, _state);
27441 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
27442 0 : spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->y, _state);
27443 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][2], xyp.stride, ae_v_len(0,n));
27444 0 : spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->z, _state);
27445 : }
27446 0 : if( st==2 )
27447 : {
27448 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
27449 0 : spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->x, _state);
27450 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
27451 0 : spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->y, _state);
27452 0 : ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][2], xyp.stride, ae_v_len(0,n));
27453 0 : spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->z, _state);
27454 : }
27455 0 : ae_frame_leave(_state);
27456 0 : }
27457 :
27458 :
27459 : /*************************************************************************
27460 : This function returns vector of parameter values correspoding to points.
27461 :
27462 : I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we
27463 : have
27464 : (X[0],Y[0]) = PSpline2Calc(P,U[0]),
27465 : (X[1],Y[1]) = PSpline2Calc(P,U[1]),
27466 : (X[2],Y[2]) = PSpline2Calc(P,U[2]),
27467 : ...
27468 :
27469 : INPUT PARAMETERS:
27470 : P - parametric spline interpolant
27471 :
27472 : OUTPUT PARAMETERS:
27473 : N - array size
27474 : T - array[0..N-1]
27475 :
27476 :
27477 : NOTES:
27478 : * for non-periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]=1
27479 : * for periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]<1
27480 :
27481 : -- ALGLIB PROJECT --
27482 : Copyright 28.05.2010 by Bochkanov Sergey
27483 : *************************************************************************/
27484 0 : void pspline2parametervalues(pspline2interpolant* p,
27485 : ae_int_t* n,
27486 : /* Real */ ae_vector* t,
27487 : ae_state *_state)
27488 : {
27489 :
27490 0 : *n = 0;
27491 0 : ae_vector_clear(t);
27492 :
27493 0 : ae_assert(p->n>=2, "PSpline2ParameterValues: internal error!", _state);
27494 0 : *n = p->n;
27495 0 : ae_vector_set_length(t, *n, _state);
27496 0 : ae_v_move(&t->ptr.p_double[0], 1, &p->p.ptr.p_double[0], 1, ae_v_len(0,*n-1));
27497 0 : t->ptr.p_double[0] = (double)(0);
27498 0 : if( !p->periodic )
27499 : {
27500 0 : t->ptr.p_double[*n-1] = (double)(1);
27501 : }
27502 0 : }
27503 :
27504 :
27505 : /*************************************************************************
27506 : This function returns vector of parameter values correspoding to points.
27507 :
27508 : Same as PSpline2ParameterValues(), but for 3D.
27509 :
27510 : -- ALGLIB PROJECT --
27511 : Copyright 28.05.2010 by Bochkanov Sergey
27512 : *************************************************************************/
27513 0 : void pspline3parametervalues(pspline3interpolant* p,
27514 : ae_int_t* n,
27515 : /* Real */ ae_vector* t,
27516 : ae_state *_state)
27517 : {
27518 :
27519 0 : *n = 0;
27520 0 : ae_vector_clear(t);
27521 :
27522 0 : ae_assert(p->n>=2, "PSpline3ParameterValues: internal error!", _state);
27523 0 : *n = p->n;
27524 0 : ae_vector_set_length(t, *n, _state);
27525 0 : ae_v_move(&t->ptr.p_double[0], 1, &p->p.ptr.p_double[0], 1, ae_v_len(0,*n-1));
27526 0 : t->ptr.p_double[0] = (double)(0);
27527 0 : if( !p->periodic )
27528 : {
27529 0 : t->ptr.p_double[*n-1] = (double)(1);
27530 : }
27531 0 : }
27532 :
27533 :
27534 : /*************************************************************************
27535 : This function calculates the value of the parametric spline for a given
27536 : value of parameter T
27537 :
27538 : INPUT PARAMETERS:
27539 : P - parametric spline interpolant
27540 : T - point:
27541 : * T in [0,1] corresponds to interval spanned by points
27542 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27543 : the curve before the first (after the last) point
27544 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27545 : by making T=T-floor(T).
27546 :
27547 : OUTPUT PARAMETERS:
27548 : X - X-position
27549 : Y - Y-position
27550 :
27551 :
27552 : -- ALGLIB PROJECT --
27553 : Copyright 28.05.2010 by Bochkanov Sergey
27554 : *************************************************************************/
27555 0 : void pspline2calc(pspline2interpolant* p,
27556 : double t,
27557 : double* x,
27558 : double* y,
27559 : ae_state *_state)
27560 : {
27561 :
27562 0 : *x = 0;
27563 0 : *y = 0;
27564 :
27565 0 : if( p->periodic )
27566 : {
27567 0 : t = t-ae_ifloor(t, _state);
27568 : }
27569 0 : *x = spline1dcalc(&p->x, t, _state);
27570 0 : *y = spline1dcalc(&p->y, t, _state);
27571 0 : }
27572 :
27573 :
27574 : /*************************************************************************
27575 : This function calculates the value of the parametric spline for a given
27576 : value of parameter T.
27577 :
27578 : INPUT PARAMETERS:
27579 : P - parametric spline interpolant
27580 : T - point:
27581 : * T in [0,1] corresponds to interval spanned by points
27582 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27583 : the curve before the first (after the last) point
27584 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27585 : by making T=T-floor(T).
27586 :
27587 : OUTPUT PARAMETERS:
27588 : X - X-position
27589 : Y - Y-position
27590 : Z - Z-position
27591 :
27592 :
27593 : -- ALGLIB PROJECT --
27594 : Copyright 28.05.2010 by Bochkanov Sergey
27595 : *************************************************************************/
27596 0 : void pspline3calc(pspline3interpolant* p,
27597 : double t,
27598 : double* x,
27599 : double* y,
27600 : double* z,
27601 : ae_state *_state)
27602 : {
27603 :
27604 0 : *x = 0;
27605 0 : *y = 0;
27606 0 : *z = 0;
27607 :
27608 0 : if( p->periodic )
27609 : {
27610 0 : t = t-ae_ifloor(t, _state);
27611 : }
27612 0 : *x = spline1dcalc(&p->x, t, _state);
27613 0 : *y = spline1dcalc(&p->y, t, _state);
27614 0 : *z = spline1dcalc(&p->z, t, _state);
27615 0 : }
27616 :
27617 :
27618 : /*************************************************************************
27619 : This function calculates tangent vector for a given value of parameter T
27620 :
27621 : INPUT PARAMETERS:
27622 : P - parametric spline interpolant
27623 : T - point:
27624 : * T in [0,1] corresponds to interval spanned by points
27625 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27626 : the curve before the first (after the last) point
27627 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27628 : by making T=T-floor(T).
27629 :
27630 : OUTPUT PARAMETERS:
27631 : X - X-component of tangent vector (normalized)
27632 : Y - Y-component of tangent vector (normalized)
27633 :
27634 : NOTE:
27635 : X^2+Y^2 is either 1 (for non-zero tangent vector) or 0.
27636 :
27637 :
27638 : -- ALGLIB PROJECT --
27639 : Copyright 28.05.2010 by Bochkanov Sergey
27640 : *************************************************************************/
27641 0 : void pspline2tangent(pspline2interpolant* p,
27642 : double t,
27643 : double* x,
27644 : double* y,
27645 : ae_state *_state)
27646 : {
27647 : double v;
27648 : double v0;
27649 : double v1;
27650 :
27651 0 : *x = 0;
27652 0 : *y = 0;
27653 :
27654 0 : if( p->periodic )
27655 : {
27656 0 : t = t-ae_ifloor(t, _state);
27657 : }
27658 0 : pspline2diff(p, t, &v0, x, &v1, y, _state);
27659 0 : if( ae_fp_neq(*x,(double)(0))||ae_fp_neq(*y,(double)(0)) )
27660 : {
27661 :
27662 : /*
27663 : * this code is a bit more complex than X^2+Y^2 to avoid
27664 : * overflow for large values of X and Y.
27665 : */
27666 0 : v = safepythag2(*x, *y, _state);
27667 0 : *x = *x/v;
27668 0 : *y = *y/v;
27669 : }
27670 0 : }
27671 :
27672 :
27673 : /*************************************************************************
27674 : This function calculates tangent vector for a given value of parameter T
27675 :
27676 : INPUT PARAMETERS:
27677 : P - parametric spline interpolant
27678 : T - point:
27679 : * T in [0,1] corresponds to interval spanned by points
27680 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27681 : the curve before the first (after the last) point
27682 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27683 : by making T=T-floor(T).
27684 :
27685 : OUTPUT PARAMETERS:
27686 : X - X-component of tangent vector (normalized)
27687 : Y - Y-component of tangent vector (normalized)
27688 : Z - Z-component of tangent vector (normalized)
27689 :
27690 : NOTE:
27691 : X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0.
27692 :
27693 :
27694 : -- ALGLIB PROJECT --
27695 : Copyright 28.05.2010 by Bochkanov Sergey
27696 : *************************************************************************/
27697 0 : void pspline3tangent(pspline3interpolant* p,
27698 : double t,
27699 : double* x,
27700 : double* y,
27701 : double* z,
27702 : ae_state *_state)
27703 : {
27704 : double v;
27705 : double v0;
27706 : double v1;
27707 : double v2;
27708 :
27709 0 : *x = 0;
27710 0 : *y = 0;
27711 0 : *z = 0;
27712 :
27713 0 : if( p->periodic )
27714 : {
27715 0 : t = t-ae_ifloor(t, _state);
27716 : }
27717 0 : pspline3diff(p, t, &v0, x, &v1, y, &v2, z, _state);
27718 0 : if( (ae_fp_neq(*x,(double)(0))||ae_fp_neq(*y,(double)(0)))||ae_fp_neq(*z,(double)(0)) )
27719 : {
27720 0 : v = safepythag3(*x, *y, *z, _state);
27721 0 : *x = *x/v;
27722 0 : *y = *y/v;
27723 0 : *z = *z/v;
27724 : }
27725 0 : }
27726 :
27727 :
27728 : /*************************************************************************
27729 : This function calculates derivative, i.e. it returns (dX/dT,dY/dT).
27730 :
27731 : INPUT PARAMETERS:
27732 : P - parametric spline interpolant
27733 : T - point:
27734 : * T in [0,1] corresponds to interval spanned by points
27735 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27736 : the curve before the first (after the last) point
27737 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27738 : by making T=T-floor(T).
27739 :
27740 : OUTPUT PARAMETERS:
27741 : X - X-value
27742 : DX - X-derivative
27743 : Y - Y-value
27744 : DY - Y-derivative
27745 :
27746 :
27747 : -- ALGLIB PROJECT --
27748 : Copyright 28.05.2010 by Bochkanov Sergey
27749 : *************************************************************************/
27750 0 : void pspline2diff(pspline2interpolant* p,
27751 : double t,
27752 : double* x,
27753 : double* dx,
27754 : double* y,
27755 : double* dy,
27756 : ae_state *_state)
27757 : {
27758 : double d2s;
27759 :
27760 0 : *x = 0;
27761 0 : *dx = 0;
27762 0 : *y = 0;
27763 0 : *dy = 0;
27764 :
27765 0 : if( p->periodic )
27766 : {
27767 0 : t = t-ae_ifloor(t, _state);
27768 : }
27769 0 : spline1ddiff(&p->x, t, x, dx, &d2s, _state);
27770 0 : spline1ddiff(&p->y, t, y, dy, &d2s, _state);
27771 0 : }
27772 :
27773 :
27774 : /*************************************************************************
27775 : This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT).
27776 :
27777 : INPUT PARAMETERS:
27778 : P - parametric spline interpolant
27779 : T - point:
27780 : * T in [0,1] corresponds to interval spanned by points
27781 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27782 : the curve before the first (after the last) point
27783 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27784 : by making T=T-floor(T).
27785 :
27786 : OUTPUT PARAMETERS:
27787 : X - X-value
27788 : DX - X-derivative
27789 : Y - Y-value
27790 : DY - Y-derivative
27791 : Z - Z-value
27792 : DZ - Z-derivative
27793 :
27794 :
27795 : -- ALGLIB PROJECT --
27796 : Copyright 28.05.2010 by Bochkanov Sergey
27797 : *************************************************************************/
27798 0 : void pspline3diff(pspline3interpolant* p,
27799 : double t,
27800 : double* x,
27801 : double* dx,
27802 : double* y,
27803 : double* dy,
27804 : double* z,
27805 : double* dz,
27806 : ae_state *_state)
27807 : {
27808 : double d2s;
27809 :
27810 0 : *x = 0;
27811 0 : *dx = 0;
27812 0 : *y = 0;
27813 0 : *dy = 0;
27814 0 : *z = 0;
27815 0 : *dz = 0;
27816 :
27817 0 : if( p->periodic )
27818 : {
27819 0 : t = t-ae_ifloor(t, _state);
27820 : }
27821 0 : spline1ddiff(&p->x, t, x, dx, &d2s, _state);
27822 0 : spline1ddiff(&p->y, t, y, dy, &d2s, _state);
27823 0 : spline1ddiff(&p->z, t, z, dz, &d2s, _state);
27824 0 : }
27825 :
27826 :
27827 : /*************************************************************************
27828 : This function calculates first and second derivative with respect to T.
27829 :
27830 : INPUT PARAMETERS:
27831 : P - parametric spline interpolant
27832 : T - point:
27833 : * T in [0,1] corresponds to interval spanned by points
27834 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27835 : the curve before the first (after the last) point
27836 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27837 : by making T=T-floor(T).
27838 :
27839 : OUTPUT PARAMETERS:
27840 : X - X-value
27841 : DX - derivative
27842 : D2X - second derivative
27843 : Y - Y-value
27844 : DY - derivative
27845 : D2Y - second derivative
27846 :
27847 :
27848 : -- ALGLIB PROJECT --
27849 : Copyright 28.05.2010 by Bochkanov Sergey
27850 : *************************************************************************/
27851 0 : void pspline2diff2(pspline2interpolant* p,
27852 : double t,
27853 : double* x,
27854 : double* dx,
27855 : double* d2x,
27856 : double* y,
27857 : double* dy,
27858 : double* d2y,
27859 : ae_state *_state)
27860 : {
27861 :
27862 0 : *x = 0;
27863 0 : *dx = 0;
27864 0 : *d2x = 0;
27865 0 : *y = 0;
27866 0 : *dy = 0;
27867 0 : *d2y = 0;
27868 :
27869 0 : if( p->periodic )
27870 : {
27871 0 : t = t-ae_ifloor(t, _state);
27872 : }
27873 0 : spline1ddiff(&p->x, t, x, dx, d2x, _state);
27874 0 : spline1ddiff(&p->y, t, y, dy, d2y, _state);
27875 0 : }
27876 :
27877 :
27878 : /*************************************************************************
27879 : This function calculates first and second derivative with respect to T.
27880 :
27881 : INPUT PARAMETERS:
27882 : P - parametric spline interpolant
27883 : T - point:
27884 : * T in [0,1] corresponds to interval spanned by points
27885 : * for non-periodic splines T<0 (or T>1) correspond to parts of
27886 : the curve before the first (after the last) point
27887 : * for periodic splines T<0 (or T>1) are projected into [0,1]
27888 : by making T=T-floor(T).
27889 :
27890 : OUTPUT PARAMETERS:
27891 : X - X-value
27892 : DX - derivative
27893 : D2X - second derivative
27894 : Y - Y-value
27895 : DY - derivative
27896 : D2Y - second derivative
27897 : Z - Z-value
27898 : DZ - derivative
27899 : D2Z - second derivative
27900 :
27901 :
27902 : -- ALGLIB PROJECT --
27903 : Copyright 28.05.2010 by Bochkanov Sergey
27904 : *************************************************************************/
27905 0 : void pspline3diff2(pspline3interpolant* p,
27906 : double t,
27907 : double* x,
27908 : double* dx,
27909 : double* d2x,
27910 : double* y,
27911 : double* dy,
27912 : double* d2y,
27913 : double* z,
27914 : double* dz,
27915 : double* d2z,
27916 : ae_state *_state)
27917 : {
27918 :
27919 0 : *x = 0;
27920 0 : *dx = 0;
27921 0 : *d2x = 0;
27922 0 : *y = 0;
27923 0 : *dy = 0;
27924 0 : *d2y = 0;
27925 0 : *z = 0;
27926 0 : *dz = 0;
27927 0 : *d2z = 0;
27928 :
27929 0 : if( p->periodic )
27930 : {
27931 0 : t = t-ae_ifloor(t, _state);
27932 : }
27933 0 : spline1ddiff(&p->x, t, x, dx, d2x, _state);
27934 0 : spline1ddiff(&p->y, t, y, dy, d2y, _state);
27935 0 : spline1ddiff(&p->z, t, z, dz, d2z, _state);
27936 0 : }
27937 :
27938 :
27939 : /*************************************************************************
27940 : This function calculates arc length, i.e. length of curve between t=a
27941 : and t=b.
27942 :
27943 : INPUT PARAMETERS:
27944 : P - parametric spline interpolant
27945 : A,B - parameter values corresponding to arc ends:
27946 : * B>A will result in positive length returned
27947 : * B<A will result in negative length returned
27948 :
27949 : RESULT:
27950 : length of arc starting at T=A and ending at T=B.
27951 :
27952 :
27953 : -- ALGLIB PROJECT --
27954 : Copyright 30.05.2010 by Bochkanov Sergey
27955 : *************************************************************************/
27956 0 : double pspline2arclength(pspline2interpolant* p,
27957 : double a,
27958 : double b,
27959 : ae_state *_state)
27960 : {
27961 : ae_frame _frame_block;
27962 : autogkstate state;
27963 : autogkreport rep;
27964 : double sx;
27965 : double dsx;
27966 : double d2sx;
27967 : double sy;
27968 : double dsy;
27969 : double d2sy;
27970 : double result;
27971 :
27972 0 : ae_frame_make(_state, &_frame_block);
27973 0 : memset(&state, 0, sizeof(state));
27974 0 : memset(&rep, 0, sizeof(rep));
27975 0 : _autogkstate_init(&state, _state, ae_true);
27976 0 : _autogkreport_init(&rep, _state, ae_true);
27977 :
27978 0 : autogksmooth(a, b, &state, _state);
27979 0 : while(autogkiteration(&state, _state))
27980 : {
27981 0 : spline1ddiff(&p->x, state.x, &sx, &dsx, &d2sx, _state);
27982 0 : spline1ddiff(&p->y, state.x, &sy, &dsy, &d2sy, _state);
27983 0 : state.f = safepythag2(dsx, dsy, _state);
27984 : }
27985 0 : autogkresults(&state, &result, &rep, _state);
27986 0 : ae_assert(rep.terminationtype>0, "PSpline2ArcLength: internal error!", _state);
27987 0 : ae_frame_leave(_state);
27988 0 : return result;
27989 : }
27990 :
27991 :
27992 : /*************************************************************************
27993 : This function calculates arc length, i.e. length of curve between t=a
27994 : and t=b.
27995 :
27996 : INPUT PARAMETERS:
27997 : P - parametric spline interpolant
27998 : A,B - parameter values corresponding to arc ends:
27999 : * B>A will result in positive length returned
28000 : * B<A will result in negative length returned
28001 :
28002 : RESULT:
28003 : length of arc starting at T=A and ending at T=B.
28004 :
28005 :
28006 : -- ALGLIB PROJECT --
28007 : Copyright 30.05.2010 by Bochkanov Sergey
28008 : *************************************************************************/
28009 0 : double pspline3arclength(pspline3interpolant* p,
28010 : double a,
28011 : double b,
28012 : ae_state *_state)
28013 : {
28014 : ae_frame _frame_block;
28015 : autogkstate state;
28016 : autogkreport rep;
28017 : double sx;
28018 : double dsx;
28019 : double d2sx;
28020 : double sy;
28021 : double dsy;
28022 : double d2sy;
28023 : double sz;
28024 : double dsz;
28025 : double d2sz;
28026 : double result;
28027 :
28028 0 : ae_frame_make(_state, &_frame_block);
28029 0 : memset(&state, 0, sizeof(state));
28030 0 : memset(&rep, 0, sizeof(rep));
28031 0 : _autogkstate_init(&state, _state, ae_true);
28032 0 : _autogkreport_init(&rep, _state, ae_true);
28033 :
28034 0 : autogksmooth(a, b, &state, _state);
28035 0 : while(autogkiteration(&state, _state))
28036 : {
28037 0 : spline1ddiff(&p->x, state.x, &sx, &dsx, &d2sx, _state);
28038 0 : spline1ddiff(&p->y, state.x, &sy, &dsy, &d2sy, _state);
28039 0 : spline1ddiff(&p->z, state.x, &sz, &dsz, &d2sz, _state);
28040 0 : state.f = safepythag3(dsx, dsy, dsz, _state);
28041 : }
28042 0 : autogkresults(&state, &result, &rep, _state);
28043 0 : ae_assert(rep.terminationtype>0, "PSpline3ArcLength: internal error!", _state);
28044 0 : ae_frame_leave(_state);
28045 0 : return result;
28046 : }
28047 :
28048 :
28049 : /*************************************************************************
28050 : This subroutine fits piecewise linear curve to points with Ramer-Douglas-
28051 : Peucker algorithm. This function performs PARAMETRIC fit, i.e. it can be
28052 : used to fit curves like circles.
28053 :
28054 : On input it accepts dataset which describes parametric multidimensional
28055 : curve X(t), with X being vector, and t taking values in [0,N), where N is
28056 : a number of points in dataset. As result, it returns reduced dataset X2,
28057 : which can be used to build parametric curve X2(t), which approximates
28058 : X(t) with desired precision (or has specified number of sections).
28059 :
28060 :
28061 : INPUT PARAMETERS:
28062 : X - array of multidimensional points:
28063 : * at least N elements, leading N elements are used if more
28064 : than N elements were specified
28065 : * order of points is IMPORTANT because it is parametric
28066 : fit
28067 : * each row of array is one point which has D coordinates
28068 : N - number of elements in X
28069 : D - number of dimensions (elements per row of X)
28070 : StopM - stopping condition - desired number of sections:
28071 : * at most M sections are generated by this function
28072 : * less than M sections can be generated if we have N<M
28073 : (or some X are non-distinct).
28074 : * zero StopM means that algorithm does not stop after
28075 : achieving some pre-specified section count
28076 : StopEps - stopping condition - desired precision:
28077 : * algorithm stops after error in each section is at most Eps
28078 : * zero Eps means that algorithm does not stop after
28079 : achieving some pre-specified precision
28080 :
28081 : OUTPUT PARAMETERS:
28082 : X2 - array of corner points for piecewise approximation,
28083 : has length NSections+1 or zero (for NSections=0).
28084 : Idx2 - array of indexes (parameter values):
28085 : * has length NSections+1 or zero (for NSections=0).
28086 : * each element of Idx2 corresponds to same-numbered
28087 : element of X2
28088 : * each element of Idx2 is index of corresponding element
28089 : of X2 at original array X, i.e. I-th row of X2 is
28090 : Idx2[I]-th row of X.
28091 : * elements of Idx2 can be treated as parameter values
28092 : which should be used when building new parametric curve
28093 : * Idx2[0]=0, Idx2[NSections]=N-1
28094 : NSections- number of sections found by algorithm, NSections<=M,
28095 : NSections can be zero for degenerate datasets
28096 : (N<=1 or all X[] are non-distinct).
28097 :
28098 : NOTE: algorithm stops after:
28099 : a) dividing curve into StopM sections
28100 : b) achieving required precision StopEps
28101 : c) dividing curve into N-1 sections
28102 : If both StopM and StopEps are non-zero, algorithm is stopped by the
28103 : FIRST criterion which is satisfied. In case both StopM and StopEps
28104 : are zero, algorithm stops because of (c).
28105 :
28106 : -- ALGLIB --
28107 : Copyright 02.10.2014 by Bochkanov Sergey
28108 : *************************************************************************/
28109 0 : void parametricrdpfixed(/* Real */ ae_matrix* x,
28110 : ae_int_t n,
28111 : ae_int_t d,
28112 : ae_int_t stopm,
28113 : double stopeps,
28114 : /* Real */ ae_matrix* x2,
28115 : /* Integer */ ae_vector* idx2,
28116 : ae_int_t* nsections,
28117 : ae_state *_state)
28118 : {
28119 : ae_frame _frame_block;
28120 : ae_int_t i;
28121 : ae_int_t j;
28122 : ae_int_t k;
28123 : ae_bool allsame;
28124 : ae_int_t k0;
28125 : ae_int_t k1;
28126 : ae_int_t k2;
28127 : double e0;
28128 : double e1;
28129 : ae_int_t idx0;
28130 : ae_int_t idx1;
28131 : ae_int_t worstidx;
28132 : double worsterror;
28133 : ae_matrix sections;
28134 : ae_vector heaperrors;
28135 : ae_vector heaptags;
28136 : ae_vector buf0;
28137 : ae_vector buf1;
28138 :
28139 0 : ae_frame_make(_state, &_frame_block);
28140 0 : memset(§ions, 0, sizeof(sections));
28141 0 : memset(&heaperrors, 0, sizeof(heaperrors));
28142 0 : memset(&heaptags, 0, sizeof(heaptags));
28143 0 : memset(&buf0, 0, sizeof(buf0));
28144 0 : memset(&buf1, 0, sizeof(buf1));
28145 0 : ae_matrix_clear(x2);
28146 0 : ae_vector_clear(idx2);
28147 0 : *nsections = 0;
28148 0 : ae_matrix_init(§ions, 0, 0, DT_REAL, _state, ae_true);
28149 0 : ae_vector_init(&heaperrors, 0, DT_REAL, _state, ae_true);
28150 0 : ae_vector_init(&heaptags, 0, DT_INT, _state, ae_true);
28151 0 : ae_vector_init(&buf0, 0, DT_REAL, _state, ae_true);
28152 0 : ae_vector_init(&buf1, 0, DT_REAL, _state, ae_true);
28153 :
28154 0 : ae_assert(n>=0, "LSTFitPiecewiseLinearParametricRDP: N<0", _state);
28155 0 : ae_assert(d>=1, "LSTFitPiecewiseLinearParametricRDP: D<=0", _state);
28156 0 : ae_assert(stopm>=0, "LSTFitPiecewiseLinearParametricRDP: StopM<1", _state);
28157 0 : ae_assert(ae_isfinite(stopeps, _state)&&ae_fp_greater_eq(stopeps,(double)(0)), "LSTFitPiecewiseLinearParametricRDP: StopEps<0 or is infinite", _state);
28158 0 : ae_assert(x->rows>=n, "LSTFitPiecewiseLinearParametricRDP: Rows(X)<N", _state);
28159 0 : ae_assert(x->cols>=d, "LSTFitPiecewiseLinearParametricRDP: Cols(X)<D", _state);
28160 0 : ae_assert(apservisfinitematrix(x, n, d, _state), "LSTFitPiecewiseLinearParametricRDP: X contains infinite/NAN values", _state);
28161 :
28162 : /*
28163 : * Handle degenerate cases
28164 : */
28165 0 : if( n<=1 )
28166 : {
28167 0 : *nsections = 0;
28168 0 : ae_frame_leave(_state);
28169 0 : return;
28170 : }
28171 0 : allsame = ae_true;
28172 0 : for(i=1; i<=n-1; i++)
28173 : {
28174 0 : for(j=0; j<=d-1; j++)
28175 : {
28176 0 : allsame = allsame&&ae_fp_eq(x->ptr.pp_double[i][j],x->ptr.pp_double[0][j]);
28177 : }
28178 : }
28179 0 : if( allsame )
28180 : {
28181 0 : *nsections = 0;
28182 0 : ae_frame_leave(_state);
28183 0 : return;
28184 : }
28185 :
28186 : /*
28187 : * Prepare first section
28188 : */
28189 0 : parametric_rdpanalyzesectionpar(x, 0, n-1, d, &worstidx, &worsterror, _state);
28190 0 : ae_matrix_set_length(§ions, n, 4, _state);
28191 0 : ae_vector_set_length(&heaperrors, n, _state);
28192 0 : ae_vector_set_length(&heaptags, n, _state);
28193 0 : *nsections = 1;
28194 0 : sections.ptr.pp_double[0][0] = (double)(0);
28195 0 : sections.ptr.pp_double[0][1] = (double)(n-1);
28196 0 : sections.ptr.pp_double[0][2] = (double)(worstidx);
28197 0 : sections.ptr.pp_double[0][3] = worsterror;
28198 0 : heaperrors.ptr.p_double[0] = worsterror;
28199 0 : heaptags.ptr.p_int[0] = 0;
28200 0 : ae_assert(ae_fp_eq(sections.ptr.pp_double[0][1],(double)(n-1)), "RDP algorithm: integrity check failed", _state);
28201 :
28202 : /*
28203 : * Main loop.
28204 : * Repeatedly find section with worst error and divide it.
28205 : * Terminate after M-th section, or because of other reasons (see loop internals).
28206 : */
28207 : for(;;)
28208 : {
28209 :
28210 : /*
28211 : * Break loop if one of the stopping conditions was met.
28212 : * Store index of worst section to K.
28213 : */
28214 0 : if( ae_fp_eq(heaperrors.ptr.p_double[0],(double)(0)) )
28215 : {
28216 0 : break;
28217 : }
28218 0 : if( ae_fp_greater(stopeps,(double)(0))&&ae_fp_less_eq(heaperrors.ptr.p_double[0],stopeps) )
28219 : {
28220 0 : break;
28221 : }
28222 0 : if( stopm>0&&*nsections>=stopm )
28223 : {
28224 0 : break;
28225 : }
28226 0 : k = heaptags.ptr.p_int[0];
28227 :
28228 : /*
28229 : * K-th section is divided in two:
28230 : * * first one spans interval from X[Sections[K,0]] to X[Sections[K,2]]
28231 : * * second one spans interval from X[Sections[K,2]] to X[Sections[K,1]]
28232 : *
28233 : * First section is stored at K-th position, second one is appended to the table.
28234 : * Then we update heap which stores pairs of (error,section_index)
28235 : */
28236 0 : k0 = ae_round(sections.ptr.pp_double[k][0], _state);
28237 0 : k1 = ae_round(sections.ptr.pp_double[k][1], _state);
28238 0 : k2 = ae_round(sections.ptr.pp_double[k][2], _state);
28239 0 : parametric_rdpanalyzesectionpar(x, k0, k2, d, &idx0, &e0, _state);
28240 0 : parametric_rdpanalyzesectionpar(x, k2, k1, d, &idx1, &e1, _state);
28241 0 : sections.ptr.pp_double[k][0] = (double)(k0);
28242 0 : sections.ptr.pp_double[k][1] = (double)(k2);
28243 0 : sections.ptr.pp_double[k][2] = (double)(idx0);
28244 0 : sections.ptr.pp_double[k][3] = e0;
28245 0 : tagheapreplacetopi(&heaperrors, &heaptags, *nsections, e0, k, _state);
28246 0 : sections.ptr.pp_double[*nsections][0] = (double)(k2);
28247 0 : sections.ptr.pp_double[*nsections][1] = (double)(k1);
28248 0 : sections.ptr.pp_double[*nsections][2] = (double)(idx1);
28249 0 : sections.ptr.pp_double[*nsections][3] = e1;
28250 0 : tagheappushi(&heaperrors, &heaptags, nsections, e1, *nsections, _state);
28251 : }
28252 :
28253 : /*
28254 : * Convert from sections to indexes
28255 : */
28256 0 : ae_vector_set_length(&buf0, *nsections+1, _state);
28257 0 : for(i=0; i<=*nsections-1; i++)
28258 : {
28259 0 : buf0.ptr.p_double[i] = (double)(ae_round(sections.ptr.pp_double[i][0], _state));
28260 : }
28261 0 : buf0.ptr.p_double[*nsections] = (double)(n-1);
28262 0 : tagsortfast(&buf0, &buf1, *nsections+1, _state);
28263 0 : ae_vector_set_length(idx2, *nsections+1, _state);
28264 0 : for(i=0; i<=*nsections; i++)
28265 : {
28266 0 : idx2->ptr.p_int[i] = ae_round(buf0.ptr.p_double[i], _state);
28267 : }
28268 0 : ae_assert(idx2->ptr.p_int[0]==0, "RDP algorithm: integrity check failed", _state);
28269 0 : ae_assert(idx2->ptr.p_int[*nsections]==n-1, "RDP algorithm: integrity check failed", _state);
28270 :
28271 : /*
28272 : * Output sections:
28273 : * * first NSection elements of X2/Y2 are filled by x/y at left boundaries of sections
28274 : * * last element of X2/Y2 is filled by right boundary of rightmost section
28275 : * * X2/Y2 is sorted by ascending of X2
28276 : */
28277 0 : ae_matrix_set_length(x2, *nsections+1, d, _state);
28278 0 : for(i=0; i<=*nsections; i++)
28279 : {
28280 0 : for(j=0; j<=d-1; j++)
28281 : {
28282 0 : x2->ptr.pp_double[i][j] = x->ptr.pp_double[idx2->ptr.p_int[i]][j];
28283 : }
28284 : }
28285 0 : ae_frame_leave(_state);
28286 : }
28287 :
28288 :
28289 : /*************************************************************************
28290 : Builds non-periodic parameterization for 2-dimensional spline
28291 : *************************************************************************/
28292 0 : static void parametric_pspline2par(/* Real */ ae_matrix* xy,
28293 : ae_int_t n,
28294 : ae_int_t pt,
28295 : /* Real */ ae_vector* p,
28296 : ae_state *_state)
28297 : {
28298 : double v;
28299 : ae_int_t i;
28300 :
28301 0 : ae_vector_clear(p);
28302 :
28303 0 : ae_assert(pt>=0&&pt<=2, "PSpline2Par: internal error!", _state);
28304 :
28305 : /*
28306 : * Build parameterization:
28307 : * * fill by non-normalized values
28308 : * * normalize them so we have P[0]=0, P[N-1]=1.
28309 : */
28310 0 : ae_vector_set_length(p, n, _state);
28311 0 : if( pt==0 )
28312 : {
28313 0 : for(i=0; i<=n-1; i++)
28314 : {
28315 0 : p->ptr.p_double[i] = (double)(i);
28316 : }
28317 : }
28318 0 : if( pt==1 )
28319 : {
28320 0 : p->ptr.p_double[0] = (double)(0);
28321 0 : for(i=1; i<=n-1; i++)
28322 : {
28323 0 : p->ptr.p_double[i] = p->ptr.p_double[i-1]+safepythag2(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], _state);
28324 : }
28325 : }
28326 0 : if( pt==2 )
28327 : {
28328 0 : p->ptr.p_double[0] = (double)(0);
28329 0 : for(i=1; i<=n-1; i++)
28330 : {
28331 0 : p->ptr.p_double[i] = p->ptr.p_double[i-1]+ae_sqrt(safepythag2(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], _state), _state);
28332 : }
28333 : }
28334 0 : v = 1/p->ptr.p_double[n-1];
28335 0 : ae_v_muld(&p->ptr.p_double[0], 1, ae_v_len(0,n-1), v);
28336 0 : }
28337 :
28338 :
28339 : /*************************************************************************
28340 : Builds non-periodic parameterization for 3-dimensional spline
28341 : *************************************************************************/
28342 0 : static void parametric_pspline3par(/* Real */ ae_matrix* xy,
28343 : ae_int_t n,
28344 : ae_int_t pt,
28345 : /* Real */ ae_vector* p,
28346 : ae_state *_state)
28347 : {
28348 : double v;
28349 : ae_int_t i;
28350 :
28351 0 : ae_vector_clear(p);
28352 :
28353 0 : ae_assert(pt>=0&&pt<=2, "PSpline3Par: internal error!", _state);
28354 :
28355 : /*
28356 : * Build parameterization:
28357 : * * fill by non-normalized values
28358 : * * normalize them so we have P[0]=0, P[N-1]=1.
28359 : */
28360 0 : ae_vector_set_length(p, n, _state);
28361 0 : if( pt==0 )
28362 : {
28363 0 : for(i=0; i<=n-1; i++)
28364 : {
28365 0 : p->ptr.p_double[i] = (double)(i);
28366 : }
28367 : }
28368 0 : if( pt==1 )
28369 : {
28370 0 : p->ptr.p_double[0] = (double)(0);
28371 0 : for(i=1; i<=n-1; i++)
28372 : {
28373 0 : p->ptr.p_double[i] = p->ptr.p_double[i-1]+safepythag3(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], xy->ptr.pp_double[i][2]-xy->ptr.pp_double[i-1][2], _state);
28374 : }
28375 : }
28376 0 : if( pt==2 )
28377 : {
28378 0 : p->ptr.p_double[0] = (double)(0);
28379 0 : for(i=1; i<=n-1; i++)
28380 : {
28381 0 : p->ptr.p_double[i] = p->ptr.p_double[i-1]+ae_sqrt(safepythag3(xy->ptr.pp_double[i][0]-xy->ptr.pp_double[i-1][0], xy->ptr.pp_double[i][1]-xy->ptr.pp_double[i-1][1], xy->ptr.pp_double[i][2]-xy->ptr.pp_double[i-1][2], _state), _state);
28382 : }
28383 : }
28384 0 : v = 1/p->ptr.p_double[n-1];
28385 0 : ae_v_muld(&p->ptr.p_double[0], 1, ae_v_len(0,n-1), v);
28386 0 : }
28387 :
28388 :
28389 : /*************************************************************************
28390 : This function analyzes section of curve for processing by RDP algorithm:
28391 : given set of points X,Y with indexes [I0,I1] it returns point with
28392 : worst deviation from linear model (PARAMETRIC version which sees curve
28393 : as X(t) with vector X).
28394 :
28395 : Input parameters:
28396 : XY - array
28397 : I0,I1 - interval (boundaries included) to process
28398 : D - number of dimensions
28399 :
28400 : OUTPUT PARAMETERS:
28401 : WorstIdx - index of worst point
28402 : WorstError - error at worst point
28403 :
28404 : NOTE: this function guarantees that it returns exactly zero for a section
28405 : with less than 3 points.
28406 :
28407 : -- ALGLIB PROJECT --
28408 : Copyright 02.10.2014 by Bochkanov Sergey
28409 : *************************************************************************/
28410 0 : static void parametric_rdpanalyzesectionpar(/* Real */ ae_matrix* xy,
28411 : ae_int_t i0,
28412 : ae_int_t i1,
28413 : ae_int_t d,
28414 : ae_int_t* worstidx,
28415 : double* worsterror,
28416 : ae_state *_state)
28417 : {
28418 : ae_int_t i;
28419 : ae_int_t j;
28420 : double v;
28421 : double d2;
28422 : double ts;
28423 : double vv;
28424 :
28425 0 : *worstidx = 0;
28426 0 : *worsterror = 0;
28427 :
28428 :
28429 : /*
28430 : * Quick exit for 0, 1, 2 points
28431 : */
28432 0 : if( i1-i0+1<3 )
28433 : {
28434 0 : *worstidx = i0;
28435 0 : *worsterror = 0.0;
28436 0 : return;
28437 : }
28438 :
28439 : /*
28440 : * Estimate D2 - squared distance between XY[I1] and XY[I0].
28441 : * In case D2=0 handle it as special case.
28442 : */
28443 0 : d2 = 0.0;
28444 0 : for(j=0; j<=d-1; j++)
28445 : {
28446 0 : d2 = d2+ae_sqr(xy->ptr.pp_double[i1][j]-xy->ptr.pp_double[i0][j], _state);
28447 : }
28448 0 : if( ae_fp_eq(d2,(double)(0)) )
28449 : {
28450 :
28451 : /*
28452 : * First and last points are equal, interval evaluation is
28453 : * trivial - we just calculate distance from all points to
28454 : * the first/last one.
28455 : */
28456 0 : *worstidx = i0;
28457 0 : *worsterror = 0.0;
28458 0 : for(i=i0+1; i<=i1-1; i++)
28459 : {
28460 0 : vv = 0.0;
28461 0 : for(j=0; j<=d-1; j++)
28462 : {
28463 0 : v = xy->ptr.pp_double[i][j]-xy->ptr.pp_double[i0][j];
28464 0 : vv = vv+v*v;
28465 : }
28466 0 : vv = ae_sqrt(vv, _state);
28467 0 : if( ae_fp_greater(vv,*worsterror) )
28468 : {
28469 0 : *worsterror = vv;
28470 0 : *worstidx = i;
28471 : }
28472 : }
28473 0 : return;
28474 : }
28475 :
28476 : /*
28477 : * General case
28478 : *
28479 : * Current section of curve is modeled as x(t) = d*t+c, where
28480 : * d = XY[I1]-XY[I0]
28481 : * c = XY[I0]
28482 : * t is in [0,1]
28483 : */
28484 0 : *worstidx = i0;
28485 0 : *worsterror = 0.0;
28486 0 : for(i=i0+1; i<=i1-1; i++)
28487 : {
28488 :
28489 : /*
28490 : * Determine t_s - parameter value for projected point.
28491 : */
28492 0 : ts = (double)(i-i0)/(double)(i1-i0);
28493 :
28494 : /*
28495 : * Estimate error norm
28496 : */
28497 0 : vv = 0.0;
28498 0 : for(j=0; j<=d-1; j++)
28499 : {
28500 0 : v = (xy->ptr.pp_double[i1][j]-xy->ptr.pp_double[i0][j])*ts-(xy->ptr.pp_double[i][j]-xy->ptr.pp_double[i0][j]);
28501 0 : vv = vv+ae_sqr(v, _state);
28502 : }
28503 0 : vv = ae_sqrt(vv, _state);
28504 0 : if( ae_fp_greater(vv,*worsterror) )
28505 : {
28506 0 : *worsterror = vv;
28507 0 : *worstidx = i;
28508 : }
28509 : }
28510 : }
28511 :
28512 :
28513 0 : void _pspline2interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
28514 : {
28515 0 : pspline2interpolant *p = (pspline2interpolant*)_p;
28516 0 : ae_touch_ptr((void*)p);
28517 0 : ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic);
28518 0 : _spline1dinterpolant_init(&p->x, _state, make_automatic);
28519 0 : _spline1dinterpolant_init(&p->y, _state, make_automatic);
28520 0 : }
28521 :
28522 :
28523 0 : void _pspline2interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
28524 : {
28525 0 : pspline2interpolant *dst = (pspline2interpolant*)_dst;
28526 0 : pspline2interpolant *src = (pspline2interpolant*)_src;
28527 0 : dst->n = src->n;
28528 0 : dst->periodic = src->periodic;
28529 0 : ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic);
28530 0 : _spline1dinterpolant_init_copy(&dst->x, &src->x, _state, make_automatic);
28531 0 : _spline1dinterpolant_init_copy(&dst->y, &src->y, _state, make_automatic);
28532 0 : }
28533 :
28534 :
28535 0 : void _pspline2interpolant_clear(void* _p)
28536 : {
28537 0 : pspline2interpolant *p = (pspline2interpolant*)_p;
28538 0 : ae_touch_ptr((void*)p);
28539 0 : ae_vector_clear(&p->p);
28540 0 : _spline1dinterpolant_clear(&p->x);
28541 0 : _spline1dinterpolant_clear(&p->y);
28542 0 : }
28543 :
28544 :
28545 0 : void _pspline2interpolant_destroy(void* _p)
28546 : {
28547 0 : pspline2interpolant *p = (pspline2interpolant*)_p;
28548 0 : ae_touch_ptr((void*)p);
28549 0 : ae_vector_destroy(&p->p);
28550 0 : _spline1dinterpolant_destroy(&p->x);
28551 0 : _spline1dinterpolant_destroy(&p->y);
28552 0 : }
28553 :
28554 :
28555 0 : void _pspline3interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
28556 : {
28557 0 : pspline3interpolant *p = (pspline3interpolant*)_p;
28558 0 : ae_touch_ptr((void*)p);
28559 0 : ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic);
28560 0 : _spline1dinterpolant_init(&p->x, _state, make_automatic);
28561 0 : _spline1dinterpolant_init(&p->y, _state, make_automatic);
28562 0 : _spline1dinterpolant_init(&p->z, _state, make_automatic);
28563 0 : }
28564 :
28565 :
28566 0 : void _pspline3interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
28567 : {
28568 0 : pspline3interpolant *dst = (pspline3interpolant*)_dst;
28569 0 : pspline3interpolant *src = (pspline3interpolant*)_src;
28570 0 : dst->n = src->n;
28571 0 : dst->periodic = src->periodic;
28572 0 : ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic);
28573 0 : _spline1dinterpolant_init_copy(&dst->x, &src->x, _state, make_automatic);
28574 0 : _spline1dinterpolant_init_copy(&dst->y, &src->y, _state, make_automatic);
28575 0 : _spline1dinterpolant_init_copy(&dst->z, &src->z, _state, make_automatic);
28576 0 : }
28577 :
28578 :
28579 0 : void _pspline3interpolant_clear(void* _p)
28580 : {
28581 0 : pspline3interpolant *p = (pspline3interpolant*)_p;
28582 0 : ae_touch_ptr((void*)p);
28583 0 : ae_vector_clear(&p->p);
28584 0 : _spline1dinterpolant_clear(&p->x);
28585 0 : _spline1dinterpolant_clear(&p->y);
28586 0 : _spline1dinterpolant_clear(&p->z);
28587 0 : }
28588 :
28589 :
28590 0 : void _pspline3interpolant_destroy(void* _p)
28591 : {
28592 0 : pspline3interpolant *p = (pspline3interpolant*)_p;
28593 0 : ae_touch_ptr((void*)p);
28594 0 : ae_vector_destroy(&p->p);
28595 0 : _spline1dinterpolant_destroy(&p->x);
28596 0 : _spline1dinterpolant_destroy(&p->y);
28597 0 : _spline1dinterpolant_destroy(&p->z);
28598 0 : }
28599 :
28600 :
28601 : #endif
28602 : #if defined(AE_COMPILE_SPLINE3D) || !defined(AE_PARTIAL_BUILD)
28603 :
28604 :
28605 : /*************************************************************************
28606 : This subroutine calculates the value of the trilinear or tricubic spline at
28607 : the given point (X,Y,Z).
28608 :
28609 : INPUT PARAMETERS:
28610 : C - coefficients table.
28611 : Built by BuildBilinearSpline or BuildBicubicSpline.
28612 : X, Y,
28613 : Z - point
28614 :
28615 : Result:
28616 : S(x,y,z)
28617 :
28618 : -- ALGLIB PROJECT --
28619 : Copyright 26.04.2012 by Bochkanov Sergey
28620 : *************************************************************************/
28621 0 : double spline3dcalc(spline3dinterpolant* c,
28622 : double x,
28623 : double y,
28624 : double z,
28625 : ae_state *_state)
28626 : {
28627 : double v;
28628 : double vx;
28629 : double vy;
28630 : double vxy;
28631 : double result;
28632 :
28633 :
28634 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalc: incorrect C (incorrect parameter C.SType)", _state);
28635 0 : ae_assert((ae_isfinite(x, _state)&&ae_isfinite(y, _state))&&ae_isfinite(z, _state), "Spline3DCalc: X=NaN/Infinite, Y=NaN/Infinite or Z=NaN/Infinite", _state);
28636 0 : if( c->d!=1 )
28637 : {
28638 0 : result = (double)(0);
28639 0 : return result;
28640 : }
28641 0 : spline3d_spline3ddiff(c, x, y, z, &v, &vx, &vy, &vxy, _state);
28642 0 : result = v;
28643 0 : return result;
28644 : }
28645 :
28646 :
28647 : /*************************************************************************
28648 : This subroutine performs linear transformation of the spline argument.
28649 :
28650 : INPUT PARAMETERS:
28651 : C - spline interpolant
28652 : AX, BX - transformation coefficients: x = A*u + B
28653 : AY, BY - transformation coefficients: y = A*v + B
28654 : AZ, BZ - transformation coefficients: z = A*w + B
28655 :
28656 : OUTPUT PARAMETERS:
28657 : C - transformed spline
28658 :
28659 : -- ALGLIB PROJECT --
28660 : Copyright 26.04.2012 by Bochkanov Sergey
28661 : *************************************************************************/
28662 0 : void spline3dlintransxyz(spline3dinterpolant* c,
28663 : double ax,
28664 : double bx,
28665 : double ay,
28666 : double by,
28667 : double az,
28668 : double bz,
28669 : ae_state *_state)
28670 : {
28671 : ae_frame _frame_block;
28672 : ae_vector x;
28673 : ae_vector y;
28674 : ae_vector z;
28675 : ae_vector f;
28676 : ae_vector v;
28677 : ae_int_t i;
28678 : ae_int_t j;
28679 : ae_int_t k;
28680 : ae_int_t di;
28681 :
28682 0 : ae_frame_make(_state, &_frame_block);
28683 0 : memset(&x, 0, sizeof(x));
28684 0 : memset(&y, 0, sizeof(y));
28685 0 : memset(&z, 0, sizeof(z));
28686 0 : memset(&f, 0, sizeof(f));
28687 0 : memset(&v, 0, sizeof(v));
28688 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
28689 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
28690 0 : ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
28691 0 : ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
28692 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
28693 :
28694 0 : ae_assert(c->stype==-3||c->stype==-1, "Spline3DLinTransXYZ: incorrect C (incorrect parameter C.SType)", _state);
28695 0 : ae_vector_set_length(&x, c->n, _state);
28696 0 : ae_vector_set_length(&y, c->m, _state);
28697 0 : ae_vector_set_length(&z, c->l, _state);
28698 0 : ae_vector_set_length(&f, c->m*c->n*c->l*c->d, _state);
28699 0 : for(j=0; j<=c->n-1; j++)
28700 : {
28701 0 : x.ptr.p_double[j] = c->x.ptr.p_double[j];
28702 : }
28703 0 : for(i=0; i<=c->m-1; i++)
28704 : {
28705 0 : y.ptr.p_double[i] = c->y.ptr.p_double[i];
28706 : }
28707 0 : for(i=0; i<=c->l-1; i++)
28708 : {
28709 0 : z.ptr.p_double[i] = c->z.ptr.p_double[i];
28710 : }
28711 :
28712 : /*
28713 : * Handle different combinations of zero/nonzero AX/AY/AZ
28714 : */
28715 0 : if( (ae_fp_neq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) )
28716 : {
28717 0 : ae_v_move(&f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,c->m*c->n*c->l*c->d-1));
28718 : }
28719 0 : if( (ae_fp_eq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) )
28720 : {
28721 0 : for(i=0; i<=c->m-1; i++)
28722 : {
28723 0 : for(j=0; j<=c->l-1; j++)
28724 : {
28725 0 : spline3dcalcv(c, bx, y.ptr.p_double[i], z.ptr.p_double[j], &v, _state);
28726 0 : for(k=0; k<=c->n-1; k++)
28727 : {
28728 0 : for(di=0; di<=c->d-1; di++)
28729 : {
28730 0 : f.ptr.p_double[c->d*(c->n*(c->m*j+i)+k)+di] = v.ptr.p_double[di];
28731 : }
28732 : }
28733 : }
28734 : }
28735 0 : ax = (double)(1);
28736 0 : bx = (double)(0);
28737 : }
28738 0 : if( (ae_fp_neq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) )
28739 : {
28740 0 : for(i=0; i<=c->n-1; i++)
28741 : {
28742 0 : for(j=0; j<=c->l-1; j++)
28743 : {
28744 0 : spline3dcalcv(c, x.ptr.p_double[i], by, z.ptr.p_double[j], &v, _state);
28745 0 : for(k=0; k<=c->m-1; k++)
28746 : {
28747 0 : for(di=0; di<=c->d-1; di++)
28748 : {
28749 0 : f.ptr.p_double[c->d*(c->n*(c->m*j+k)+i)+di] = v.ptr.p_double[di];
28750 : }
28751 : }
28752 : }
28753 : }
28754 0 : ay = (double)(1);
28755 0 : by = (double)(0);
28756 : }
28757 0 : if( (ae_fp_neq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) )
28758 : {
28759 0 : for(i=0; i<=c->n-1; i++)
28760 : {
28761 0 : for(j=0; j<=c->m-1; j++)
28762 : {
28763 0 : spline3dcalcv(c, x.ptr.p_double[i], y.ptr.p_double[j], bz, &v, _state);
28764 0 : for(k=0; k<=c->l-1; k++)
28765 : {
28766 0 : for(di=0; di<=c->d-1; di++)
28767 : {
28768 0 : f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di];
28769 : }
28770 : }
28771 : }
28772 : }
28773 0 : az = (double)(1);
28774 0 : bz = (double)(0);
28775 : }
28776 0 : if( (ae_fp_eq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_neq(az,(double)(0)) )
28777 : {
28778 0 : for(i=0; i<=c->l-1; i++)
28779 : {
28780 0 : spline3dcalcv(c, bx, by, z.ptr.p_double[i], &v, _state);
28781 0 : for(k=0; k<=c->m-1; k++)
28782 : {
28783 0 : for(j=0; j<=c->n-1; j++)
28784 : {
28785 0 : for(di=0; di<=c->d-1; di++)
28786 : {
28787 0 : f.ptr.p_double[c->d*(c->n*(c->m*i+k)+j)+di] = v.ptr.p_double[di];
28788 : }
28789 : }
28790 : }
28791 : }
28792 0 : ax = (double)(1);
28793 0 : bx = (double)(0);
28794 0 : ay = (double)(1);
28795 0 : by = (double)(0);
28796 : }
28797 0 : if( (ae_fp_eq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) )
28798 : {
28799 0 : for(i=0; i<=c->m-1; i++)
28800 : {
28801 0 : spline3dcalcv(c, bx, y.ptr.p_double[i], bz, &v, _state);
28802 0 : for(k=0; k<=c->l-1; k++)
28803 : {
28804 0 : for(j=0; j<=c->n-1; j++)
28805 : {
28806 0 : for(di=0; di<=c->d-1; di++)
28807 : {
28808 0 : f.ptr.p_double[c->d*(c->n*(c->m*k+i)+j)+di] = v.ptr.p_double[di];
28809 : }
28810 : }
28811 : }
28812 : }
28813 0 : ax = (double)(1);
28814 0 : bx = (double)(0);
28815 0 : az = (double)(1);
28816 0 : bz = (double)(0);
28817 : }
28818 0 : if( (ae_fp_neq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) )
28819 : {
28820 0 : for(i=0; i<=c->n-1; i++)
28821 : {
28822 0 : spline3dcalcv(c, x.ptr.p_double[i], by, bz, &v, _state);
28823 0 : for(k=0; k<=c->l-1; k++)
28824 : {
28825 0 : for(j=0; j<=c->m-1; j++)
28826 : {
28827 0 : for(di=0; di<=c->d-1; di++)
28828 : {
28829 0 : f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di];
28830 : }
28831 : }
28832 : }
28833 : }
28834 0 : ay = (double)(1);
28835 0 : by = (double)(0);
28836 0 : az = (double)(1);
28837 0 : bz = (double)(0);
28838 : }
28839 0 : if( (ae_fp_eq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)))&&ae_fp_eq(az,(double)(0)) )
28840 : {
28841 0 : spline3dcalcv(c, bx, by, bz, &v, _state);
28842 0 : for(k=0; k<=c->l-1; k++)
28843 : {
28844 0 : for(j=0; j<=c->m-1; j++)
28845 : {
28846 0 : for(i=0; i<=c->n-1; i++)
28847 : {
28848 0 : for(di=0; di<=c->d-1; di++)
28849 : {
28850 0 : f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di];
28851 : }
28852 : }
28853 : }
28854 : }
28855 0 : ax = (double)(1);
28856 0 : bx = (double)(0);
28857 0 : ay = (double)(1);
28858 0 : by = (double)(0);
28859 0 : az = (double)(1);
28860 0 : bz = (double)(0);
28861 : }
28862 :
28863 : /*
28864 : * General case: AX<>0, AY<>0, AZ<>0
28865 : * Unpack, scale and pack again.
28866 : */
28867 0 : for(i=0; i<=c->n-1; i++)
28868 : {
28869 0 : x.ptr.p_double[i] = (x.ptr.p_double[i]-bx)/ax;
28870 : }
28871 0 : for(i=0; i<=c->m-1; i++)
28872 : {
28873 0 : y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay;
28874 : }
28875 0 : for(i=0; i<=c->l-1; i++)
28876 : {
28877 0 : z.ptr.p_double[i] = (z.ptr.p_double[i]-bz)/az;
28878 : }
28879 0 : if( c->stype==-1 )
28880 : {
28881 0 : spline3dbuildtrilinearv(&x, c->n, &y, c->m, &z, c->l, &f, c->d, c, _state);
28882 : }
28883 0 : ae_frame_leave(_state);
28884 0 : }
28885 :
28886 :
28887 : /*************************************************************************
28888 : This subroutine performs linear transformation of the spline.
28889 :
28890 : INPUT PARAMETERS:
28891 : C - spline interpolant.
28892 : A, B- transformation coefficients: S2(x,y) = A*S(x,y,z) + B
28893 :
28894 : OUTPUT PARAMETERS:
28895 : C - transformed spline
28896 :
28897 : -- ALGLIB PROJECT --
28898 : Copyright 26.04.2012 by Bochkanov Sergey
28899 : *************************************************************************/
28900 0 : void spline3dlintransf(spline3dinterpolant* c,
28901 : double a,
28902 : double b,
28903 : ae_state *_state)
28904 : {
28905 : ae_frame _frame_block;
28906 : ae_vector x;
28907 : ae_vector y;
28908 : ae_vector z;
28909 : ae_vector f;
28910 : ae_int_t i;
28911 : ae_int_t j;
28912 :
28913 0 : ae_frame_make(_state, &_frame_block);
28914 0 : memset(&x, 0, sizeof(x));
28915 0 : memset(&y, 0, sizeof(y));
28916 0 : memset(&z, 0, sizeof(z));
28917 0 : memset(&f, 0, sizeof(f));
28918 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
28919 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
28920 0 : ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
28921 0 : ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
28922 :
28923 0 : ae_assert(c->stype==-3||c->stype==-1, "Spline3DLinTransF: incorrect C (incorrect parameter C.SType)", _state);
28924 0 : ae_vector_set_length(&x, c->n, _state);
28925 0 : ae_vector_set_length(&y, c->m, _state);
28926 0 : ae_vector_set_length(&z, c->l, _state);
28927 0 : ae_vector_set_length(&f, c->m*c->n*c->l*c->d, _state);
28928 0 : for(j=0; j<=c->n-1; j++)
28929 : {
28930 0 : x.ptr.p_double[j] = c->x.ptr.p_double[j];
28931 : }
28932 0 : for(i=0; i<=c->m-1; i++)
28933 : {
28934 0 : y.ptr.p_double[i] = c->y.ptr.p_double[i];
28935 : }
28936 0 : for(i=0; i<=c->l-1; i++)
28937 : {
28938 0 : z.ptr.p_double[i] = c->z.ptr.p_double[i];
28939 : }
28940 0 : for(i=0; i<=c->m*c->n*c->l*c->d-1; i++)
28941 : {
28942 0 : f.ptr.p_double[i] = a*c->f.ptr.p_double[i]+b;
28943 : }
28944 0 : if( c->stype==-1 )
28945 : {
28946 0 : spline3dbuildtrilinearv(&x, c->n, &y, c->m, &z, c->l, &f, c->d, c, _state);
28947 : }
28948 0 : ae_frame_leave(_state);
28949 0 : }
28950 :
28951 :
28952 : /*************************************************************************
28953 : This subroutine makes the copy of the spline model.
28954 :
28955 : INPUT PARAMETERS:
28956 : C - spline interpolant
28957 :
28958 : OUTPUT PARAMETERS:
28959 : CC - spline copy
28960 :
28961 : -- ALGLIB PROJECT --
28962 : Copyright 26.04.2012 by Bochkanov Sergey
28963 : *************************************************************************/
28964 0 : void spline3dcopy(spline3dinterpolant* c,
28965 : spline3dinterpolant* cc,
28966 : ae_state *_state)
28967 : {
28968 : ae_int_t tblsize;
28969 :
28970 0 : _spline3dinterpolant_clear(cc);
28971 :
28972 0 : ae_assert(c->k==1||c->k==3, "Spline3DCopy: incorrect C (incorrect parameter C.K)", _state);
28973 0 : cc->k = c->k;
28974 0 : cc->n = c->n;
28975 0 : cc->m = c->m;
28976 0 : cc->l = c->l;
28977 0 : cc->d = c->d;
28978 0 : tblsize = c->n*c->m*c->l*c->d;
28979 0 : cc->stype = c->stype;
28980 0 : ae_vector_set_length(&cc->x, cc->n, _state);
28981 0 : ae_vector_set_length(&cc->y, cc->m, _state);
28982 0 : ae_vector_set_length(&cc->z, cc->l, _state);
28983 0 : ae_vector_set_length(&cc->f, tblsize, _state);
28984 0 : ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1));
28985 0 : ae_v_move(&cc->y.ptr.p_double[0], 1, &c->y.ptr.p_double[0], 1, ae_v_len(0,cc->m-1));
28986 0 : ae_v_move(&cc->z.ptr.p_double[0], 1, &c->z.ptr.p_double[0], 1, ae_v_len(0,cc->l-1));
28987 0 : ae_v_move(&cc->f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,tblsize-1));
28988 0 : }
28989 :
28990 :
28991 : /*************************************************************************
28992 : Trilinear spline resampling
28993 :
28994 : INPUT PARAMETERS:
28995 : A - array[0..OldXCount*OldYCount*OldZCount-1], function
28996 : values at the old grid, :
28997 : A[0] x=0,y=0,z=0
28998 : A[1] x=1,y=0,z=0
28999 : A[..] ...
29000 : A[..] x=oldxcount-1,y=0,z=0
29001 : A[..] x=0,y=1,z=0
29002 : A[..] ...
29003 : ...
29004 : OldZCount - old Z-count, OldZCount>1
29005 : OldYCount - old Y-count, OldYCount>1
29006 : OldXCount - old X-count, OldXCount>1
29007 : NewZCount - new Z-count, NewZCount>1
29008 : NewYCount - new Y-count, NewYCount>1
29009 : NewXCount - new X-count, NewXCount>1
29010 :
29011 : OUTPUT PARAMETERS:
29012 : B - array[0..NewXCount*NewYCount*NewZCount-1], function
29013 : values at the new grid:
29014 : B[0] x=0,y=0,z=0
29015 : B[1] x=1,y=0,z=0
29016 : B[..] ...
29017 : B[..] x=newxcount-1,y=0,z=0
29018 : B[..] x=0,y=1,z=0
29019 : B[..] ...
29020 : ...
29021 :
29022 : -- ALGLIB routine --
29023 : 26.04.2012
29024 : Copyright by Bochkanov Sergey
29025 : *************************************************************************/
29026 0 : void spline3dresampletrilinear(/* Real */ ae_vector* a,
29027 : ae_int_t oldzcount,
29028 : ae_int_t oldycount,
29029 : ae_int_t oldxcount,
29030 : ae_int_t newzcount,
29031 : ae_int_t newycount,
29032 : ae_int_t newxcount,
29033 : /* Real */ ae_vector* b,
29034 : ae_state *_state)
29035 : {
29036 : double xd;
29037 : double yd;
29038 : double zd;
29039 : double c0;
29040 : double c1;
29041 : double c2;
29042 : double c3;
29043 : ae_int_t ix;
29044 : ae_int_t iy;
29045 : ae_int_t iz;
29046 : ae_int_t i;
29047 : ae_int_t j;
29048 : ae_int_t k;
29049 :
29050 0 : ae_vector_clear(b);
29051 :
29052 0 : ae_assert((oldycount>1&&oldzcount>1)&&oldxcount>1, "Spline3DResampleTrilinear: length/width/height less than 1", _state);
29053 0 : ae_assert((newycount>1&&newzcount>1)&&newxcount>1, "Spline3DResampleTrilinear: length/width/height less than 1", _state);
29054 0 : ae_assert(a->cnt>=oldycount*oldzcount*oldxcount, "Spline3DResampleTrilinear: length/width/height less than 1", _state);
29055 0 : ae_vector_set_length(b, newxcount*newycount*newzcount, _state);
29056 0 : for(i=0; i<=newxcount-1; i++)
29057 : {
29058 0 : for(j=0; j<=newycount-1; j++)
29059 : {
29060 0 : for(k=0; k<=newzcount-1; k++)
29061 : {
29062 0 : ix = i*(oldxcount-1)/(newxcount-1);
29063 0 : if( ix==oldxcount-1 )
29064 : {
29065 0 : ix = oldxcount-2;
29066 : }
29067 0 : xd = (double)(i*(oldxcount-1))/(double)(newxcount-1)-ix;
29068 0 : iy = j*(oldycount-1)/(newycount-1);
29069 0 : if( iy==oldycount-1 )
29070 : {
29071 0 : iy = oldycount-2;
29072 : }
29073 0 : yd = (double)(j*(oldycount-1))/(double)(newycount-1)-iy;
29074 0 : iz = k*(oldzcount-1)/(newzcount-1);
29075 0 : if( iz==oldzcount-1 )
29076 : {
29077 0 : iz = oldzcount-2;
29078 : }
29079 0 : zd = (double)(k*(oldzcount-1))/(double)(newzcount-1)-iz;
29080 0 : c0 = a->ptr.p_double[oldxcount*(oldycount*iz+iy)+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*iz+iy)+(ix+1)]*xd;
29081 0 : c1 = a->ptr.p_double[oldxcount*(oldycount*iz+(iy+1))+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*iz+(iy+1))+(ix+1)]*xd;
29082 0 : c2 = a->ptr.p_double[oldxcount*(oldycount*(iz+1)+iy)+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*(iz+1)+iy)+(ix+1)]*xd;
29083 0 : c3 = a->ptr.p_double[oldxcount*(oldycount*(iz+1)+(iy+1))+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*(iz+1)+(iy+1))+(ix+1)]*xd;
29084 0 : c0 = c0*(1-yd)+c1*yd;
29085 0 : c1 = c2*(1-yd)+c3*yd;
29086 0 : b->ptr.p_double[newxcount*(newycount*k+j)+i] = c0*(1-zd)+c1*zd;
29087 : }
29088 : }
29089 : }
29090 0 : }
29091 :
29092 :
29093 : /*************************************************************************
29094 : This subroutine builds trilinear vector-valued spline.
29095 :
29096 : INPUT PARAMETERS:
29097 : X - spline abscissas, array[0..N-1]
29098 : Y - spline ordinates, array[0..M-1]
29099 : Z - spline applicates, array[0..L-1]
29100 : F - function values, array[0..M*N*L*D-1]:
29101 : * first D elements store D values at (X[0],Y[0],Z[0])
29102 : * next D elements store D values at (X[1],Y[0],Z[0])
29103 : * next D elements store D values at (X[2],Y[0],Z[0])
29104 : * ...
29105 : * next D elements store D values at (X[0],Y[1],Z[0])
29106 : * next D elements store D values at (X[1],Y[1],Z[0])
29107 : * next D elements store D values at (X[2],Y[1],Z[0])
29108 : * ...
29109 : * next D elements store D values at (X[0],Y[0],Z[1])
29110 : * next D elements store D values at (X[1],Y[0],Z[1])
29111 : * next D elements store D values at (X[2],Y[0],Z[1])
29112 : * ...
29113 : * general form - D function values at (X[i],Y[j]) are stored
29114 : at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1].
29115 : M,N,
29116 : L - grid size, M>=2, N>=2, L>=2
29117 : D - vector dimension, D>=1
29118 :
29119 : OUTPUT PARAMETERS:
29120 : C - spline interpolant
29121 :
29122 : -- ALGLIB PROJECT --
29123 : Copyright 26.04.2012 by Bochkanov Sergey
29124 : *************************************************************************/
29125 0 : void spline3dbuildtrilinearv(/* Real */ ae_vector* x,
29126 : ae_int_t n,
29127 : /* Real */ ae_vector* y,
29128 : ae_int_t m,
29129 : /* Real */ ae_vector* z,
29130 : ae_int_t l,
29131 : /* Real */ ae_vector* f,
29132 : ae_int_t d,
29133 : spline3dinterpolant* c,
29134 : ae_state *_state)
29135 : {
29136 : double t;
29137 : ae_int_t tblsize;
29138 : ae_int_t i;
29139 : ae_int_t j;
29140 : ae_int_t k;
29141 : ae_int_t i0;
29142 : ae_int_t j0;
29143 :
29144 0 : _spline3dinterpolant_clear(c);
29145 :
29146 0 : ae_assert(m>=2, "Spline3DBuildTrilinearV: M<2", _state);
29147 0 : ae_assert(n>=2, "Spline3DBuildTrilinearV: N<2", _state);
29148 0 : ae_assert(l>=2, "Spline3DBuildTrilinearV: L<2", _state);
29149 0 : ae_assert(d>=1, "Spline3DBuildTrilinearV: D<1", _state);
29150 0 : ae_assert((x->cnt>=n&&y->cnt>=m)&&z->cnt>=l, "Spline3DBuildTrilinearV: length of X, Y or Z is too short (Length(X/Y/Z)<N/M/L)", _state);
29151 0 : ae_assert((isfinitevector(x, n, _state)&&isfinitevector(y, m, _state))&&isfinitevector(z, l, _state), "Spline3DBuildTrilinearV: X, Y or Z contains NaN or Infinite value", _state);
29152 0 : tblsize = n*m*l*d;
29153 0 : ae_assert(f->cnt>=tblsize, "Spline3DBuildTrilinearV: length of F is too short (Length(F)<N*M*L*D)", _state);
29154 0 : ae_assert(isfinitevector(f, tblsize, _state), "Spline3DBuildTrilinearV: F contains NaN or Infinite value", _state);
29155 :
29156 : /*
29157 : * Fill interpolant
29158 : */
29159 0 : c->k = 1;
29160 0 : c->n = n;
29161 0 : c->m = m;
29162 0 : c->l = l;
29163 0 : c->d = d;
29164 0 : c->stype = -1;
29165 0 : ae_vector_set_length(&c->x, c->n, _state);
29166 0 : ae_vector_set_length(&c->y, c->m, _state);
29167 0 : ae_vector_set_length(&c->z, c->l, _state);
29168 0 : ae_vector_set_length(&c->f, tblsize, _state);
29169 0 : for(i=0; i<=c->n-1; i++)
29170 : {
29171 0 : c->x.ptr.p_double[i] = x->ptr.p_double[i];
29172 : }
29173 0 : for(i=0; i<=c->m-1; i++)
29174 : {
29175 0 : c->y.ptr.p_double[i] = y->ptr.p_double[i];
29176 : }
29177 0 : for(i=0; i<=c->l-1; i++)
29178 : {
29179 0 : c->z.ptr.p_double[i] = z->ptr.p_double[i];
29180 : }
29181 0 : for(i=0; i<=tblsize-1; i++)
29182 : {
29183 0 : c->f.ptr.p_double[i] = f->ptr.p_double[i];
29184 : }
29185 :
29186 : /*
29187 : * Sort points:
29188 : * * sort x;
29189 : * * sort y;
29190 : * * sort z.
29191 : */
29192 0 : for(j=0; j<=c->n-1; j++)
29193 : {
29194 0 : k = j;
29195 0 : for(i=j+1; i<=c->n-1; i++)
29196 : {
29197 0 : if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
29198 : {
29199 0 : k = i;
29200 : }
29201 : }
29202 0 : if( k!=j )
29203 : {
29204 0 : for(i=0; i<=c->m-1; i++)
29205 : {
29206 0 : for(j0=0; j0<=c->l-1; j0++)
29207 : {
29208 0 : for(i0=0; i0<=c->d-1; i0++)
29209 : {
29210 0 : t = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0];
29211 0 : c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0] = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+k)+i0];
29212 0 : c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+k)+i0] = t;
29213 : }
29214 : }
29215 : }
29216 0 : t = c->x.ptr.p_double[j];
29217 0 : c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
29218 0 : c->x.ptr.p_double[k] = t;
29219 : }
29220 : }
29221 0 : for(i=0; i<=c->m-1; i++)
29222 : {
29223 0 : k = i;
29224 0 : for(j=i+1; j<=c->m-1; j++)
29225 : {
29226 0 : if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
29227 : {
29228 0 : k = j;
29229 : }
29230 : }
29231 0 : if( k!=i )
29232 : {
29233 0 : for(j=0; j<=c->n-1; j++)
29234 : {
29235 0 : for(j0=0; j0<=c->l-1; j0++)
29236 : {
29237 0 : for(i0=0; i0<=c->d-1; i0++)
29238 : {
29239 0 : t = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0];
29240 0 : c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0] = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+k)+j)+i0];
29241 0 : c->f.ptr.p_double[c->d*(c->n*(c->m*j0+k)+j)+i0] = t;
29242 : }
29243 : }
29244 : }
29245 0 : t = c->y.ptr.p_double[i];
29246 0 : c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
29247 0 : c->y.ptr.p_double[k] = t;
29248 : }
29249 : }
29250 0 : for(k=0; k<=c->l-1; k++)
29251 : {
29252 0 : i = k;
29253 0 : for(j=i+1; j<=c->l-1; j++)
29254 : {
29255 0 : if( ae_fp_less(c->z.ptr.p_double[j],c->z.ptr.p_double[i]) )
29256 : {
29257 0 : i = j;
29258 : }
29259 : }
29260 0 : if( i!=k )
29261 : {
29262 0 : for(j=0; j<=c->m-1; j++)
29263 : {
29264 0 : for(j0=0; j0<=c->n-1; j0++)
29265 : {
29266 0 : for(i0=0; i0<=c->d-1; i0++)
29267 : {
29268 0 : t = c->f.ptr.p_double[c->d*(c->n*(c->m*k+j)+j0)+i0];
29269 0 : c->f.ptr.p_double[c->d*(c->n*(c->m*k+j)+j0)+i0] = c->f.ptr.p_double[c->d*(c->n*(c->m*i+j)+j0)+i0];
29270 0 : c->f.ptr.p_double[c->d*(c->n*(c->m*i+j)+j0)+i0] = t;
29271 : }
29272 : }
29273 : }
29274 0 : t = c->z.ptr.p_double[k];
29275 0 : c->z.ptr.p_double[k] = c->z.ptr.p_double[i];
29276 0 : c->z.ptr.p_double[i] = t;
29277 : }
29278 : }
29279 0 : }
29280 :
29281 :
29282 : /*************************************************************************
29283 : This subroutine calculates bilinear or bicubic vector-valued spline at the
29284 : given point (X,Y,Z).
29285 :
29286 : INPUT PARAMETERS:
29287 : C - spline interpolant.
29288 : X, Y,
29289 : Z - point
29290 : F - output buffer, possibly preallocated array. In case array size
29291 : is large enough to store result, it is not reallocated. Array
29292 : which is too short will be reallocated
29293 :
29294 : OUTPUT PARAMETERS:
29295 : F - array[D] (or larger) which stores function values
29296 :
29297 : -- ALGLIB PROJECT --
29298 : Copyright 26.04.2012 by Bochkanov Sergey
29299 : *************************************************************************/
29300 0 : void spline3dcalcvbuf(spline3dinterpolant* c,
29301 : double x,
29302 : double y,
29303 : double z,
29304 : /* Real */ ae_vector* f,
29305 : ae_state *_state)
29306 : {
29307 : double xd;
29308 : double yd;
29309 : double zd;
29310 : double c0;
29311 : double c1;
29312 : double c2;
29313 : double c3;
29314 : ae_int_t ix;
29315 : ae_int_t iy;
29316 : ae_int_t iz;
29317 : ae_int_t l;
29318 : ae_int_t r;
29319 : ae_int_t h;
29320 : ae_int_t i;
29321 :
29322 :
29323 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalcVBuf: incorrect C (incorrect parameter C.SType)", _state);
29324 0 : ae_assert((ae_isfinite(x, _state)&&ae_isfinite(y, _state))&&ae_isfinite(z, _state), "Spline3DCalcVBuf: X, Y or Z contains NaN/Infinite", _state);
29325 0 : rvectorsetlengthatleast(f, c->d, _state);
29326 :
29327 : /*
29328 : * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
29329 : */
29330 0 : l = 0;
29331 0 : r = c->n-1;
29332 0 : while(l!=r-1)
29333 : {
29334 0 : h = (l+r)/2;
29335 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
29336 : {
29337 0 : r = h;
29338 : }
29339 : else
29340 : {
29341 0 : l = h;
29342 : }
29343 : }
29344 0 : ix = l;
29345 :
29346 : /*
29347 : * Binary search in the [ y[0], ..., y[n-2] ] (y[n-1] is not included)
29348 : */
29349 0 : l = 0;
29350 0 : r = c->m-1;
29351 0 : while(l!=r-1)
29352 : {
29353 0 : h = (l+r)/2;
29354 0 : if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
29355 : {
29356 0 : r = h;
29357 : }
29358 : else
29359 : {
29360 0 : l = h;
29361 : }
29362 : }
29363 0 : iy = l;
29364 :
29365 : /*
29366 : * Binary search in the [ z[0], ..., z[n-2] ] (z[n-1] is not included)
29367 : */
29368 0 : l = 0;
29369 0 : r = c->l-1;
29370 0 : while(l!=r-1)
29371 : {
29372 0 : h = (l+r)/2;
29373 0 : if( ae_fp_greater_eq(c->z.ptr.p_double[h],z) )
29374 : {
29375 0 : r = h;
29376 : }
29377 : else
29378 : {
29379 0 : l = h;
29380 : }
29381 : }
29382 0 : iz = l;
29383 0 : xd = (x-c->x.ptr.p_double[ix])/(c->x.ptr.p_double[ix+1]-c->x.ptr.p_double[ix]);
29384 0 : yd = (y-c->y.ptr.p_double[iy])/(c->y.ptr.p_double[iy+1]-c->y.ptr.p_double[iy]);
29385 0 : zd = (z-c->z.ptr.p_double[iz])/(c->z.ptr.p_double[iz+1]-c->z.ptr.p_double[iz]);
29386 0 : for(i=0; i<=c->d-1; i++)
29387 : {
29388 :
29389 : /*
29390 : * Trilinear interpolation
29391 : */
29392 0 : if( c->stype==-1 )
29393 : {
29394 0 : c0 = c->f.ptr.p_double[c->d*(c->n*(c->m*iz+iy)+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*iz+iy)+(ix+1))+i]*xd;
29395 0 : c1 = c->f.ptr.p_double[c->d*(c->n*(c->m*iz+(iy+1))+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*iz+(iy+1))+(ix+1))+i]*xd;
29396 0 : c2 = c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+iy)+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+iy)+(ix+1))+i]*xd;
29397 0 : c3 = c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+(iy+1))+ix)+i]*(1-xd)+c->f.ptr.p_double[c->d*(c->n*(c->m*(iz+1)+(iy+1))+(ix+1))+i]*xd;
29398 0 : c0 = c0*(1-yd)+c1*yd;
29399 0 : c1 = c2*(1-yd)+c3*yd;
29400 0 : f->ptr.p_double[i] = c0*(1-zd)+c1*zd;
29401 : }
29402 : }
29403 0 : }
29404 :
29405 :
29406 : /*************************************************************************
29407 : This subroutine calculates trilinear or tricubic vector-valued spline at the
29408 : given point (X,Y,Z).
29409 :
29410 : INPUT PARAMETERS:
29411 : C - spline interpolant.
29412 : X, Y,
29413 : Z - point
29414 :
29415 : OUTPUT PARAMETERS:
29416 : F - array[D] which stores function values. F is out-parameter and
29417 : it is reallocated after call to this function. In case you
29418 : want to reuse previously allocated F, you may use
29419 : Spline2DCalcVBuf(), which reallocates F only when it is too
29420 : small.
29421 :
29422 : -- ALGLIB PROJECT --
29423 : Copyright 26.04.2012 by Bochkanov Sergey
29424 : *************************************************************************/
29425 0 : void spline3dcalcv(spline3dinterpolant* c,
29426 : double x,
29427 : double y,
29428 : double z,
29429 : /* Real */ ae_vector* f,
29430 : ae_state *_state)
29431 : {
29432 :
29433 0 : ae_vector_clear(f);
29434 :
29435 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalcV: incorrect C (incorrect parameter C.SType)", _state);
29436 0 : ae_assert((ae_isfinite(x, _state)&&ae_isfinite(y, _state))&&ae_isfinite(z, _state), "Spline3DCalcV: X=NaN/Infinite, Y=NaN/Infinite or Z=NaN/Infinite", _state);
29437 0 : ae_vector_set_length(f, c->d, _state);
29438 0 : spline3dcalcvbuf(c, x, y, z, f, _state);
29439 0 : }
29440 :
29441 :
29442 : /*************************************************************************
29443 : This subroutine unpacks tri-dimensional spline into the coefficients table
29444 :
29445 : INPUT PARAMETERS:
29446 : C - spline interpolant.
29447 :
29448 : Result:
29449 : N - grid size (X)
29450 : M - grid size (Y)
29451 : L - grid size (Z)
29452 : D - number of components
29453 : SType- spline type. Currently, only one spline type is supported:
29454 : trilinear spline, as indicated by SType=1.
29455 : Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13].
29456 : For T=0..D-1 (component index), I = 0...N-2 (x index),
29457 : J=0..M-2 (y index), K=0..L-2 (z index):
29458 : Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1),
29459 :
29460 : Q-th row stores decomposition for T-th component of the
29461 : vector-valued function
29462 :
29463 : Tbl[Q,0] = X[i]
29464 : Tbl[Q,1] = X[i+1]
29465 : Tbl[Q,2] = Y[j]
29466 : Tbl[Q,3] = Y[j+1]
29467 : Tbl[Q,4] = Z[k]
29468 : Tbl[Q,5] = Z[k+1]
29469 :
29470 : Tbl[Q,6] = C000
29471 : Tbl[Q,7] = C100
29472 : Tbl[Q,8] = C010
29473 : Tbl[Q,9] = C110
29474 : Tbl[Q,10]= C001
29475 : Tbl[Q,11]= C101
29476 : Tbl[Q,12]= C011
29477 : Tbl[Q,13]= C111
29478 : On each grid square spline is equals to:
29479 : S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1)
29480 : t = x-x[j]
29481 : u = y-y[i]
29482 : v = z-z[k]
29483 :
29484 : NOTE: format of Tbl is given for SType=1. Future versions of
29485 : ALGLIB can use different formats for different values of
29486 : SType.
29487 :
29488 : -- ALGLIB PROJECT --
29489 : Copyright 26.04.2012 by Bochkanov Sergey
29490 : *************************************************************************/
29491 0 : void spline3dunpackv(spline3dinterpolant* c,
29492 : ae_int_t* n,
29493 : ae_int_t* m,
29494 : ae_int_t* l,
29495 : ae_int_t* d,
29496 : ae_int_t* stype,
29497 : /* Real */ ae_matrix* tbl,
29498 : ae_state *_state)
29499 : {
29500 : ae_int_t p;
29501 : ae_int_t ci;
29502 : ae_int_t cj;
29503 : ae_int_t ck;
29504 : double du;
29505 : double dv;
29506 : double dw;
29507 : ae_int_t i;
29508 : ae_int_t j;
29509 : ae_int_t k;
29510 : ae_int_t di;
29511 : ae_int_t i0;
29512 :
29513 0 : *n = 0;
29514 0 : *m = 0;
29515 0 : *l = 0;
29516 0 : *d = 0;
29517 0 : *stype = 0;
29518 0 : ae_matrix_clear(tbl);
29519 :
29520 0 : ae_assert(c->stype==-1, "Spline3DUnpackV: incorrect C (incorrect parameter C.SType)", _state);
29521 0 : *n = c->n;
29522 0 : *m = c->m;
29523 0 : *l = c->l;
29524 0 : *d = c->d;
29525 0 : *stype = ae_iabs(c->stype, _state);
29526 0 : ae_matrix_set_length(tbl, (*n-1)*(*m-1)*(*l-1)*(*d), 14, _state);
29527 :
29528 : /*
29529 : * Fill
29530 : */
29531 0 : for(i=0; i<=*n-2; i++)
29532 : {
29533 0 : for(j=0; j<=*m-2; j++)
29534 : {
29535 0 : for(k=0; k<=*l-2; k++)
29536 : {
29537 0 : for(di=0; di<=*d-1; di++)
29538 : {
29539 0 : p = *d*((*n-1)*((*m-1)*k+j)+i)+di;
29540 0 : tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[i];
29541 0 : tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[i+1];
29542 0 : tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[j];
29543 0 : tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[j+1];
29544 0 : tbl->ptr.pp_double[p][4] = c->z.ptr.p_double[k];
29545 0 : tbl->ptr.pp_double[p][5] = c->z.ptr.p_double[k+1];
29546 0 : du = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]);
29547 0 : dv = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]);
29548 0 : dw = 1/(tbl->ptr.pp_double[p][5]-tbl->ptr.pp_double[p][4]);
29549 :
29550 : /*
29551 : * Trilinear interpolation
29552 : */
29553 0 : if( c->stype==-1 )
29554 : {
29555 0 : for(i0=6; i0<=13; i0++)
29556 : {
29557 0 : tbl->ptr.pp_double[p][i0] = (double)(0);
29558 : }
29559 0 : tbl->ptr.pp_double[p][6+2*(2*0+0)+0] = c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29560 0 : tbl->ptr.pp_double[p][6+2*(2*0+0)+1] = c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29561 0 : tbl->ptr.pp_double[p][6+2*(2*0+1)+0] = c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29562 0 : tbl->ptr.pp_double[p][6+2*(2*0+1)+1] = c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29563 0 : tbl->ptr.pp_double[p][6+2*(2*1+0)+0] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29564 0 : tbl->ptr.pp_double[p][6+2*(2*1+0)+1] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29565 0 : tbl->ptr.pp_double[p][6+2*(2*1+1)+0] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29566 0 : tbl->ptr.pp_double[p][6+2*(2*1+1)+1] = c->f.ptr.p_double[*d*(*n*(*m*(k+1)+(j+1))+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+(j+1))+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*(k+1)+j)+i)+di]-c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+(i+1))+di]+c->f.ptr.p_double[*d*(*n*(*m*k+(j+1))+i)+di]+c->f.ptr.p_double[*d*(*n*(*m*k+j)+(i+1))+di]-c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
29567 : }
29568 :
29569 : /*
29570 : * Rescale Cij
29571 : */
29572 0 : for(ci=0; ci<=1; ci++)
29573 : {
29574 0 : for(cj=0; cj<=1; cj++)
29575 : {
29576 0 : for(ck=0; ck<=1; ck++)
29577 : {
29578 0 : tbl->ptr.pp_double[p][6+2*(2*ck+cj)+ci] = tbl->ptr.pp_double[p][6+2*(2*ck+cj)+ci]*ae_pow(du, (double)(ci), _state)*ae_pow(dv, (double)(cj), _state)*ae_pow(dw, (double)(ck), _state);
29579 : }
29580 : }
29581 : }
29582 : }
29583 : }
29584 : }
29585 : }
29586 0 : }
29587 :
29588 :
29589 : /*************************************************************************
29590 : This subroutine calculates the value of the trilinear(or tricubic;possible
29591 : will be later) spline at the given point X(and its derivatives; possible
29592 : will be later).
29593 :
29594 : INPUT PARAMETERS:
29595 : C - spline interpolant.
29596 : X, Y, Z - point
29597 :
29598 : OUTPUT PARAMETERS:
29599 : F - S(x,y,z)
29600 : FX - dS(x,y,z)/dX
29601 : FY - dS(x,y,z)/dY
29602 : FXY - d2S(x,y,z)/dXdY
29603 :
29604 : -- ALGLIB PROJECT --
29605 : Copyright 26.04.2012 by Bochkanov Sergey
29606 : *************************************************************************/
29607 0 : static void spline3d_spline3ddiff(spline3dinterpolant* c,
29608 : double x,
29609 : double y,
29610 : double z,
29611 : double* f,
29612 : double* fx,
29613 : double* fy,
29614 : double* fxy,
29615 : ae_state *_state)
29616 : {
29617 : double xd;
29618 : double yd;
29619 : double zd;
29620 : double c0;
29621 : double c1;
29622 : double c2;
29623 : double c3;
29624 : ae_int_t ix;
29625 : ae_int_t iy;
29626 : ae_int_t iz;
29627 : ae_int_t l;
29628 : ae_int_t r;
29629 : ae_int_t h;
29630 :
29631 0 : *f = 0;
29632 0 : *fx = 0;
29633 0 : *fy = 0;
29634 0 : *fxy = 0;
29635 :
29636 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline3DDiff: incorrect C (incorrect parameter C.SType)", _state);
29637 0 : ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline3DDiff: X or Y contains NaN or Infinite value", _state);
29638 :
29639 : /*
29640 : * Prepare F, dF/dX, dF/dY, d2F/dXdY
29641 : */
29642 0 : *f = (double)(0);
29643 0 : *fx = (double)(0);
29644 0 : *fy = (double)(0);
29645 0 : *fxy = (double)(0);
29646 0 : if( c->d!=1 )
29647 : {
29648 0 : return;
29649 : }
29650 :
29651 : /*
29652 : * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
29653 : */
29654 0 : l = 0;
29655 0 : r = c->n-1;
29656 0 : while(l!=r-1)
29657 : {
29658 0 : h = (l+r)/2;
29659 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
29660 : {
29661 0 : r = h;
29662 : }
29663 : else
29664 : {
29665 0 : l = h;
29666 : }
29667 : }
29668 0 : ix = l;
29669 :
29670 : /*
29671 : * Binary search in the [ y[0], ..., y[n-2] ] (y[n-1] is not included)
29672 : */
29673 0 : l = 0;
29674 0 : r = c->m-1;
29675 0 : while(l!=r-1)
29676 : {
29677 0 : h = (l+r)/2;
29678 0 : if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
29679 : {
29680 0 : r = h;
29681 : }
29682 : else
29683 : {
29684 0 : l = h;
29685 : }
29686 : }
29687 0 : iy = l;
29688 :
29689 : /*
29690 : * Binary search in the [ z[0], ..., z[n-2] ] (z[n-1] is not included)
29691 : */
29692 0 : l = 0;
29693 0 : r = c->l-1;
29694 0 : while(l!=r-1)
29695 : {
29696 0 : h = (l+r)/2;
29697 0 : if( ae_fp_greater_eq(c->z.ptr.p_double[h],z) )
29698 : {
29699 0 : r = h;
29700 : }
29701 : else
29702 : {
29703 0 : l = h;
29704 : }
29705 : }
29706 0 : iz = l;
29707 0 : xd = (x-c->x.ptr.p_double[ix])/(c->x.ptr.p_double[ix+1]-c->x.ptr.p_double[ix]);
29708 0 : yd = (y-c->y.ptr.p_double[iy])/(c->y.ptr.p_double[iy+1]-c->y.ptr.p_double[iy]);
29709 0 : zd = (z-c->z.ptr.p_double[iz])/(c->z.ptr.p_double[iz+1]-c->z.ptr.p_double[iz]);
29710 :
29711 : /*
29712 : * Trilinear interpolation
29713 : */
29714 0 : if( c->stype==-1 )
29715 : {
29716 0 : c0 = c->f.ptr.p_double[c->n*(c->m*iz+iy)+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*iz+iy)+(ix+1)]*xd;
29717 0 : c1 = c->f.ptr.p_double[c->n*(c->m*iz+(iy+1))+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*iz+(iy+1))+(ix+1)]*xd;
29718 0 : c2 = c->f.ptr.p_double[c->n*(c->m*(iz+1)+iy)+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*(iz+1)+iy)+(ix+1)]*xd;
29719 0 : c3 = c->f.ptr.p_double[c->n*(c->m*(iz+1)+(iy+1))+ix]*(1-xd)+c->f.ptr.p_double[c->n*(c->m*(iz+1)+(iy+1))+(ix+1)]*xd;
29720 0 : c0 = c0*(1-yd)+c1*yd;
29721 0 : c1 = c2*(1-yd)+c3*yd;
29722 0 : *f = c0*(1-zd)+c1*zd;
29723 : }
29724 : }
29725 :
29726 :
29727 0 : void _spline3dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
29728 : {
29729 0 : spline3dinterpolant *p = (spline3dinterpolant*)_p;
29730 0 : ae_touch_ptr((void*)p);
29731 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
29732 0 : ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic);
29733 0 : ae_vector_init(&p->z, 0, DT_REAL, _state, make_automatic);
29734 0 : ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic);
29735 0 : }
29736 :
29737 :
29738 0 : void _spline3dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29739 : {
29740 0 : spline3dinterpolant *dst = (spline3dinterpolant*)_dst;
29741 0 : spline3dinterpolant *src = (spline3dinterpolant*)_src;
29742 0 : dst->k = src->k;
29743 0 : dst->stype = src->stype;
29744 0 : dst->n = src->n;
29745 0 : dst->m = src->m;
29746 0 : dst->l = src->l;
29747 0 : dst->d = src->d;
29748 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
29749 0 : ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic);
29750 0 : ae_vector_init_copy(&dst->z, &src->z, _state, make_automatic);
29751 0 : ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic);
29752 0 : }
29753 :
29754 :
29755 0 : void _spline3dinterpolant_clear(void* _p)
29756 : {
29757 0 : spline3dinterpolant *p = (spline3dinterpolant*)_p;
29758 0 : ae_touch_ptr((void*)p);
29759 0 : ae_vector_clear(&p->x);
29760 0 : ae_vector_clear(&p->y);
29761 0 : ae_vector_clear(&p->z);
29762 0 : ae_vector_clear(&p->f);
29763 0 : }
29764 :
29765 :
29766 0 : void _spline3dinterpolant_destroy(void* _p)
29767 : {
29768 0 : spline3dinterpolant *p = (spline3dinterpolant*)_p;
29769 0 : ae_touch_ptr((void*)p);
29770 0 : ae_vector_destroy(&p->x);
29771 0 : ae_vector_destroy(&p->y);
29772 0 : ae_vector_destroy(&p->z);
29773 0 : ae_vector_destroy(&p->f);
29774 0 : }
29775 :
29776 :
29777 : #endif
29778 : #if defined(AE_COMPILE_POLINT) || !defined(AE_PARTIAL_BUILD)
29779 :
29780 :
29781 : /*************************************************************************
29782 : Conversion from barycentric representation to Chebyshev basis.
29783 : This function has O(N^2) complexity.
29784 :
29785 : INPUT PARAMETERS:
29786 : P - polynomial in barycentric form
29787 : A,B - base interval for Chebyshev polynomials (see below)
29788 : A<>B
29789 :
29790 : OUTPUT PARAMETERS
29791 : T - coefficients of Chebyshev representation;
29792 : P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 },
29793 : where Ti - I-th Chebyshev polynomial.
29794 :
29795 : NOTES:
29796 : barycentric interpolant passed as P may be either polynomial obtained
29797 : from polynomial interpolation/ fitting or rational function which is
29798 : NOT polynomial. We can't distinguish between these two cases, and this
29799 : algorithm just tries to work assuming that P IS a polynomial. If not,
29800 : algorithm will return results, but they won't have any meaning.
29801 :
29802 : -- ALGLIB --
29803 : Copyright 30.09.2010 by Bochkanov Sergey
29804 : *************************************************************************/
29805 0 : void polynomialbar2cheb(barycentricinterpolant* p,
29806 : double a,
29807 : double b,
29808 : /* Real */ ae_vector* t,
29809 : ae_state *_state)
29810 : {
29811 : ae_frame _frame_block;
29812 : ae_int_t i;
29813 : ae_int_t k;
29814 : ae_vector vp;
29815 : ae_vector vx;
29816 : ae_vector tk;
29817 : ae_vector tk1;
29818 : double v;
29819 :
29820 0 : ae_frame_make(_state, &_frame_block);
29821 0 : memset(&vp, 0, sizeof(vp));
29822 0 : memset(&vx, 0, sizeof(vx));
29823 0 : memset(&tk, 0, sizeof(tk));
29824 0 : memset(&tk1, 0, sizeof(tk1));
29825 0 : ae_vector_clear(t);
29826 0 : ae_vector_init(&vp, 0, DT_REAL, _state, ae_true);
29827 0 : ae_vector_init(&vx, 0, DT_REAL, _state, ae_true);
29828 0 : ae_vector_init(&tk, 0, DT_REAL, _state, ae_true);
29829 0 : ae_vector_init(&tk1, 0, DT_REAL, _state, ae_true);
29830 :
29831 0 : ae_assert(ae_isfinite(a, _state), "PolynomialBar2Cheb: A is not finite!", _state);
29832 0 : ae_assert(ae_isfinite(b, _state), "PolynomialBar2Cheb: B is not finite!", _state);
29833 0 : ae_assert(ae_fp_neq(a,b), "PolynomialBar2Cheb: A=B!", _state);
29834 0 : ae_assert(p->n>0, "PolynomialBar2Cheb: P is not correctly initialized barycentric interpolant!", _state);
29835 :
29836 : /*
29837 : * Calculate function values on a Chebyshev grid
29838 : */
29839 0 : ae_vector_set_length(&vp, p->n, _state);
29840 0 : ae_vector_set_length(&vx, p->n, _state);
29841 0 : for(i=0; i<=p->n-1; i++)
29842 : {
29843 0 : vx.ptr.p_double[i] = ae_cos(ae_pi*(i+0.5)/p->n, _state);
29844 0 : vp.ptr.p_double[i] = barycentriccalc(p, 0.5*(vx.ptr.p_double[i]+1)*(b-a)+a, _state);
29845 : }
29846 :
29847 : /*
29848 : * T[0]
29849 : */
29850 0 : ae_vector_set_length(t, p->n, _state);
29851 0 : v = (double)(0);
29852 0 : for(i=0; i<=p->n-1; i++)
29853 : {
29854 0 : v = v+vp.ptr.p_double[i];
29855 : }
29856 0 : t->ptr.p_double[0] = v/p->n;
29857 :
29858 : /*
29859 : * other T's.
29860 : *
29861 : * NOTES:
29862 : * 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX
29863 : * 2. we can do same calculations with fast DCT, but it
29864 : * * adds dependencies
29865 : * * still leaves us with O(N^2) algorithm because
29866 : * preparation of function values is O(N^2) process
29867 : */
29868 0 : if( p->n>1 )
29869 : {
29870 0 : ae_vector_set_length(&tk, p->n, _state);
29871 0 : ae_vector_set_length(&tk1, p->n, _state);
29872 0 : for(i=0; i<=p->n-1; i++)
29873 : {
29874 0 : tk.ptr.p_double[i] = vx.ptr.p_double[i];
29875 0 : tk1.ptr.p_double[i] = (double)(1);
29876 : }
29877 0 : for(k=1; k<=p->n-1; k++)
29878 : {
29879 :
29880 : /*
29881 : * calculate discrete product of function vector and TK
29882 : */
29883 0 : v = ae_v_dotproduct(&tk.ptr.p_double[0], 1, &vp.ptr.p_double[0], 1, ae_v_len(0,p->n-1));
29884 0 : t->ptr.p_double[k] = v/(0.5*p->n);
29885 :
29886 : /*
29887 : * Update TK and TK1
29888 : */
29889 0 : for(i=0; i<=p->n-1; i++)
29890 : {
29891 0 : v = 2*vx.ptr.p_double[i]*tk.ptr.p_double[i]-tk1.ptr.p_double[i];
29892 0 : tk1.ptr.p_double[i] = tk.ptr.p_double[i];
29893 0 : tk.ptr.p_double[i] = v;
29894 : }
29895 : }
29896 : }
29897 0 : ae_frame_leave(_state);
29898 0 : }
29899 :
29900 :
29901 : /*************************************************************************
29902 : Conversion from Chebyshev basis to barycentric representation.
29903 : This function has O(N^2) complexity.
29904 :
29905 : INPUT PARAMETERS:
29906 : T - coefficients of Chebyshev representation;
29907 : P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N },
29908 : where Ti - I-th Chebyshev polynomial.
29909 : N - number of coefficients:
29910 : * if given, only leading N elements of T are used
29911 : * if not given, automatically determined from size of T
29912 : A,B - base interval for Chebyshev polynomials (see above)
29913 : A<B
29914 :
29915 : OUTPUT PARAMETERS
29916 : P - polynomial in barycentric form
29917 :
29918 : -- ALGLIB --
29919 : Copyright 30.09.2010 by Bochkanov Sergey
29920 : *************************************************************************/
29921 0 : void polynomialcheb2bar(/* Real */ ae_vector* t,
29922 : ae_int_t n,
29923 : double a,
29924 : double b,
29925 : barycentricinterpolant* p,
29926 : ae_state *_state)
29927 : {
29928 : ae_frame _frame_block;
29929 : ae_int_t i;
29930 : ae_int_t k;
29931 : ae_vector y;
29932 : double tk;
29933 : double tk1;
29934 : double vx;
29935 : double vy;
29936 : double v;
29937 :
29938 0 : ae_frame_make(_state, &_frame_block);
29939 0 : memset(&y, 0, sizeof(y));
29940 0 : _barycentricinterpolant_clear(p);
29941 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
29942 :
29943 0 : ae_assert(ae_isfinite(a, _state), "PolynomialBar2Cheb: A is not finite!", _state);
29944 0 : ae_assert(ae_isfinite(b, _state), "PolynomialBar2Cheb: B is not finite!", _state);
29945 0 : ae_assert(ae_fp_neq(a,b), "PolynomialBar2Cheb: A=B!", _state);
29946 0 : ae_assert(n>=1, "PolynomialBar2Cheb: N<1", _state);
29947 0 : ae_assert(t->cnt>=n, "PolynomialBar2Cheb: Length(T)<N", _state);
29948 0 : ae_assert(isfinitevector(t, n, _state), "PolynomialBar2Cheb: T[] contains INF or NAN", _state);
29949 :
29950 : /*
29951 : * Calculate function values on a Chebyshev grid spanning [-1,+1]
29952 : */
29953 0 : ae_vector_set_length(&y, n, _state);
29954 0 : for(i=0; i<=n-1; i++)
29955 : {
29956 :
29957 : /*
29958 : * Calculate value on a grid spanning [-1,+1]
29959 : */
29960 0 : vx = ae_cos(ae_pi*(i+0.5)/n, _state);
29961 0 : vy = t->ptr.p_double[0];
29962 0 : tk1 = (double)(1);
29963 0 : tk = vx;
29964 0 : for(k=1; k<=n-1; k++)
29965 : {
29966 0 : vy = vy+t->ptr.p_double[k]*tk;
29967 0 : v = 2*vx*tk-tk1;
29968 0 : tk1 = tk;
29969 0 : tk = v;
29970 : }
29971 0 : y.ptr.p_double[i] = vy;
29972 : }
29973 :
29974 : /*
29975 : * Build barycentric interpolant, map grid from [-1,+1] to [A,B]
29976 : */
29977 0 : polynomialbuildcheb1(a, b, &y, n, p, _state);
29978 0 : ae_frame_leave(_state);
29979 0 : }
29980 :
29981 :
29982 : /*************************************************************************
29983 : Conversion from barycentric representation to power basis.
29984 : This function has O(N^2) complexity.
29985 :
29986 : INPUT PARAMETERS:
29987 : P - polynomial in barycentric form
29988 : C - offset (see below); 0.0 is used as default value.
29989 : S - scale (see below); 1.0 is used as default value. S<>0.
29990 :
29991 : OUTPUT PARAMETERS
29992 : A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
29993 : N - number of coefficients (polynomial degree plus 1)
29994 :
29995 : NOTES:
29996 : 1. this function accepts offset and scale, which can be set to improve
29997 : numerical properties of polynomial. For example, if P was obtained as
29998 : result of interpolation on [-1,+1], you can set C=0 and S=1 and
29999 : represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it
30000 : is exactly what you need.
30001 :
30002 : However, if your interpolation model was built on [999,1001], you will
30003 : see significant growth of numerical errors when using {1, x, x^2, x^3}
30004 : as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
30005 : will be better option. Such representation can be obtained by using
30006 : 1000.0 as offset C and 1.0 as scale S.
30007 :
30008 : 2. power basis is ill-conditioned and tricks described above can't solve
30009 : this problem completely. This function will return coefficients in
30010 : any case, but for N>8 they will become unreliable. However, N's
30011 : less than 5 are pretty safe.
30012 :
30013 : 3. barycentric interpolant passed as P may be either polynomial obtained
30014 : from polynomial interpolation/ fitting or rational function which is
30015 : NOT polynomial. We can't distinguish between these two cases, and this
30016 : algorithm just tries to work assuming that P IS a polynomial. If not,
30017 : algorithm will return results, but they won't have any meaning.
30018 :
30019 : -- ALGLIB --
30020 : Copyright 30.09.2010 by Bochkanov Sergey
30021 : *************************************************************************/
30022 0 : void polynomialbar2pow(barycentricinterpolant* p,
30023 : double c,
30024 : double s,
30025 : /* Real */ ae_vector* a,
30026 : ae_state *_state)
30027 : {
30028 : ae_frame _frame_block;
30029 : ae_int_t i;
30030 : ae_int_t k;
30031 : double e;
30032 : double d;
30033 : ae_vector vp;
30034 : ae_vector vx;
30035 : ae_vector tk;
30036 : ae_vector tk1;
30037 : ae_vector t;
30038 : double v;
30039 : double c0;
30040 : double s0;
30041 : double va;
30042 : double vb;
30043 : ae_vector vai;
30044 : ae_vector vbi;
30045 : double minx;
30046 : double maxx;
30047 :
30048 0 : ae_frame_make(_state, &_frame_block);
30049 0 : memset(&vp, 0, sizeof(vp));
30050 0 : memset(&vx, 0, sizeof(vx));
30051 0 : memset(&tk, 0, sizeof(tk));
30052 0 : memset(&tk1, 0, sizeof(tk1));
30053 0 : memset(&t, 0, sizeof(t));
30054 0 : memset(&vai, 0, sizeof(vai));
30055 0 : memset(&vbi, 0, sizeof(vbi));
30056 0 : ae_vector_clear(a);
30057 0 : ae_vector_init(&vp, 0, DT_REAL, _state, ae_true);
30058 0 : ae_vector_init(&vx, 0, DT_REAL, _state, ae_true);
30059 0 : ae_vector_init(&tk, 0, DT_REAL, _state, ae_true);
30060 0 : ae_vector_init(&tk1, 0, DT_REAL, _state, ae_true);
30061 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
30062 0 : ae_vector_init(&vai, 0, DT_REAL, _state, ae_true);
30063 0 : ae_vector_init(&vbi, 0, DT_REAL, _state, ae_true);
30064 :
30065 :
30066 : /*
30067 : * We have barycentric model built using set of points X[], and we
30068 : * want to convert it to power basis centered about point C with
30069 : * scale S: I-th basis function is ((X-C)/S)^i.
30070 : *
30071 : * We use following three-stage algorithm:
30072 : *
30073 : * 1. we build Chebyshev representation of polynomial using
30074 : * intermediate center C0 and scale S0, which are derived from X[]:
30075 : * C0 = 0.5*(min(X)+max(X)), S0 = 0.5*(max(X)-min(X)). Chebyshev
30076 : * representation is built by sampling points around center C0,
30077 : * with typical distance between them proportional to S0.
30078 : * 2. then we transform form Chebyshev basis to intermediate power
30079 : * basis, using same center/scale C0/S0.
30080 : * 3. after that, we apply linear transformation to intermediate
30081 : * power basis which moves it to final center/scale C/S.
30082 : *
30083 : * The idea of such multi-stage algorithm is that it is much easier to
30084 : * transform barycentric model to Chebyshev basis, and only later to
30085 : * power basis, than transforming it directly to power basis. It is
30086 : * also more numerically stable to sample points using intermediate C0/S0,
30087 : * which are derived from user-supplied model, than using "final" C/S,
30088 : * which may be unsuitable for sampling (say, if S=1, we may have stability
30089 : * problems when working with models built from dataset with non-unit
30090 : * scale of abscissas).
30091 : */
30092 0 : ae_assert(ae_isfinite(c, _state), "PolynomialBar2Pow: C is not finite!", _state);
30093 0 : ae_assert(ae_isfinite(s, _state), "PolynomialBar2Pow: S is not finite!", _state);
30094 0 : ae_assert(ae_fp_neq(s,(double)(0)), "PolynomialBar2Pow: S=0!", _state);
30095 0 : ae_assert(p->n>0, "PolynomialBar2Pow: P is not correctly initialized barycentric interpolant!", _state);
30096 :
30097 : /*
30098 : * Select intermediate center/scale
30099 : */
30100 0 : minx = p->x.ptr.p_double[0];
30101 0 : maxx = p->x.ptr.p_double[0];
30102 0 : for(i=1; i<=p->n-1; i++)
30103 : {
30104 0 : minx = ae_minreal(minx, p->x.ptr.p_double[i], _state);
30105 0 : maxx = ae_maxreal(maxx, p->x.ptr.p_double[i], _state);
30106 : }
30107 0 : if( ae_fp_eq(minx,maxx) )
30108 : {
30109 0 : c0 = minx;
30110 0 : s0 = 1.0;
30111 : }
30112 : else
30113 : {
30114 0 : c0 = 0.5*(maxx+minx);
30115 0 : s0 = 0.5*(maxx-minx);
30116 : }
30117 :
30118 : /*
30119 : * Calculate function values on a Chebyshev grid using intermediate C0/S0
30120 : */
30121 0 : ae_vector_set_length(&vp, p->n+1, _state);
30122 0 : ae_vector_set_length(&vx, p->n, _state);
30123 0 : for(i=0; i<=p->n-1; i++)
30124 : {
30125 0 : vx.ptr.p_double[i] = ae_cos(ae_pi*(i+0.5)/p->n, _state);
30126 0 : vp.ptr.p_double[i] = barycentriccalc(p, s0*vx.ptr.p_double[i]+c0, _state);
30127 : }
30128 :
30129 : /*
30130 : * T[0]
30131 : */
30132 0 : ae_vector_set_length(&t, p->n, _state);
30133 0 : v = (double)(0);
30134 0 : for(i=0; i<=p->n-1; i++)
30135 : {
30136 0 : v = v+vp.ptr.p_double[i];
30137 : }
30138 0 : t.ptr.p_double[0] = v/p->n;
30139 :
30140 : /*
30141 : * other T's.
30142 : *
30143 : * NOTES:
30144 : * 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX
30145 : * 2. we can do same calculations with fast DCT, but it
30146 : * * adds dependencies
30147 : * * still leaves us with O(N^2) algorithm because
30148 : * preparation of function values is O(N^2) process
30149 : */
30150 0 : if( p->n>1 )
30151 : {
30152 0 : ae_vector_set_length(&tk, p->n, _state);
30153 0 : ae_vector_set_length(&tk1, p->n, _state);
30154 0 : for(i=0; i<=p->n-1; i++)
30155 : {
30156 0 : tk.ptr.p_double[i] = vx.ptr.p_double[i];
30157 0 : tk1.ptr.p_double[i] = (double)(1);
30158 : }
30159 0 : for(k=1; k<=p->n-1; k++)
30160 : {
30161 :
30162 : /*
30163 : * calculate discrete product of function vector and TK
30164 : */
30165 0 : v = ae_v_dotproduct(&tk.ptr.p_double[0], 1, &vp.ptr.p_double[0], 1, ae_v_len(0,p->n-1));
30166 0 : t.ptr.p_double[k] = v/(0.5*p->n);
30167 :
30168 : /*
30169 : * Update TK and TK1
30170 : */
30171 0 : for(i=0; i<=p->n-1; i++)
30172 : {
30173 0 : v = 2*vx.ptr.p_double[i]*tk.ptr.p_double[i]-tk1.ptr.p_double[i];
30174 0 : tk1.ptr.p_double[i] = tk.ptr.p_double[i];
30175 0 : tk.ptr.p_double[i] = v;
30176 : }
30177 : }
30178 : }
30179 :
30180 : /*
30181 : * Convert from Chebyshev basis to power basis
30182 : */
30183 0 : ae_vector_set_length(a, p->n, _state);
30184 0 : for(i=0; i<=p->n-1; i++)
30185 : {
30186 0 : a->ptr.p_double[i] = (double)(0);
30187 : }
30188 0 : d = (double)(0);
30189 0 : for(i=0; i<=p->n-1; i++)
30190 : {
30191 0 : for(k=i; k<=p->n-1; k++)
30192 : {
30193 0 : e = a->ptr.p_double[k];
30194 0 : a->ptr.p_double[k] = (double)(0);
30195 0 : if( i<=1&&k==i )
30196 : {
30197 0 : a->ptr.p_double[k] = (double)(1);
30198 : }
30199 : else
30200 : {
30201 0 : if( i!=0 )
30202 : {
30203 0 : a->ptr.p_double[k] = 2*d;
30204 : }
30205 0 : if( k>i+1 )
30206 : {
30207 0 : a->ptr.p_double[k] = a->ptr.p_double[k]-a->ptr.p_double[k-2];
30208 : }
30209 : }
30210 0 : d = e;
30211 : }
30212 0 : d = a->ptr.p_double[i];
30213 0 : e = (double)(0);
30214 0 : k = i;
30215 0 : while(k<=p->n-1)
30216 : {
30217 0 : e = e+a->ptr.p_double[k]*t.ptr.p_double[k];
30218 0 : k = k+2;
30219 : }
30220 0 : a->ptr.p_double[i] = e;
30221 : }
30222 :
30223 : /*
30224 : * Apply linear transformation which converts basis from intermediate
30225 : * one Fi=((x-C0)/S0)^i to final one Fi=((x-C)/S)^i.
30226 : *
30227 : * We have y=(x-C0)/S0, z=(x-C)/S, and coefficients A[] for basis Fi(y).
30228 : * Because we have y=A*z+B, for A=s/s0 and B=c/s0-c0/s0, we can perform
30229 : * substitution and get coefficients A_new[] in basis Fi(z).
30230 : */
30231 0 : ae_assert(vp.cnt>=p->n+1, "PolynomialBar2Pow: internal error", _state);
30232 0 : ae_assert(t.cnt>=p->n, "PolynomialBar2Pow: internal error", _state);
30233 0 : for(i=0; i<=p->n-1; i++)
30234 : {
30235 0 : t.ptr.p_double[i] = 0.0;
30236 : }
30237 0 : va = s/s0;
30238 0 : vb = c/s0-c0/s0;
30239 0 : ae_vector_set_length(&vai, p->n, _state);
30240 0 : ae_vector_set_length(&vbi, p->n, _state);
30241 0 : vai.ptr.p_double[0] = (double)(1);
30242 0 : vbi.ptr.p_double[0] = (double)(1);
30243 0 : for(k=1; k<=p->n-1; k++)
30244 : {
30245 0 : vai.ptr.p_double[k] = vai.ptr.p_double[k-1]*va;
30246 0 : vbi.ptr.p_double[k] = vbi.ptr.p_double[k-1]*vb;
30247 : }
30248 0 : for(k=0; k<=p->n-1; k++)
30249 : {
30250 :
30251 : /*
30252 : * Generate set of binomial coefficients in VP[]
30253 : */
30254 0 : if( k>0 )
30255 : {
30256 0 : vp.ptr.p_double[k] = (double)(1);
30257 0 : for(i=k-1; i>=1; i--)
30258 : {
30259 0 : vp.ptr.p_double[i] = vp.ptr.p_double[i]+vp.ptr.p_double[i-1];
30260 : }
30261 0 : vp.ptr.p_double[0] = (double)(1);
30262 : }
30263 : else
30264 : {
30265 0 : vp.ptr.p_double[0] = (double)(1);
30266 : }
30267 :
30268 : /*
30269 : * Update T[] with expansion of K-th basis function
30270 : */
30271 0 : for(i=0; i<=k; i++)
30272 : {
30273 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+a->ptr.p_double[k]*vai.ptr.p_double[i]*vbi.ptr.p_double[k-i]*vp.ptr.p_double[i];
30274 : }
30275 : }
30276 0 : for(k=0; k<=p->n-1; k++)
30277 : {
30278 0 : a->ptr.p_double[k] = t.ptr.p_double[k];
30279 : }
30280 0 : ae_frame_leave(_state);
30281 0 : }
30282 :
30283 :
30284 : /*************************************************************************
30285 : Conversion from power basis to barycentric representation.
30286 : This function has O(N^2) complexity.
30287 :
30288 : INPUT PARAMETERS:
30289 : A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
30290 : N - number of coefficients (polynomial degree plus 1)
30291 : * if given, only leading N elements of A are used
30292 : * if not given, automatically determined from size of A
30293 : C - offset (see below); 0.0 is used as default value.
30294 : S - scale (see below); 1.0 is used as default value. S<>0.
30295 :
30296 : OUTPUT PARAMETERS
30297 : P - polynomial in barycentric form
30298 :
30299 :
30300 : NOTES:
30301 : 1. this function accepts offset and scale, which can be set to improve
30302 : numerical properties of polynomial. For example, if you interpolate on
30303 : [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2,
30304 : x^3 and so on. In most cases you it is exactly what you need.
30305 :
30306 : However, if your interpolation model was built on [999,1001], you will
30307 : see significant growth of numerical errors when using {1, x, x^2, x^3}
30308 : as input basis. Converting from sum of 1, (x-1000), (x-1000)^2,
30309 : (x-1000)^3 will be better option (you have to specify 1000.0 as offset
30310 : C and 1.0 as scale S).
30311 :
30312 : 2. power basis is ill-conditioned and tricks described above can't solve
30313 : this problem completely. This function will return barycentric model
30314 : in any case, but for N>8 accuracy well degrade. However, N's less than
30315 : 5 are pretty safe.
30316 :
30317 : -- ALGLIB --
30318 : Copyright 30.09.2010 by Bochkanov Sergey
30319 : *************************************************************************/
30320 0 : void polynomialpow2bar(/* Real */ ae_vector* a,
30321 : ae_int_t n,
30322 : double c,
30323 : double s,
30324 : barycentricinterpolant* p,
30325 : ae_state *_state)
30326 : {
30327 : ae_frame _frame_block;
30328 : ae_int_t i;
30329 : ae_int_t k;
30330 : ae_vector y;
30331 : double vx;
30332 : double vy;
30333 : double px;
30334 :
30335 0 : ae_frame_make(_state, &_frame_block);
30336 0 : memset(&y, 0, sizeof(y));
30337 0 : _barycentricinterpolant_clear(p);
30338 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
30339 :
30340 0 : ae_assert(ae_isfinite(c, _state), "PolynomialPow2Bar: C is not finite!", _state);
30341 0 : ae_assert(ae_isfinite(s, _state), "PolynomialPow2Bar: S is not finite!", _state);
30342 0 : ae_assert(ae_fp_neq(s,(double)(0)), "PolynomialPow2Bar: S is zero!", _state);
30343 0 : ae_assert(n>=1, "PolynomialPow2Bar: N<1", _state);
30344 0 : ae_assert(a->cnt>=n, "PolynomialPow2Bar: Length(A)<N", _state);
30345 0 : ae_assert(isfinitevector(a, n, _state), "PolynomialPow2Bar: A[] contains INF or NAN", _state);
30346 :
30347 : /*
30348 : * Calculate function values on a Chebyshev grid spanning [-1,+1]
30349 : */
30350 0 : ae_vector_set_length(&y, n, _state);
30351 0 : for(i=0; i<=n-1; i++)
30352 : {
30353 :
30354 : /*
30355 : * Calculate value on a grid spanning [-1,+1]
30356 : */
30357 0 : vx = ae_cos(ae_pi*(i+0.5)/n, _state);
30358 0 : vy = a->ptr.p_double[0];
30359 0 : px = vx;
30360 0 : for(k=1; k<=n-1; k++)
30361 : {
30362 0 : vy = vy+px*a->ptr.p_double[k];
30363 0 : px = px*vx;
30364 : }
30365 0 : y.ptr.p_double[i] = vy;
30366 : }
30367 :
30368 : /*
30369 : * Build barycentric interpolant, map grid from [-1,+1] to [A,B]
30370 : */
30371 0 : polynomialbuildcheb1(c-s, c+s, &y, n, p, _state);
30372 0 : ae_frame_leave(_state);
30373 0 : }
30374 :
30375 :
30376 : /*************************************************************************
30377 : Lagrange intepolant: generation of the model on the general grid.
30378 : This function has O(N^2) complexity.
30379 :
30380 : INPUT PARAMETERS:
30381 : X - abscissas, array[0..N-1]
30382 : Y - function values, array[0..N-1]
30383 : N - number of points, N>=1
30384 :
30385 : OUTPUT PARAMETERS
30386 : P - barycentric model which represents Lagrange interpolant
30387 : (see ratint unit info and BarycentricCalc() description for
30388 : more information).
30389 :
30390 : -- ALGLIB --
30391 : Copyright 02.12.2009 by Bochkanov Sergey
30392 : *************************************************************************/
30393 0 : void polynomialbuild(/* Real */ ae_vector* x,
30394 : /* Real */ ae_vector* y,
30395 : ae_int_t n,
30396 : barycentricinterpolant* p,
30397 : ae_state *_state)
30398 : {
30399 : ae_frame _frame_block;
30400 : ae_vector _x;
30401 : ae_vector _y;
30402 : ae_int_t j;
30403 : ae_int_t k;
30404 : ae_vector w;
30405 : double b;
30406 : double a;
30407 : double v;
30408 : double mx;
30409 : ae_vector sortrbuf;
30410 : ae_vector sortrbuf2;
30411 :
30412 0 : ae_frame_make(_state, &_frame_block);
30413 0 : memset(&_x, 0, sizeof(_x));
30414 0 : memset(&_y, 0, sizeof(_y));
30415 0 : memset(&w, 0, sizeof(w));
30416 0 : memset(&sortrbuf, 0, sizeof(sortrbuf));
30417 0 : memset(&sortrbuf2, 0, sizeof(sortrbuf2));
30418 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
30419 0 : x = &_x;
30420 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
30421 0 : y = &_y;
30422 0 : _barycentricinterpolant_clear(p);
30423 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
30424 0 : ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true);
30425 0 : ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true);
30426 :
30427 0 : ae_assert(n>0, "PolynomialBuild: N<=0!", _state);
30428 0 : ae_assert(x->cnt>=n, "PolynomialBuild: Length(X)<N!", _state);
30429 0 : ae_assert(y->cnt>=n, "PolynomialBuild: Length(Y)<N!", _state);
30430 0 : ae_assert(isfinitevector(x, n, _state), "PolynomialBuild: X contains infinite or NaN values!", _state);
30431 0 : ae_assert(isfinitevector(y, n, _state), "PolynomialBuild: Y contains infinite or NaN values!", _state);
30432 0 : tagsortfastr(x, y, &sortrbuf, &sortrbuf2, n, _state);
30433 0 : ae_assert(aredistinct(x, n, _state), "PolynomialBuild: at least two consequent points are too close!", _state);
30434 :
30435 : /*
30436 : * calculate W[j]
30437 : * multi-pass algorithm is used to avoid overflow
30438 : */
30439 0 : ae_vector_set_length(&w, n, _state);
30440 0 : a = x->ptr.p_double[0];
30441 0 : b = x->ptr.p_double[0];
30442 0 : for(j=0; j<=n-1; j++)
30443 : {
30444 0 : w.ptr.p_double[j] = (double)(1);
30445 0 : a = ae_minreal(a, x->ptr.p_double[j], _state);
30446 0 : b = ae_maxreal(b, x->ptr.p_double[j], _state);
30447 : }
30448 0 : for(k=0; k<=n-1; k++)
30449 : {
30450 :
30451 : /*
30452 : * W[K] is used instead of 0.0 because
30453 : * cycle on J does not touch K-th element
30454 : * and we MUST get maximum from ALL elements
30455 : */
30456 0 : mx = ae_fabs(w.ptr.p_double[k], _state);
30457 0 : for(j=0; j<=n-1; j++)
30458 : {
30459 0 : if( j!=k )
30460 : {
30461 0 : v = (b-a)/(x->ptr.p_double[j]-x->ptr.p_double[k]);
30462 0 : w.ptr.p_double[j] = w.ptr.p_double[j]*v;
30463 0 : mx = ae_maxreal(mx, ae_fabs(w.ptr.p_double[j], _state), _state);
30464 : }
30465 : }
30466 0 : if( k%5==0 )
30467 : {
30468 :
30469 : /*
30470 : * every 5-th run we renormalize W[]
30471 : */
30472 0 : v = 1/mx;
30473 0 : ae_v_muld(&w.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
30474 : }
30475 : }
30476 0 : barycentricbuildxyw(x, y, &w, n, p, _state);
30477 0 : ae_frame_leave(_state);
30478 0 : }
30479 :
30480 :
30481 : /*************************************************************************
30482 : Lagrange intepolant: generation of the model on equidistant grid.
30483 : This function has O(N) complexity.
30484 :
30485 : INPUT PARAMETERS:
30486 : A - left boundary of [A,B]
30487 : B - right boundary of [A,B]
30488 : Y - function values at the nodes, array[0..N-1]
30489 : N - number of points, N>=1
30490 : for N=1 a constant model is constructed.
30491 :
30492 : OUTPUT PARAMETERS
30493 : P - barycentric model which represents Lagrange interpolant
30494 : (see ratint unit info and BarycentricCalc() description for
30495 : more information).
30496 :
30497 : -- ALGLIB --
30498 : Copyright 03.12.2009 by Bochkanov Sergey
30499 : *************************************************************************/
30500 0 : void polynomialbuildeqdist(double a,
30501 : double b,
30502 : /* Real */ ae_vector* y,
30503 : ae_int_t n,
30504 : barycentricinterpolant* p,
30505 : ae_state *_state)
30506 : {
30507 : ae_frame _frame_block;
30508 : ae_int_t i;
30509 : ae_vector w;
30510 : ae_vector x;
30511 : double v;
30512 :
30513 0 : ae_frame_make(_state, &_frame_block);
30514 0 : memset(&w, 0, sizeof(w));
30515 0 : memset(&x, 0, sizeof(x));
30516 0 : _barycentricinterpolant_clear(p);
30517 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
30518 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
30519 :
30520 0 : ae_assert(n>0, "PolynomialBuildEqDist: N<=0!", _state);
30521 0 : ae_assert(y->cnt>=n, "PolynomialBuildEqDist: Length(Y)<N!", _state);
30522 0 : ae_assert(ae_isfinite(a, _state), "PolynomialBuildEqDist: A is infinite or NaN!", _state);
30523 0 : ae_assert(ae_isfinite(b, _state), "PolynomialBuildEqDist: B is infinite or NaN!", _state);
30524 0 : ae_assert(isfinitevector(y, n, _state), "PolynomialBuildEqDist: Y contains infinite or NaN values!", _state);
30525 0 : ae_assert(ae_fp_neq(b,a), "PolynomialBuildEqDist: B=A!", _state);
30526 0 : ae_assert(ae_fp_neq(a+(b-a)/n,a), "PolynomialBuildEqDist: B is too close to A!", _state);
30527 :
30528 : /*
30529 : * Special case: N=1
30530 : */
30531 0 : if( n==1 )
30532 : {
30533 0 : ae_vector_set_length(&x, 1, _state);
30534 0 : ae_vector_set_length(&w, 1, _state);
30535 0 : x.ptr.p_double[0] = 0.5*(b+a);
30536 0 : w.ptr.p_double[0] = (double)(1);
30537 0 : barycentricbuildxyw(&x, y, &w, 1, p, _state);
30538 0 : ae_frame_leave(_state);
30539 0 : return;
30540 : }
30541 :
30542 : /*
30543 : * general case
30544 : */
30545 0 : ae_vector_set_length(&x, n, _state);
30546 0 : ae_vector_set_length(&w, n, _state);
30547 0 : v = (double)(1);
30548 0 : for(i=0; i<=n-1; i++)
30549 : {
30550 0 : w.ptr.p_double[i] = v;
30551 0 : x.ptr.p_double[i] = a+(b-a)*i/(n-1);
30552 0 : v = -v*(n-1-i);
30553 0 : v = v/(i+1);
30554 : }
30555 0 : barycentricbuildxyw(&x, y, &w, n, p, _state);
30556 0 : ae_frame_leave(_state);
30557 : }
30558 :
30559 :
30560 : /*************************************************************************
30561 : Lagrange intepolant on Chebyshev grid (first kind).
30562 : This function has O(N) complexity.
30563 :
30564 : INPUT PARAMETERS:
30565 : A - left boundary of [A,B]
30566 : B - right boundary of [A,B]
30567 : Y - function values at the nodes, array[0..N-1],
30568 : Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
30569 : N - number of points, N>=1
30570 : for N=1 a constant model is constructed.
30571 :
30572 : OUTPUT PARAMETERS
30573 : P - barycentric model which represents Lagrange interpolant
30574 : (see ratint unit info and BarycentricCalc() description for
30575 : more information).
30576 :
30577 : -- ALGLIB --
30578 : Copyright 03.12.2009 by Bochkanov Sergey
30579 : *************************************************************************/
30580 0 : void polynomialbuildcheb1(double a,
30581 : double b,
30582 : /* Real */ ae_vector* y,
30583 : ae_int_t n,
30584 : barycentricinterpolant* p,
30585 : ae_state *_state)
30586 : {
30587 : ae_frame _frame_block;
30588 : ae_int_t i;
30589 : ae_vector w;
30590 : ae_vector x;
30591 : double v;
30592 : double t;
30593 :
30594 0 : ae_frame_make(_state, &_frame_block);
30595 0 : memset(&w, 0, sizeof(w));
30596 0 : memset(&x, 0, sizeof(x));
30597 0 : _barycentricinterpolant_clear(p);
30598 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
30599 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
30600 :
30601 0 : ae_assert(n>0, "PolynomialBuildCheb1: N<=0!", _state);
30602 0 : ae_assert(y->cnt>=n, "PolynomialBuildCheb1: Length(Y)<N!", _state);
30603 0 : ae_assert(ae_isfinite(a, _state), "PolynomialBuildCheb1: A is infinite or NaN!", _state);
30604 0 : ae_assert(ae_isfinite(b, _state), "PolynomialBuildCheb1: B is infinite or NaN!", _state);
30605 0 : ae_assert(isfinitevector(y, n, _state), "PolynomialBuildCheb1: Y contains infinite or NaN values!", _state);
30606 0 : ae_assert(ae_fp_neq(b,a), "PolynomialBuildCheb1: B=A!", _state);
30607 :
30608 : /*
30609 : * Special case: N=1
30610 : */
30611 0 : if( n==1 )
30612 : {
30613 0 : ae_vector_set_length(&x, 1, _state);
30614 0 : ae_vector_set_length(&w, 1, _state);
30615 0 : x.ptr.p_double[0] = 0.5*(b+a);
30616 0 : w.ptr.p_double[0] = (double)(1);
30617 0 : barycentricbuildxyw(&x, y, &w, 1, p, _state);
30618 0 : ae_frame_leave(_state);
30619 0 : return;
30620 : }
30621 :
30622 : /*
30623 : * general case
30624 : */
30625 0 : ae_vector_set_length(&x, n, _state);
30626 0 : ae_vector_set_length(&w, n, _state);
30627 0 : v = (double)(1);
30628 0 : for(i=0; i<=n-1; i++)
30629 : {
30630 0 : t = ae_tan(0.5*ae_pi*(2*i+1)/(2*n), _state);
30631 0 : w.ptr.p_double[i] = 2*v*t/(1+ae_sqr(t, _state));
30632 0 : x.ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*(1-ae_sqr(t, _state))/(1+ae_sqr(t, _state));
30633 0 : v = -v;
30634 : }
30635 0 : barycentricbuildxyw(&x, y, &w, n, p, _state);
30636 0 : ae_frame_leave(_state);
30637 : }
30638 :
30639 :
30640 : /*************************************************************************
30641 : Lagrange intepolant on Chebyshev grid (second kind).
30642 : This function has O(N) complexity.
30643 :
30644 : INPUT PARAMETERS:
30645 : A - left boundary of [A,B]
30646 : B - right boundary of [A,B]
30647 : Y - function values at the nodes, array[0..N-1],
30648 : Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
30649 : N - number of points, N>=1
30650 : for N=1 a constant model is constructed.
30651 :
30652 : OUTPUT PARAMETERS
30653 : P - barycentric model which represents Lagrange interpolant
30654 : (see ratint unit info and BarycentricCalc() description for
30655 : more information).
30656 :
30657 : -- ALGLIB --
30658 : Copyright 03.12.2009 by Bochkanov Sergey
30659 : *************************************************************************/
30660 0 : void polynomialbuildcheb2(double a,
30661 : double b,
30662 : /* Real */ ae_vector* y,
30663 : ae_int_t n,
30664 : barycentricinterpolant* p,
30665 : ae_state *_state)
30666 : {
30667 : ae_frame _frame_block;
30668 : ae_int_t i;
30669 : ae_vector w;
30670 : ae_vector x;
30671 : double v;
30672 :
30673 0 : ae_frame_make(_state, &_frame_block);
30674 0 : memset(&w, 0, sizeof(w));
30675 0 : memset(&x, 0, sizeof(x));
30676 0 : _barycentricinterpolant_clear(p);
30677 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
30678 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
30679 :
30680 0 : ae_assert(n>0, "PolynomialBuildCheb2: N<=0!", _state);
30681 0 : ae_assert(y->cnt>=n, "PolynomialBuildCheb2: Length(Y)<N!", _state);
30682 0 : ae_assert(ae_isfinite(a, _state), "PolynomialBuildCheb2: A is infinite or NaN!", _state);
30683 0 : ae_assert(ae_isfinite(b, _state), "PolynomialBuildCheb2: B is infinite or NaN!", _state);
30684 0 : ae_assert(ae_fp_neq(b,a), "PolynomialBuildCheb2: B=A!", _state);
30685 0 : ae_assert(isfinitevector(y, n, _state), "PolynomialBuildCheb2: Y contains infinite or NaN values!", _state);
30686 :
30687 : /*
30688 : * Special case: N=1
30689 : */
30690 0 : if( n==1 )
30691 : {
30692 0 : ae_vector_set_length(&x, 1, _state);
30693 0 : ae_vector_set_length(&w, 1, _state);
30694 0 : x.ptr.p_double[0] = 0.5*(b+a);
30695 0 : w.ptr.p_double[0] = (double)(1);
30696 0 : barycentricbuildxyw(&x, y, &w, 1, p, _state);
30697 0 : ae_frame_leave(_state);
30698 0 : return;
30699 : }
30700 :
30701 : /*
30702 : * general case
30703 : */
30704 0 : ae_vector_set_length(&x, n, _state);
30705 0 : ae_vector_set_length(&w, n, _state);
30706 0 : v = (double)(1);
30707 0 : for(i=0; i<=n-1; i++)
30708 : {
30709 0 : if( i==0||i==n-1 )
30710 : {
30711 0 : w.ptr.p_double[i] = v*0.5;
30712 : }
30713 : else
30714 : {
30715 0 : w.ptr.p_double[i] = v;
30716 : }
30717 0 : x.ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*i/(n-1), _state);
30718 0 : v = -v;
30719 : }
30720 0 : barycentricbuildxyw(&x, y, &w, n, p, _state);
30721 0 : ae_frame_leave(_state);
30722 : }
30723 :
30724 :
30725 : /*************************************************************************
30726 : Fast equidistant polynomial interpolation function with O(N) complexity
30727 :
30728 : INPUT PARAMETERS:
30729 : A - left boundary of [A,B]
30730 : B - right boundary of [A,B]
30731 : F - function values, array[0..N-1]
30732 : N - number of points on equidistant grid, N>=1
30733 : for N=1 a constant model is constructed.
30734 : T - position where P(x) is calculated
30735 :
30736 : RESULT
30737 : value of the Lagrange interpolant at T
30738 :
30739 : IMPORTANT
30740 : this function provides fast interface which is not overflow-safe
30741 : nor it is very precise.
30742 : the best option is to use PolynomialBuildEqDist()/BarycentricCalc()
30743 : subroutines unless you are pretty sure that your data will not result
30744 : in overflow.
30745 :
30746 : -- ALGLIB --
30747 : Copyright 02.12.2009 by Bochkanov Sergey
30748 : *************************************************************************/
30749 0 : double polynomialcalceqdist(double a,
30750 : double b,
30751 : /* Real */ ae_vector* f,
30752 : ae_int_t n,
30753 : double t,
30754 : ae_state *_state)
30755 : {
30756 : double s1;
30757 : double s2;
30758 : double v;
30759 : double threshold;
30760 : double s;
30761 : double h;
30762 : ae_int_t i;
30763 : ae_int_t j;
30764 : double w;
30765 : double x;
30766 : double result;
30767 :
30768 :
30769 0 : ae_assert(n>0, "PolynomialCalcEqDist: N<=0!", _state);
30770 0 : ae_assert(f->cnt>=n, "PolynomialCalcEqDist: Length(F)<N!", _state);
30771 0 : ae_assert(ae_isfinite(a, _state), "PolynomialCalcEqDist: A is infinite or NaN!", _state);
30772 0 : ae_assert(ae_isfinite(b, _state), "PolynomialCalcEqDist: B is infinite or NaN!", _state);
30773 0 : ae_assert(isfinitevector(f, n, _state), "PolynomialCalcEqDist: F contains infinite or NaN values!", _state);
30774 0 : ae_assert(ae_fp_neq(b,a), "PolynomialCalcEqDist: B=A!", _state);
30775 0 : ae_assert(!ae_isinf(t, _state), "PolynomialCalcEqDist: T is infinite!", _state);
30776 :
30777 : /*
30778 : * Special case: T is NAN
30779 : */
30780 0 : if( ae_isnan(t, _state) )
30781 : {
30782 0 : result = _state->v_nan;
30783 0 : return result;
30784 : }
30785 :
30786 : /*
30787 : * Special case: N=1
30788 : */
30789 0 : if( n==1 )
30790 : {
30791 0 : result = f->ptr.p_double[0];
30792 0 : return result;
30793 : }
30794 :
30795 : /*
30796 : * First, decide: should we use "safe" formula (guarded
30797 : * against overflow) or fast one?
30798 : */
30799 0 : threshold = ae_sqrt(ae_minrealnumber, _state);
30800 0 : j = 0;
30801 0 : s = t-a;
30802 0 : for(i=1; i<=n-1; i++)
30803 : {
30804 0 : x = a+(double)i/(double)(n-1)*(b-a);
30805 0 : if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) )
30806 : {
30807 0 : s = t-x;
30808 0 : j = i;
30809 : }
30810 : }
30811 0 : if( ae_fp_eq(s,(double)(0)) )
30812 : {
30813 0 : result = f->ptr.p_double[j];
30814 0 : return result;
30815 : }
30816 0 : if( ae_fp_greater(ae_fabs(s, _state),threshold) )
30817 : {
30818 :
30819 : /*
30820 : * use fast formula
30821 : */
30822 0 : j = -1;
30823 0 : s = 1.0;
30824 : }
30825 :
30826 : /*
30827 : * Calculate using safe or fast barycentric formula
30828 : */
30829 0 : s1 = (double)(0);
30830 0 : s2 = (double)(0);
30831 0 : w = 1.0;
30832 0 : h = (b-a)/(n-1);
30833 0 : for(i=0; i<=n-1; i++)
30834 : {
30835 0 : if( i!=j )
30836 : {
30837 0 : v = s*w/(t-(a+i*h));
30838 0 : s1 = s1+v*f->ptr.p_double[i];
30839 0 : s2 = s2+v;
30840 : }
30841 : else
30842 : {
30843 0 : v = w;
30844 0 : s1 = s1+v*f->ptr.p_double[i];
30845 0 : s2 = s2+v;
30846 : }
30847 0 : w = -w*(n-1-i);
30848 0 : w = w/(i+1);
30849 : }
30850 0 : result = s1/s2;
30851 0 : return result;
30852 : }
30853 :
30854 :
30855 : /*************************************************************************
30856 : Fast polynomial interpolation function on Chebyshev points (first kind)
30857 : with O(N) complexity.
30858 :
30859 : INPUT PARAMETERS:
30860 : A - left boundary of [A,B]
30861 : B - right boundary of [A,B]
30862 : F - function values, array[0..N-1]
30863 : N - number of points on Chebyshev grid (first kind),
30864 : X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))
30865 : for N=1 a constant model is constructed.
30866 : T - position where P(x) is calculated
30867 :
30868 : RESULT
30869 : value of the Lagrange interpolant at T
30870 :
30871 : IMPORTANT
30872 : this function provides fast interface which is not overflow-safe
30873 : nor it is very precise.
30874 : the best option is to use PolIntBuildCheb1()/BarycentricCalc()
30875 : subroutines unless you are pretty sure that your data will not result
30876 : in overflow.
30877 :
30878 : -- ALGLIB --
30879 : Copyright 02.12.2009 by Bochkanov Sergey
30880 : *************************************************************************/
30881 0 : double polynomialcalccheb1(double a,
30882 : double b,
30883 : /* Real */ ae_vector* f,
30884 : ae_int_t n,
30885 : double t,
30886 : ae_state *_state)
30887 : {
30888 : double s1;
30889 : double s2;
30890 : double v;
30891 : double threshold;
30892 : double s;
30893 : ae_int_t i;
30894 : ae_int_t j;
30895 : double a0;
30896 : double delta;
30897 : double alpha;
30898 : double beta;
30899 : double ca;
30900 : double sa;
30901 : double tempc;
30902 : double temps;
30903 : double x;
30904 : double w;
30905 : double p1;
30906 : double result;
30907 :
30908 :
30909 0 : ae_assert(n>0, "PolynomialCalcCheb1: N<=0!", _state);
30910 0 : ae_assert(f->cnt>=n, "PolynomialCalcCheb1: Length(F)<N!", _state);
30911 0 : ae_assert(ae_isfinite(a, _state), "PolynomialCalcCheb1: A is infinite or NaN!", _state);
30912 0 : ae_assert(ae_isfinite(b, _state), "PolynomialCalcCheb1: B is infinite or NaN!", _state);
30913 0 : ae_assert(isfinitevector(f, n, _state), "PolynomialCalcCheb1: F contains infinite or NaN values!", _state);
30914 0 : ae_assert(ae_fp_neq(b,a), "PolynomialCalcCheb1: B=A!", _state);
30915 0 : ae_assert(!ae_isinf(t, _state), "PolynomialCalcCheb1: T is infinite!", _state);
30916 :
30917 : /*
30918 : * Special case: T is NAN
30919 : */
30920 0 : if( ae_isnan(t, _state) )
30921 : {
30922 0 : result = _state->v_nan;
30923 0 : return result;
30924 : }
30925 :
30926 : /*
30927 : * Special case: N=1
30928 : */
30929 0 : if( n==1 )
30930 : {
30931 0 : result = f->ptr.p_double[0];
30932 0 : return result;
30933 : }
30934 :
30935 : /*
30936 : * Prepare information for the recurrence formula
30937 : * used to calculate sin(pi*(2j+1)/(2n+2)) and
30938 : * cos(pi*(2j+1)/(2n+2)):
30939 : *
30940 : * A0 = pi/(2n+2)
30941 : * Delta = pi/(n+1)
30942 : * Alpha = 2 sin^2 (Delta/2)
30943 : * Beta = sin(Delta)
30944 : *
30945 : * so that sin(..) = sin(A0+j*delta) and cos(..) = cos(A0+j*delta).
30946 : * Then we use
30947 : *
30948 : * sin(x+delta) = sin(x) - (alpha*sin(x) - beta*cos(x))
30949 : * cos(x+delta) = cos(x) - (alpha*cos(x) - beta*sin(x))
30950 : *
30951 : * to repeatedly calculate sin(..) and cos(..).
30952 : */
30953 0 : threshold = ae_sqrt(ae_minrealnumber, _state);
30954 0 : t = (t-0.5*(a+b))/(0.5*(b-a));
30955 0 : a0 = ae_pi/(2*(n-1)+2);
30956 0 : delta = 2*ae_pi/(2*(n-1)+2);
30957 0 : alpha = 2*ae_sqr(ae_sin(delta/2, _state), _state);
30958 0 : beta = ae_sin(delta, _state);
30959 :
30960 : /*
30961 : * First, decide: should we use "safe" formula (guarded
30962 : * against overflow) or fast one?
30963 : */
30964 0 : ca = ae_cos(a0, _state);
30965 0 : sa = ae_sin(a0, _state);
30966 0 : j = 0;
30967 0 : x = ca;
30968 0 : s = t-x;
30969 0 : for(i=1; i<=n-1; i++)
30970 : {
30971 :
30972 : /*
30973 : * Next X[i]
30974 : */
30975 0 : temps = sa-(alpha*sa-beta*ca);
30976 0 : tempc = ca-(alpha*ca+beta*sa);
30977 0 : sa = temps;
30978 0 : ca = tempc;
30979 0 : x = ca;
30980 :
30981 : /*
30982 : * Use X[i]
30983 : */
30984 0 : if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) )
30985 : {
30986 0 : s = t-x;
30987 0 : j = i;
30988 : }
30989 : }
30990 0 : if( ae_fp_eq(s,(double)(0)) )
30991 : {
30992 0 : result = f->ptr.p_double[j];
30993 0 : return result;
30994 : }
30995 0 : if( ae_fp_greater(ae_fabs(s, _state),threshold) )
30996 : {
30997 :
30998 : /*
30999 : * use fast formula
31000 : */
31001 0 : j = -1;
31002 0 : s = 1.0;
31003 : }
31004 :
31005 : /*
31006 : * Calculate using safe or fast barycentric formula
31007 : */
31008 0 : s1 = (double)(0);
31009 0 : s2 = (double)(0);
31010 0 : ca = ae_cos(a0, _state);
31011 0 : sa = ae_sin(a0, _state);
31012 0 : p1 = 1.0;
31013 0 : for(i=0; i<=n-1; i++)
31014 : {
31015 :
31016 : /*
31017 : * Calculate X[i], W[i]
31018 : */
31019 0 : x = ca;
31020 0 : w = p1*sa;
31021 :
31022 : /*
31023 : * Proceed
31024 : */
31025 0 : if( i!=j )
31026 : {
31027 0 : v = s*w/(t-x);
31028 0 : s1 = s1+v*f->ptr.p_double[i];
31029 0 : s2 = s2+v;
31030 : }
31031 : else
31032 : {
31033 0 : v = w;
31034 0 : s1 = s1+v*f->ptr.p_double[i];
31035 0 : s2 = s2+v;
31036 : }
31037 :
31038 : /*
31039 : * Next CA, SA, P1
31040 : */
31041 0 : temps = sa-(alpha*sa-beta*ca);
31042 0 : tempc = ca-(alpha*ca+beta*sa);
31043 0 : sa = temps;
31044 0 : ca = tempc;
31045 0 : p1 = -p1;
31046 : }
31047 0 : result = s1/s2;
31048 0 : return result;
31049 : }
31050 :
31051 :
31052 : /*************************************************************************
31053 : Fast polynomial interpolation function on Chebyshev points (second kind)
31054 : with O(N) complexity.
31055 :
31056 : INPUT PARAMETERS:
31057 : A - left boundary of [A,B]
31058 : B - right boundary of [A,B]
31059 : F - function values, array[0..N-1]
31060 : N - number of points on Chebyshev grid (second kind),
31061 : X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))
31062 : for N=1 a constant model is constructed.
31063 : T - position where P(x) is calculated
31064 :
31065 : RESULT
31066 : value of the Lagrange interpolant at T
31067 :
31068 : IMPORTANT
31069 : this function provides fast interface which is not overflow-safe
31070 : nor it is very precise.
31071 : the best option is to use PolIntBuildCheb2()/BarycentricCalc()
31072 : subroutines unless you are pretty sure that your data will not result
31073 : in overflow.
31074 :
31075 : -- ALGLIB --
31076 : Copyright 02.12.2009 by Bochkanov Sergey
31077 : *************************************************************************/
31078 0 : double polynomialcalccheb2(double a,
31079 : double b,
31080 : /* Real */ ae_vector* f,
31081 : ae_int_t n,
31082 : double t,
31083 : ae_state *_state)
31084 : {
31085 : double s1;
31086 : double s2;
31087 : double v;
31088 : double threshold;
31089 : double s;
31090 : ae_int_t i;
31091 : ae_int_t j;
31092 : double a0;
31093 : double delta;
31094 : double alpha;
31095 : double beta;
31096 : double ca;
31097 : double sa;
31098 : double tempc;
31099 : double temps;
31100 : double x;
31101 : double w;
31102 : double p1;
31103 : double result;
31104 :
31105 :
31106 0 : ae_assert(n>0, "PolynomialCalcCheb2: N<=0!", _state);
31107 0 : ae_assert(f->cnt>=n, "PolynomialCalcCheb2: Length(F)<N!", _state);
31108 0 : ae_assert(ae_isfinite(a, _state), "PolynomialCalcCheb2: A is infinite or NaN!", _state);
31109 0 : ae_assert(ae_isfinite(b, _state), "PolynomialCalcCheb2: B is infinite or NaN!", _state);
31110 0 : ae_assert(ae_fp_neq(b,a), "PolynomialCalcCheb2: B=A!", _state);
31111 0 : ae_assert(isfinitevector(f, n, _state), "PolynomialCalcCheb2: F contains infinite or NaN values!", _state);
31112 0 : ae_assert(!ae_isinf(t, _state), "PolynomialCalcEqDist: T is infinite!", _state);
31113 :
31114 : /*
31115 : * Special case: T is NAN
31116 : */
31117 0 : if( ae_isnan(t, _state) )
31118 : {
31119 0 : result = _state->v_nan;
31120 0 : return result;
31121 : }
31122 :
31123 : /*
31124 : * Special case: N=1
31125 : */
31126 0 : if( n==1 )
31127 : {
31128 0 : result = f->ptr.p_double[0];
31129 0 : return result;
31130 : }
31131 :
31132 : /*
31133 : * Prepare information for the recurrence formula
31134 : * used to calculate sin(pi*i/n) and
31135 : * cos(pi*i/n):
31136 : *
31137 : * A0 = 0
31138 : * Delta = pi/n
31139 : * Alpha = 2 sin^2 (Delta/2)
31140 : * Beta = sin(Delta)
31141 : *
31142 : * so that sin(..) = sin(A0+j*delta) and cos(..) = cos(A0+j*delta).
31143 : * Then we use
31144 : *
31145 : * sin(x+delta) = sin(x) - (alpha*sin(x) - beta*cos(x))
31146 : * cos(x+delta) = cos(x) - (alpha*cos(x) - beta*sin(x))
31147 : *
31148 : * to repeatedly calculate sin(..) and cos(..).
31149 : */
31150 0 : threshold = ae_sqrt(ae_minrealnumber, _state);
31151 0 : t = (t-0.5*(a+b))/(0.5*(b-a));
31152 0 : a0 = 0.0;
31153 0 : delta = ae_pi/(n-1);
31154 0 : alpha = 2*ae_sqr(ae_sin(delta/2, _state), _state);
31155 0 : beta = ae_sin(delta, _state);
31156 :
31157 : /*
31158 : * First, decide: should we use "safe" formula (guarded
31159 : * against overflow) or fast one?
31160 : */
31161 0 : ca = ae_cos(a0, _state);
31162 0 : sa = ae_sin(a0, _state);
31163 0 : j = 0;
31164 0 : x = ca;
31165 0 : s = t-x;
31166 0 : for(i=1; i<=n-1; i++)
31167 : {
31168 :
31169 : /*
31170 : * Next X[i]
31171 : */
31172 0 : temps = sa-(alpha*sa-beta*ca);
31173 0 : tempc = ca-(alpha*ca+beta*sa);
31174 0 : sa = temps;
31175 0 : ca = tempc;
31176 0 : x = ca;
31177 :
31178 : /*
31179 : * Use X[i]
31180 : */
31181 0 : if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) )
31182 : {
31183 0 : s = t-x;
31184 0 : j = i;
31185 : }
31186 : }
31187 0 : if( ae_fp_eq(s,(double)(0)) )
31188 : {
31189 0 : result = f->ptr.p_double[j];
31190 0 : return result;
31191 : }
31192 0 : if( ae_fp_greater(ae_fabs(s, _state),threshold) )
31193 : {
31194 :
31195 : /*
31196 : * use fast formula
31197 : */
31198 0 : j = -1;
31199 0 : s = 1.0;
31200 : }
31201 :
31202 : /*
31203 : * Calculate using safe or fast barycentric formula
31204 : */
31205 0 : s1 = (double)(0);
31206 0 : s2 = (double)(0);
31207 0 : ca = ae_cos(a0, _state);
31208 0 : sa = ae_sin(a0, _state);
31209 0 : p1 = 1.0;
31210 0 : for(i=0; i<=n-1; i++)
31211 : {
31212 :
31213 : /*
31214 : * Calculate X[i], W[i]
31215 : */
31216 0 : x = ca;
31217 0 : if( i==0||i==n-1 )
31218 : {
31219 0 : w = 0.5*p1;
31220 : }
31221 : else
31222 : {
31223 0 : w = 1.0*p1;
31224 : }
31225 :
31226 : /*
31227 : * Proceed
31228 : */
31229 0 : if( i!=j )
31230 : {
31231 0 : v = s*w/(t-x);
31232 0 : s1 = s1+v*f->ptr.p_double[i];
31233 0 : s2 = s2+v;
31234 : }
31235 : else
31236 : {
31237 0 : v = w;
31238 0 : s1 = s1+v*f->ptr.p_double[i];
31239 0 : s2 = s2+v;
31240 : }
31241 :
31242 : /*
31243 : * Next CA, SA, P1
31244 : */
31245 0 : temps = sa-(alpha*sa-beta*ca);
31246 0 : tempc = ca-(alpha*ca+beta*sa);
31247 0 : sa = temps;
31248 0 : ca = tempc;
31249 0 : p1 = -p1;
31250 : }
31251 0 : result = s1/s2;
31252 0 : return result;
31253 : }
31254 :
31255 :
31256 : #endif
31257 : #if defined(AE_COMPILE_LSFIT) || !defined(AE_PARTIAL_BUILD)
31258 :
31259 :
31260 : /*************************************************************************
31261 : This subroutine fits piecewise linear curve to points with Ramer-Douglas-
31262 : Peucker algorithm, which stops after generating specified number of linear
31263 : sections.
31264 :
31265 : IMPORTANT:
31266 : * it does NOT perform least-squares fitting; it builds curve, but this
31267 : curve does not minimize some least squares metric. See description of
31268 : RDP algorithm (say, in Wikipedia) for more details on WHAT is performed.
31269 : * this function does NOT work with parametric curves (i.e. curves which
31270 : can be represented as {X(t),Y(t)}. It works with curves which can be
31271 : represented as Y(X). Thus, it is impossible to model figures like
31272 : circles with this functions.
31273 : If you want to work with parametric curves, you should use
31274 : ParametricRDPFixed() function provided by "Parametric" subpackage of
31275 : "Interpolation" package.
31276 :
31277 : INPUT PARAMETERS:
31278 : X - array of X-coordinates:
31279 : * at least N elements
31280 : * can be unordered (points are automatically sorted)
31281 : * this function may accept non-distinct X (see below for
31282 : more information on handling of such inputs)
31283 : Y - array of Y-coordinates:
31284 : * at least N elements
31285 : N - number of elements in X/Y
31286 : M - desired number of sections:
31287 : * at most M sections are generated by this function
31288 : * less than M sections can be generated if we have N<M
31289 : (or some X are non-distinct).
31290 :
31291 : OUTPUT PARAMETERS:
31292 : X2 - X-values of corner points for piecewise approximation,
31293 : has length NSections+1 or zero (for NSections=0).
31294 : Y2 - Y-values of corner points,
31295 : has length NSections+1 or zero (for NSections=0).
31296 : NSections- number of sections found by algorithm, NSections<=M,
31297 : NSections can be zero for degenerate datasets
31298 : (N<=1 or all X[] are non-distinct).
31299 :
31300 : NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of
31301 : curve, (X2[NSection-1],Y2[NSection-1]) is the last point.
31302 :
31303 : -- ALGLIB --
31304 : Copyright 02.10.2014 by Bochkanov Sergey
31305 : *************************************************************************/
31306 0 : void lstfitpiecewiselinearrdpfixed(/* Real */ ae_vector* x,
31307 : /* Real */ ae_vector* y,
31308 : ae_int_t n,
31309 : ae_int_t m,
31310 : /* Real */ ae_vector* x2,
31311 : /* Real */ ae_vector* y2,
31312 : ae_int_t* nsections,
31313 : ae_state *_state)
31314 : {
31315 : ae_frame _frame_block;
31316 : ae_vector _x;
31317 : ae_vector _y;
31318 : ae_int_t i;
31319 : ae_int_t j;
31320 : ae_int_t k;
31321 : ae_int_t k0;
31322 : ae_int_t k1;
31323 : ae_int_t k2;
31324 : ae_vector buf0;
31325 : ae_vector buf1;
31326 : ae_matrix sections;
31327 : ae_vector points;
31328 : double v;
31329 : ae_int_t worstidx;
31330 : double worsterror;
31331 : ae_int_t idx0;
31332 : ae_int_t idx1;
31333 : double e0;
31334 : double e1;
31335 : ae_vector heaperrors;
31336 : ae_vector heaptags;
31337 :
31338 0 : ae_frame_make(_state, &_frame_block);
31339 0 : memset(&_x, 0, sizeof(_x));
31340 0 : memset(&_y, 0, sizeof(_y));
31341 0 : memset(&buf0, 0, sizeof(buf0));
31342 0 : memset(&buf1, 0, sizeof(buf1));
31343 0 : memset(§ions, 0, sizeof(sections));
31344 0 : memset(&points, 0, sizeof(points));
31345 0 : memset(&heaperrors, 0, sizeof(heaperrors));
31346 0 : memset(&heaptags, 0, sizeof(heaptags));
31347 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
31348 0 : x = &_x;
31349 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
31350 0 : y = &_y;
31351 0 : ae_vector_clear(x2);
31352 0 : ae_vector_clear(y2);
31353 0 : *nsections = 0;
31354 0 : ae_vector_init(&buf0, 0, DT_REAL, _state, ae_true);
31355 0 : ae_vector_init(&buf1, 0, DT_REAL, _state, ae_true);
31356 0 : ae_matrix_init(§ions, 0, 0, DT_REAL, _state, ae_true);
31357 0 : ae_vector_init(&points, 0, DT_REAL, _state, ae_true);
31358 0 : ae_vector_init(&heaperrors, 0, DT_REAL, _state, ae_true);
31359 0 : ae_vector_init(&heaptags, 0, DT_INT, _state, ae_true);
31360 :
31361 0 : ae_assert(n>=0, "LSTFitPiecewiseLinearRDPFixed: N<0", _state);
31362 0 : ae_assert(m>=1, "LSTFitPiecewiseLinearRDPFixed: M<1", _state);
31363 0 : ae_assert(x->cnt>=n, "LSTFitPiecewiseLinearRDPFixed: Length(X)<N", _state);
31364 0 : ae_assert(y->cnt>=n, "LSTFitPiecewiseLinearRDPFixed: Length(Y)<N", _state);
31365 0 : if( n<=1 )
31366 : {
31367 0 : *nsections = 0;
31368 0 : ae_frame_leave(_state);
31369 0 : return;
31370 : }
31371 :
31372 : /*
31373 : * Sort points.
31374 : * Handle possible ties (tied values are replaced by their mean)
31375 : */
31376 0 : tagsortfastr(x, y, &buf0, &buf1, n, _state);
31377 0 : i = 0;
31378 0 : while(i<=n-1)
31379 : {
31380 0 : j = i+1;
31381 0 : v = y->ptr.p_double[i];
31382 0 : while(j<=n-1&&ae_fp_eq(x->ptr.p_double[j],x->ptr.p_double[i]))
31383 : {
31384 0 : v = v+y->ptr.p_double[j];
31385 0 : j = j+1;
31386 : }
31387 0 : v = v/(j-i);
31388 0 : for(k=i; k<=j-1; k++)
31389 : {
31390 0 : y->ptr.p_double[k] = v;
31391 : }
31392 0 : i = j;
31393 : }
31394 :
31395 : /*
31396 : * Handle degenerate case x[0]=x[N-1]
31397 : */
31398 0 : if( ae_fp_eq(x->ptr.p_double[n-1],x->ptr.p_double[0]) )
31399 : {
31400 0 : *nsections = 0;
31401 0 : ae_frame_leave(_state);
31402 0 : return;
31403 : }
31404 :
31405 : /*
31406 : * Prepare first section
31407 : */
31408 0 : lsfit_rdpanalyzesection(x, y, 0, n-1, &worstidx, &worsterror, _state);
31409 0 : ae_matrix_set_length(§ions, m, 4, _state);
31410 0 : ae_vector_set_length(&heaperrors, m, _state);
31411 0 : ae_vector_set_length(&heaptags, m, _state);
31412 0 : *nsections = 1;
31413 0 : sections.ptr.pp_double[0][0] = (double)(0);
31414 0 : sections.ptr.pp_double[0][1] = (double)(n-1);
31415 0 : sections.ptr.pp_double[0][2] = (double)(worstidx);
31416 0 : sections.ptr.pp_double[0][3] = worsterror;
31417 0 : heaperrors.ptr.p_double[0] = worsterror;
31418 0 : heaptags.ptr.p_int[0] = 0;
31419 0 : ae_assert(ae_fp_eq(sections.ptr.pp_double[0][1],(double)(n-1)), "RDP algorithm: integrity check failed", _state);
31420 :
31421 : /*
31422 : * Main loop.
31423 : * Repeatedly find section with worst error and divide it.
31424 : * Terminate after M-th section, or because of other reasons (see loop internals).
31425 : */
31426 0 : while(*nsections<m)
31427 : {
31428 :
31429 : /*
31430 : * Break if worst section has zero error.
31431 : * Store index of worst section to K.
31432 : */
31433 0 : if( ae_fp_eq(heaperrors.ptr.p_double[0],(double)(0)) )
31434 : {
31435 0 : break;
31436 : }
31437 0 : k = heaptags.ptr.p_int[0];
31438 :
31439 : /*
31440 : * K-th section is divided in two:
31441 : * * first one spans interval from X[Sections[K,0]] to X[Sections[K,2]]
31442 : * * second one spans interval from X[Sections[K,2]] to X[Sections[K,1]]
31443 : *
31444 : * First section is stored at K-th position, second one is appended to the table.
31445 : * Then we update heap which stores pairs of (error,section_index)
31446 : */
31447 0 : k0 = ae_round(sections.ptr.pp_double[k][0], _state);
31448 0 : k1 = ae_round(sections.ptr.pp_double[k][1], _state);
31449 0 : k2 = ae_round(sections.ptr.pp_double[k][2], _state);
31450 0 : lsfit_rdpanalyzesection(x, y, k0, k2, &idx0, &e0, _state);
31451 0 : lsfit_rdpanalyzesection(x, y, k2, k1, &idx1, &e1, _state);
31452 0 : sections.ptr.pp_double[k][0] = (double)(k0);
31453 0 : sections.ptr.pp_double[k][1] = (double)(k2);
31454 0 : sections.ptr.pp_double[k][2] = (double)(idx0);
31455 0 : sections.ptr.pp_double[k][3] = e0;
31456 0 : tagheapreplacetopi(&heaperrors, &heaptags, *nsections, e0, k, _state);
31457 0 : sections.ptr.pp_double[*nsections][0] = (double)(k2);
31458 0 : sections.ptr.pp_double[*nsections][1] = (double)(k1);
31459 0 : sections.ptr.pp_double[*nsections][2] = (double)(idx1);
31460 0 : sections.ptr.pp_double[*nsections][3] = e1;
31461 0 : tagheappushi(&heaperrors, &heaptags, nsections, e1, *nsections, _state);
31462 : }
31463 :
31464 : /*
31465 : * Convert from sections to points
31466 : */
31467 0 : ae_vector_set_length(&points, *nsections+1, _state);
31468 0 : k = ae_round(sections.ptr.pp_double[0][1], _state);
31469 0 : for(i=0; i<=*nsections-1; i++)
31470 : {
31471 0 : points.ptr.p_double[i] = (double)(ae_round(sections.ptr.pp_double[i][0], _state));
31472 0 : if( ae_fp_greater(x->ptr.p_double[ae_round(sections.ptr.pp_double[i][1], _state)],x->ptr.p_double[k]) )
31473 : {
31474 0 : k = ae_round(sections.ptr.pp_double[i][1], _state);
31475 : }
31476 : }
31477 0 : points.ptr.p_double[*nsections] = (double)(k);
31478 0 : tagsortfast(&points, &buf0, *nsections+1, _state);
31479 :
31480 : /*
31481 : * Output sections:
31482 : * * first NSection elements of X2/Y2 are filled by x/y at left boundaries of sections
31483 : * * last element of X2/Y2 is filled by right boundary of rightmost section
31484 : * * X2/Y2 is sorted by ascending of X2
31485 : */
31486 0 : ae_vector_set_length(x2, *nsections+1, _state);
31487 0 : ae_vector_set_length(y2, *nsections+1, _state);
31488 0 : for(i=0; i<=*nsections; i++)
31489 : {
31490 0 : x2->ptr.p_double[i] = x->ptr.p_double[ae_round(points.ptr.p_double[i], _state)];
31491 0 : y2->ptr.p_double[i] = y->ptr.p_double[ae_round(points.ptr.p_double[i], _state)];
31492 : }
31493 0 : ae_frame_leave(_state);
31494 : }
31495 :
31496 :
31497 : /*************************************************************************
31498 : This subroutine fits piecewise linear curve to points with Ramer-Douglas-
31499 : Peucker algorithm, which stops after achieving desired precision.
31500 :
31501 : IMPORTANT:
31502 : * it performs non-least-squares fitting; it builds curve, but this curve
31503 : does not minimize some least squares metric. See description of RDP
31504 : algorithm (say, in Wikipedia) for more details on WHAT is performed.
31505 : * this function does NOT work with parametric curves (i.e. curves which
31506 : can be represented as {X(t),Y(t)}. It works with curves which can be
31507 : represented as Y(X). Thus, it is impossible to model figures like circles
31508 : with this functions.
31509 : If you want to work with parametric curves, you should use
31510 : ParametricRDPFixed() function provided by "Parametric" subpackage of
31511 : "Interpolation" package.
31512 :
31513 : INPUT PARAMETERS:
31514 : X - array of X-coordinates:
31515 : * at least N elements
31516 : * can be unordered (points are automatically sorted)
31517 : * this function may accept non-distinct X (see below for
31518 : more information on handling of such inputs)
31519 : Y - array of Y-coordinates:
31520 : * at least N elements
31521 : N - number of elements in X/Y
31522 : Eps - positive number, desired precision.
31523 :
31524 :
31525 : OUTPUT PARAMETERS:
31526 : X2 - X-values of corner points for piecewise approximation,
31527 : has length NSections+1 or zero (for NSections=0).
31528 : Y2 - Y-values of corner points,
31529 : has length NSections+1 or zero (for NSections=0).
31530 : NSections- number of sections found by algorithm,
31531 : NSections can be zero for degenerate datasets
31532 : (N<=1 or all X[] are non-distinct).
31533 :
31534 : NOTE: X2/Y2 are ordered arrays, i.e. (X2[0],Y2[0]) is a first point of
31535 : curve, (X2[NSection-1],Y2[NSection-1]) is the last point.
31536 :
31537 : -- ALGLIB --
31538 : Copyright 02.10.2014 by Bochkanov Sergey
31539 : *************************************************************************/
31540 0 : void lstfitpiecewiselinearrdp(/* Real */ ae_vector* x,
31541 : /* Real */ ae_vector* y,
31542 : ae_int_t n,
31543 : double eps,
31544 : /* Real */ ae_vector* x2,
31545 : /* Real */ ae_vector* y2,
31546 : ae_int_t* nsections,
31547 : ae_state *_state)
31548 : {
31549 : ae_frame _frame_block;
31550 : ae_vector _x;
31551 : ae_vector _y;
31552 : ae_int_t i;
31553 : ae_int_t j;
31554 : ae_int_t k;
31555 : ae_vector buf0;
31556 : ae_vector buf1;
31557 : ae_vector xtmp;
31558 : ae_vector ytmp;
31559 : double v;
31560 : ae_int_t npts;
31561 :
31562 0 : ae_frame_make(_state, &_frame_block);
31563 0 : memset(&_x, 0, sizeof(_x));
31564 0 : memset(&_y, 0, sizeof(_y));
31565 0 : memset(&buf0, 0, sizeof(buf0));
31566 0 : memset(&buf1, 0, sizeof(buf1));
31567 0 : memset(&xtmp, 0, sizeof(xtmp));
31568 0 : memset(&ytmp, 0, sizeof(ytmp));
31569 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
31570 0 : x = &_x;
31571 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
31572 0 : y = &_y;
31573 0 : ae_vector_clear(x2);
31574 0 : ae_vector_clear(y2);
31575 0 : *nsections = 0;
31576 0 : ae_vector_init(&buf0, 0, DT_REAL, _state, ae_true);
31577 0 : ae_vector_init(&buf1, 0, DT_REAL, _state, ae_true);
31578 0 : ae_vector_init(&xtmp, 0, DT_REAL, _state, ae_true);
31579 0 : ae_vector_init(&ytmp, 0, DT_REAL, _state, ae_true);
31580 :
31581 0 : ae_assert(n>=0, "LSTFitPiecewiseLinearRDP: N<0", _state);
31582 0 : ae_assert(ae_fp_greater(eps,(double)(0)), "LSTFitPiecewiseLinearRDP: Eps<=0", _state);
31583 0 : ae_assert(x->cnt>=n, "LSTFitPiecewiseLinearRDP: Length(X)<N", _state);
31584 0 : ae_assert(y->cnt>=n, "LSTFitPiecewiseLinearRDP: Length(Y)<N", _state);
31585 0 : if( n<=1 )
31586 : {
31587 0 : *nsections = 0;
31588 0 : ae_frame_leave(_state);
31589 0 : return;
31590 : }
31591 :
31592 : /*
31593 : * Sort points.
31594 : * Handle possible ties (tied values are replaced by their mean)
31595 : */
31596 0 : tagsortfastr(x, y, &buf0, &buf1, n, _state);
31597 0 : i = 0;
31598 0 : while(i<=n-1)
31599 : {
31600 0 : j = i+1;
31601 0 : v = y->ptr.p_double[i];
31602 0 : while(j<=n-1&&ae_fp_eq(x->ptr.p_double[j],x->ptr.p_double[i]))
31603 : {
31604 0 : v = v+y->ptr.p_double[j];
31605 0 : j = j+1;
31606 : }
31607 0 : v = v/(j-i);
31608 0 : for(k=i; k<=j-1; k++)
31609 : {
31610 0 : y->ptr.p_double[k] = v;
31611 : }
31612 0 : i = j;
31613 : }
31614 :
31615 : /*
31616 : * Handle degenerate case x[0]=x[N-1]
31617 : */
31618 0 : if( ae_fp_eq(x->ptr.p_double[n-1],x->ptr.p_double[0]) )
31619 : {
31620 0 : *nsections = 0;
31621 0 : ae_frame_leave(_state);
31622 0 : return;
31623 : }
31624 :
31625 : /*
31626 : * Prepare data for recursive algorithm
31627 : */
31628 0 : ae_vector_set_length(&xtmp, n, _state);
31629 0 : ae_vector_set_length(&ytmp, n, _state);
31630 0 : npts = 2;
31631 0 : xtmp.ptr.p_double[0] = x->ptr.p_double[0];
31632 0 : ytmp.ptr.p_double[0] = y->ptr.p_double[0];
31633 0 : xtmp.ptr.p_double[1] = x->ptr.p_double[n-1];
31634 0 : ytmp.ptr.p_double[1] = y->ptr.p_double[n-1];
31635 0 : lsfit_rdprecursive(x, y, 0, n-1, eps, &xtmp, &ytmp, &npts, _state);
31636 :
31637 : /*
31638 : * Output sections:
31639 : * * first NSection elements of X2/Y2 are filled by x/y at left boundaries of sections
31640 : * * last element of X2/Y2 is filled by right boundary of rightmost section
31641 : * * X2/Y2 is sorted by ascending of X2
31642 : */
31643 0 : *nsections = npts-1;
31644 0 : ae_vector_set_length(x2, npts, _state);
31645 0 : ae_vector_set_length(y2, npts, _state);
31646 0 : for(i=0; i<=*nsections; i++)
31647 : {
31648 0 : x2->ptr.p_double[i] = xtmp.ptr.p_double[i];
31649 0 : y2->ptr.p_double[i] = ytmp.ptr.p_double[i];
31650 : }
31651 0 : tagsortfastr(x2, y2, &buf0, &buf1, npts, _state);
31652 0 : ae_frame_leave(_state);
31653 : }
31654 :
31655 :
31656 : /*************************************************************************
31657 : Fitting by polynomials in barycentric form. This function provides simple
31658 : unterface for unconstrained unweighted fitting. See PolynomialFitWC() if
31659 : you need constrained fitting.
31660 :
31661 : Task is linear, so linear least squares solver is used. Complexity of this
31662 : computational scheme is O(N*M^2), mostly dominated by least squares solver
31663 :
31664 : SEE ALSO:
31665 : PolynomialFitWC()
31666 :
31667 : NOTES:
31668 : you can convert P from barycentric form to the power or Chebyshev
31669 : basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
31670 : POLINT subpackage.
31671 :
31672 : ! COMMERCIAL EDITION OF ALGLIB:
31673 : !
31674 : ! Commercial Edition of ALGLIB includes following important improvements
31675 : ! of this function:
31676 : ! * high-performance native backend with same C# interface (C# version)
31677 : ! * multithreading support (C++ and C# versions)
31678 : ! * hardware vendor (Intel) implementations of linear algebra primitives
31679 : ! (C++ and C# versions, x86/x64 platform)
31680 : !
31681 : ! We recommend you to read 'Working with commercial version' section of
31682 : ! ALGLIB Reference Manual in order to find out how to use performance-
31683 : ! related features provided by commercial edition of ALGLIB.
31684 :
31685 : INPUT PARAMETERS:
31686 : X - points, array[0..N-1].
31687 : Y - function values, array[0..N-1].
31688 : N - number of points, N>0
31689 : * if given, only leading N elements of X/Y are used
31690 : * if not given, automatically determined from sizes of X/Y
31691 : M - number of basis functions (= polynomial_degree + 1), M>=1
31692 :
31693 : OUTPUT PARAMETERS:
31694 : Info- same format as in LSFitLinearW() subroutine:
31695 : * Info>0 task is solved
31696 : * Info<=0 an error occured:
31697 : -4 means inconvergence of internal SVD
31698 : P - interpolant in barycentric form.
31699 : Rep - report, same format as in LSFitLinearW() subroutine.
31700 : Following fields are set:
31701 : * RMSError rms error on the (X,Y).
31702 : * AvgError average error on the (X,Y).
31703 : * AvgRelError average relative error on the non-zero Y
31704 : * MaxError maximum error
31705 : NON-WEIGHTED ERRORS ARE CALCULATED
31706 :
31707 : -- ALGLIB PROJECT --
31708 : Copyright 10.12.2009 by Bochkanov Sergey
31709 : *************************************************************************/
31710 0 : void polynomialfit(/* Real */ ae_vector* x,
31711 : /* Real */ ae_vector* y,
31712 : ae_int_t n,
31713 : ae_int_t m,
31714 : ae_int_t* info,
31715 : barycentricinterpolant* p,
31716 : polynomialfitreport* rep,
31717 : ae_state *_state)
31718 : {
31719 : ae_frame _frame_block;
31720 : ae_int_t i;
31721 : ae_vector w;
31722 : ae_vector xc;
31723 : ae_vector yc;
31724 : ae_vector dc;
31725 :
31726 0 : ae_frame_make(_state, &_frame_block);
31727 0 : memset(&w, 0, sizeof(w));
31728 0 : memset(&xc, 0, sizeof(xc));
31729 0 : memset(&yc, 0, sizeof(yc));
31730 0 : memset(&dc, 0, sizeof(dc));
31731 0 : *info = 0;
31732 0 : _barycentricinterpolant_clear(p);
31733 0 : _polynomialfitreport_clear(rep);
31734 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
31735 0 : ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
31736 0 : ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
31737 0 : ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
31738 :
31739 0 : ae_assert(n>0, "PolynomialFit: N<=0!", _state);
31740 0 : ae_assert(m>0, "PolynomialFit: M<=0!", _state);
31741 0 : ae_assert(x->cnt>=n, "PolynomialFit: Length(X)<N!", _state);
31742 0 : ae_assert(y->cnt>=n, "PolynomialFit: Length(Y)<N!", _state);
31743 0 : ae_assert(isfinitevector(x, n, _state), "PolynomialFit: X contains infinite or NaN values!", _state);
31744 0 : ae_assert(isfinitevector(y, n, _state), "PolynomialFit: Y contains infinite or NaN values!", _state);
31745 0 : ae_vector_set_length(&w, n, _state);
31746 0 : for(i=0; i<=n-1; i++)
31747 : {
31748 0 : w.ptr.p_double[i] = (double)(1);
31749 : }
31750 0 : polynomialfitwc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, p, rep, _state);
31751 0 : ae_frame_leave(_state);
31752 0 : }
31753 :
31754 :
31755 : /*************************************************************************
31756 : Weighted fitting by polynomials in barycentric form, with constraints on
31757 : function values or first derivatives.
31758 :
31759 : Small regularizing term is used when solving constrained tasks (to improve
31760 : stability).
31761 :
31762 : Task is linear, so linear least squares solver is used. Complexity of this
31763 : computational scheme is O(N*M^2), mostly dominated by least squares solver
31764 :
31765 : SEE ALSO:
31766 : PolynomialFit()
31767 :
31768 : NOTES:
31769 : you can convert P from barycentric form to the power or Chebyshev
31770 : basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
31771 : POLINT subpackage.
31772 :
31773 : ! COMMERCIAL EDITION OF ALGLIB:
31774 : !
31775 : ! Commercial Edition of ALGLIB includes following important improvements
31776 : ! of this function:
31777 : ! * high-performance native backend with same C# interface (C# version)
31778 : ! * multithreading support (C++ and C# versions)
31779 : ! * hardware vendor (Intel) implementations of linear algebra primitives
31780 : ! (C++ and C# versions, x86/x64 platform)
31781 : !
31782 : ! We recommend you to read 'Working with commercial version' section of
31783 : ! ALGLIB Reference Manual in order to find out how to use performance-
31784 : ! related features provided by commercial edition of ALGLIB.
31785 :
31786 : INPUT PARAMETERS:
31787 : X - points, array[0..N-1].
31788 : Y - function values, array[0..N-1].
31789 : W - weights, array[0..N-1]
31790 : Each summand in square sum of approximation deviations from
31791 : given values is multiplied by the square of corresponding
31792 : weight. Fill it by 1's if you don't want to solve weighted
31793 : task.
31794 : N - number of points, N>0.
31795 : * if given, only leading N elements of X/Y/W are used
31796 : * if not given, automatically determined from sizes of X/Y/W
31797 : XC - points where polynomial values/derivatives are constrained,
31798 : array[0..K-1].
31799 : YC - values of constraints, array[0..K-1]
31800 : DC - array[0..K-1], types of constraints:
31801 : * DC[i]=0 means that P(XC[i])=YC[i]
31802 : * DC[i]=1 means that P'(XC[i])=YC[i]
31803 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
31804 : K - number of constraints, 0<=K<M.
31805 : K=0 means no constraints (XC/YC/DC are not used in such cases)
31806 : M - number of basis functions (= polynomial_degree + 1), M>=1
31807 :
31808 : OUTPUT PARAMETERS:
31809 : Info- same format as in LSFitLinearW() subroutine:
31810 : * Info>0 task is solved
31811 : * Info<=0 an error occured:
31812 : -4 means inconvergence of internal SVD
31813 : -3 means inconsistent constraints
31814 : P - interpolant in barycentric form.
31815 : Rep - report, same format as in LSFitLinearW() subroutine.
31816 : Following fields are set:
31817 : * RMSError rms error on the (X,Y).
31818 : * AvgError average error on the (X,Y).
31819 : * AvgRelError average relative error on the non-zero Y
31820 : * MaxError maximum error
31821 : NON-WEIGHTED ERRORS ARE CALCULATED
31822 :
31823 : IMPORTANT:
31824 : this subroitine doesn't calculate task's condition number for K<>0.
31825 :
31826 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
31827 :
31828 : Setting constraints can lead to undesired results, like ill-conditioned
31829 : behavior, or inconsistency being detected. From the other side, it allows
31830 : us to improve quality of the fit. Here we summarize our experience with
31831 : constrained regression splines:
31832 : * even simple constraints can be inconsistent, see Wikipedia article on
31833 : this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
31834 : * the greater is M (given fixed constraints), the more chances that
31835 : constraints will be consistent
31836 : * in the general case, consistency of constraints is NOT GUARANTEED.
31837 : * in the one special cases, however, we can guarantee consistency. This
31838 : case is: M>1 and constraints on the function values (NOT DERIVATIVES)
31839 :
31840 : Our final recommendation is to use constraints WHEN AND ONLY when you
31841 : can't solve your task without them. Anything beyond special cases given
31842 : above is not guaranteed and may result in inconsistency.
31843 :
31844 : -- ALGLIB PROJECT --
31845 : Copyright 10.12.2009 by Bochkanov Sergey
31846 : *************************************************************************/
31847 0 : void polynomialfitwc(/* Real */ ae_vector* x,
31848 : /* Real */ ae_vector* y,
31849 : /* Real */ ae_vector* w,
31850 : ae_int_t n,
31851 : /* Real */ ae_vector* xc,
31852 : /* Real */ ae_vector* yc,
31853 : /* Integer */ ae_vector* dc,
31854 : ae_int_t k,
31855 : ae_int_t m,
31856 : ae_int_t* info,
31857 : barycentricinterpolant* p,
31858 : polynomialfitreport* rep,
31859 : ae_state *_state)
31860 : {
31861 : ae_frame _frame_block;
31862 : ae_vector _x;
31863 : ae_vector _y;
31864 : ae_vector _w;
31865 : ae_vector _xc;
31866 : ae_vector _yc;
31867 : double xa;
31868 : double xb;
31869 : double sa;
31870 : double sb;
31871 : ae_vector xoriginal;
31872 : ae_vector yoriginal;
31873 : ae_vector y2;
31874 : ae_vector w2;
31875 : ae_vector tmp;
31876 : ae_vector tmp2;
31877 : ae_vector bx;
31878 : ae_vector by;
31879 : ae_vector bw;
31880 : ae_int_t i;
31881 : ae_int_t j;
31882 : double u;
31883 : double v;
31884 : double s;
31885 : ae_int_t relcnt;
31886 : lsfitreport lrep;
31887 :
31888 0 : ae_frame_make(_state, &_frame_block);
31889 0 : memset(&_x, 0, sizeof(_x));
31890 0 : memset(&_y, 0, sizeof(_y));
31891 0 : memset(&_w, 0, sizeof(_w));
31892 0 : memset(&_xc, 0, sizeof(_xc));
31893 0 : memset(&_yc, 0, sizeof(_yc));
31894 0 : memset(&xoriginal, 0, sizeof(xoriginal));
31895 0 : memset(&yoriginal, 0, sizeof(yoriginal));
31896 0 : memset(&y2, 0, sizeof(y2));
31897 0 : memset(&w2, 0, sizeof(w2));
31898 0 : memset(&tmp, 0, sizeof(tmp));
31899 0 : memset(&tmp2, 0, sizeof(tmp2));
31900 0 : memset(&bx, 0, sizeof(bx));
31901 0 : memset(&by, 0, sizeof(by));
31902 0 : memset(&bw, 0, sizeof(bw));
31903 0 : memset(&lrep, 0, sizeof(lrep));
31904 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
31905 0 : x = &_x;
31906 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
31907 0 : y = &_y;
31908 0 : ae_vector_init_copy(&_w, w, _state, ae_true);
31909 0 : w = &_w;
31910 0 : ae_vector_init_copy(&_xc, xc, _state, ae_true);
31911 0 : xc = &_xc;
31912 0 : ae_vector_init_copy(&_yc, yc, _state, ae_true);
31913 0 : yc = &_yc;
31914 0 : *info = 0;
31915 0 : _barycentricinterpolant_clear(p);
31916 0 : _polynomialfitreport_clear(rep);
31917 0 : ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
31918 0 : ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
31919 0 : ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
31920 0 : ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
31921 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
31922 0 : ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
31923 0 : ae_vector_init(&bx, 0, DT_REAL, _state, ae_true);
31924 0 : ae_vector_init(&by, 0, DT_REAL, _state, ae_true);
31925 0 : ae_vector_init(&bw, 0, DT_REAL, _state, ae_true);
31926 0 : _lsfitreport_init(&lrep, _state, ae_true);
31927 :
31928 0 : ae_assert(n>0, "PolynomialFitWC: N<=0!", _state);
31929 0 : ae_assert(m>0, "PolynomialFitWC: M<=0!", _state);
31930 0 : ae_assert(k>=0, "PolynomialFitWC: K<0!", _state);
31931 0 : ae_assert(k<m, "PolynomialFitWC: K>=M!", _state);
31932 0 : ae_assert(x->cnt>=n, "PolynomialFitWC: Length(X)<N!", _state);
31933 0 : ae_assert(y->cnt>=n, "PolynomialFitWC: Length(Y)<N!", _state);
31934 0 : ae_assert(w->cnt>=n, "PolynomialFitWC: Length(W)<N!", _state);
31935 0 : ae_assert(xc->cnt>=k, "PolynomialFitWC: Length(XC)<K!", _state);
31936 0 : ae_assert(yc->cnt>=k, "PolynomialFitWC: Length(YC)<K!", _state);
31937 0 : ae_assert(dc->cnt>=k, "PolynomialFitWC: Length(DC)<K!", _state);
31938 0 : ae_assert(isfinitevector(x, n, _state), "PolynomialFitWC: X contains infinite or NaN values!", _state);
31939 0 : ae_assert(isfinitevector(y, n, _state), "PolynomialFitWC: Y contains infinite or NaN values!", _state);
31940 0 : ae_assert(isfinitevector(w, n, _state), "PolynomialFitWC: X contains infinite or NaN values!", _state);
31941 0 : ae_assert(isfinitevector(xc, k, _state), "PolynomialFitWC: XC contains infinite or NaN values!", _state);
31942 0 : ae_assert(isfinitevector(yc, k, _state), "PolynomialFitWC: YC contains infinite or NaN values!", _state);
31943 0 : for(i=0; i<=k-1; i++)
31944 : {
31945 0 : ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "PolynomialFitWC: one of DC[] is not 0 or 1!", _state);
31946 : }
31947 :
31948 : /*
31949 : * Scale X, Y, XC, YC.
31950 : * Solve scaled problem using internal Chebyshev fitting function.
31951 : */
31952 0 : lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
31953 0 : lsfit_internalchebyshevfit(x, y, w, n, xc, yc, dc, k, m, info, &tmp, &lrep, _state);
31954 0 : if( *info<0 )
31955 : {
31956 0 : ae_frame_leave(_state);
31957 0 : return;
31958 : }
31959 :
31960 : /*
31961 : * Generate barycentric model and scale it
31962 : * * BX, BY store barycentric model nodes
31963 : * * FMatrix is reused (remember - it is at least MxM, what we need)
31964 : *
31965 : * Model intialization is done in O(M^2). In principle, it can be
31966 : * done in O(M*log(M)), but before it we solved task with O(N*M^2)
31967 : * complexity, so it is only a small amount of total time spent.
31968 : */
31969 0 : ae_vector_set_length(&bx, m, _state);
31970 0 : ae_vector_set_length(&by, m, _state);
31971 0 : ae_vector_set_length(&bw, m, _state);
31972 0 : ae_vector_set_length(&tmp2, m, _state);
31973 0 : s = (double)(1);
31974 0 : for(i=0; i<=m-1; i++)
31975 : {
31976 0 : if( m!=1 )
31977 : {
31978 0 : u = ae_cos(ae_pi*i/(m-1), _state);
31979 : }
31980 : else
31981 : {
31982 0 : u = (double)(0);
31983 : }
31984 0 : v = (double)(0);
31985 0 : for(j=0; j<=m-1; j++)
31986 : {
31987 0 : if( j==0 )
31988 : {
31989 0 : tmp2.ptr.p_double[j] = (double)(1);
31990 : }
31991 : else
31992 : {
31993 0 : if( j==1 )
31994 : {
31995 0 : tmp2.ptr.p_double[j] = u;
31996 : }
31997 : else
31998 : {
31999 0 : tmp2.ptr.p_double[j] = 2*u*tmp2.ptr.p_double[j-1]-tmp2.ptr.p_double[j-2];
32000 : }
32001 : }
32002 0 : v = v+tmp.ptr.p_double[j]*tmp2.ptr.p_double[j];
32003 : }
32004 0 : bx.ptr.p_double[i] = u;
32005 0 : by.ptr.p_double[i] = v;
32006 0 : bw.ptr.p_double[i] = s;
32007 0 : if( i==0||i==m-1 )
32008 : {
32009 0 : bw.ptr.p_double[i] = 0.5*bw.ptr.p_double[i];
32010 : }
32011 0 : s = -s;
32012 : }
32013 0 : barycentricbuildxyw(&bx, &by, &bw, m, p, _state);
32014 0 : barycentriclintransx(p, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
32015 0 : barycentriclintransy(p, sb-sa, sa, _state);
32016 :
32017 : /*
32018 : * Scale absolute errors obtained from LSFitLinearW.
32019 : * Relative error should be calculated separately
32020 : * (because of shifting/scaling of the task)
32021 : */
32022 0 : rep->taskrcond = lrep.taskrcond;
32023 0 : rep->rmserror = lrep.rmserror*(sb-sa);
32024 0 : rep->avgerror = lrep.avgerror*(sb-sa);
32025 0 : rep->maxerror = lrep.maxerror*(sb-sa);
32026 0 : rep->avgrelerror = (double)(0);
32027 0 : relcnt = 0;
32028 0 : for(i=0; i<=n-1; i++)
32029 : {
32030 0 : if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) )
32031 : {
32032 0 : rep->avgrelerror = rep->avgrelerror+ae_fabs(barycentriccalc(p, xoriginal.ptr.p_double[i], _state)-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state);
32033 0 : relcnt = relcnt+1;
32034 : }
32035 : }
32036 0 : if( relcnt!=0 )
32037 : {
32038 0 : rep->avgrelerror = rep->avgrelerror/relcnt;
32039 : }
32040 0 : ae_frame_leave(_state);
32041 : }
32042 :
32043 :
32044 : /*************************************************************************
32045 : This function calculates value of four-parameter logistic (4PL) model at
32046 : specified point X. 4PL model has following form:
32047 :
32048 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B))
32049 :
32050 : INPUT PARAMETERS:
32051 : X - current point, X>=0:
32052 : * zero X is correctly handled even for B<=0
32053 : * negative X results in exception.
32054 : A, B, C, D- parameters of 4PL model:
32055 : * A is unconstrained
32056 : * B is unconstrained; zero or negative values are handled
32057 : correctly.
32058 : * C>0, non-positive value results in exception
32059 : * D is unconstrained
32060 :
32061 : RESULT:
32062 : model value at X
32063 :
32064 : NOTE: if B=0, denominator is assumed to be equal to 2.0 even for zero X
32065 : (strictly speaking, 0^0 is undefined).
32066 :
32067 : NOTE: this function also throws exception if all input parameters are
32068 : correct, but overflow was detected during calculations.
32069 :
32070 : NOTE: this function performs a lot of checks; if you need really high
32071 : performance, consider evaluating model yourself, without checking
32072 : for degenerate cases.
32073 :
32074 :
32075 : -- ALGLIB PROJECT --
32076 : Copyright 14.05.2014 by Bochkanov Sergey
32077 : *************************************************************************/
32078 0 : double logisticcalc4(double x,
32079 : double a,
32080 : double b,
32081 : double c,
32082 : double d,
32083 : ae_state *_state)
32084 : {
32085 : double result;
32086 :
32087 :
32088 0 : ae_assert(ae_isfinite(x, _state), "LogisticCalc4: X is not finite", _state);
32089 0 : ae_assert(ae_isfinite(a, _state), "LogisticCalc4: A is not finite", _state);
32090 0 : ae_assert(ae_isfinite(b, _state), "LogisticCalc4: B is not finite", _state);
32091 0 : ae_assert(ae_isfinite(c, _state), "LogisticCalc4: C is not finite", _state);
32092 0 : ae_assert(ae_isfinite(d, _state), "LogisticCalc4: D is not finite", _state);
32093 0 : ae_assert(ae_fp_greater_eq(x,(double)(0)), "LogisticCalc4: X is negative", _state);
32094 0 : ae_assert(ae_fp_greater(c,(double)(0)), "LogisticCalc4: C is non-positive", _state);
32095 :
32096 : /*
32097 : * Check for degenerate cases
32098 : */
32099 0 : if( ae_fp_eq(b,(double)(0)) )
32100 : {
32101 0 : result = 0.5*(a+d);
32102 0 : return result;
32103 : }
32104 0 : if( ae_fp_eq(x,(double)(0)) )
32105 : {
32106 0 : if( ae_fp_greater(b,(double)(0)) )
32107 : {
32108 0 : result = a;
32109 : }
32110 : else
32111 : {
32112 0 : result = d;
32113 : }
32114 0 : return result;
32115 : }
32116 :
32117 : /*
32118 : * General case
32119 : */
32120 0 : result = d+(a-d)/(1.0+ae_pow(x/c, b, _state));
32121 0 : ae_assert(ae_isfinite(result, _state), "LogisticCalc4: overflow during calculations", _state);
32122 0 : return result;
32123 : }
32124 :
32125 :
32126 : /*************************************************************************
32127 : This function calculates value of five-parameter logistic (5PL) model at
32128 : specified point X. 5PL model has following form:
32129 :
32130 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G)
32131 :
32132 : INPUT PARAMETERS:
32133 : X - current point, X>=0:
32134 : * zero X is correctly handled even for B<=0
32135 : * negative X results in exception.
32136 : A, B, C, D, G- parameters of 5PL model:
32137 : * A is unconstrained
32138 : * B is unconstrained; zero or negative values are handled
32139 : correctly.
32140 : * C>0, non-positive value results in exception
32141 : * D is unconstrained
32142 : * G>0, non-positive value results in exception
32143 :
32144 : RESULT:
32145 : model value at X
32146 :
32147 : NOTE: if B=0, denominator is assumed to be equal to Power(2.0,G) even for
32148 : zero X (strictly speaking, 0^0 is undefined).
32149 :
32150 : NOTE: this function also throws exception if all input parameters are
32151 : correct, but overflow was detected during calculations.
32152 :
32153 : NOTE: this function performs a lot of checks; if you need really high
32154 : performance, consider evaluating model yourself, without checking
32155 : for degenerate cases.
32156 :
32157 :
32158 : -- ALGLIB PROJECT --
32159 : Copyright 14.05.2014 by Bochkanov Sergey
32160 : *************************************************************************/
32161 0 : double logisticcalc5(double x,
32162 : double a,
32163 : double b,
32164 : double c,
32165 : double d,
32166 : double g,
32167 : ae_state *_state)
32168 : {
32169 : double result;
32170 :
32171 :
32172 0 : ae_assert(ae_isfinite(x, _state), "LogisticCalc5: X is not finite", _state);
32173 0 : ae_assert(ae_isfinite(a, _state), "LogisticCalc5: A is not finite", _state);
32174 0 : ae_assert(ae_isfinite(b, _state), "LogisticCalc5: B is not finite", _state);
32175 0 : ae_assert(ae_isfinite(c, _state), "LogisticCalc5: C is not finite", _state);
32176 0 : ae_assert(ae_isfinite(d, _state), "LogisticCalc5: D is not finite", _state);
32177 0 : ae_assert(ae_isfinite(g, _state), "LogisticCalc5: G is not finite", _state);
32178 0 : ae_assert(ae_fp_greater_eq(x,(double)(0)), "LogisticCalc5: X is negative", _state);
32179 0 : ae_assert(ae_fp_greater(c,(double)(0)), "LogisticCalc5: C is non-positive", _state);
32180 0 : ae_assert(ae_fp_greater(g,(double)(0)), "LogisticCalc5: G is non-positive", _state);
32181 :
32182 : /*
32183 : * Check for degenerate cases
32184 : */
32185 0 : if( ae_fp_eq(b,(double)(0)) )
32186 : {
32187 0 : result = d+(a-d)/ae_pow(2.0, g, _state);
32188 0 : return result;
32189 : }
32190 0 : if( ae_fp_eq(x,(double)(0)) )
32191 : {
32192 0 : if( ae_fp_greater(b,(double)(0)) )
32193 : {
32194 0 : result = a;
32195 : }
32196 : else
32197 : {
32198 0 : result = d;
32199 : }
32200 0 : return result;
32201 : }
32202 :
32203 : /*
32204 : * General case
32205 : */
32206 0 : result = d+(a-d)/ae_pow(1.0+ae_pow(x/c, b, _state), g, _state);
32207 0 : ae_assert(ae_isfinite(result, _state), "LogisticCalc5: overflow during calculations", _state);
32208 0 : return result;
32209 : }
32210 :
32211 :
32212 : /*************************************************************************
32213 : This function fits four-parameter logistic (4PL) model to data provided
32214 : by user. 4PL model has following form:
32215 :
32216 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B))
32217 :
32218 : Here:
32219 : * A, D - unconstrained (see LogisticFit4EC() for constrained 4PL)
32220 : * B>=0
32221 : * C>0
32222 :
32223 : IMPORTANT: output of this function is constrained in such way that B>0.
32224 : Because 4PL model is symmetric with respect to B, there is no
32225 : need to explore B<0. Constraining B makes algorithm easier
32226 : to stabilize and debug.
32227 : Users who for some reason prefer to work with negative B's
32228 : should transform output themselves (swap A and D, replace B by
32229 : -B).
32230 :
32231 : 4PL fitting is implemented as follows:
32232 : * we perform small number of restarts from random locations which helps to
32233 : solve problem of bad local extrema. Locations are only partially random
32234 : - we use input data to determine good initial guess, but we include
32235 : controlled amount of randomness.
32236 : * we perform Levenberg-Marquardt fitting with very tight constraints on
32237 : parameters B and C - it allows us to find good initial guess for the
32238 : second stage without risk of running into "flat spot".
32239 : * second Levenberg-Marquardt round is performed without excessive
32240 : constraints. Results from the previous round are used as initial guess.
32241 : * after fitting is done, we compare results with best values found so far,
32242 : rewrite "best solution" if needed, and move to next random location.
32243 :
32244 : Overall algorithm is very stable and is not prone to bad local extrema.
32245 : Furthermore, it automatically scales when input data have very large or
32246 : very small range.
32247 :
32248 : INPUT PARAMETERS:
32249 : X - array[N], stores X-values.
32250 : MUST include only non-negative numbers (but may include
32251 : zero values). Can be unsorted.
32252 : Y - array[N], values to fit.
32253 : N - number of points. If N is less than length of X/Y, only
32254 : leading N elements are used.
32255 :
32256 : OUTPUT PARAMETERS:
32257 : A, B, C, D- parameters of 4PL model
32258 : Rep - fitting report. This structure has many fields, but ONLY
32259 : ONES LISTED BELOW ARE SET:
32260 : * Rep.IterationsCount - number of iterations performed
32261 : * Rep.RMSError - root-mean-square error
32262 : * Rep.AvgError - average absolute error
32263 : * Rep.AvgRelError - average relative error (calculated for
32264 : non-zero Y-values)
32265 : * Rep.MaxError - maximum absolute error
32266 : * Rep.R2 - coefficient of determination, R-squared. This
32267 : coefficient is calculated as R2=1-RSS/TSS (in case
32268 : of nonlinear regression there are multiple ways to
32269 : define R2, each of them giving different results).
32270 :
32271 : NOTE: for stability reasons the B parameter is restricted by [1/1000,1000]
32272 : range. It prevents algorithm from making trial steps deep into the
32273 : area of bad parameters.
32274 :
32275 : NOTE: after you obtained coefficients, you can evaluate model with
32276 : LogisticCalc4() function.
32277 :
32278 : NOTE: if you need better control over fitting process than provided by this
32279 : function, you may use LogisticFit45X().
32280 :
32281 : NOTE: step is automatically scaled according to scale of parameters being
32282 : fitted before we compare its length with EpsX. Thus, this function
32283 : can be used to fit data with very small or very large values without
32284 : changing EpsX.
32285 :
32286 :
32287 : -- ALGLIB PROJECT --
32288 : Copyright 14.02.2014 by Bochkanov Sergey
32289 : *************************************************************************/
32290 0 : void logisticfit4(/* Real */ ae_vector* x,
32291 : /* Real */ ae_vector* y,
32292 : ae_int_t n,
32293 : double* a,
32294 : double* b,
32295 : double* c,
32296 : double* d,
32297 : lsfitreport* rep,
32298 : ae_state *_state)
32299 : {
32300 : ae_frame _frame_block;
32301 : ae_vector _x;
32302 : ae_vector _y;
32303 : double g;
32304 :
32305 0 : ae_frame_make(_state, &_frame_block);
32306 0 : memset(&_x, 0, sizeof(_x));
32307 0 : memset(&_y, 0, sizeof(_y));
32308 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
32309 0 : x = &_x;
32310 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
32311 0 : y = &_y;
32312 0 : *a = 0;
32313 0 : *b = 0;
32314 0 : *c = 0;
32315 0 : *d = 0;
32316 0 : _lsfitreport_clear(rep);
32317 :
32318 0 : logisticfit45x(x, y, n, _state->v_nan, _state->v_nan, ae_true, 0.0, 0.0, 0, a, b, c, d, &g, rep, _state);
32319 0 : ae_frame_leave(_state);
32320 0 : }
32321 :
32322 :
32323 : /*************************************************************************
32324 : This function fits four-parameter logistic (4PL) model to data provided
32325 : by user, with optional constraints on parameters A and D. 4PL model has
32326 : following form:
32327 :
32328 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B))
32329 :
32330 : Here:
32331 : * A, D - with optional equality constraints
32332 : * B>=0
32333 : * C>0
32334 :
32335 : IMPORTANT: output of this function is constrained in such way that B>0.
32336 : Because 4PL model is symmetric with respect to B, there is no
32337 : need to explore B<0. Constraining B makes algorithm easier
32338 : to stabilize and debug.
32339 : Users who for some reason prefer to work with negative B's
32340 : should transform output themselves (swap A and D, replace B by
32341 : -B).
32342 :
32343 : 4PL fitting is implemented as follows:
32344 : * we perform small number of restarts from random locations which helps to
32345 : solve problem of bad local extrema. Locations are only partially random
32346 : - we use input data to determine good initial guess, but we include
32347 : controlled amount of randomness.
32348 : * we perform Levenberg-Marquardt fitting with very tight constraints on
32349 : parameters B and C - it allows us to find good initial guess for the
32350 : second stage without risk of running into "flat spot".
32351 : * second Levenberg-Marquardt round is performed without excessive
32352 : constraints. Results from the previous round are used as initial guess.
32353 : * after fitting is done, we compare results with best values found so far,
32354 : rewrite "best solution" if needed, and move to next random location.
32355 :
32356 : Overall algorithm is very stable and is not prone to bad local extrema.
32357 : Furthermore, it automatically scales when input data have very large or
32358 : very small range.
32359 :
32360 : INPUT PARAMETERS:
32361 : X - array[N], stores X-values.
32362 : MUST include only non-negative numbers (but may include
32363 : zero values). Can be unsorted.
32364 : Y - array[N], values to fit.
32365 : N - number of points. If N is less than length of X/Y, only
32366 : leading N elements are used.
32367 : CnstrLeft- optional equality constraint for model value at the left
32368 : boundary (at X=0). Specify NAN (Not-a-Number) if you do
32369 : not need constraint on the model value at X=0 (in C++ you
32370 : can pass alglib::fp_nan as parameter, in C# it will be
32371 : Double.NaN).
32372 : See below, section "EQUALITY CONSTRAINTS" for more
32373 : information about constraints.
32374 : CnstrRight- optional equality constraint for model value at X=infinity.
32375 : Specify NAN (Not-a-Number) if you do not need constraint
32376 : on the model value (in C++ you can pass alglib::fp_nan as
32377 : parameter, in C# it will be Double.NaN).
32378 : See below, section "EQUALITY CONSTRAINTS" for more
32379 : information about constraints.
32380 :
32381 : OUTPUT PARAMETERS:
32382 : A, B, C, D- parameters of 4PL model
32383 : Rep - fitting report. This structure has many fields, but ONLY
32384 : ONES LISTED BELOW ARE SET:
32385 : * Rep.IterationsCount - number of iterations performed
32386 : * Rep.RMSError - root-mean-square error
32387 : * Rep.AvgError - average absolute error
32388 : * Rep.AvgRelError - average relative error (calculated for
32389 : non-zero Y-values)
32390 : * Rep.MaxError - maximum absolute error
32391 : * Rep.R2 - coefficient of determination, R-squared. This
32392 : coefficient is calculated as R2=1-RSS/TSS (in case
32393 : of nonlinear regression there are multiple ways to
32394 : define R2, each of them giving different results).
32395 :
32396 : NOTE: for stability reasons the B parameter is restricted by [1/1000,1000]
32397 : range. It prevents algorithm from making trial steps deep into the
32398 : area of bad parameters.
32399 :
32400 : NOTE: after you obtained coefficients, you can evaluate model with
32401 : LogisticCalc4() function.
32402 :
32403 : NOTE: if you need better control over fitting process than provided by this
32404 : function, you may use LogisticFit45X().
32405 :
32406 : NOTE: step is automatically scaled according to scale of parameters being
32407 : fitted before we compare its length with EpsX. Thus, this function
32408 : can be used to fit data with very small or very large values without
32409 : changing EpsX.
32410 :
32411 : EQUALITY CONSTRAINTS ON PARAMETERS
32412 :
32413 : 4PL/5PL solver supports equality constraints on model values at the left
32414 : boundary (X=0) and right boundary (X=infinity). These constraints are
32415 : completely optional and you can specify both of them, only one - or no
32416 : constraints at all.
32417 :
32418 : Parameter CnstrLeft contains left constraint (or NAN for unconstrained
32419 : fitting), and CnstrRight contains right one. For 4PL, left constraint
32420 : ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on
32421 : D. That's because 4PL model is normalized in such way that B>=0.
32422 :
32423 :
32424 : -- ALGLIB PROJECT --
32425 : Copyright 14.02.2014 by Bochkanov Sergey
32426 : *************************************************************************/
32427 0 : void logisticfit4ec(/* Real */ ae_vector* x,
32428 : /* Real */ ae_vector* y,
32429 : ae_int_t n,
32430 : double cnstrleft,
32431 : double cnstrright,
32432 : double* a,
32433 : double* b,
32434 : double* c,
32435 : double* d,
32436 : lsfitreport* rep,
32437 : ae_state *_state)
32438 : {
32439 : ae_frame _frame_block;
32440 : ae_vector _x;
32441 : ae_vector _y;
32442 : double g;
32443 :
32444 0 : ae_frame_make(_state, &_frame_block);
32445 0 : memset(&_x, 0, sizeof(_x));
32446 0 : memset(&_y, 0, sizeof(_y));
32447 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
32448 0 : x = &_x;
32449 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
32450 0 : y = &_y;
32451 0 : *a = 0;
32452 0 : *b = 0;
32453 0 : *c = 0;
32454 0 : *d = 0;
32455 0 : _lsfitreport_clear(rep);
32456 :
32457 0 : logisticfit45x(x, y, n, cnstrleft, cnstrright, ae_true, 0.0, 0.0, 0, a, b, c, d, &g, rep, _state);
32458 0 : ae_frame_leave(_state);
32459 0 : }
32460 :
32461 :
32462 : /*************************************************************************
32463 : This function fits five-parameter logistic (5PL) model to data provided
32464 : by user. 5PL model has following form:
32465 :
32466 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G)
32467 :
32468 : Here:
32469 : * A, D - unconstrained
32470 : * B - unconstrained
32471 : * C>0
32472 : * G>0
32473 :
32474 : IMPORTANT: unlike in 4PL fitting, output of this function is NOT
32475 : constrained in such way that B is guaranteed to be positive.
32476 : Furthermore, unlike 4PL, 5PL model is NOT symmetric with
32477 : respect to B, so you can NOT transform model to equivalent one,
32478 : with B having desired sign (>0 or <0).
32479 :
32480 : 5PL fitting is implemented as follows:
32481 : * we perform small number of restarts from random locations which helps to
32482 : solve problem of bad local extrema. Locations are only partially random
32483 : - we use input data to determine good initial guess, but we include
32484 : controlled amount of randomness.
32485 : * we perform Levenberg-Marquardt fitting with very tight constraints on
32486 : parameters B and C - it allows us to find good initial guess for the
32487 : second stage without risk of running into "flat spot". Parameter G is
32488 : fixed at G=1.
32489 : * second Levenberg-Marquardt round is performed without excessive
32490 : constraints on B and C, but with G still equal to 1. Results from the
32491 : previous round are used as initial guess.
32492 : * third Levenberg-Marquardt round relaxes constraints on G and tries two
32493 : different models - one with B>0 and one with B<0.
32494 : * after fitting is done, we compare results with best values found so far,
32495 : rewrite "best solution" if needed, and move to next random location.
32496 :
32497 : Overall algorithm is very stable and is not prone to bad local extrema.
32498 : Furthermore, it automatically scales when input data have very large or
32499 : very small range.
32500 :
32501 : INPUT PARAMETERS:
32502 : X - array[N], stores X-values.
32503 : MUST include only non-negative numbers (but may include
32504 : zero values). Can be unsorted.
32505 : Y - array[N], values to fit.
32506 : N - number of points. If N is less than length of X/Y, only
32507 : leading N elements are used.
32508 :
32509 : OUTPUT PARAMETERS:
32510 : A,B,C,D,G- parameters of 5PL model
32511 : Rep - fitting report. This structure has many fields, but ONLY
32512 : ONES LISTED BELOW ARE SET:
32513 : * Rep.IterationsCount - number of iterations performed
32514 : * Rep.RMSError - root-mean-square error
32515 : * Rep.AvgError - average absolute error
32516 : * Rep.AvgRelError - average relative error (calculated for
32517 : non-zero Y-values)
32518 : * Rep.MaxError - maximum absolute error
32519 : * Rep.R2 - coefficient of determination, R-squared. This
32520 : coefficient is calculated as R2=1-RSS/TSS (in case
32521 : of nonlinear regression there are multiple ways to
32522 : define R2, each of them giving different results).
32523 :
32524 : NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000]
32525 : range, and G is restricted by [1/10,10] range. It prevents algorithm
32526 : from making trial steps deep into the area of bad parameters.
32527 :
32528 : NOTE: after you obtained coefficients, you can evaluate model with
32529 : LogisticCalc5() function.
32530 :
32531 : NOTE: if you need better control over fitting process than provided by this
32532 : function, you may use LogisticFit45X().
32533 :
32534 : NOTE: step is automatically scaled according to scale of parameters being
32535 : fitted before we compare its length with EpsX. Thus, this function
32536 : can be used to fit data with very small or very large values without
32537 : changing EpsX.
32538 :
32539 :
32540 : -- ALGLIB PROJECT --
32541 : Copyright 14.02.2014 by Bochkanov Sergey
32542 : *************************************************************************/
32543 0 : void logisticfit5(/* Real */ ae_vector* x,
32544 : /* Real */ ae_vector* y,
32545 : ae_int_t n,
32546 : double* a,
32547 : double* b,
32548 : double* c,
32549 : double* d,
32550 : double* g,
32551 : lsfitreport* rep,
32552 : ae_state *_state)
32553 : {
32554 : ae_frame _frame_block;
32555 : ae_vector _x;
32556 : ae_vector _y;
32557 :
32558 0 : ae_frame_make(_state, &_frame_block);
32559 0 : memset(&_x, 0, sizeof(_x));
32560 0 : memset(&_y, 0, sizeof(_y));
32561 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
32562 0 : x = &_x;
32563 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
32564 0 : y = &_y;
32565 0 : *a = 0;
32566 0 : *b = 0;
32567 0 : *c = 0;
32568 0 : *d = 0;
32569 0 : *g = 0;
32570 0 : _lsfitreport_clear(rep);
32571 :
32572 0 : logisticfit45x(x, y, n, _state->v_nan, _state->v_nan, ae_false, 0.0, 0.0, 0, a, b, c, d, g, rep, _state);
32573 0 : ae_frame_leave(_state);
32574 0 : }
32575 :
32576 :
32577 : /*************************************************************************
32578 : This function fits five-parameter logistic (5PL) model to data provided
32579 : by user, subject to optional equality constraints on parameters A and D.
32580 : 5PL model has following form:
32581 :
32582 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G)
32583 :
32584 : Here:
32585 : * A, D - with optional equality constraints
32586 : * B - unconstrained
32587 : * C>0
32588 : * G>0
32589 :
32590 : IMPORTANT: unlike in 4PL fitting, output of this function is NOT
32591 : constrained in such way that B is guaranteed to be positive.
32592 : Furthermore, unlike 4PL, 5PL model is NOT symmetric with
32593 : respect to B, so you can NOT transform model to equivalent one,
32594 : with B having desired sign (>0 or <0).
32595 :
32596 : 5PL fitting is implemented as follows:
32597 : * we perform small number of restarts from random locations which helps to
32598 : solve problem of bad local extrema. Locations are only partially random
32599 : - we use input data to determine good initial guess, but we include
32600 : controlled amount of randomness.
32601 : * we perform Levenberg-Marquardt fitting with very tight constraints on
32602 : parameters B and C - it allows us to find good initial guess for the
32603 : second stage without risk of running into "flat spot". Parameter G is
32604 : fixed at G=1.
32605 : * second Levenberg-Marquardt round is performed without excessive
32606 : constraints on B and C, but with G still equal to 1. Results from the
32607 : previous round are used as initial guess.
32608 : * third Levenberg-Marquardt round relaxes constraints on G and tries two
32609 : different models - one with B>0 and one with B<0.
32610 : * after fitting is done, we compare results with best values found so far,
32611 : rewrite "best solution" if needed, and move to next random location.
32612 :
32613 : Overall algorithm is very stable and is not prone to bad local extrema.
32614 : Furthermore, it automatically scales when input data have very large or
32615 : very small range.
32616 :
32617 : INPUT PARAMETERS:
32618 : X - array[N], stores X-values.
32619 : MUST include only non-negative numbers (but may include
32620 : zero values). Can be unsorted.
32621 : Y - array[N], values to fit.
32622 : N - number of points. If N is less than length of X/Y, only
32623 : leading N elements are used.
32624 : CnstrLeft- optional equality constraint for model value at the left
32625 : boundary (at X=0). Specify NAN (Not-a-Number) if you do
32626 : not need constraint on the model value at X=0 (in C++ you
32627 : can pass alglib::fp_nan as parameter, in C# it will be
32628 : Double.NaN).
32629 : See below, section "EQUALITY CONSTRAINTS" for more
32630 : information about constraints.
32631 : CnstrRight- optional equality constraint for model value at X=infinity.
32632 : Specify NAN (Not-a-Number) if you do not need constraint
32633 : on the model value (in C++ you can pass alglib::fp_nan as
32634 : parameter, in C# it will be Double.NaN).
32635 : See below, section "EQUALITY CONSTRAINTS" for more
32636 : information about constraints.
32637 :
32638 : OUTPUT PARAMETERS:
32639 : A,B,C,D,G- parameters of 5PL model
32640 : Rep - fitting report. This structure has many fields, but ONLY
32641 : ONES LISTED BELOW ARE SET:
32642 : * Rep.IterationsCount - number of iterations performed
32643 : * Rep.RMSError - root-mean-square error
32644 : * Rep.AvgError - average absolute error
32645 : * Rep.AvgRelError - average relative error (calculated for
32646 : non-zero Y-values)
32647 : * Rep.MaxError - maximum absolute error
32648 : * Rep.R2 - coefficient of determination, R-squared. This
32649 : coefficient is calculated as R2=1-RSS/TSS (in case
32650 : of nonlinear regression there are multiple ways to
32651 : define R2, each of them giving different results).
32652 :
32653 : NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000]
32654 : range, and G is restricted by [1/10,10] range. It prevents algorithm
32655 : from making trial steps deep into the area of bad parameters.
32656 :
32657 : NOTE: after you obtained coefficients, you can evaluate model with
32658 : LogisticCalc5() function.
32659 :
32660 : NOTE: if you need better control over fitting process than provided by this
32661 : function, you may use LogisticFit45X().
32662 :
32663 : NOTE: step is automatically scaled according to scale of parameters being
32664 : fitted before we compare its length with EpsX. Thus, this function
32665 : can be used to fit data with very small or very large values without
32666 : changing EpsX.
32667 :
32668 : EQUALITY CONSTRAINTS ON PARAMETERS
32669 :
32670 : 5PL solver supports equality constraints on model values at the left
32671 : boundary (X=0) and right boundary (X=infinity). These constraints are
32672 : completely optional and you can specify both of them, only one - or no
32673 : constraints at all.
32674 :
32675 : Parameter CnstrLeft contains left constraint (or NAN for unconstrained
32676 : fitting), and CnstrRight contains right one.
32677 :
32678 : Unlike 4PL one, 5PL model is NOT symmetric with respect to change in sign
32679 : of B. Thus, negative B's are possible, and left constraint may constrain
32680 : parameter A (for positive B's) - or parameter D (for negative B's).
32681 : Similarly changes meaning of right constraint.
32682 :
32683 : You do not have to decide what parameter to constrain - algorithm will
32684 : automatically determine correct parameters as fitting progresses. However,
32685 : question highlighted above is important when you interpret fitting results.
32686 :
32687 :
32688 : -- ALGLIB PROJECT --
32689 : Copyright 14.02.2014 by Bochkanov Sergey
32690 : *************************************************************************/
32691 0 : void logisticfit5ec(/* Real */ ae_vector* x,
32692 : /* Real */ ae_vector* y,
32693 : ae_int_t n,
32694 : double cnstrleft,
32695 : double cnstrright,
32696 : double* a,
32697 : double* b,
32698 : double* c,
32699 : double* d,
32700 : double* g,
32701 : lsfitreport* rep,
32702 : ae_state *_state)
32703 : {
32704 : ae_frame _frame_block;
32705 : ae_vector _x;
32706 : ae_vector _y;
32707 :
32708 0 : ae_frame_make(_state, &_frame_block);
32709 0 : memset(&_x, 0, sizeof(_x));
32710 0 : memset(&_y, 0, sizeof(_y));
32711 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
32712 0 : x = &_x;
32713 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
32714 0 : y = &_y;
32715 0 : *a = 0;
32716 0 : *b = 0;
32717 0 : *c = 0;
32718 0 : *d = 0;
32719 0 : *g = 0;
32720 0 : _lsfitreport_clear(rep);
32721 :
32722 0 : logisticfit45x(x, y, n, cnstrleft, cnstrright, ae_false, 0.0, 0.0, 0, a, b, c, d, g, rep, _state);
32723 0 : ae_frame_leave(_state);
32724 0 : }
32725 :
32726 :
32727 : /*************************************************************************
32728 : This is "expert" 4PL/5PL fitting function, which can be used if you need
32729 : better control over fitting process than provided by LogisticFit4() or
32730 : LogisticFit5().
32731 :
32732 : This function fits model of the form
32733 :
32734 : F(x|A,B,C,D) = D+(A-D)/(1+Power(x/C,B)) (4PL model)
32735 :
32736 : or
32737 :
32738 : F(x|A,B,C,D,G) = D+(A-D)/Power(1+Power(x/C,B),G) (5PL model)
32739 :
32740 : Here:
32741 : * A, D - unconstrained
32742 : * B>=0 for 4PL, unconstrained for 5PL
32743 : * C>0
32744 : * G>0 (if present)
32745 :
32746 : INPUT PARAMETERS:
32747 : X - array[N], stores X-values.
32748 : MUST include only non-negative numbers (but may include
32749 : zero values). Can be unsorted.
32750 : Y - array[N], values to fit.
32751 : N - number of points. If N is less than length of X/Y, only
32752 : leading N elements are used.
32753 : CnstrLeft- optional equality constraint for model value at the left
32754 : boundary (at X=0). Specify NAN (Not-a-Number) if you do
32755 : not need constraint on the model value at X=0 (in C++ you
32756 : can pass alglib::fp_nan as parameter, in C# it will be
32757 : Double.NaN).
32758 : See below, section "EQUALITY CONSTRAINTS" for more
32759 : information about constraints.
32760 : CnstrRight- optional equality constraint for model value at X=infinity.
32761 : Specify NAN (Not-a-Number) if you do not need constraint
32762 : on the model value (in C++ you can pass alglib::fp_nan as
32763 : parameter, in C# it will be Double.NaN).
32764 : See below, section "EQUALITY CONSTRAINTS" for more
32765 : information about constraints.
32766 : Is4PL - whether 4PL or 5PL models are fitted
32767 : LambdaV - regularization coefficient, LambdaV>=0.
32768 : Set it to zero unless you know what you are doing.
32769 : EpsX - stopping condition (step size), EpsX>=0.
32770 : Zero value means that small step is automatically chosen.
32771 : See notes below for more information.
32772 : RsCnt - number of repeated restarts from random points. 4PL/5PL
32773 : models are prone to problem of bad local extrema. Utilizing
32774 : multiple random restarts allows us to improve algorithm
32775 : convergence.
32776 : RsCnt>=0.
32777 : Zero value means that function automatically choose small
32778 : amount of restarts (recommended).
32779 :
32780 : OUTPUT PARAMETERS:
32781 : A, B, C, D- parameters of 4PL model
32782 : G - parameter of 5PL model; for Is4PL=True, G=1 is returned.
32783 : Rep - fitting report. This structure has many fields, but ONLY
32784 : ONES LISTED BELOW ARE SET:
32785 : * Rep.IterationsCount - number of iterations performed
32786 : * Rep.RMSError - root-mean-square error
32787 : * Rep.AvgError - average absolute error
32788 : * Rep.AvgRelError - average relative error (calculated for
32789 : non-zero Y-values)
32790 : * Rep.MaxError - maximum absolute error
32791 : * Rep.R2 - coefficient of determination, R-squared. This
32792 : coefficient is calculated as R2=1-RSS/TSS (in case
32793 : of nonlinear regression there are multiple ways to
32794 : define R2, each of them giving different results).
32795 :
32796 : NOTE: for better stability B parameter is restricted by [+-1/1000,+-1000]
32797 : range, and G is restricted by [1/10,10] range. It prevents algorithm
32798 : from making trial steps deep into the area of bad parameters.
32799 :
32800 : NOTE: after you obtained coefficients, you can evaluate model with
32801 : LogisticCalc5() function.
32802 :
32803 : NOTE: step is automatically scaled according to scale of parameters being
32804 : fitted before we compare its length with EpsX. Thus, this function
32805 : can be used to fit data with very small or very large values without
32806 : changing EpsX.
32807 :
32808 : EQUALITY CONSTRAINTS ON PARAMETERS
32809 :
32810 : 4PL/5PL solver supports equality constraints on model values at the left
32811 : boundary (X=0) and right boundary (X=infinity). These constraints are
32812 : completely optional and you can specify both of them, only one - or no
32813 : constraints at all.
32814 :
32815 : Parameter CnstrLeft contains left constraint (or NAN for unconstrained
32816 : fitting), and CnstrRight contains right one. For 4PL, left constraint
32817 : ALWAYS corresponds to parameter A, and right one is ALWAYS constraint on
32818 : D. That's because 4PL model is normalized in such way that B>=0.
32819 :
32820 : For 5PL model things are different. Unlike 4PL one, 5PL model is NOT
32821 : symmetric with respect to change in sign of B. Thus, negative B's are
32822 : possible, and left constraint may constrain parameter A (for positive B's)
32823 : - or parameter D (for negative B's). Similarly changes meaning of right
32824 : constraint.
32825 :
32826 : You do not have to decide what parameter to constrain - algorithm will
32827 : automatically determine correct parameters as fitting progresses. However,
32828 : question highlighted above is important when you interpret fitting results.
32829 :
32830 :
32831 : -- ALGLIB PROJECT --
32832 : Copyright 14.02.2014 by Bochkanov Sergey
32833 : *************************************************************************/
32834 0 : void logisticfit45x(/* Real */ ae_vector* x,
32835 : /* Real */ ae_vector* y,
32836 : ae_int_t n,
32837 : double cnstrleft,
32838 : double cnstrright,
32839 : ae_bool is4pl,
32840 : double lambdav,
32841 : double epsx,
32842 : ae_int_t rscnt,
32843 : double* a,
32844 : double* b,
32845 : double* c,
32846 : double* d,
32847 : double* g,
32848 : lsfitreport* rep,
32849 : ae_state *_state)
32850 : {
32851 : ae_frame _frame_block;
32852 : ae_vector _x;
32853 : ae_vector _y;
32854 : ae_int_t i;
32855 : ae_int_t outerit;
32856 : ae_int_t nz;
32857 : double v;
32858 : ae_vector p0;
32859 : ae_vector p1;
32860 : ae_vector p2;
32861 : ae_vector bndl;
32862 : ae_vector bndu;
32863 : ae_vector s;
32864 : ae_vector bndl1;
32865 : ae_vector bndu1;
32866 : ae_vector bndl2;
32867 : ae_vector bndu2;
32868 : ae_matrix z;
32869 : hqrndstate rs;
32870 : minlmstate state;
32871 : minlmreport replm;
32872 : ae_int_t maxits;
32873 : double fbest;
32874 : double flast;
32875 : double scalex;
32876 : double scaley;
32877 : ae_vector bufx;
32878 : ae_vector bufy;
32879 : double fposb;
32880 : double fnegb;
32881 :
32882 0 : ae_frame_make(_state, &_frame_block);
32883 0 : memset(&_x, 0, sizeof(_x));
32884 0 : memset(&_y, 0, sizeof(_y));
32885 0 : memset(&p0, 0, sizeof(p0));
32886 0 : memset(&p1, 0, sizeof(p1));
32887 0 : memset(&p2, 0, sizeof(p2));
32888 0 : memset(&bndl, 0, sizeof(bndl));
32889 0 : memset(&bndu, 0, sizeof(bndu));
32890 0 : memset(&s, 0, sizeof(s));
32891 0 : memset(&bndl1, 0, sizeof(bndl1));
32892 0 : memset(&bndu1, 0, sizeof(bndu1));
32893 0 : memset(&bndl2, 0, sizeof(bndl2));
32894 0 : memset(&bndu2, 0, sizeof(bndu2));
32895 0 : memset(&z, 0, sizeof(z));
32896 0 : memset(&rs, 0, sizeof(rs));
32897 0 : memset(&state, 0, sizeof(state));
32898 0 : memset(&replm, 0, sizeof(replm));
32899 0 : memset(&bufx, 0, sizeof(bufx));
32900 0 : memset(&bufy, 0, sizeof(bufy));
32901 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
32902 0 : x = &_x;
32903 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
32904 0 : y = &_y;
32905 0 : *a = 0;
32906 0 : *b = 0;
32907 0 : *c = 0;
32908 0 : *d = 0;
32909 0 : *g = 0;
32910 0 : _lsfitreport_clear(rep);
32911 0 : ae_vector_init(&p0, 0, DT_REAL, _state, ae_true);
32912 0 : ae_vector_init(&p1, 0, DT_REAL, _state, ae_true);
32913 0 : ae_vector_init(&p2, 0, DT_REAL, _state, ae_true);
32914 0 : ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
32915 0 : ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
32916 0 : ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
32917 0 : ae_vector_init(&bndl1, 0, DT_REAL, _state, ae_true);
32918 0 : ae_vector_init(&bndu1, 0, DT_REAL, _state, ae_true);
32919 0 : ae_vector_init(&bndl2, 0, DT_REAL, _state, ae_true);
32920 0 : ae_vector_init(&bndu2, 0, DT_REAL, _state, ae_true);
32921 0 : ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
32922 0 : _hqrndstate_init(&rs, _state, ae_true);
32923 0 : _minlmstate_init(&state, _state, ae_true);
32924 0 : _minlmreport_init(&replm, _state, ae_true);
32925 0 : ae_vector_init(&bufx, 0, DT_REAL, _state, ae_true);
32926 0 : ae_vector_init(&bufy, 0, DT_REAL, _state, ae_true);
32927 :
32928 0 : ae_assert(ae_isfinite(epsx, _state), "LogisticFitX: EpsX is infinite/NAN", _state);
32929 0 : ae_assert(ae_isfinite(lambdav, _state), "LogisticFitX: LambdaV is infinite/NAN", _state);
32930 0 : ae_assert(ae_isfinite(cnstrleft, _state)||ae_isnan(cnstrleft, _state), "LogisticFitX: CnstrLeft is NOT finite or NAN", _state);
32931 0 : ae_assert(ae_isfinite(cnstrright, _state)||ae_isnan(cnstrright, _state), "LogisticFitX: CnstrRight is NOT finite or NAN", _state);
32932 0 : ae_assert(ae_fp_greater_eq(lambdav,(double)(0)), "LogisticFitX: negative LambdaV", _state);
32933 0 : ae_assert(n>0, "LogisticFitX: N<=0", _state);
32934 0 : ae_assert(rscnt>=0, "LogisticFitX: RsCnt<0", _state);
32935 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "LogisticFitX: EpsX<0", _state);
32936 0 : ae_assert(x->cnt>=n, "LogisticFitX: Length(X)<N", _state);
32937 0 : ae_assert(y->cnt>=n, "LogisticFitX: Length(Y)<N", _state);
32938 0 : ae_assert(isfinitevector(x, n, _state), "LogisticFitX: X contains infinite/NAN values", _state);
32939 0 : ae_assert(isfinitevector(y, n, _state), "LogisticFitX: X contains infinite/NAN values", _state);
32940 0 : hqrndseed(2211, 1033044, &rs, _state);
32941 0 : lsfit_clearreport(rep, _state);
32942 0 : if( ae_fp_eq(epsx,(double)(0)) )
32943 : {
32944 0 : epsx = 1.0E-10;
32945 : }
32946 0 : if( rscnt==0 )
32947 : {
32948 0 : rscnt = 4;
32949 : }
32950 0 : maxits = 1000;
32951 :
32952 : /*
32953 : * Sort points by X.
32954 : * Determine number of zero and non-zero values.
32955 : */
32956 0 : tagsortfastr(x, y, &bufx, &bufy, n, _state);
32957 0 : ae_assert(ae_fp_greater_eq(x->ptr.p_double[0],(double)(0)), "LogisticFitX: some X[] are negative", _state);
32958 0 : nz = n;
32959 0 : for(i=0; i<=n-1; i++)
32960 : {
32961 0 : if( ae_fp_greater(x->ptr.p_double[i],(double)(0)) )
32962 : {
32963 0 : nz = i;
32964 0 : break;
32965 : }
32966 : }
32967 :
32968 : /*
32969 : * For NZ=N (all X[] are zero) special code is used.
32970 : * For NZ<N we use general-purpose code.
32971 : */
32972 0 : rep->iterationscount = 0;
32973 0 : if( nz==n )
32974 : {
32975 :
32976 : /*
32977 : * NZ=N, degenerate problem.
32978 : * No need to run optimizer.
32979 : */
32980 0 : v = 0.0;
32981 0 : for(i=0; i<=n-1; i++)
32982 : {
32983 0 : v = v+y->ptr.p_double[i];
32984 : }
32985 0 : v = v/n;
32986 0 : if( ae_isfinite(cnstrleft, _state) )
32987 : {
32988 0 : *a = cnstrleft;
32989 : }
32990 : else
32991 : {
32992 0 : *a = v;
32993 : }
32994 0 : *b = (double)(1);
32995 0 : *c = (double)(1);
32996 0 : if( ae_isfinite(cnstrright, _state) )
32997 : {
32998 0 : *d = cnstrright;
32999 : }
33000 : else
33001 : {
33002 0 : *d = *a;
33003 : }
33004 0 : *g = (double)(1);
33005 0 : lsfit_logisticfit45errors(x, y, n, *a, *b, *c, *d, *g, rep, _state);
33006 0 : ae_frame_leave(_state);
33007 0 : return;
33008 : }
33009 :
33010 : /*
33011 : * Non-degenerate problem.
33012 : * Determine scale of data.
33013 : */
33014 0 : scalex = x->ptr.p_double[nz+(n-nz)/2];
33015 0 : ae_assert(ae_fp_greater(scalex,(double)(0)), "LogisticFitX: internal error", _state);
33016 0 : v = 0.0;
33017 0 : for(i=0; i<=n-1; i++)
33018 : {
33019 0 : v = v+y->ptr.p_double[i];
33020 : }
33021 0 : v = v/n;
33022 0 : scaley = 0.0;
33023 0 : for(i=0; i<=n-1; i++)
33024 : {
33025 0 : scaley = scaley+ae_sqr(y->ptr.p_double[i]-v, _state);
33026 : }
33027 0 : scaley = ae_sqrt(scaley/n, _state);
33028 0 : if( ae_fp_eq(scaley,(double)(0)) )
33029 : {
33030 0 : scaley = 1.0;
33031 : }
33032 0 : ae_vector_set_length(&s, 5, _state);
33033 0 : s.ptr.p_double[0] = scaley;
33034 0 : s.ptr.p_double[1] = 0.1;
33035 0 : s.ptr.p_double[2] = scalex;
33036 0 : s.ptr.p_double[3] = scaley;
33037 0 : s.ptr.p_double[4] = 0.1;
33038 0 : ae_vector_set_length(&p0, 5, _state);
33039 0 : p0.ptr.p_double[0] = (double)(0);
33040 0 : p0.ptr.p_double[1] = (double)(0);
33041 0 : p0.ptr.p_double[2] = (double)(0);
33042 0 : p0.ptr.p_double[3] = (double)(0);
33043 0 : p0.ptr.p_double[4] = (double)(0);
33044 0 : ae_vector_set_length(&bndl, 5, _state);
33045 0 : ae_vector_set_length(&bndu, 5, _state);
33046 0 : ae_vector_set_length(&bndl1, 5, _state);
33047 0 : ae_vector_set_length(&bndu1, 5, _state);
33048 0 : ae_vector_set_length(&bndl2, 5, _state);
33049 0 : ae_vector_set_length(&bndu2, 5, _state);
33050 0 : minlmcreatevj(5, n+5, &p0, &state, _state);
33051 0 : minlmsetscale(&state, &s, _state);
33052 0 : minlmsetcond(&state, epsx, maxits, _state);
33053 0 : minlmsetxrep(&state, ae_true, _state);
33054 0 : ae_vector_set_length(&p1, 5, _state);
33055 0 : ae_vector_set_length(&p2, 5, _state);
33056 :
33057 : /*
33058 : * Is it 4PL problem?
33059 : */
33060 0 : if( is4pl )
33061 : {
33062 :
33063 : /*
33064 : * Run outer iterations
33065 : */
33066 0 : *a = (double)(0);
33067 0 : *b = (double)(1);
33068 0 : *c = (double)(1);
33069 0 : *d = (double)(1);
33070 0 : *g = (double)(1);
33071 0 : fbest = ae_maxrealnumber;
33072 0 : for(outerit=0; outerit<=rscnt-1; outerit++)
33073 : {
33074 :
33075 : /*
33076 : * Prepare initial point; use B>0
33077 : */
33078 0 : if( ae_isfinite(cnstrleft, _state) )
33079 : {
33080 0 : p1.ptr.p_double[0] = cnstrleft;
33081 : }
33082 : else
33083 : {
33084 0 : p1.ptr.p_double[0] = y->ptr.p_double[0]+0.15*scaley*(hqrnduniformr(&rs, _state)-0.5);
33085 : }
33086 0 : p1.ptr.p_double[1] = 0.5+hqrnduniformr(&rs, _state);
33087 0 : p1.ptr.p_double[2] = x->ptr.p_double[nz+hqrnduniformi(&rs, n-nz, _state)];
33088 0 : if( ae_isfinite(cnstrright, _state) )
33089 : {
33090 0 : p1.ptr.p_double[3] = cnstrright;
33091 : }
33092 : else
33093 : {
33094 0 : p1.ptr.p_double[3] = y->ptr.p_double[n-1]+0.25*scaley*(hqrnduniformr(&rs, _state)-0.5);
33095 : }
33096 0 : p1.ptr.p_double[4] = 1.0;
33097 :
33098 : /*
33099 : * Run optimization with tight constraints and increased regularization
33100 : */
33101 0 : if( ae_isfinite(cnstrleft, _state) )
33102 : {
33103 0 : bndl.ptr.p_double[0] = cnstrleft;
33104 0 : bndu.ptr.p_double[0] = cnstrleft;
33105 : }
33106 : else
33107 : {
33108 0 : bndl.ptr.p_double[0] = _state->v_neginf;
33109 0 : bndu.ptr.p_double[0] = _state->v_posinf;
33110 : }
33111 0 : bndl.ptr.p_double[1] = 0.5;
33112 0 : bndu.ptr.p_double[1] = 2.0;
33113 0 : bndl.ptr.p_double[2] = 0.5*scalex;
33114 0 : bndu.ptr.p_double[2] = 2.0*scalex;
33115 0 : if( ae_isfinite(cnstrright, _state) )
33116 : {
33117 0 : bndl.ptr.p_double[3] = cnstrright;
33118 0 : bndu.ptr.p_double[3] = cnstrright;
33119 : }
33120 : else
33121 : {
33122 0 : bndl.ptr.p_double[3] = _state->v_neginf;
33123 0 : bndu.ptr.p_double[3] = _state->v_posinf;
33124 : }
33125 0 : bndl.ptr.p_double[4] = 1.0;
33126 0 : bndu.ptr.p_double[4] = 1.0;
33127 0 : minlmsetbc(&state, &bndl, &bndu, _state);
33128 0 : lsfit_logisticfitinternal(x, y, n, is4pl, 100*lambdav, &state, &replm, &p1, &flast, _state);
33129 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33130 :
33131 : /*
33132 : * Relax constraints, run optimization one more time
33133 : */
33134 0 : bndl.ptr.p_double[1] = 0.1;
33135 0 : bndu.ptr.p_double[1] = 10.0;
33136 0 : bndl.ptr.p_double[2] = ae_machineepsilon*scalex;
33137 0 : bndu.ptr.p_double[2] = scalex/ae_machineepsilon;
33138 0 : minlmsetbc(&state, &bndl, &bndu, _state);
33139 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state);
33140 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33141 :
33142 : /*
33143 : * Relax constraints more, run optimization one more time
33144 : */
33145 0 : bndl.ptr.p_double[1] = 0.01;
33146 0 : bndu.ptr.p_double[1] = 100.0;
33147 0 : minlmsetbc(&state, &bndl, &bndu, _state);
33148 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state);
33149 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33150 :
33151 : /*
33152 : * Relax constraints ever more, run optimization one more time
33153 : */
33154 0 : bndl.ptr.p_double[1] = 0.001;
33155 0 : bndu.ptr.p_double[1] = 1000.0;
33156 0 : minlmsetbc(&state, &bndl, &bndu, _state);
33157 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state);
33158 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33159 :
33160 : /*
33161 : * Compare results with best value found so far.
33162 : */
33163 0 : if( ae_fp_less(flast,fbest) )
33164 : {
33165 0 : *a = p1.ptr.p_double[0];
33166 0 : *b = p1.ptr.p_double[1];
33167 0 : *c = p1.ptr.p_double[2];
33168 0 : *d = p1.ptr.p_double[3];
33169 0 : *g = p1.ptr.p_double[4];
33170 0 : fbest = flast;
33171 : }
33172 : }
33173 0 : lsfit_logisticfit45errors(x, y, n, *a, *b, *c, *d, *g, rep, _state);
33174 0 : ae_frame_leave(_state);
33175 0 : return;
33176 : }
33177 :
33178 : /*
33179 : * Well.... we have 5PL fit, and we have to test two separate branches:
33180 : * B>0 and B<0, because of asymmetry in the curve. First, we run optimization
33181 : * with tight constraints two times, in order to determine better sign for B.
33182 : *
33183 : * Run outer iterations
33184 : */
33185 0 : *a = (double)(0);
33186 0 : *b = (double)(1);
33187 0 : *c = (double)(1);
33188 0 : *d = (double)(1);
33189 0 : *g = (double)(1);
33190 0 : fbest = ae_maxrealnumber;
33191 0 : for(outerit=0; outerit<=rscnt-1; outerit++)
33192 : {
33193 :
33194 : /*
33195 : * First, we try positive B.
33196 : */
33197 0 : p1.ptr.p_double[0] = y->ptr.p_double[0]+0.15*scaley*(hqrnduniformr(&rs, _state)-0.5);
33198 0 : p1.ptr.p_double[1] = 0.5+hqrnduniformr(&rs, _state);
33199 0 : p1.ptr.p_double[2] = x->ptr.p_double[nz+hqrnduniformi(&rs, n-nz, _state)];
33200 0 : p1.ptr.p_double[3] = y->ptr.p_double[n-1]+0.25*scaley*(hqrnduniformr(&rs, _state)-0.5);
33201 0 : p1.ptr.p_double[4] = 1.0;
33202 0 : bndl1.ptr.p_double[0] = _state->v_neginf;
33203 0 : bndu1.ptr.p_double[0] = _state->v_posinf;
33204 0 : bndl1.ptr.p_double[1] = 0.5;
33205 0 : bndu1.ptr.p_double[1] = 2.0;
33206 0 : bndl1.ptr.p_double[2] = 0.5*scalex;
33207 0 : bndu1.ptr.p_double[2] = 2.0*scalex;
33208 0 : bndl1.ptr.p_double[3] = _state->v_neginf;
33209 0 : bndu1.ptr.p_double[3] = _state->v_posinf;
33210 0 : bndl1.ptr.p_double[4] = 0.5;
33211 0 : bndu1.ptr.p_double[4] = 2.0;
33212 0 : if( ae_isfinite(cnstrleft, _state) )
33213 : {
33214 0 : p1.ptr.p_double[0] = cnstrleft;
33215 0 : bndl1.ptr.p_double[0] = cnstrleft;
33216 0 : bndu1.ptr.p_double[0] = cnstrleft;
33217 : }
33218 0 : if( ae_isfinite(cnstrright, _state) )
33219 : {
33220 0 : p1.ptr.p_double[3] = cnstrright;
33221 0 : bndl1.ptr.p_double[3] = cnstrright;
33222 0 : bndu1.ptr.p_double[3] = cnstrright;
33223 : }
33224 0 : minlmsetbc(&state, &bndl1, &bndu1, _state);
33225 0 : lsfit_logisticfitinternal(x, y, n, is4pl, 100*lambdav, &state, &replm, &p1, &fposb, _state);
33226 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33227 :
33228 : /*
33229 : * Second attempt - with negative B (constraints are still tight).
33230 : */
33231 0 : p2.ptr.p_double[0] = y->ptr.p_double[n-1]+0.15*scaley*(hqrnduniformr(&rs, _state)-0.5);
33232 0 : p2.ptr.p_double[1] = -(0.5+hqrnduniformr(&rs, _state));
33233 0 : p2.ptr.p_double[2] = x->ptr.p_double[nz+hqrnduniformi(&rs, n-nz, _state)];
33234 0 : p2.ptr.p_double[3] = y->ptr.p_double[0]+0.25*scaley*(hqrnduniformr(&rs, _state)-0.5);
33235 0 : p2.ptr.p_double[4] = 1.0;
33236 0 : bndl2.ptr.p_double[0] = _state->v_neginf;
33237 0 : bndu2.ptr.p_double[0] = _state->v_posinf;
33238 0 : bndl2.ptr.p_double[1] = -2.0;
33239 0 : bndu2.ptr.p_double[1] = -0.5;
33240 0 : bndl2.ptr.p_double[2] = 0.5*scalex;
33241 0 : bndu2.ptr.p_double[2] = 2.0*scalex;
33242 0 : bndl2.ptr.p_double[3] = _state->v_neginf;
33243 0 : bndu2.ptr.p_double[3] = _state->v_posinf;
33244 0 : bndl2.ptr.p_double[4] = 0.5;
33245 0 : bndu2.ptr.p_double[4] = 2.0;
33246 0 : if( ae_isfinite(cnstrleft, _state) )
33247 : {
33248 0 : p2.ptr.p_double[3] = cnstrleft;
33249 0 : bndl2.ptr.p_double[3] = cnstrleft;
33250 0 : bndu2.ptr.p_double[3] = cnstrleft;
33251 : }
33252 0 : if( ae_isfinite(cnstrright, _state) )
33253 : {
33254 0 : p2.ptr.p_double[0] = cnstrright;
33255 0 : bndl2.ptr.p_double[0] = cnstrright;
33256 0 : bndu2.ptr.p_double[0] = cnstrright;
33257 : }
33258 0 : minlmsetbc(&state, &bndl2, &bndu2, _state);
33259 0 : lsfit_logisticfitinternal(x, y, n, is4pl, 100*lambdav, &state, &replm, &p2, &fnegb, _state);
33260 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33261 :
33262 : /*
33263 : * Select best version of B sign
33264 : */
33265 0 : if( ae_fp_less(fposb,fnegb) )
33266 : {
33267 :
33268 : /*
33269 : * Prepare relaxed constraints assuming that B is positive
33270 : */
33271 0 : bndl1.ptr.p_double[1] = 0.1;
33272 0 : bndu1.ptr.p_double[1] = 10.0;
33273 0 : bndl1.ptr.p_double[2] = ae_machineepsilon*scalex;
33274 0 : bndu1.ptr.p_double[2] = scalex/ae_machineepsilon;
33275 0 : bndl1.ptr.p_double[4] = 0.1;
33276 0 : bndu1.ptr.p_double[4] = 10.0;
33277 0 : minlmsetbc(&state, &bndl1, &bndu1, _state);
33278 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state);
33279 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33280 :
33281 : /*
33282 : * Prepare stronger relaxation of constraints
33283 : */
33284 0 : bndl1.ptr.p_double[1] = 0.01;
33285 0 : bndu1.ptr.p_double[1] = 100.0;
33286 0 : minlmsetbc(&state, &bndl1, &bndu1, _state);
33287 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state);
33288 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33289 :
33290 : /*
33291 : * Prepare stronger relaxation of constraints
33292 : */
33293 0 : bndl1.ptr.p_double[1] = 0.001;
33294 0 : bndu1.ptr.p_double[1] = 1000.0;
33295 0 : minlmsetbc(&state, &bndl1, &bndu1, _state);
33296 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p1, &flast, _state);
33297 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33298 :
33299 : /*
33300 : * Compare results with best value found so far.
33301 : */
33302 0 : if( ae_fp_less(flast,fbest) )
33303 : {
33304 0 : *a = p1.ptr.p_double[0];
33305 0 : *b = p1.ptr.p_double[1];
33306 0 : *c = p1.ptr.p_double[2];
33307 0 : *d = p1.ptr.p_double[3];
33308 0 : *g = p1.ptr.p_double[4];
33309 0 : fbest = flast;
33310 : }
33311 : }
33312 : else
33313 : {
33314 :
33315 : /*
33316 : * Prepare relaxed constraints assuming that B is negative
33317 : */
33318 0 : bndl2.ptr.p_double[1] = -10.0;
33319 0 : bndu2.ptr.p_double[1] = -0.1;
33320 0 : bndl2.ptr.p_double[2] = ae_machineepsilon*scalex;
33321 0 : bndu2.ptr.p_double[2] = scalex/ae_machineepsilon;
33322 0 : bndl2.ptr.p_double[4] = 0.1;
33323 0 : bndu2.ptr.p_double[4] = 10.0;
33324 0 : minlmsetbc(&state, &bndl2, &bndu2, _state);
33325 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p2, &flast, _state);
33326 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33327 :
33328 : /*
33329 : * Prepare stronger relaxation
33330 : */
33331 0 : bndl2.ptr.p_double[1] = -100.0;
33332 0 : bndu2.ptr.p_double[1] = -0.01;
33333 0 : minlmsetbc(&state, &bndl2, &bndu2, _state);
33334 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p2, &flast, _state);
33335 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33336 :
33337 : /*
33338 : * Prepare stronger relaxation
33339 : */
33340 0 : bndl2.ptr.p_double[1] = -1000.0;
33341 0 : bndu2.ptr.p_double[1] = -0.001;
33342 0 : minlmsetbc(&state, &bndl2, &bndu2, _state);
33343 0 : lsfit_logisticfitinternal(x, y, n, is4pl, lambdav, &state, &replm, &p2, &flast, _state);
33344 0 : rep->iterationscount = rep->iterationscount+replm.iterationscount;
33345 :
33346 : /*
33347 : * Compare results with best value found so far.
33348 : */
33349 0 : if( ae_fp_less(flast,fbest) )
33350 : {
33351 0 : *a = p2.ptr.p_double[0];
33352 0 : *b = p2.ptr.p_double[1];
33353 0 : *c = p2.ptr.p_double[2];
33354 0 : *d = p2.ptr.p_double[3];
33355 0 : *g = p2.ptr.p_double[4];
33356 0 : fbest = flast;
33357 : }
33358 : }
33359 : }
33360 0 : lsfit_logisticfit45errors(x, y, n, *a, *b, *c, *d, *g, rep, _state);
33361 0 : ae_frame_leave(_state);
33362 : }
33363 :
33364 :
33365 : /*************************************************************************
33366 : Weghted rational least squares fitting using Floater-Hormann rational
33367 : functions with optimal D chosen from [0,9], with constraints and
33368 : individual weights.
33369 :
33370 : Equidistant grid with M node on [min(x),max(x)] is used to build basis
33371 : functions. Different values of D are tried, optimal D (least WEIGHTED root
33372 : mean square error) is chosen. Task is linear, so linear least squares
33373 : solver is used. Complexity of this computational scheme is O(N*M^2)
33374 : (mostly dominated by the least squares solver).
33375 :
33376 : SEE ALSO
33377 : * BarycentricFitFloaterHormann(), "lightweight" fitting without invididual
33378 : weights and constraints.
33379 :
33380 : ! COMMERCIAL EDITION OF ALGLIB:
33381 : !
33382 : ! Commercial Edition of ALGLIB includes following important improvements
33383 : ! of this function:
33384 : ! * high-performance native backend with same C# interface (C# version)
33385 : ! * multithreading support (C++ and C# versions)
33386 : ! * hardware vendor (Intel) implementations of linear algebra primitives
33387 : ! (C++ and C# versions, x86/x64 platform)
33388 : !
33389 : ! We recommend you to read 'Working with commercial version' section of
33390 : ! ALGLIB Reference Manual in order to find out how to use performance-
33391 : ! related features provided by commercial edition of ALGLIB.
33392 :
33393 : INPUT PARAMETERS:
33394 : X - points, array[0..N-1].
33395 : Y - function values, array[0..N-1].
33396 : W - weights, array[0..N-1]
33397 : Each summand in square sum of approximation deviations from
33398 : given values is multiplied by the square of corresponding
33399 : weight. Fill it by 1's if you don't want to solve weighted
33400 : task.
33401 : N - number of points, N>0.
33402 : XC - points where function values/derivatives are constrained,
33403 : array[0..K-1].
33404 : YC - values of constraints, array[0..K-1]
33405 : DC - array[0..K-1], types of constraints:
33406 : * DC[i]=0 means that S(XC[i])=YC[i]
33407 : * DC[i]=1 means that S'(XC[i])=YC[i]
33408 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
33409 : K - number of constraints, 0<=K<M.
33410 : K=0 means no constraints (XC/YC/DC are not used in such cases)
33411 : M - number of basis functions ( = number_of_nodes), M>=2.
33412 :
33413 : OUTPUT PARAMETERS:
33414 : Info- same format as in LSFitLinearWC() subroutine.
33415 : * Info>0 task is solved
33416 : * Info<=0 an error occured:
33417 : -4 means inconvergence of internal SVD
33418 : -3 means inconsistent constraints
33419 : -1 means another errors in parameters passed
33420 : (N<=0, for example)
33421 : B - barycentric interpolant.
33422 : Rep - report, same format as in LSFitLinearWC() subroutine.
33423 : Following fields are set:
33424 : * DBest best value of the D parameter
33425 : * RMSError rms error on the (X,Y).
33426 : * AvgError average error on the (X,Y).
33427 : * AvgRelError average relative error on the non-zero Y
33428 : * MaxError maximum error
33429 : NON-WEIGHTED ERRORS ARE CALCULATED
33430 :
33431 : IMPORTANT:
33432 : this subroutine doesn't calculate task's condition number for K<>0.
33433 :
33434 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
33435 :
33436 : Setting constraints can lead to undesired results, like ill-conditioned
33437 : behavior, or inconsistency being detected. From the other side, it allows
33438 : us to improve quality of the fit. Here we summarize our experience with
33439 : constrained barycentric interpolants:
33440 : * excessive constraints can be inconsistent. Floater-Hormann basis
33441 : functions aren't as flexible as splines (although they are very smooth).
33442 : * the more evenly constraints are spread across [min(x),max(x)], the more
33443 : chances that they will be consistent
33444 : * the greater is M (given fixed constraints), the more chances that
33445 : constraints will be consistent
33446 : * in the general case, consistency of constraints IS NOT GUARANTEED.
33447 : * in the several special cases, however, we CAN guarantee consistency.
33448 : * one of this cases is constraints on the function VALUES at the interval
33449 : boundaries. Note that consustency of the constraints on the function
33450 : DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines
33451 : which are more flexible).
33452 : * another special case is ONE constraint on the function value (OR, but
33453 : not AND, derivative) anywhere in the interval
33454 :
33455 : Our final recommendation is to use constraints WHEN AND ONLY WHEN you
33456 : can't solve your task without them. Anything beyond special cases given
33457 : above is not guaranteed and may result in inconsistency.
33458 :
33459 : -- ALGLIB PROJECT --
33460 : Copyright 18.08.2009 by Bochkanov Sergey
33461 : *************************************************************************/
33462 0 : void barycentricfitfloaterhormannwc(/* Real */ ae_vector* x,
33463 : /* Real */ ae_vector* y,
33464 : /* Real */ ae_vector* w,
33465 : ae_int_t n,
33466 : /* Real */ ae_vector* xc,
33467 : /* Real */ ae_vector* yc,
33468 : /* Integer */ ae_vector* dc,
33469 : ae_int_t k,
33470 : ae_int_t m,
33471 : ae_int_t* info,
33472 : barycentricinterpolant* b,
33473 : barycentricfitreport* rep,
33474 : ae_state *_state)
33475 : {
33476 : ae_frame _frame_block;
33477 : ae_int_t d;
33478 : ae_int_t i;
33479 : double wrmscur;
33480 : double wrmsbest;
33481 : barycentricinterpolant locb;
33482 : barycentricfitreport locrep;
33483 : ae_int_t locinfo;
33484 :
33485 0 : ae_frame_make(_state, &_frame_block);
33486 0 : memset(&locb, 0, sizeof(locb));
33487 0 : memset(&locrep, 0, sizeof(locrep));
33488 0 : *info = 0;
33489 0 : _barycentricinterpolant_clear(b);
33490 0 : _barycentricfitreport_clear(rep);
33491 0 : _barycentricinterpolant_init(&locb, _state, ae_true);
33492 0 : _barycentricfitreport_init(&locrep, _state, ae_true);
33493 :
33494 0 : ae_assert(n>0, "BarycentricFitFloaterHormannWC: N<=0!", _state);
33495 0 : ae_assert(m>0, "BarycentricFitFloaterHormannWC: M<=0!", _state);
33496 0 : ae_assert(k>=0, "BarycentricFitFloaterHormannWC: K<0!", _state);
33497 0 : ae_assert(k<m, "BarycentricFitFloaterHormannWC: K>=M!", _state);
33498 0 : ae_assert(x->cnt>=n, "BarycentricFitFloaterHormannWC: Length(X)<N!", _state);
33499 0 : ae_assert(y->cnt>=n, "BarycentricFitFloaterHormannWC: Length(Y)<N!", _state);
33500 0 : ae_assert(w->cnt>=n, "BarycentricFitFloaterHormannWC: Length(W)<N!", _state);
33501 0 : ae_assert(xc->cnt>=k, "BarycentricFitFloaterHormannWC: Length(XC)<K!", _state);
33502 0 : ae_assert(yc->cnt>=k, "BarycentricFitFloaterHormannWC: Length(YC)<K!", _state);
33503 0 : ae_assert(dc->cnt>=k, "BarycentricFitFloaterHormannWC: Length(DC)<K!", _state);
33504 0 : ae_assert(isfinitevector(x, n, _state), "BarycentricFitFloaterHormannWC: X contains infinite or NaN values!", _state);
33505 0 : ae_assert(isfinitevector(y, n, _state), "BarycentricFitFloaterHormannWC: Y contains infinite or NaN values!", _state);
33506 0 : ae_assert(isfinitevector(w, n, _state), "BarycentricFitFloaterHormannWC: X contains infinite or NaN values!", _state);
33507 0 : ae_assert(isfinitevector(xc, k, _state), "BarycentricFitFloaterHormannWC: XC contains infinite or NaN values!", _state);
33508 0 : ae_assert(isfinitevector(yc, k, _state), "BarycentricFitFloaterHormannWC: YC contains infinite or NaN values!", _state);
33509 0 : for(i=0; i<=k-1; i++)
33510 : {
33511 0 : ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "BarycentricFitFloaterHormannWC: one of DC[] is not 0 or 1!", _state);
33512 : }
33513 :
33514 : /*
33515 : * Find optimal D
33516 : *
33517 : * Info is -3 by default (degenerate constraints).
33518 : * If LocInfo will always be equal to -3, Info will remain equal to -3.
33519 : * If at least once LocInfo will be -4, Info will be -4.
33520 : */
33521 0 : wrmsbest = ae_maxrealnumber;
33522 0 : rep->dbest = -1;
33523 0 : *info = -3;
33524 0 : for(d=0; d<=ae_minint(9, n-1, _state); d++)
33525 : {
33526 0 : lsfit_barycentricfitwcfixedd(x, y, w, n, xc, yc, dc, k, m, d, &locinfo, &locb, &locrep, _state);
33527 0 : ae_assert((locinfo==-4||locinfo==-3)||locinfo>0, "BarycentricFitFloaterHormannWC: unexpected result from BarycentricFitWCFixedD!", _state);
33528 0 : if( locinfo>0 )
33529 : {
33530 :
33531 : /*
33532 : * Calculate weghted RMS
33533 : */
33534 0 : wrmscur = (double)(0);
33535 0 : for(i=0; i<=n-1; i++)
33536 : {
33537 0 : wrmscur = wrmscur+ae_sqr(w->ptr.p_double[i]*(y->ptr.p_double[i]-barycentriccalc(&locb, x->ptr.p_double[i], _state)), _state);
33538 : }
33539 0 : wrmscur = ae_sqrt(wrmscur/n, _state);
33540 0 : if( ae_fp_less(wrmscur,wrmsbest)||rep->dbest<0 )
33541 : {
33542 0 : barycentriccopy(&locb, b, _state);
33543 0 : rep->dbest = d;
33544 0 : *info = 1;
33545 0 : rep->rmserror = locrep.rmserror;
33546 0 : rep->avgerror = locrep.avgerror;
33547 0 : rep->avgrelerror = locrep.avgrelerror;
33548 0 : rep->maxerror = locrep.maxerror;
33549 0 : rep->taskrcond = locrep.taskrcond;
33550 0 : wrmsbest = wrmscur;
33551 : }
33552 : }
33553 : else
33554 : {
33555 0 : if( locinfo!=-3&&*info<0 )
33556 : {
33557 0 : *info = locinfo;
33558 : }
33559 : }
33560 : }
33561 0 : ae_frame_leave(_state);
33562 0 : }
33563 :
33564 :
33565 : /*************************************************************************
33566 : Rational least squares fitting using Floater-Hormann rational functions
33567 : with optimal D chosen from [0,9].
33568 :
33569 : Equidistant grid with M node on [min(x),max(x)] is used to build basis
33570 : functions. Different values of D are tried, optimal D (least root mean
33571 : square error) is chosen. Task is linear, so linear least squares solver
33572 : is used. Complexity of this computational scheme is O(N*M^2) (mostly
33573 : dominated by the least squares solver).
33574 :
33575 : ! COMMERCIAL EDITION OF ALGLIB:
33576 : !
33577 : ! Commercial Edition of ALGLIB includes following important improvements
33578 : ! of this function:
33579 : ! * high-performance native backend with same C# interface (C# version)
33580 : ! * multithreading support (C++ and C# versions)
33581 : ! * hardware vendor (Intel) implementations of linear algebra primitives
33582 : ! (C++ and C# versions, x86/x64 platform)
33583 : !
33584 : ! We recommend you to read 'Working with commercial version' section of
33585 : ! ALGLIB Reference Manual in order to find out how to use performance-
33586 : ! related features provided by commercial edition of ALGLIB.
33587 :
33588 : INPUT PARAMETERS:
33589 : X - points, array[0..N-1].
33590 : Y - function values, array[0..N-1].
33591 : N - number of points, N>0.
33592 : M - number of basis functions ( = number_of_nodes), M>=2.
33593 :
33594 : OUTPUT PARAMETERS:
33595 : Info- same format as in LSFitLinearWC() subroutine.
33596 : * Info>0 task is solved
33597 : * Info<=0 an error occured:
33598 : -4 means inconvergence of internal SVD
33599 : -3 means inconsistent constraints
33600 : B - barycentric interpolant.
33601 : Rep - report, same format as in LSFitLinearWC() subroutine.
33602 : Following fields are set:
33603 : * DBest best value of the D parameter
33604 : * RMSError rms error on the (X,Y).
33605 : * AvgError average error on the (X,Y).
33606 : * AvgRelError average relative error on the non-zero Y
33607 : * MaxError maximum error
33608 : NON-WEIGHTED ERRORS ARE CALCULATED
33609 :
33610 : -- ALGLIB PROJECT --
33611 : Copyright 18.08.2009 by Bochkanov Sergey
33612 : *************************************************************************/
33613 0 : void barycentricfitfloaterhormann(/* Real */ ae_vector* x,
33614 : /* Real */ ae_vector* y,
33615 : ae_int_t n,
33616 : ae_int_t m,
33617 : ae_int_t* info,
33618 : barycentricinterpolant* b,
33619 : barycentricfitreport* rep,
33620 : ae_state *_state)
33621 : {
33622 : ae_frame _frame_block;
33623 : ae_vector w;
33624 : ae_vector xc;
33625 : ae_vector yc;
33626 : ae_vector dc;
33627 : ae_int_t i;
33628 :
33629 0 : ae_frame_make(_state, &_frame_block);
33630 0 : memset(&w, 0, sizeof(w));
33631 0 : memset(&xc, 0, sizeof(xc));
33632 0 : memset(&yc, 0, sizeof(yc));
33633 0 : memset(&dc, 0, sizeof(dc));
33634 0 : *info = 0;
33635 0 : _barycentricinterpolant_clear(b);
33636 0 : _barycentricfitreport_clear(rep);
33637 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
33638 0 : ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
33639 0 : ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
33640 0 : ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
33641 :
33642 0 : ae_assert(n>0, "BarycentricFitFloaterHormann: N<=0!", _state);
33643 0 : ae_assert(m>0, "BarycentricFitFloaterHormann: M<=0!", _state);
33644 0 : ae_assert(x->cnt>=n, "BarycentricFitFloaterHormann: Length(X)<N!", _state);
33645 0 : ae_assert(y->cnt>=n, "BarycentricFitFloaterHormann: Length(Y)<N!", _state);
33646 0 : ae_assert(isfinitevector(x, n, _state), "BarycentricFitFloaterHormann: X contains infinite or NaN values!", _state);
33647 0 : ae_assert(isfinitevector(y, n, _state), "BarycentricFitFloaterHormann: Y contains infinite or NaN values!", _state);
33648 0 : ae_vector_set_length(&w, n, _state);
33649 0 : for(i=0; i<=n-1; i++)
33650 : {
33651 0 : w.ptr.p_double[i] = (double)(1);
33652 : }
33653 0 : barycentricfitfloaterhormannwc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, b, rep, _state);
33654 0 : ae_frame_leave(_state);
33655 0 : }
33656 :
33657 :
33658 : /*************************************************************************
33659 : Weighted fitting by cubic spline, with constraints on function values or
33660 : derivatives.
33661 :
33662 : Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build
33663 : basis functions. Basis functions are cubic splines with continuous second
33664 : derivatives and non-fixed first derivatives at interval ends. Small
33665 : regularizing term is used when solving constrained tasks (to improve
33666 : stability).
33667 :
33668 : Task is linear, so linear least squares solver is used. Complexity of this
33669 : computational scheme is O(N*M^2), mostly dominated by least squares solver
33670 :
33671 : SEE ALSO
33672 : Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible,
33673 : less smooth)
33674 : Spline1DFitCubic() - "lightweight" fitting by cubic splines,
33675 : without invididual weights and constraints
33676 :
33677 : ! COMMERCIAL EDITION OF ALGLIB:
33678 : !
33679 : ! Commercial Edition of ALGLIB includes following important improvements
33680 : ! of this function:
33681 : ! * high-performance native backend with same C# interface (C# version)
33682 : ! * multithreading support (C++ and C# versions)
33683 : ! * hardware vendor (Intel) implementations of linear algebra primitives
33684 : ! (C++ and C# versions, x86/x64 platform)
33685 : !
33686 : ! We recommend you to read 'Working with commercial version' section of
33687 : ! ALGLIB Reference Manual in order to find out how to use performance-
33688 : ! related features provided by commercial edition of ALGLIB.
33689 :
33690 : INPUT PARAMETERS:
33691 : X - points, array[0..N-1].
33692 : Y - function values, array[0..N-1].
33693 : W - weights, array[0..N-1]
33694 : Each summand in square sum of approximation deviations from
33695 : given values is multiplied by the square of corresponding
33696 : weight. Fill it by 1's if you don't want to solve weighted
33697 : task.
33698 : N - number of points (optional):
33699 : * N>0
33700 : * if given, only first N elements of X/Y/W are processed
33701 : * if not given, automatically determined from X/Y/W sizes
33702 : XC - points where spline values/derivatives are constrained,
33703 : array[0..K-1].
33704 : YC - values of constraints, array[0..K-1]
33705 : DC - array[0..K-1], types of constraints:
33706 : * DC[i]=0 means that S(XC[i])=YC[i]
33707 : * DC[i]=1 means that S'(XC[i])=YC[i]
33708 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
33709 : K - number of constraints (optional):
33710 : * 0<=K<M.
33711 : * K=0 means no constraints (XC/YC/DC are not used)
33712 : * if given, only first K elements of XC/YC/DC are used
33713 : * if not given, automatically determined from XC/YC/DC
33714 : M - number of basis functions ( = number_of_nodes+2), M>=4.
33715 :
33716 : OUTPUT PARAMETERS:
33717 : Info- same format as in LSFitLinearWC() subroutine.
33718 : * Info>0 task is solved
33719 : * Info<=0 an error occured:
33720 : -4 means inconvergence of internal SVD
33721 : -3 means inconsistent constraints
33722 : S - spline interpolant.
33723 : Rep - report, same format as in LSFitLinearWC() subroutine.
33724 : Following fields are set:
33725 : * RMSError rms error on the (X,Y).
33726 : * AvgError average error on the (X,Y).
33727 : * AvgRelError average relative error on the non-zero Y
33728 : * MaxError maximum error
33729 : NON-WEIGHTED ERRORS ARE CALCULATED
33730 :
33731 : IMPORTANT:
33732 : this subroitine doesn't calculate task's condition number for K<>0.
33733 :
33734 :
33735 : ORDER OF POINTS
33736 :
33737 : Subroutine automatically sorts points, so caller may pass unsorted array.
33738 :
33739 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
33740 :
33741 : Setting constraints can lead to undesired results, like ill-conditioned
33742 : behavior, or inconsistency being detected. From the other side, it allows
33743 : us to improve quality of the fit. Here we summarize our experience with
33744 : constrained regression splines:
33745 : * excessive constraints can be inconsistent. Splines are piecewise cubic
33746 : functions, and it is easy to create an example, where large number of
33747 : constraints concentrated in small area will result in inconsistency.
33748 : Just because spline is not flexible enough to satisfy all of them. And
33749 : same constraints spread across the [min(x),max(x)] will be perfectly
33750 : consistent.
33751 : * the more evenly constraints are spread across [min(x),max(x)], the more
33752 : chances that they will be consistent
33753 : * the greater is M (given fixed constraints), the more chances that
33754 : constraints will be consistent
33755 : * in the general case, consistency of constraints IS NOT GUARANTEED.
33756 : * in the several special cases, however, we CAN guarantee consistency.
33757 : * one of this cases is constraints on the function values AND/OR its
33758 : derivatives at the interval boundaries.
33759 : * another special case is ONE constraint on the function value (OR, but
33760 : not AND, derivative) anywhere in the interval
33761 :
33762 : Our final recommendation is to use constraints WHEN AND ONLY WHEN you
33763 : can't solve your task without them. Anything beyond special cases given
33764 : above is not guaranteed and may result in inconsistency.
33765 :
33766 :
33767 : -- ALGLIB PROJECT --
33768 : Copyright 18.08.2009 by Bochkanov Sergey
33769 : *************************************************************************/
33770 0 : void spline1dfitcubicwc(/* Real */ ae_vector* x,
33771 : /* Real */ ae_vector* y,
33772 : /* Real */ ae_vector* w,
33773 : ae_int_t n,
33774 : /* Real */ ae_vector* xc,
33775 : /* Real */ ae_vector* yc,
33776 : /* Integer */ ae_vector* dc,
33777 : ae_int_t k,
33778 : ae_int_t m,
33779 : ae_int_t* info,
33780 : spline1dinterpolant* s,
33781 : spline1dfitreport* rep,
33782 : ae_state *_state)
33783 : {
33784 : ae_int_t i;
33785 :
33786 0 : *info = 0;
33787 0 : _spline1dinterpolant_clear(s);
33788 0 : _spline1dfitreport_clear(rep);
33789 :
33790 0 : ae_assert(n>=1, "Spline1DFitCubicWC: N<1!", _state);
33791 0 : ae_assert(m>=4, "Spline1DFitCubicWC: M<4!", _state);
33792 0 : ae_assert(k>=0, "Spline1DFitCubicWC: K<0!", _state);
33793 0 : ae_assert(k<m, "Spline1DFitCubicWC: K>=M!", _state);
33794 0 : ae_assert(x->cnt>=n, "Spline1DFitCubicWC: Length(X)<N!", _state);
33795 0 : ae_assert(y->cnt>=n, "Spline1DFitCubicWC: Length(Y)<N!", _state);
33796 0 : ae_assert(w->cnt>=n, "Spline1DFitCubicWC: Length(W)<N!", _state);
33797 0 : ae_assert(xc->cnt>=k, "Spline1DFitCubicWC: Length(XC)<K!", _state);
33798 0 : ae_assert(yc->cnt>=k, "Spline1DFitCubicWC: Length(YC)<K!", _state);
33799 0 : ae_assert(dc->cnt>=k, "Spline1DFitCubicWC: Length(DC)<K!", _state);
33800 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DFitCubicWC: X contains infinite or NAN values!", _state);
33801 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DFitCubicWC: Y contains infinite or NAN values!", _state);
33802 0 : ae_assert(isfinitevector(w, n, _state), "Spline1DFitCubicWC: Y contains infinite or NAN values!", _state);
33803 0 : ae_assert(isfinitevector(xc, k, _state), "Spline1DFitCubicWC: X contains infinite or NAN values!", _state);
33804 0 : ae_assert(isfinitevector(yc, k, _state), "Spline1DFitCubicWC: Y contains infinite or NAN values!", _state);
33805 0 : for(i=0; i<=k-1; i++)
33806 : {
33807 0 : ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "Spline1DFitCubicWC: DC[i] is neither 0 or 1!", _state);
33808 : }
33809 0 : lsfit_spline1dfitinternal(0, x, y, w, n, xc, yc, dc, k, m, info, s, rep, _state);
33810 0 : }
33811 :
33812 :
33813 : /*************************************************************************
33814 : Weighted fitting by Hermite spline, with constraints on function values
33815 : or first derivatives.
33816 :
33817 : Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
33818 : basis functions. Basis functions are Hermite splines. Small regularizing
33819 : term is used when solving constrained tasks (to improve stability).
33820 :
33821 : Task is linear, so linear least squares solver is used. Complexity of this
33822 : computational scheme is O(N*M^2), mostly dominated by least squares solver
33823 :
33824 : SEE ALSO
33825 : Spline1DFitCubicWC() - fitting by Cubic splines (less flexible,
33826 : more smooth)
33827 : Spline1DFitHermite() - "lightweight" Hermite fitting, without
33828 : invididual weights and constraints
33829 :
33830 : ! COMMERCIAL EDITION OF ALGLIB:
33831 : !
33832 : ! Commercial Edition of ALGLIB includes following important improvements
33833 : ! of this function:
33834 : ! * high-performance native backend with same C# interface (C# version)
33835 : ! * multithreading support (C++ and C# versions)
33836 : ! * hardware vendor (Intel) implementations of linear algebra primitives
33837 : ! (C++ and C# versions, x86/x64 platform)
33838 : !
33839 : ! We recommend you to read 'Working with commercial version' section of
33840 : ! ALGLIB Reference Manual in order to find out how to use performance-
33841 : ! related features provided by commercial edition of ALGLIB.
33842 :
33843 : INPUT PARAMETERS:
33844 : X - points, array[0..N-1].
33845 : Y - function values, array[0..N-1].
33846 : W - weights, array[0..N-1]
33847 : Each summand in square sum of approximation deviations from
33848 : given values is multiplied by the square of corresponding
33849 : weight. Fill it by 1's if you don't want to solve weighted
33850 : task.
33851 : N - number of points (optional):
33852 : * N>0
33853 : * if given, only first N elements of X/Y/W are processed
33854 : * if not given, automatically determined from X/Y/W sizes
33855 : XC - points where spline values/derivatives are constrained,
33856 : array[0..K-1].
33857 : YC - values of constraints, array[0..K-1]
33858 : DC - array[0..K-1], types of constraints:
33859 : * DC[i]=0 means that S(XC[i])=YC[i]
33860 : * DC[i]=1 means that S'(XC[i])=YC[i]
33861 : SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
33862 : K - number of constraints (optional):
33863 : * 0<=K<M.
33864 : * K=0 means no constraints (XC/YC/DC are not used)
33865 : * if given, only first K elements of XC/YC/DC are used
33866 : * if not given, automatically determined from XC/YC/DC
33867 : M - number of basis functions (= 2 * number of nodes),
33868 : M>=4,
33869 : M IS EVEN!
33870 :
33871 : OUTPUT PARAMETERS:
33872 : Info- same format as in LSFitLinearW() subroutine:
33873 : * Info>0 task is solved
33874 : * Info<=0 an error occured:
33875 : -4 means inconvergence of internal SVD
33876 : -3 means inconsistent constraints
33877 : -2 means odd M was passed (which is not supported)
33878 : -1 means another errors in parameters passed
33879 : (N<=0, for example)
33880 : S - spline interpolant.
33881 : Rep - report, same format as in LSFitLinearW() subroutine.
33882 : Following fields are set:
33883 : * RMSError rms error on the (X,Y).
33884 : * AvgError average error on the (X,Y).
33885 : * AvgRelError average relative error on the non-zero Y
33886 : * MaxError maximum error
33887 : NON-WEIGHTED ERRORS ARE CALCULATED
33888 :
33889 : IMPORTANT:
33890 : this subroitine doesn't calculate task's condition number for K<>0.
33891 :
33892 : IMPORTANT:
33893 : this subroitine supports only even M's
33894 :
33895 :
33896 : ORDER OF POINTS
33897 :
33898 : Subroutine automatically sorts points, so caller may pass unsorted array.
33899 :
33900 : SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
33901 :
33902 : Setting constraints can lead to undesired results, like ill-conditioned
33903 : behavior, or inconsistency being detected. From the other side, it allows
33904 : us to improve quality of the fit. Here we summarize our experience with
33905 : constrained regression splines:
33906 : * excessive constraints can be inconsistent. Splines are piecewise cubic
33907 : functions, and it is easy to create an example, where large number of
33908 : constraints concentrated in small area will result in inconsistency.
33909 : Just because spline is not flexible enough to satisfy all of them. And
33910 : same constraints spread across the [min(x),max(x)] will be perfectly
33911 : consistent.
33912 : * the more evenly constraints are spread across [min(x),max(x)], the more
33913 : chances that they will be consistent
33914 : * the greater is M (given fixed constraints), the more chances that
33915 : constraints will be consistent
33916 : * in the general case, consistency of constraints is NOT GUARANTEED.
33917 : * in the several special cases, however, we can guarantee consistency.
33918 : * one of this cases is M>=4 and constraints on the function value
33919 : (AND/OR its derivative) at the interval boundaries.
33920 : * another special case is M>=4 and ONE constraint on the function value
33921 : (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]
33922 :
33923 : Our final recommendation is to use constraints WHEN AND ONLY when you
33924 : can't solve your task without them. Anything beyond special cases given
33925 : above is not guaranteed and may result in inconsistency.
33926 :
33927 : -- ALGLIB PROJECT --
33928 : Copyright 18.08.2009 by Bochkanov Sergey
33929 : *************************************************************************/
33930 0 : void spline1dfithermitewc(/* Real */ ae_vector* x,
33931 : /* Real */ ae_vector* y,
33932 : /* Real */ ae_vector* w,
33933 : ae_int_t n,
33934 : /* Real */ ae_vector* xc,
33935 : /* Real */ ae_vector* yc,
33936 : /* Integer */ ae_vector* dc,
33937 : ae_int_t k,
33938 : ae_int_t m,
33939 : ae_int_t* info,
33940 : spline1dinterpolant* s,
33941 : spline1dfitreport* rep,
33942 : ae_state *_state)
33943 : {
33944 : ae_int_t i;
33945 :
33946 0 : *info = 0;
33947 0 : _spline1dinterpolant_clear(s);
33948 0 : _spline1dfitreport_clear(rep);
33949 :
33950 0 : ae_assert(n>=1, "Spline1DFitHermiteWC: N<1!", _state);
33951 0 : ae_assert(m>=4, "Spline1DFitHermiteWC: M<4!", _state);
33952 0 : ae_assert(m%2==0, "Spline1DFitHermiteWC: M is odd!", _state);
33953 0 : ae_assert(k>=0, "Spline1DFitHermiteWC: K<0!", _state);
33954 0 : ae_assert(k<m, "Spline1DFitHermiteWC: K>=M!", _state);
33955 0 : ae_assert(x->cnt>=n, "Spline1DFitHermiteWC: Length(X)<N!", _state);
33956 0 : ae_assert(y->cnt>=n, "Spline1DFitHermiteWC: Length(Y)<N!", _state);
33957 0 : ae_assert(w->cnt>=n, "Spline1DFitHermiteWC: Length(W)<N!", _state);
33958 0 : ae_assert(xc->cnt>=k, "Spline1DFitHermiteWC: Length(XC)<K!", _state);
33959 0 : ae_assert(yc->cnt>=k, "Spline1DFitHermiteWC: Length(YC)<K!", _state);
33960 0 : ae_assert(dc->cnt>=k, "Spline1DFitHermiteWC: Length(DC)<K!", _state);
33961 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DFitHermiteWC: X contains infinite or NAN values!", _state);
33962 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DFitHermiteWC: Y contains infinite or NAN values!", _state);
33963 0 : ae_assert(isfinitevector(w, n, _state), "Spline1DFitHermiteWC: Y contains infinite or NAN values!", _state);
33964 0 : ae_assert(isfinitevector(xc, k, _state), "Spline1DFitHermiteWC: X contains infinite or NAN values!", _state);
33965 0 : ae_assert(isfinitevector(yc, k, _state), "Spline1DFitHermiteWC: Y contains infinite or NAN values!", _state);
33966 0 : for(i=0; i<=k-1; i++)
33967 : {
33968 0 : ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "Spline1DFitHermiteWC: DC[i] is neither 0 or 1!", _state);
33969 : }
33970 0 : lsfit_spline1dfitinternal(1, x, y, w, n, xc, yc, dc, k, m, info, s, rep, _state);
33971 0 : }
33972 :
33973 :
33974 : /*************************************************************************
33975 : Least squares fitting by cubic spline.
33976 :
33977 : This subroutine is "lightweight" alternative for more complex and feature-
33978 : rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information
33979 : about subroutine parameters (we don't duplicate it here because of length)
33980 :
33981 : ! COMMERCIAL EDITION OF ALGLIB:
33982 : !
33983 : ! Commercial Edition of ALGLIB includes following important improvements
33984 : ! of this function:
33985 : ! * high-performance native backend with same C# interface (C# version)
33986 : ! * multithreading support (C++ and C# versions)
33987 : ! * hardware vendor (Intel) implementations of linear algebra primitives
33988 : ! (C++ and C# versions, x86/x64 platform)
33989 : !
33990 : ! We recommend you to read 'Working with commercial version' section of
33991 : ! ALGLIB Reference Manual in order to find out how to use performance-
33992 : ! related features provided by commercial edition of ALGLIB.
33993 :
33994 : -- ALGLIB PROJECT --
33995 : Copyright 18.08.2009 by Bochkanov Sergey
33996 : *************************************************************************/
33997 0 : void spline1dfitcubic(/* Real */ ae_vector* x,
33998 : /* Real */ ae_vector* y,
33999 : ae_int_t n,
34000 : ae_int_t m,
34001 : ae_int_t* info,
34002 : spline1dinterpolant* s,
34003 : spline1dfitreport* rep,
34004 : ae_state *_state)
34005 : {
34006 : ae_frame _frame_block;
34007 : ae_int_t i;
34008 : ae_vector w;
34009 : ae_vector xc;
34010 : ae_vector yc;
34011 : ae_vector dc;
34012 :
34013 0 : ae_frame_make(_state, &_frame_block);
34014 0 : memset(&w, 0, sizeof(w));
34015 0 : memset(&xc, 0, sizeof(xc));
34016 0 : memset(&yc, 0, sizeof(yc));
34017 0 : memset(&dc, 0, sizeof(dc));
34018 0 : *info = 0;
34019 0 : _spline1dinterpolant_clear(s);
34020 0 : _spline1dfitreport_clear(rep);
34021 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
34022 0 : ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
34023 0 : ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
34024 0 : ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
34025 :
34026 0 : ae_assert(n>=1, "Spline1DFitCubic: N<1!", _state);
34027 0 : ae_assert(m>=4, "Spline1DFitCubic: M<4!", _state);
34028 0 : ae_assert(x->cnt>=n, "Spline1DFitCubic: Length(X)<N!", _state);
34029 0 : ae_assert(y->cnt>=n, "Spline1DFitCubic: Length(Y)<N!", _state);
34030 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DFitCubic: X contains infinite or NAN values!", _state);
34031 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DFitCubic: Y contains infinite or NAN values!", _state);
34032 0 : ae_vector_set_length(&w, n, _state);
34033 0 : for(i=0; i<=n-1; i++)
34034 : {
34035 0 : w.ptr.p_double[i] = (double)(1);
34036 : }
34037 0 : spline1dfitcubicwc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, s, rep, _state);
34038 0 : ae_frame_leave(_state);
34039 0 : }
34040 :
34041 :
34042 : /*************************************************************************
34043 : Least squares fitting by Hermite spline.
34044 :
34045 : This subroutine is "lightweight" alternative for more complex and feature-
34046 : rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for
34047 : more information about subroutine parameters (we don't duplicate it here
34048 : because of length).
34049 :
34050 : ! COMMERCIAL EDITION OF ALGLIB:
34051 : !
34052 : ! Commercial Edition of ALGLIB includes following important improvements
34053 : ! of this function:
34054 : ! * high-performance native backend with same C# interface (C# version)
34055 : ! * multithreading support (C++ and C# versions)
34056 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34057 : ! (C++ and C# versions, x86/x64 platform)
34058 : !
34059 : ! We recommend you to read 'Working with commercial version' section of
34060 : ! ALGLIB Reference Manual in order to find out how to use performance-
34061 : ! related features provided by commercial edition of ALGLIB.
34062 :
34063 : -- ALGLIB PROJECT --
34064 : Copyright 18.08.2009 by Bochkanov Sergey
34065 : *************************************************************************/
34066 0 : void spline1dfithermite(/* Real */ ae_vector* x,
34067 : /* Real */ ae_vector* y,
34068 : ae_int_t n,
34069 : ae_int_t m,
34070 : ae_int_t* info,
34071 : spline1dinterpolant* s,
34072 : spline1dfitreport* rep,
34073 : ae_state *_state)
34074 : {
34075 : ae_frame _frame_block;
34076 : ae_int_t i;
34077 : ae_vector w;
34078 : ae_vector xc;
34079 : ae_vector yc;
34080 : ae_vector dc;
34081 :
34082 0 : ae_frame_make(_state, &_frame_block);
34083 0 : memset(&w, 0, sizeof(w));
34084 0 : memset(&xc, 0, sizeof(xc));
34085 0 : memset(&yc, 0, sizeof(yc));
34086 0 : memset(&dc, 0, sizeof(dc));
34087 0 : *info = 0;
34088 0 : _spline1dinterpolant_clear(s);
34089 0 : _spline1dfitreport_clear(rep);
34090 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
34091 0 : ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
34092 0 : ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
34093 0 : ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
34094 :
34095 0 : ae_assert(n>=1, "Spline1DFitHermite: N<1!", _state);
34096 0 : ae_assert(m>=4, "Spline1DFitHermite: M<4!", _state);
34097 0 : ae_assert(m%2==0, "Spline1DFitHermite: M is odd!", _state);
34098 0 : ae_assert(x->cnt>=n, "Spline1DFitHermite: Length(X)<N!", _state);
34099 0 : ae_assert(y->cnt>=n, "Spline1DFitHermite: Length(Y)<N!", _state);
34100 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DFitHermite: X contains infinite or NAN values!", _state);
34101 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DFitHermite: Y contains infinite or NAN values!", _state);
34102 0 : ae_vector_set_length(&w, n, _state);
34103 0 : for(i=0; i<=n-1; i++)
34104 : {
34105 0 : w.ptr.p_double[i] = (double)(1);
34106 : }
34107 0 : spline1dfithermitewc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, s, rep, _state);
34108 0 : ae_frame_leave(_state);
34109 0 : }
34110 :
34111 :
34112 : /*************************************************************************
34113 : Weighted linear least squares fitting.
34114 :
34115 : QR decomposition is used to reduce task to MxM, then triangular solver or
34116 : SVD-based solver is used depending on condition number of the system. It
34117 : allows to maximize speed and retain decent accuracy.
34118 :
34119 : IMPORTANT: if you want to perform polynomial fitting, it may be more
34120 : convenient to use PolynomialFit() function. This function gives
34121 : best results on polynomial problems and solves numerical
34122 : stability issues which arise when you fit high-degree
34123 : polynomials to your data.
34124 :
34125 : ! COMMERCIAL EDITION OF ALGLIB:
34126 : !
34127 : ! Commercial Edition of ALGLIB includes following important improvements
34128 : ! of this function:
34129 : ! * high-performance native backend with same C# interface (C# version)
34130 : ! * multithreading support (C++ and C# versions)
34131 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34132 : ! (C++ and C# versions, x86/x64 platform)
34133 : !
34134 : ! We recommend you to read 'Working with commercial version' section of
34135 : ! ALGLIB Reference Manual in order to find out how to use performance-
34136 : ! related features provided by commercial edition of ALGLIB.
34137 :
34138 : INPUT PARAMETERS:
34139 : Y - array[0..N-1] Function values in N points.
34140 : W - array[0..N-1] Weights corresponding to function values.
34141 : Each summand in square sum of approximation deviations
34142 : from given values is multiplied by the square of
34143 : corresponding weight.
34144 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
34145 : FMatrix[I, J] - value of J-th basis function in I-th point.
34146 : N - number of points used. N>=1.
34147 : M - number of basis functions, M>=1.
34148 :
34149 : OUTPUT PARAMETERS:
34150 : Info - error code:
34151 : * -4 internal SVD decomposition subroutine failed (very
34152 : rare and for degenerate systems only)
34153 : * -1 incorrect N/M were specified
34154 : * 1 task is solved
34155 : C - decomposition coefficients, array[0..M-1]
34156 : Rep - fitting report. Following fields are set:
34157 : * Rep.TaskRCond reciprocal of condition number
34158 : * R2 non-adjusted coefficient of determination
34159 : (non-weighted)
34160 : * RMSError rms error on the (X,Y).
34161 : * AvgError average error on the (X,Y).
34162 : * AvgRelError average relative error on the non-zero Y
34163 : * MaxError maximum error
34164 : NON-WEIGHTED ERRORS ARE CALCULATED
34165 :
34166 : ERRORS IN PARAMETERS
34167 :
34168 : This solver also calculates different kinds of errors in parameters and
34169 : fills corresponding fields of report:
34170 : * Rep.CovPar covariance matrix for parameters, array[K,K].
34171 : * Rep.ErrPar errors in parameters, array[K],
34172 : errpar = sqrt(diag(CovPar))
34173 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
34174 : best-fit curve from "ideal" best-fit curve built with
34175 : infinite number of samples, array[N].
34176 : errcurve = sqrt(diag(F*CovPar*F')),
34177 : where F is functions matrix.
34178 : * Rep.Noise vector of per-point estimates of noise, array[N]
34179 :
34180 : NOTE: noise in the data is estimated as follows:
34181 : * for fitting without user-supplied weights all points are
34182 : assumed to have same level of noise, which is estimated from
34183 : the data
34184 : * for fitting with user-supplied weights we assume that noise
34185 : level in I-th point is inversely proportional to Ith weight.
34186 : Coefficient of proportionality is estimated from the data.
34187 :
34188 : NOTE: we apply small amount of regularization when we invert squared
34189 : Jacobian and calculate covariance matrix. It guarantees that
34190 : algorithm won't divide by zero during inversion, but skews
34191 : error estimates a bit (fractional error is about 10^-9).
34192 :
34193 : However, we believe that this difference is insignificant for
34194 : all practical purposes except for the situation when you want
34195 : to compare ALGLIB results with "reference" implementation up
34196 : to the last significant digit.
34197 :
34198 : NOTE: covariance matrix is estimated using correction for degrees
34199 : of freedom (covariances are divided by N-M instead of dividing
34200 : by N).
34201 :
34202 : -- ALGLIB --
34203 : Copyright 17.08.2009 by Bochkanov Sergey
34204 : *************************************************************************/
34205 0 : void lsfitlinearw(/* Real */ ae_vector* y,
34206 : /* Real */ ae_vector* w,
34207 : /* Real */ ae_matrix* fmatrix,
34208 : ae_int_t n,
34209 : ae_int_t m,
34210 : ae_int_t* info,
34211 : /* Real */ ae_vector* c,
34212 : lsfitreport* rep,
34213 : ae_state *_state)
34214 : {
34215 :
34216 0 : *info = 0;
34217 0 : ae_vector_clear(c);
34218 0 : _lsfitreport_clear(rep);
34219 :
34220 0 : ae_assert(n>=1, "LSFitLinearW: N<1!", _state);
34221 0 : ae_assert(m>=1, "LSFitLinearW: M<1!", _state);
34222 0 : ae_assert(y->cnt>=n, "LSFitLinearW: length(Y)<N!", _state);
34223 0 : ae_assert(isfinitevector(y, n, _state), "LSFitLinearW: Y contains infinite or NaN values!", _state);
34224 0 : ae_assert(w->cnt>=n, "LSFitLinearW: length(W)<N!", _state);
34225 0 : ae_assert(isfinitevector(w, n, _state), "LSFitLinearW: W contains infinite or NaN values!", _state);
34226 0 : ae_assert(fmatrix->rows>=n, "LSFitLinearW: rows(FMatrix)<N!", _state);
34227 0 : ae_assert(fmatrix->cols>=m, "LSFitLinearW: cols(FMatrix)<M!", _state);
34228 0 : ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinearW: FMatrix contains infinite or NaN values!", _state);
34229 0 : lsfit_lsfitlinearinternal(y, w, fmatrix, n, m, info, c, rep, _state);
34230 0 : }
34231 :
34232 :
34233 : /*************************************************************************
34234 : Weighted constained linear least squares fitting.
34235 :
34236 : This is variation of LSFitLinearW(), which searchs for min|A*x=b| given
34237 : that K additional constaints C*x=bc are satisfied. It reduces original
34238 : task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW()
34239 : is called.
34240 :
34241 : IMPORTANT: if you want to perform polynomial fitting, it may be more
34242 : convenient to use PolynomialFit() function. This function gives
34243 : best results on polynomial problems and solves numerical
34244 : stability issues which arise when you fit high-degree
34245 : polynomials to your data.
34246 :
34247 : ! COMMERCIAL EDITION OF ALGLIB:
34248 : !
34249 : ! Commercial Edition of ALGLIB includes following important improvements
34250 : ! of this function:
34251 : ! * high-performance native backend with same C# interface (C# version)
34252 : ! * multithreading support (C++ and C# versions)
34253 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34254 : ! (C++ and C# versions, x86/x64 platform)
34255 : !
34256 : ! We recommend you to read 'Working with commercial version' section of
34257 : ! ALGLIB Reference Manual in order to find out how to use performance-
34258 : ! related features provided by commercial edition of ALGLIB.
34259 :
34260 : INPUT PARAMETERS:
34261 : Y - array[0..N-1] Function values in N points.
34262 : W - array[0..N-1] Weights corresponding to function values.
34263 : Each summand in square sum of approximation deviations
34264 : from given values is multiplied by the square of
34265 : corresponding weight.
34266 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
34267 : FMatrix[I,J] - value of J-th basis function in I-th point.
34268 : CMatrix - a table of constaints, array[0..K-1,0..M].
34269 : I-th row of CMatrix corresponds to I-th linear constraint:
34270 : CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
34271 : N - number of points used. N>=1.
34272 : M - number of basis functions, M>=1.
34273 : K - number of constraints, 0 <= K < M
34274 : K=0 corresponds to absence of constraints.
34275 :
34276 : OUTPUT PARAMETERS:
34277 : Info - error code:
34278 : * -4 internal SVD decomposition subroutine failed (very
34279 : rare and for degenerate systems only)
34280 : * -3 either too many constraints (M or more),
34281 : degenerate constraints (some constraints are
34282 : repetead twice) or inconsistent constraints were
34283 : specified.
34284 : * 1 task is solved
34285 : C - decomposition coefficients, array[0..M-1]
34286 : Rep - fitting report. Following fields are set:
34287 : * R2 non-adjusted coefficient of determination
34288 : (non-weighted)
34289 : * RMSError rms error on the (X,Y).
34290 : * AvgError average error on the (X,Y).
34291 : * AvgRelError average relative error on the non-zero Y
34292 : * MaxError maximum error
34293 : NON-WEIGHTED ERRORS ARE CALCULATED
34294 :
34295 : IMPORTANT:
34296 : this subroitine doesn't calculate task's condition number for K<>0.
34297 :
34298 : ERRORS IN PARAMETERS
34299 :
34300 : This solver also calculates different kinds of errors in parameters and
34301 : fills corresponding fields of report:
34302 : * Rep.CovPar covariance matrix for parameters, array[K,K].
34303 : * Rep.ErrPar errors in parameters, array[K],
34304 : errpar = sqrt(diag(CovPar))
34305 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
34306 : best-fit curve from "ideal" best-fit curve built with
34307 : infinite number of samples, array[N].
34308 : errcurve = sqrt(diag(F*CovPar*F')),
34309 : where F is functions matrix.
34310 : * Rep.Noise vector of per-point estimates of noise, array[N]
34311 :
34312 : IMPORTANT: errors in parameters are calculated without taking into
34313 : account boundary/linear constraints! Presence of constraints
34314 : changes distribution of errors, but there is no easy way to
34315 : account for constraints when you calculate covariance matrix.
34316 :
34317 : NOTE: noise in the data is estimated as follows:
34318 : * for fitting without user-supplied weights all points are
34319 : assumed to have same level of noise, which is estimated from
34320 : the data
34321 : * for fitting with user-supplied weights we assume that noise
34322 : level in I-th point is inversely proportional to Ith weight.
34323 : Coefficient of proportionality is estimated from the data.
34324 :
34325 : NOTE: we apply small amount of regularization when we invert squared
34326 : Jacobian and calculate covariance matrix. It guarantees that
34327 : algorithm won't divide by zero during inversion, but skews
34328 : error estimates a bit (fractional error is about 10^-9).
34329 :
34330 : However, we believe that this difference is insignificant for
34331 : all practical purposes except for the situation when you want
34332 : to compare ALGLIB results with "reference" implementation up
34333 : to the last significant digit.
34334 :
34335 : NOTE: covariance matrix is estimated using correction for degrees
34336 : of freedom (covariances are divided by N-M instead of dividing
34337 : by N).
34338 :
34339 : -- ALGLIB --
34340 : Copyright 07.09.2009 by Bochkanov Sergey
34341 : *************************************************************************/
34342 0 : void lsfitlinearwc(/* Real */ ae_vector* y,
34343 : /* Real */ ae_vector* w,
34344 : /* Real */ ae_matrix* fmatrix,
34345 : /* Real */ ae_matrix* cmatrix,
34346 : ae_int_t n,
34347 : ae_int_t m,
34348 : ae_int_t k,
34349 : ae_int_t* info,
34350 : /* Real */ ae_vector* c,
34351 : lsfitreport* rep,
34352 : ae_state *_state)
34353 : {
34354 : ae_frame _frame_block;
34355 : ae_vector _y;
34356 : ae_matrix _cmatrix;
34357 : ae_int_t i;
34358 : ae_int_t j;
34359 : ae_vector tau;
34360 : ae_matrix q;
34361 : ae_matrix f2;
34362 : ae_vector tmp;
34363 : ae_vector c0;
34364 : double v;
34365 :
34366 0 : ae_frame_make(_state, &_frame_block);
34367 0 : memset(&_y, 0, sizeof(_y));
34368 0 : memset(&_cmatrix, 0, sizeof(_cmatrix));
34369 0 : memset(&tau, 0, sizeof(tau));
34370 0 : memset(&q, 0, sizeof(q));
34371 0 : memset(&f2, 0, sizeof(f2));
34372 0 : memset(&tmp, 0, sizeof(tmp));
34373 0 : memset(&c0, 0, sizeof(c0));
34374 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
34375 0 : y = &_y;
34376 0 : ae_matrix_init_copy(&_cmatrix, cmatrix, _state, ae_true);
34377 0 : cmatrix = &_cmatrix;
34378 0 : *info = 0;
34379 0 : ae_vector_clear(c);
34380 0 : _lsfitreport_clear(rep);
34381 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
34382 0 : ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
34383 0 : ae_matrix_init(&f2, 0, 0, DT_REAL, _state, ae_true);
34384 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
34385 0 : ae_vector_init(&c0, 0, DT_REAL, _state, ae_true);
34386 :
34387 0 : ae_assert(n>=1, "LSFitLinearWC: N<1!", _state);
34388 0 : ae_assert(m>=1, "LSFitLinearWC: M<1!", _state);
34389 0 : ae_assert(k>=0, "LSFitLinearWC: K<0!", _state);
34390 0 : ae_assert(y->cnt>=n, "LSFitLinearWC: length(Y)<N!", _state);
34391 0 : ae_assert(isfinitevector(y, n, _state), "LSFitLinearWC: Y contains infinite or NaN values!", _state);
34392 0 : ae_assert(w->cnt>=n, "LSFitLinearWC: length(W)<N!", _state);
34393 0 : ae_assert(isfinitevector(w, n, _state), "LSFitLinearWC: W contains infinite or NaN values!", _state);
34394 0 : ae_assert(fmatrix->rows>=n, "LSFitLinearWC: rows(FMatrix)<N!", _state);
34395 0 : ae_assert(fmatrix->cols>=m, "LSFitLinearWC: cols(FMatrix)<M!", _state);
34396 0 : ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinearWC: FMatrix contains infinite or NaN values!", _state);
34397 0 : ae_assert(cmatrix->rows>=k, "LSFitLinearWC: rows(CMatrix)<K!", _state);
34398 0 : ae_assert(cmatrix->cols>=m+1||k==0, "LSFitLinearWC: cols(CMatrix)<M+1!", _state);
34399 0 : ae_assert(apservisfinitematrix(cmatrix, k, m+1, _state), "LSFitLinearWC: CMatrix contains infinite or NaN values!", _state);
34400 0 : if( k>=m )
34401 : {
34402 0 : *info = -3;
34403 0 : ae_frame_leave(_state);
34404 0 : return;
34405 : }
34406 :
34407 : /*
34408 : * Solve
34409 : */
34410 0 : if( k==0 )
34411 : {
34412 :
34413 : /*
34414 : * no constraints
34415 : */
34416 0 : lsfit_lsfitlinearinternal(y, w, fmatrix, n, m, info, c, rep, _state);
34417 : }
34418 : else
34419 : {
34420 :
34421 : /*
34422 : * First, find general form solution of constraints system:
34423 : * * factorize C = L*Q
34424 : * * unpack Q
34425 : * * fill upper part of C with zeros (for RCond)
34426 : *
34427 : * We got C=C0+Q2'*y where Q2 is lower M-K rows of Q.
34428 : */
34429 0 : rmatrixlq(cmatrix, k, m, &tau, _state);
34430 0 : rmatrixlqunpackq(cmatrix, k, m, &tau, m, &q, _state);
34431 0 : for(i=0; i<=k-1; i++)
34432 : {
34433 0 : for(j=i+1; j<=m-1; j++)
34434 : {
34435 0 : cmatrix->ptr.pp_double[i][j] = 0.0;
34436 : }
34437 : }
34438 0 : if( ae_fp_less(rmatrixlurcondinf(cmatrix, k, _state),1000*ae_machineepsilon) )
34439 : {
34440 0 : *info = -3;
34441 0 : ae_frame_leave(_state);
34442 0 : return;
34443 : }
34444 0 : ae_vector_set_length(&tmp, k, _state);
34445 0 : for(i=0; i<=k-1; i++)
34446 : {
34447 0 : if( i>0 )
34448 : {
34449 0 : v = ae_v_dotproduct(&cmatrix->ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,i-1));
34450 : }
34451 : else
34452 : {
34453 0 : v = (double)(0);
34454 : }
34455 0 : tmp.ptr.p_double[i] = (cmatrix->ptr.pp_double[i][m]-v)/cmatrix->ptr.pp_double[i][i];
34456 : }
34457 0 : ae_vector_set_length(&c0, m, _state);
34458 0 : for(i=0; i<=m-1; i++)
34459 : {
34460 0 : c0.ptr.p_double[i] = (double)(0);
34461 : }
34462 0 : for(i=0; i<=k-1; i++)
34463 : {
34464 0 : v = tmp.ptr.p_double[i];
34465 0 : ae_v_addd(&c0.ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
34466 : }
34467 :
34468 : /*
34469 : * Second, prepare modified matrix F2 = F*Q2' and solve modified task
34470 : */
34471 0 : ae_vector_set_length(&tmp, ae_maxint(n, m, _state)+1, _state);
34472 0 : ae_matrix_set_length(&f2, n, m-k, _state);
34473 0 : matrixvectormultiply(fmatrix, 0, n-1, 0, m-1, ae_false, &c0, 0, m-1, -1.0, y, 0, n-1, 1.0, _state);
34474 0 : rmatrixgemm(n, m-k, m, 1.0, fmatrix, 0, 0, 0, &q, k, 0, 1, 0.0, &f2, 0, 0, _state);
34475 0 : lsfit_lsfitlinearinternal(y, w, &f2, n, m-k, info, &tmp, rep, _state);
34476 0 : rep->taskrcond = (double)(-1);
34477 0 : if( *info<=0 )
34478 : {
34479 0 : ae_frame_leave(_state);
34480 0 : return;
34481 : }
34482 :
34483 : /*
34484 : * then, convert back to original answer: C = C0 + Q2'*Y0
34485 : */
34486 0 : ae_vector_set_length(c, m, _state);
34487 0 : ae_v_move(&c->ptr.p_double[0], 1, &c0.ptr.p_double[0], 1, ae_v_len(0,m-1));
34488 0 : matrixvectormultiply(&q, k, m-1, 0, m-1, ae_true, &tmp, 0, m-k-1, 1.0, c, 0, m-1, 1.0, _state);
34489 : }
34490 0 : ae_frame_leave(_state);
34491 : }
34492 :
34493 :
34494 : /*************************************************************************
34495 : Linear least squares fitting.
34496 :
34497 : QR decomposition is used to reduce task to MxM, then triangular solver or
34498 : SVD-based solver is used depending on condition number of the system. It
34499 : allows to maximize speed and retain decent accuracy.
34500 :
34501 : IMPORTANT: if you want to perform polynomial fitting, it may be more
34502 : convenient to use PolynomialFit() function. This function gives
34503 : best results on polynomial problems and solves numerical
34504 : stability issues which arise when you fit high-degree
34505 : polynomials to your data.
34506 :
34507 : ! COMMERCIAL EDITION OF ALGLIB:
34508 : !
34509 : ! Commercial Edition of ALGLIB includes following important improvements
34510 : ! of this function:
34511 : ! * high-performance native backend with same C# interface (C# version)
34512 : ! * multithreading support (C++ and C# versions)
34513 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34514 : ! (C++ and C# versions, x86/x64 platform)
34515 : !
34516 : ! We recommend you to read 'Working with commercial version' section of
34517 : ! ALGLIB Reference Manual in order to find out how to use performance-
34518 : ! related features provided by commercial edition of ALGLIB.
34519 :
34520 : INPUT PARAMETERS:
34521 : Y - array[0..N-1] Function values in N points.
34522 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
34523 : FMatrix[I, J] - value of J-th basis function in I-th point.
34524 : N - number of points used. N>=1.
34525 : M - number of basis functions, M>=1.
34526 :
34527 : OUTPUT PARAMETERS:
34528 : Info - error code:
34529 : * -4 internal SVD decomposition subroutine failed (very
34530 : rare and for degenerate systems only)
34531 : * 1 task is solved
34532 : C - decomposition coefficients, array[0..M-1]
34533 : Rep - fitting report. Following fields are set:
34534 : * Rep.TaskRCond reciprocal of condition number
34535 : * R2 non-adjusted coefficient of determination
34536 : (non-weighted)
34537 : * RMSError rms error on the (X,Y).
34538 : * AvgError average error on the (X,Y).
34539 : * AvgRelError average relative error on the non-zero Y
34540 : * MaxError maximum error
34541 : NON-WEIGHTED ERRORS ARE CALCULATED
34542 :
34543 : ERRORS IN PARAMETERS
34544 :
34545 : This solver also calculates different kinds of errors in parameters and
34546 : fills corresponding fields of report:
34547 : * Rep.CovPar covariance matrix for parameters, array[K,K].
34548 : * Rep.ErrPar errors in parameters, array[K],
34549 : errpar = sqrt(diag(CovPar))
34550 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
34551 : best-fit curve from "ideal" best-fit curve built with
34552 : infinite number of samples, array[N].
34553 : errcurve = sqrt(diag(F*CovPar*F')),
34554 : where F is functions matrix.
34555 : * Rep.Noise vector of per-point estimates of noise, array[N]
34556 :
34557 : NOTE: noise in the data is estimated as follows:
34558 : * for fitting without user-supplied weights all points are
34559 : assumed to have same level of noise, which is estimated from
34560 : the data
34561 : * for fitting with user-supplied weights we assume that noise
34562 : level in I-th point is inversely proportional to Ith weight.
34563 : Coefficient of proportionality is estimated from the data.
34564 :
34565 : NOTE: we apply small amount of regularization when we invert squared
34566 : Jacobian and calculate covariance matrix. It guarantees that
34567 : algorithm won't divide by zero during inversion, but skews
34568 : error estimates a bit (fractional error is about 10^-9).
34569 :
34570 : However, we believe that this difference is insignificant for
34571 : all practical purposes except for the situation when you want
34572 : to compare ALGLIB results with "reference" implementation up
34573 : to the last significant digit.
34574 :
34575 : NOTE: covariance matrix is estimated using correction for degrees
34576 : of freedom (covariances are divided by N-M instead of dividing
34577 : by N).
34578 :
34579 : -- ALGLIB --
34580 : Copyright 17.08.2009 by Bochkanov Sergey
34581 : *************************************************************************/
34582 0 : void lsfitlinear(/* Real */ ae_vector* y,
34583 : /* Real */ ae_matrix* fmatrix,
34584 : ae_int_t n,
34585 : ae_int_t m,
34586 : ae_int_t* info,
34587 : /* Real */ ae_vector* c,
34588 : lsfitreport* rep,
34589 : ae_state *_state)
34590 : {
34591 : ae_frame _frame_block;
34592 : ae_vector w;
34593 : ae_int_t i;
34594 :
34595 0 : ae_frame_make(_state, &_frame_block);
34596 0 : memset(&w, 0, sizeof(w));
34597 0 : *info = 0;
34598 0 : ae_vector_clear(c);
34599 0 : _lsfitreport_clear(rep);
34600 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
34601 :
34602 0 : ae_assert(n>=1, "LSFitLinear: N<1!", _state);
34603 0 : ae_assert(m>=1, "LSFitLinear: M<1!", _state);
34604 0 : ae_assert(y->cnt>=n, "LSFitLinear: length(Y)<N!", _state);
34605 0 : ae_assert(isfinitevector(y, n, _state), "LSFitLinear: Y contains infinite or NaN values!", _state);
34606 0 : ae_assert(fmatrix->rows>=n, "LSFitLinear: rows(FMatrix)<N!", _state);
34607 0 : ae_assert(fmatrix->cols>=m, "LSFitLinear: cols(FMatrix)<M!", _state);
34608 0 : ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinear: FMatrix contains infinite or NaN values!", _state);
34609 0 : ae_vector_set_length(&w, n, _state);
34610 0 : for(i=0; i<=n-1; i++)
34611 : {
34612 0 : w.ptr.p_double[i] = (double)(1);
34613 : }
34614 0 : lsfit_lsfitlinearinternal(y, &w, fmatrix, n, m, info, c, rep, _state);
34615 0 : ae_frame_leave(_state);
34616 0 : }
34617 :
34618 :
34619 : /*************************************************************************
34620 : Constained linear least squares fitting.
34621 :
34622 : This is variation of LSFitLinear(), which searchs for min|A*x=b| given
34623 : that K additional constaints C*x=bc are satisfied. It reduces original
34624 : task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear()
34625 : is called.
34626 :
34627 : IMPORTANT: if you want to perform polynomial fitting, it may be more
34628 : convenient to use PolynomialFit() function. This function gives
34629 : best results on polynomial problems and solves numerical
34630 : stability issues which arise when you fit high-degree
34631 : polynomials to your data.
34632 :
34633 : ! COMMERCIAL EDITION OF ALGLIB:
34634 : !
34635 : ! Commercial Edition of ALGLIB includes following important improvements
34636 : ! of this function:
34637 : ! * high-performance native backend with same C# interface (C# version)
34638 : ! * multithreading support (C++ and C# versions)
34639 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34640 : ! (C++ and C# versions, x86/x64 platform)
34641 : !
34642 : ! We recommend you to read 'Working with commercial version' section of
34643 : ! ALGLIB Reference Manual in order to find out how to use performance-
34644 : ! related features provided by commercial edition of ALGLIB.
34645 :
34646 : INPUT PARAMETERS:
34647 : Y - array[0..N-1] Function values in N points.
34648 : FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
34649 : FMatrix[I,J] - value of J-th basis function in I-th point.
34650 : CMatrix - a table of constaints, array[0..K-1,0..M].
34651 : I-th row of CMatrix corresponds to I-th linear constraint:
34652 : CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
34653 : N - number of points used. N>=1.
34654 : M - number of basis functions, M>=1.
34655 : K - number of constraints, 0 <= K < M
34656 : K=0 corresponds to absence of constraints.
34657 :
34658 : OUTPUT PARAMETERS:
34659 : Info - error code:
34660 : * -4 internal SVD decomposition subroutine failed (very
34661 : rare and for degenerate systems only)
34662 : * -3 either too many constraints (M or more),
34663 : degenerate constraints (some constraints are
34664 : repetead twice) or inconsistent constraints were
34665 : specified.
34666 : * 1 task is solved
34667 : C - decomposition coefficients, array[0..M-1]
34668 : Rep - fitting report. Following fields are set:
34669 : * R2 non-adjusted coefficient of determination
34670 : (non-weighted)
34671 : * RMSError rms error on the (X,Y).
34672 : * AvgError average error on the (X,Y).
34673 : * AvgRelError average relative error on the non-zero Y
34674 : * MaxError maximum error
34675 : NON-WEIGHTED ERRORS ARE CALCULATED
34676 :
34677 : IMPORTANT:
34678 : this subroitine doesn't calculate task's condition number for K<>0.
34679 :
34680 : ERRORS IN PARAMETERS
34681 :
34682 : This solver also calculates different kinds of errors in parameters and
34683 : fills corresponding fields of report:
34684 : * Rep.CovPar covariance matrix for parameters, array[K,K].
34685 : * Rep.ErrPar errors in parameters, array[K],
34686 : errpar = sqrt(diag(CovPar))
34687 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
34688 : best-fit curve from "ideal" best-fit curve built with
34689 : infinite number of samples, array[N].
34690 : errcurve = sqrt(diag(F*CovPar*F')),
34691 : where F is functions matrix.
34692 : * Rep.Noise vector of per-point estimates of noise, array[N]
34693 :
34694 : IMPORTANT: errors in parameters are calculated without taking into
34695 : account boundary/linear constraints! Presence of constraints
34696 : changes distribution of errors, but there is no easy way to
34697 : account for constraints when you calculate covariance matrix.
34698 :
34699 : NOTE: noise in the data is estimated as follows:
34700 : * for fitting without user-supplied weights all points are
34701 : assumed to have same level of noise, which is estimated from
34702 : the data
34703 : * for fitting with user-supplied weights we assume that noise
34704 : level in I-th point is inversely proportional to Ith weight.
34705 : Coefficient of proportionality is estimated from the data.
34706 :
34707 : NOTE: we apply small amount of regularization when we invert squared
34708 : Jacobian and calculate covariance matrix. It guarantees that
34709 : algorithm won't divide by zero during inversion, but skews
34710 : error estimates a bit (fractional error is about 10^-9).
34711 :
34712 : However, we believe that this difference is insignificant for
34713 : all practical purposes except for the situation when you want
34714 : to compare ALGLIB results with "reference" implementation up
34715 : to the last significant digit.
34716 :
34717 : NOTE: covariance matrix is estimated using correction for degrees
34718 : of freedom (covariances are divided by N-M instead of dividing
34719 : by N).
34720 :
34721 : -- ALGLIB --
34722 : Copyright 07.09.2009 by Bochkanov Sergey
34723 : *************************************************************************/
34724 0 : void lsfitlinearc(/* Real */ ae_vector* y,
34725 : /* Real */ ae_matrix* fmatrix,
34726 : /* Real */ ae_matrix* cmatrix,
34727 : ae_int_t n,
34728 : ae_int_t m,
34729 : ae_int_t k,
34730 : ae_int_t* info,
34731 : /* Real */ ae_vector* c,
34732 : lsfitreport* rep,
34733 : ae_state *_state)
34734 : {
34735 : ae_frame _frame_block;
34736 : ae_vector _y;
34737 : ae_vector w;
34738 : ae_int_t i;
34739 :
34740 0 : ae_frame_make(_state, &_frame_block);
34741 0 : memset(&_y, 0, sizeof(_y));
34742 0 : memset(&w, 0, sizeof(w));
34743 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
34744 0 : y = &_y;
34745 0 : *info = 0;
34746 0 : ae_vector_clear(c);
34747 0 : _lsfitreport_clear(rep);
34748 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
34749 :
34750 0 : ae_assert(n>=1, "LSFitLinearC: N<1!", _state);
34751 0 : ae_assert(m>=1, "LSFitLinearC: M<1!", _state);
34752 0 : ae_assert(k>=0, "LSFitLinearC: K<0!", _state);
34753 0 : ae_assert(y->cnt>=n, "LSFitLinearC: length(Y)<N!", _state);
34754 0 : ae_assert(isfinitevector(y, n, _state), "LSFitLinearC: Y contains infinite or NaN values!", _state);
34755 0 : ae_assert(fmatrix->rows>=n, "LSFitLinearC: rows(FMatrix)<N!", _state);
34756 0 : ae_assert(fmatrix->cols>=m, "LSFitLinearC: cols(FMatrix)<M!", _state);
34757 0 : ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinearC: FMatrix contains infinite or NaN values!", _state);
34758 0 : ae_assert(cmatrix->rows>=k, "LSFitLinearC: rows(CMatrix)<K!", _state);
34759 0 : ae_assert(cmatrix->cols>=m+1||k==0, "LSFitLinearC: cols(CMatrix)<M+1!", _state);
34760 0 : ae_assert(apservisfinitematrix(cmatrix, k, m+1, _state), "LSFitLinearC: CMatrix contains infinite or NaN values!", _state);
34761 0 : ae_vector_set_length(&w, n, _state);
34762 0 : for(i=0; i<=n-1; i++)
34763 : {
34764 0 : w.ptr.p_double[i] = (double)(1);
34765 : }
34766 0 : lsfitlinearwc(y, &w, fmatrix, cmatrix, n, m, k, info, c, rep, _state);
34767 0 : ae_frame_leave(_state);
34768 0 : }
34769 :
34770 :
34771 : /*************************************************************************
34772 : Weighted nonlinear least squares fitting using function values only.
34773 :
34774 : Combination of numerical differentiation and secant updates is used to
34775 : obtain function Jacobian.
34776 :
34777 : Nonlinear task min(F(c)) is solved, where
34778 :
34779 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
34780 :
34781 : * N is a number of points,
34782 : * M is a dimension of a space points belong to,
34783 : * K is a dimension of a space of parameters being fitted,
34784 : * w is an N-dimensional vector of weight coefficients,
34785 : * x is a set of N points, each of them is an M-dimensional vector,
34786 : * c is a K-dimensional vector of parameters being fitted
34787 :
34788 : This subroutine uses only f(c,x[i]).
34789 :
34790 : INPUT PARAMETERS:
34791 : X - array[0..N-1,0..M-1], points (one row = one point)
34792 : Y - array[0..N-1], function values.
34793 : W - weights, array[0..N-1]
34794 : C - array[0..K-1], initial approximation to the solution,
34795 : N - number of points, N>1
34796 : M - dimension of space
34797 : K - number of parameters being fitted
34798 : DiffStep- numerical differentiation step;
34799 : should not be very small or large;
34800 : large = loss of accuracy
34801 : small = growth of round-off errors
34802 :
34803 : OUTPUT PARAMETERS:
34804 : State - structure which stores algorithm state
34805 :
34806 : -- ALGLIB --
34807 : Copyright 18.10.2008 by Bochkanov Sergey
34808 : *************************************************************************/
34809 0 : void lsfitcreatewf(/* Real */ ae_matrix* x,
34810 : /* Real */ ae_vector* y,
34811 : /* Real */ ae_vector* w,
34812 : /* Real */ ae_vector* c,
34813 : ae_int_t n,
34814 : ae_int_t m,
34815 : ae_int_t k,
34816 : double diffstep,
34817 : lsfitstate* state,
34818 : ae_state *_state)
34819 : {
34820 : ae_int_t i;
34821 :
34822 0 : _lsfitstate_clear(state);
34823 :
34824 0 : ae_assert(n>=1, "LSFitCreateWF: N<1!", _state);
34825 0 : ae_assert(m>=1, "LSFitCreateWF: M<1!", _state);
34826 0 : ae_assert(k>=1, "LSFitCreateWF: K<1!", _state);
34827 0 : ae_assert(c->cnt>=k, "LSFitCreateWF: length(C)<K!", _state);
34828 0 : ae_assert(isfinitevector(c, k, _state), "LSFitCreateWF: C contains infinite or NaN values!", _state);
34829 0 : ae_assert(y->cnt>=n, "LSFitCreateWF: length(Y)<N!", _state);
34830 0 : ae_assert(isfinitevector(y, n, _state), "LSFitCreateWF: Y contains infinite or NaN values!", _state);
34831 0 : ae_assert(w->cnt>=n, "LSFitCreateWF: length(W)<N!", _state);
34832 0 : ae_assert(isfinitevector(w, n, _state), "LSFitCreateWF: W contains infinite or NaN values!", _state);
34833 0 : ae_assert(x->rows>=n, "LSFitCreateWF: rows(X)<N!", _state);
34834 0 : ae_assert(x->cols>=m, "LSFitCreateWF: cols(X)<M!", _state);
34835 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateWF: X contains infinite or NaN values!", _state);
34836 0 : ae_assert(ae_isfinite(diffstep, _state), "LSFitCreateWF: DiffStep is not finite!", _state);
34837 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "LSFitCreateWF: DiffStep<=0!", _state);
34838 0 : state->teststep = (double)(0);
34839 0 : state->diffstep = diffstep;
34840 0 : state->npoints = n;
34841 0 : state->nweights = n;
34842 0 : state->wkind = 1;
34843 0 : state->m = m;
34844 0 : state->k = k;
34845 0 : lsfitsetcond(state, 0.0, 0, _state);
34846 0 : lsfitsetstpmax(state, 0.0, _state);
34847 0 : lsfitsetxrep(state, ae_false, _state);
34848 0 : ae_matrix_set_length(&state->taskx, n, m, _state);
34849 0 : ae_vector_set_length(&state->tasky, n, _state);
34850 0 : ae_vector_set_length(&state->taskw, n, _state);
34851 0 : ae_vector_set_length(&state->c, k, _state);
34852 0 : ae_vector_set_length(&state->c0, k, _state);
34853 0 : ae_vector_set_length(&state->c1, k, _state);
34854 0 : ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
34855 0 : ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
34856 0 : ae_vector_set_length(&state->x, m, _state);
34857 0 : ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
34858 0 : for(i=0; i<=n-1; i++)
34859 : {
34860 0 : ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
34861 0 : state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
34862 : }
34863 0 : ae_vector_set_length(&state->s, k, _state);
34864 0 : ae_vector_set_length(&state->bndl, k, _state);
34865 0 : ae_vector_set_length(&state->bndu, k, _state);
34866 0 : for(i=0; i<=k-1; i++)
34867 : {
34868 0 : state->s.ptr.p_double[i] = 1.0;
34869 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
34870 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
34871 : }
34872 0 : state->optalgo = 0;
34873 0 : state->prevnpt = -1;
34874 0 : state->prevalgo = -1;
34875 0 : state->nec = 0;
34876 0 : state->nic = 0;
34877 0 : minlmcreatev(k, n, &state->c0, diffstep, &state->optstate, _state);
34878 0 : lsfit_lsfitclearrequestfields(state, _state);
34879 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
34880 0 : ae_vector_set_length(&state->rstate.ra, 8+1, _state);
34881 0 : state->rstate.stage = -1;
34882 0 : }
34883 :
34884 :
34885 : /*************************************************************************
34886 : Nonlinear least squares fitting using function values only.
34887 :
34888 : Combination of numerical differentiation and secant updates is used to
34889 : obtain function Jacobian.
34890 :
34891 : Nonlinear task min(F(c)) is solved, where
34892 :
34893 : F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2,
34894 :
34895 : * N is a number of points,
34896 : * M is a dimension of a space points belong to,
34897 : * K is a dimension of a space of parameters being fitted,
34898 : * w is an N-dimensional vector of weight coefficients,
34899 : * x is a set of N points, each of them is an M-dimensional vector,
34900 : * c is a K-dimensional vector of parameters being fitted
34901 :
34902 : This subroutine uses only f(c,x[i]).
34903 :
34904 : INPUT PARAMETERS:
34905 : X - array[0..N-1,0..M-1], points (one row = one point)
34906 : Y - array[0..N-1], function values.
34907 : C - array[0..K-1], initial approximation to the solution,
34908 : N - number of points, N>1
34909 : M - dimension of space
34910 : K - number of parameters being fitted
34911 : DiffStep- numerical differentiation step;
34912 : should not be very small or large;
34913 : large = loss of accuracy
34914 : small = growth of round-off errors
34915 :
34916 : OUTPUT PARAMETERS:
34917 : State - structure which stores algorithm state
34918 :
34919 : -- ALGLIB --
34920 : Copyright 18.10.2008 by Bochkanov Sergey
34921 : *************************************************************************/
34922 0 : void lsfitcreatef(/* Real */ ae_matrix* x,
34923 : /* Real */ ae_vector* y,
34924 : /* Real */ ae_vector* c,
34925 : ae_int_t n,
34926 : ae_int_t m,
34927 : ae_int_t k,
34928 : double diffstep,
34929 : lsfitstate* state,
34930 : ae_state *_state)
34931 : {
34932 : ae_int_t i;
34933 :
34934 0 : _lsfitstate_clear(state);
34935 :
34936 0 : ae_assert(n>=1, "LSFitCreateF: N<1!", _state);
34937 0 : ae_assert(m>=1, "LSFitCreateF: M<1!", _state);
34938 0 : ae_assert(k>=1, "LSFitCreateF: K<1!", _state);
34939 0 : ae_assert(c->cnt>=k, "LSFitCreateF: length(C)<K!", _state);
34940 0 : ae_assert(isfinitevector(c, k, _state), "LSFitCreateF: C contains infinite or NaN values!", _state);
34941 0 : ae_assert(y->cnt>=n, "LSFitCreateF: length(Y)<N!", _state);
34942 0 : ae_assert(isfinitevector(y, n, _state), "LSFitCreateF: Y contains infinite or NaN values!", _state);
34943 0 : ae_assert(x->rows>=n, "LSFitCreateF: rows(X)<N!", _state);
34944 0 : ae_assert(x->cols>=m, "LSFitCreateF: cols(X)<M!", _state);
34945 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateF: X contains infinite or NaN values!", _state);
34946 0 : ae_assert(x->rows>=n, "LSFitCreateF: rows(X)<N!", _state);
34947 0 : ae_assert(x->cols>=m, "LSFitCreateF: cols(X)<M!", _state);
34948 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateF: X contains infinite or NaN values!", _state);
34949 0 : ae_assert(ae_isfinite(diffstep, _state), "LSFitCreateF: DiffStep is not finite!", _state);
34950 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "LSFitCreateF: DiffStep<=0!", _state);
34951 0 : state->teststep = (double)(0);
34952 0 : state->diffstep = diffstep;
34953 0 : state->npoints = n;
34954 0 : state->wkind = 0;
34955 0 : state->m = m;
34956 0 : state->k = k;
34957 0 : lsfitsetcond(state, 0.0, 0, _state);
34958 0 : lsfitsetstpmax(state, 0.0, _state);
34959 0 : lsfitsetxrep(state, ae_false, _state);
34960 0 : ae_matrix_set_length(&state->taskx, n, m, _state);
34961 0 : ae_vector_set_length(&state->tasky, n, _state);
34962 0 : ae_vector_set_length(&state->c, k, _state);
34963 0 : ae_vector_set_length(&state->c0, k, _state);
34964 0 : ae_vector_set_length(&state->c1, k, _state);
34965 0 : ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
34966 0 : ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
34967 0 : ae_vector_set_length(&state->x, m, _state);
34968 0 : for(i=0; i<=n-1; i++)
34969 : {
34970 0 : ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
34971 0 : state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
34972 : }
34973 0 : ae_vector_set_length(&state->s, k, _state);
34974 0 : ae_vector_set_length(&state->bndl, k, _state);
34975 0 : ae_vector_set_length(&state->bndu, k, _state);
34976 0 : for(i=0; i<=k-1; i++)
34977 : {
34978 0 : state->s.ptr.p_double[i] = 1.0;
34979 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
34980 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
34981 : }
34982 0 : state->optalgo = 0;
34983 0 : state->prevnpt = -1;
34984 0 : state->prevalgo = -1;
34985 0 : state->nec = 0;
34986 0 : state->nic = 0;
34987 0 : minlmcreatev(k, n, &state->c0, diffstep, &state->optstate, _state);
34988 0 : lsfit_lsfitclearrequestfields(state, _state);
34989 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
34990 0 : ae_vector_set_length(&state->rstate.ra, 8+1, _state);
34991 0 : state->rstate.stage = -1;
34992 0 : }
34993 :
34994 :
34995 : /*************************************************************************
34996 : Weighted nonlinear least squares fitting using gradient only.
34997 :
34998 : Nonlinear task min(F(c)) is solved, where
34999 :
35000 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
35001 :
35002 : * N is a number of points,
35003 : * M is a dimension of a space points belong to,
35004 : * K is a dimension of a space of parameters being fitted,
35005 : * w is an N-dimensional vector of weight coefficients,
35006 : * x is a set of N points, each of them is an M-dimensional vector,
35007 : * c is a K-dimensional vector of parameters being fitted
35008 :
35009 : This subroutine uses only f(c,x[i]) and its gradient.
35010 :
35011 : INPUT PARAMETERS:
35012 : X - array[0..N-1,0..M-1], points (one row = one point)
35013 : Y - array[0..N-1], function values.
35014 : W - weights, array[0..N-1]
35015 : C - array[0..K-1], initial approximation to the solution,
35016 : N - number of points, N>1
35017 : M - dimension of space
35018 : K - number of parameters being fitted
35019 : CheapFG - boolean flag, which is:
35020 : * True if both function and gradient calculation complexity
35021 : are less than O(M^2). An improved algorithm can
35022 : be used which corresponds to FGJ scheme from
35023 : MINLM unit.
35024 : * False otherwise.
35025 : Standard Jacibian-bases Levenberg-Marquardt algo
35026 : will be used (FJ scheme).
35027 :
35028 : OUTPUT PARAMETERS:
35029 : State - structure which stores algorithm state
35030 :
35031 : See also:
35032 : LSFitResults
35033 : LSFitCreateFG (fitting without weights)
35034 : LSFitCreateWFGH (fitting using Hessian)
35035 : LSFitCreateFGH (fitting using Hessian, without weights)
35036 :
35037 : -- ALGLIB --
35038 : Copyright 17.08.2009 by Bochkanov Sergey
35039 : *************************************************************************/
35040 0 : void lsfitcreatewfg(/* Real */ ae_matrix* x,
35041 : /* Real */ ae_vector* y,
35042 : /* Real */ ae_vector* w,
35043 : /* Real */ ae_vector* c,
35044 : ae_int_t n,
35045 : ae_int_t m,
35046 : ae_int_t k,
35047 : ae_bool cheapfg,
35048 : lsfitstate* state,
35049 : ae_state *_state)
35050 : {
35051 : ae_int_t i;
35052 :
35053 0 : _lsfitstate_clear(state);
35054 :
35055 0 : ae_assert(n>=1, "LSFitCreateWFG: N<1!", _state);
35056 0 : ae_assert(m>=1, "LSFitCreateWFG: M<1!", _state);
35057 0 : ae_assert(k>=1, "LSFitCreateWFG: K<1!", _state);
35058 0 : ae_assert(c->cnt>=k, "LSFitCreateWFG: length(C)<K!", _state);
35059 0 : ae_assert(isfinitevector(c, k, _state), "LSFitCreateWFG: C contains infinite or NaN values!", _state);
35060 0 : ae_assert(y->cnt>=n, "LSFitCreateWFG: length(Y)<N!", _state);
35061 0 : ae_assert(isfinitevector(y, n, _state), "LSFitCreateWFG: Y contains infinite or NaN values!", _state);
35062 0 : ae_assert(w->cnt>=n, "LSFitCreateWFG: length(W)<N!", _state);
35063 0 : ae_assert(isfinitevector(w, n, _state), "LSFitCreateWFG: W contains infinite or NaN values!", _state);
35064 0 : ae_assert(x->rows>=n, "LSFitCreateWFG: rows(X)<N!", _state);
35065 0 : ae_assert(x->cols>=m, "LSFitCreateWFG: cols(X)<M!", _state);
35066 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateWFG: X contains infinite or NaN values!", _state);
35067 0 : state->teststep = (double)(0);
35068 0 : state->diffstep = (double)(0);
35069 0 : state->npoints = n;
35070 0 : state->nweights = n;
35071 0 : state->wkind = 1;
35072 0 : state->m = m;
35073 0 : state->k = k;
35074 0 : lsfitsetcond(state, 0.0, 0, _state);
35075 0 : lsfitsetstpmax(state, 0.0, _state);
35076 0 : lsfitsetxrep(state, ae_false, _state);
35077 0 : ae_matrix_set_length(&state->taskx, n, m, _state);
35078 0 : ae_vector_set_length(&state->tasky, n, _state);
35079 0 : ae_vector_set_length(&state->taskw, n, _state);
35080 0 : ae_vector_set_length(&state->c, k, _state);
35081 0 : ae_vector_set_length(&state->c0, k, _state);
35082 0 : ae_vector_set_length(&state->c1, k, _state);
35083 0 : ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35084 0 : ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35085 0 : ae_vector_set_length(&state->x, m, _state);
35086 0 : ae_vector_set_length(&state->g, k, _state);
35087 0 : ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
35088 0 : for(i=0; i<=n-1; i++)
35089 : {
35090 0 : ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
35091 0 : state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
35092 : }
35093 0 : ae_vector_set_length(&state->s, k, _state);
35094 0 : ae_vector_set_length(&state->bndl, k, _state);
35095 0 : ae_vector_set_length(&state->bndu, k, _state);
35096 0 : for(i=0; i<=k-1; i++)
35097 : {
35098 0 : state->s.ptr.p_double[i] = 1.0;
35099 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
35100 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
35101 : }
35102 0 : state->optalgo = 1;
35103 0 : state->prevnpt = -1;
35104 0 : state->prevalgo = -1;
35105 0 : state->nec = 0;
35106 0 : state->nic = 0;
35107 0 : if( cheapfg )
35108 : {
35109 0 : minlmcreatevgj(k, n, &state->c0, &state->optstate, _state);
35110 : }
35111 : else
35112 : {
35113 0 : minlmcreatevj(k, n, &state->c0, &state->optstate, _state);
35114 : }
35115 0 : lsfit_lsfitclearrequestfields(state, _state);
35116 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
35117 0 : ae_vector_set_length(&state->rstate.ra, 8+1, _state);
35118 0 : state->rstate.stage = -1;
35119 0 : }
35120 :
35121 :
35122 : /*************************************************************************
35123 : Nonlinear least squares fitting using gradient only, without individual
35124 : weights.
35125 :
35126 : Nonlinear task min(F(c)) is solved, where
35127 :
35128 : F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
35129 :
35130 : * N is a number of points,
35131 : * M is a dimension of a space points belong to,
35132 : * K is a dimension of a space of parameters being fitted,
35133 : * x is a set of N points, each of them is an M-dimensional vector,
35134 : * c is a K-dimensional vector of parameters being fitted
35135 :
35136 : This subroutine uses only f(c,x[i]) and its gradient.
35137 :
35138 : INPUT PARAMETERS:
35139 : X - array[0..N-1,0..M-1], points (one row = one point)
35140 : Y - array[0..N-1], function values.
35141 : C - array[0..K-1], initial approximation to the solution,
35142 : N - number of points, N>1
35143 : M - dimension of space
35144 : K - number of parameters being fitted
35145 : CheapFG - boolean flag, which is:
35146 : * True if both function and gradient calculation complexity
35147 : are less than O(M^2). An improved algorithm can
35148 : be used which corresponds to FGJ scheme from
35149 : MINLM unit.
35150 : * False otherwise.
35151 : Standard Jacibian-bases Levenberg-Marquardt algo
35152 : will be used (FJ scheme).
35153 :
35154 : OUTPUT PARAMETERS:
35155 : State - structure which stores algorithm state
35156 :
35157 : -- ALGLIB --
35158 : Copyright 17.08.2009 by Bochkanov Sergey
35159 : *************************************************************************/
35160 0 : void lsfitcreatefg(/* Real */ ae_matrix* x,
35161 : /* Real */ ae_vector* y,
35162 : /* Real */ ae_vector* c,
35163 : ae_int_t n,
35164 : ae_int_t m,
35165 : ae_int_t k,
35166 : ae_bool cheapfg,
35167 : lsfitstate* state,
35168 : ae_state *_state)
35169 : {
35170 : ae_int_t i;
35171 :
35172 0 : _lsfitstate_clear(state);
35173 :
35174 0 : ae_assert(n>=1, "LSFitCreateFG: N<1!", _state);
35175 0 : ae_assert(m>=1, "LSFitCreateFG: M<1!", _state);
35176 0 : ae_assert(k>=1, "LSFitCreateFG: K<1!", _state);
35177 0 : ae_assert(c->cnt>=k, "LSFitCreateFG: length(C)<K!", _state);
35178 0 : ae_assert(isfinitevector(c, k, _state), "LSFitCreateFG: C contains infinite or NaN values!", _state);
35179 0 : ae_assert(y->cnt>=n, "LSFitCreateFG: length(Y)<N!", _state);
35180 0 : ae_assert(isfinitevector(y, n, _state), "LSFitCreateFG: Y contains infinite or NaN values!", _state);
35181 0 : ae_assert(x->rows>=n, "LSFitCreateFG: rows(X)<N!", _state);
35182 0 : ae_assert(x->cols>=m, "LSFitCreateFG: cols(X)<M!", _state);
35183 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateFG: X contains infinite or NaN values!", _state);
35184 0 : ae_assert(x->rows>=n, "LSFitCreateFG: rows(X)<N!", _state);
35185 0 : ae_assert(x->cols>=m, "LSFitCreateFG: cols(X)<M!", _state);
35186 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateFG: X contains infinite or NaN values!", _state);
35187 0 : state->teststep = (double)(0);
35188 0 : state->diffstep = (double)(0);
35189 0 : state->npoints = n;
35190 0 : state->wkind = 0;
35191 0 : state->m = m;
35192 0 : state->k = k;
35193 0 : lsfitsetcond(state, 0.0, 0, _state);
35194 0 : lsfitsetstpmax(state, 0.0, _state);
35195 0 : lsfitsetxrep(state, ae_false, _state);
35196 0 : ae_matrix_set_length(&state->taskx, n, m, _state);
35197 0 : ae_vector_set_length(&state->tasky, n, _state);
35198 0 : ae_vector_set_length(&state->c, k, _state);
35199 0 : ae_vector_set_length(&state->c0, k, _state);
35200 0 : ae_vector_set_length(&state->c1, k, _state);
35201 0 : ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35202 0 : ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35203 0 : ae_vector_set_length(&state->x, m, _state);
35204 0 : ae_vector_set_length(&state->g, k, _state);
35205 0 : for(i=0; i<=n-1; i++)
35206 : {
35207 0 : ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
35208 0 : state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
35209 : }
35210 0 : ae_vector_set_length(&state->s, k, _state);
35211 0 : ae_vector_set_length(&state->bndl, k, _state);
35212 0 : ae_vector_set_length(&state->bndu, k, _state);
35213 0 : for(i=0; i<=k-1; i++)
35214 : {
35215 0 : state->s.ptr.p_double[i] = 1.0;
35216 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
35217 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
35218 : }
35219 0 : state->optalgo = 1;
35220 0 : state->prevnpt = -1;
35221 0 : state->prevalgo = -1;
35222 0 : state->nec = 0;
35223 0 : state->nic = 0;
35224 0 : if( cheapfg )
35225 : {
35226 0 : minlmcreatevgj(k, n, &state->c0, &state->optstate, _state);
35227 : }
35228 : else
35229 : {
35230 0 : minlmcreatevj(k, n, &state->c0, &state->optstate, _state);
35231 : }
35232 0 : lsfit_lsfitclearrequestfields(state, _state);
35233 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
35234 0 : ae_vector_set_length(&state->rstate.ra, 8+1, _state);
35235 0 : state->rstate.stage = -1;
35236 0 : }
35237 :
35238 :
35239 : /*************************************************************************
35240 : Weighted nonlinear least squares fitting using gradient/Hessian.
35241 :
35242 : Nonlinear task min(F(c)) is solved, where
35243 :
35244 : F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
35245 :
35246 : * N is a number of points,
35247 : * M is a dimension of a space points belong to,
35248 : * K is a dimension of a space of parameters being fitted,
35249 : * w is an N-dimensional vector of weight coefficients,
35250 : * x is a set of N points, each of them is an M-dimensional vector,
35251 : * c is a K-dimensional vector of parameters being fitted
35252 :
35253 : This subroutine uses f(c,x[i]), its gradient and its Hessian.
35254 :
35255 : INPUT PARAMETERS:
35256 : X - array[0..N-1,0..M-1], points (one row = one point)
35257 : Y - array[0..N-1], function values.
35258 : W - weights, array[0..N-1]
35259 : C - array[0..K-1], initial approximation to the solution,
35260 : N - number of points, N>1
35261 : M - dimension of space
35262 : K - number of parameters being fitted
35263 :
35264 : OUTPUT PARAMETERS:
35265 : State - structure which stores algorithm state
35266 :
35267 : -- ALGLIB --
35268 : Copyright 17.08.2009 by Bochkanov Sergey
35269 : *************************************************************************/
35270 0 : void lsfitcreatewfgh(/* Real */ ae_matrix* x,
35271 : /* Real */ ae_vector* y,
35272 : /* Real */ ae_vector* w,
35273 : /* Real */ ae_vector* c,
35274 : ae_int_t n,
35275 : ae_int_t m,
35276 : ae_int_t k,
35277 : lsfitstate* state,
35278 : ae_state *_state)
35279 : {
35280 : ae_int_t i;
35281 :
35282 0 : _lsfitstate_clear(state);
35283 :
35284 0 : ae_assert(n>=1, "LSFitCreateWFGH: N<1!", _state);
35285 0 : ae_assert(m>=1, "LSFitCreateWFGH: M<1!", _state);
35286 0 : ae_assert(k>=1, "LSFitCreateWFGH: K<1!", _state);
35287 0 : ae_assert(c->cnt>=k, "LSFitCreateWFGH: length(C)<K!", _state);
35288 0 : ae_assert(isfinitevector(c, k, _state), "LSFitCreateWFGH: C contains infinite or NaN values!", _state);
35289 0 : ae_assert(y->cnt>=n, "LSFitCreateWFGH: length(Y)<N!", _state);
35290 0 : ae_assert(isfinitevector(y, n, _state), "LSFitCreateWFGH: Y contains infinite or NaN values!", _state);
35291 0 : ae_assert(w->cnt>=n, "LSFitCreateWFGH: length(W)<N!", _state);
35292 0 : ae_assert(isfinitevector(w, n, _state), "LSFitCreateWFGH: W contains infinite or NaN values!", _state);
35293 0 : ae_assert(x->rows>=n, "LSFitCreateWFGH: rows(X)<N!", _state);
35294 0 : ae_assert(x->cols>=m, "LSFitCreateWFGH: cols(X)<M!", _state);
35295 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateWFGH: X contains infinite or NaN values!", _state);
35296 0 : state->teststep = (double)(0);
35297 0 : state->diffstep = (double)(0);
35298 0 : state->npoints = n;
35299 0 : state->nweights = n;
35300 0 : state->wkind = 1;
35301 0 : state->m = m;
35302 0 : state->k = k;
35303 0 : lsfitsetcond(state, 0.0, 0, _state);
35304 0 : lsfitsetstpmax(state, 0.0, _state);
35305 0 : lsfitsetxrep(state, ae_false, _state);
35306 0 : ae_matrix_set_length(&state->taskx, n, m, _state);
35307 0 : ae_vector_set_length(&state->tasky, n, _state);
35308 0 : ae_vector_set_length(&state->taskw, n, _state);
35309 0 : ae_vector_set_length(&state->c, k, _state);
35310 0 : ae_vector_set_length(&state->c0, k, _state);
35311 0 : ae_vector_set_length(&state->c1, k, _state);
35312 0 : ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35313 0 : ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35314 0 : ae_matrix_set_length(&state->h, k, k, _state);
35315 0 : ae_vector_set_length(&state->x, m, _state);
35316 0 : ae_vector_set_length(&state->g, k, _state);
35317 0 : ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
35318 0 : for(i=0; i<=n-1; i++)
35319 : {
35320 0 : ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
35321 0 : state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
35322 : }
35323 0 : ae_vector_set_length(&state->s, k, _state);
35324 0 : ae_vector_set_length(&state->bndl, k, _state);
35325 0 : ae_vector_set_length(&state->bndu, k, _state);
35326 0 : for(i=0; i<=k-1; i++)
35327 : {
35328 0 : state->s.ptr.p_double[i] = 1.0;
35329 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
35330 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
35331 : }
35332 0 : state->optalgo = 2;
35333 0 : state->prevnpt = -1;
35334 0 : state->prevalgo = -1;
35335 0 : state->nec = 0;
35336 0 : state->nic = 0;
35337 0 : minlmcreatefgh(k, &state->c0, &state->optstate, _state);
35338 0 : lsfit_lsfitclearrequestfields(state, _state);
35339 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
35340 0 : ae_vector_set_length(&state->rstate.ra, 8+1, _state);
35341 0 : state->rstate.stage = -1;
35342 0 : }
35343 :
35344 :
35345 : /*************************************************************************
35346 : Nonlinear least squares fitting using gradient/Hessian, without individial
35347 : weights.
35348 :
35349 : Nonlinear task min(F(c)) is solved, where
35350 :
35351 : F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
35352 :
35353 : * N is a number of points,
35354 : * M is a dimension of a space points belong to,
35355 : * K is a dimension of a space of parameters being fitted,
35356 : * x is a set of N points, each of them is an M-dimensional vector,
35357 : * c is a K-dimensional vector of parameters being fitted
35358 :
35359 : This subroutine uses f(c,x[i]), its gradient and its Hessian.
35360 :
35361 : INPUT PARAMETERS:
35362 : X - array[0..N-1,0..M-1], points (one row = one point)
35363 : Y - array[0..N-1], function values.
35364 : C - array[0..K-1], initial approximation to the solution,
35365 : N - number of points, N>1
35366 : M - dimension of space
35367 : K - number of parameters being fitted
35368 :
35369 : OUTPUT PARAMETERS:
35370 : State - structure which stores algorithm state
35371 :
35372 :
35373 : -- ALGLIB --
35374 : Copyright 17.08.2009 by Bochkanov Sergey
35375 : *************************************************************************/
35376 0 : void lsfitcreatefgh(/* Real */ ae_matrix* x,
35377 : /* Real */ ae_vector* y,
35378 : /* Real */ ae_vector* c,
35379 : ae_int_t n,
35380 : ae_int_t m,
35381 : ae_int_t k,
35382 : lsfitstate* state,
35383 : ae_state *_state)
35384 : {
35385 : ae_int_t i;
35386 :
35387 0 : _lsfitstate_clear(state);
35388 :
35389 0 : ae_assert(n>=1, "LSFitCreateFGH: N<1!", _state);
35390 0 : ae_assert(m>=1, "LSFitCreateFGH: M<1!", _state);
35391 0 : ae_assert(k>=1, "LSFitCreateFGH: K<1!", _state);
35392 0 : ae_assert(c->cnt>=k, "LSFitCreateFGH: length(C)<K!", _state);
35393 0 : ae_assert(isfinitevector(c, k, _state), "LSFitCreateFGH: C contains infinite or NaN values!", _state);
35394 0 : ae_assert(y->cnt>=n, "LSFitCreateFGH: length(Y)<N!", _state);
35395 0 : ae_assert(isfinitevector(y, n, _state), "LSFitCreateFGH: Y contains infinite or NaN values!", _state);
35396 0 : ae_assert(x->rows>=n, "LSFitCreateFGH: rows(X)<N!", _state);
35397 0 : ae_assert(x->cols>=m, "LSFitCreateFGH: cols(X)<M!", _state);
35398 0 : ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateFGH: X contains infinite or NaN values!", _state);
35399 0 : state->teststep = (double)(0);
35400 0 : state->diffstep = (double)(0);
35401 0 : state->npoints = n;
35402 0 : state->wkind = 0;
35403 0 : state->m = m;
35404 0 : state->k = k;
35405 0 : lsfitsetcond(state, 0.0, 0, _state);
35406 0 : lsfitsetstpmax(state, 0.0, _state);
35407 0 : lsfitsetxrep(state, ae_false, _state);
35408 0 : ae_matrix_set_length(&state->taskx, n, m, _state);
35409 0 : ae_vector_set_length(&state->tasky, n, _state);
35410 0 : ae_vector_set_length(&state->c, k, _state);
35411 0 : ae_vector_set_length(&state->c0, k, _state);
35412 0 : ae_vector_set_length(&state->c1, k, _state);
35413 0 : ae_v_move(&state->c0.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35414 0 : ae_v_move(&state->c1.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
35415 0 : ae_matrix_set_length(&state->h, k, k, _state);
35416 0 : ae_vector_set_length(&state->x, m, _state);
35417 0 : ae_vector_set_length(&state->g, k, _state);
35418 0 : for(i=0; i<=n-1; i++)
35419 : {
35420 0 : ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
35421 0 : state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
35422 : }
35423 0 : ae_vector_set_length(&state->s, k, _state);
35424 0 : ae_vector_set_length(&state->bndl, k, _state);
35425 0 : ae_vector_set_length(&state->bndu, k, _state);
35426 0 : for(i=0; i<=k-1; i++)
35427 : {
35428 0 : state->s.ptr.p_double[i] = 1.0;
35429 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
35430 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
35431 : }
35432 0 : state->optalgo = 2;
35433 0 : state->prevnpt = -1;
35434 0 : state->prevalgo = -1;
35435 0 : state->nec = 0;
35436 0 : state->nic = 0;
35437 0 : minlmcreatefgh(k, &state->c0, &state->optstate, _state);
35438 0 : lsfit_lsfitclearrequestfields(state, _state);
35439 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
35440 0 : ae_vector_set_length(&state->rstate.ra, 8+1, _state);
35441 0 : state->rstate.stage = -1;
35442 0 : }
35443 :
35444 :
35445 : /*************************************************************************
35446 : Stopping conditions for nonlinear least squares fitting.
35447 :
35448 : INPUT PARAMETERS:
35449 : State - structure which stores algorithm state
35450 : EpsX - >=0
35451 : The subroutine finishes its work if on k+1-th iteration
35452 : the condition |v|<=EpsX is fulfilled, where:
35453 : * |.| means Euclidian norm
35454 : * v - scaled step vector, v[i]=dx[i]/s[i]
35455 : * dx - ste pvector, dx=X(k+1)-X(k)
35456 : * s - scaling coefficients set by LSFitSetScale()
35457 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
35458 : iterations is unlimited. Only Levenberg-Marquardt
35459 : iterations are counted (L-BFGS/CG iterations are NOT
35460 : counted because their cost is very low compared to that of
35461 : LM).
35462 :
35463 : NOTE
35464 :
35465 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
35466 : stopping criterion selection (according to the scheme used by MINLM unit).
35467 :
35468 :
35469 : -- ALGLIB --
35470 : Copyright 17.08.2009 by Bochkanov Sergey
35471 : *************************************************************************/
35472 0 : void lsfitsetcond(lsfitstate* state,
35473 : double epsx,
35474 : ae_int_t maxits,
35475 : ae_state *_state)
35476 : {
35477 :
35478 :
35479 0 : ae_assert(ae_isfinite(epsx, _state), "LSFitSetCond: EpsX is not finite!", _state);
35480 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "LSFitSetCond: negative EpsX!", _state);
35481 0 : ae_assert(maxits>=0, "LSFitSetCond: negative MaxIts!", _state);
35482 0 : state->epsx = epsx;
35483 0 : state->maxits = maxits;
35484 0 : }
35485 :
35486 :
35487 : /*************************************************************************
35488 : This function sets maximum step length
35489 :
35490 : INPUT PARAMETERS:
35491 : State - structure which stores algorithm state
35492 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
35493 : want to limit step length.
35494 :
35495 : Use this subroutine when you optimize target function which contains exp()
35496 : or other fast growing functions, and optimization algorithm makes too
35497 : large steps which leads to overflow. This function allows us to reject
35498 : steps that are too large (and therefore expose us to the possible
35499 : overflow) without actually calculating function value at the x+stp*d.
35500 :
35501 : NOTE: non-zero StpMax leads to moderate performance degradation because
35502 : intermediate step of preconditioned L-BFGS optimization is incompatible
35503 : with limits on step size.
35504 :
35505 : -- ALGLIB --
35506 : Copyright 02.04.2010 by Bochkanov Sergey
35507 : *************************************************************************/
35508 0 : void lsfitsetstpmax(lsfitstate* state, double stpmax, ae_state *_state)
35509 : {
35510 :
35511 :
35512 0 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "LSFitSetStpMax: StpMax<0!", _state);
35513 0 : state->stpmax = stpmax;
35514 0 : }
35515 :
35516 :
35517 : /*************************************************************************
35518 : This function turns on/off reporting.
35519 :
35520 : INPUT PARAMETERS:
35521 : State - structure which stores algorithm state
35522 : NeedXRep- whether iteration reports are needed or not
35523 :
35524 : When reports are needed, State.C (current parameters) and State.F (current
35525 : value of fitting function) are reported.
35526 :
35527 :
35528 : -- ALGLIB --
35529 : Copyright 15.08.2010 by Bochkanov Sergey
35530 : *************************************************************************/
35531 0 : void lsfitsetxrep(lsfitstate* state, ae_bool needxrep, ae_state *_state)
35532 : {
35533 :
35534 :
35535 0 : state->xrep = needxrep;
35536 0 : }
35537 :
35538 :
35539 : /*************************************************************************
35540 : This function sets scaling coefficients for underlying optimizer.
35541 :
35542 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
35543 : size and gradient are scaled before comparison with tolerances). Scale of
35544 : the I-th variable is a translation invariant measure of:
35545 : a) "how large" the variable is
35546 : b) how large the step should be to make significant changes in the function
35547 :
35548 : Generally, scale is NOT considered to be a form of preconditioner. But LM
35549 : optimizer is unique in that it uses scaling matrix both in the stopping
35550 : condition tests and as Marquardt damping factor.
35551 :
35552 : Proper scaling is very important for the algorithm performance. It is less
35553 : important for the quality of results, but still has some influence (it is
35554 : easier to converge when variables are properly scaled, so premature
35555 : stopping is possible when very badly scalled variables are combined with
35556 : relaxed stopping conditions).
35557 :
35558 : INPUT PARAMETERS:
35559 : State - structure stores algorithm state
35560 : S - array[N], non-zero scaling coefficients
35561 : S[i] may be negative, sign doesn't matter.
35562 :
35563 : -- ALGLIB --
35564 : Copyright 14.01.2011 by Bochkanov Sergey
35565 : *************************************************************************/
35566 0 : void lsfitsetscale(lsfitstate* state,
35567 : /* Real */ ae_vector* s,
35568 : ae_state *_state)
35569 : {
35570 : ae_int_t i;
35571 :
35572 :
35573 0 : ae_assert(s->cnt>=state->k, "LSFitSetScale: Length(S)<K", _state);
35574 0 : for(i=0; i<=state->k-1; i++)
35575 : {
35576 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "LSFitSetScale: S contains infinite or NAN elements", _state);
35577 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "LSFitSetScale: S contains infinite or NAN elements", _state);
35578 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
35579 : }
35580 0 : }
35581 :
35582 :
35583 : /*************************************************************************
35584 : This function sets boundary constraints for underlying optimizer
35585 :
35586 : Boundary constraints are inactive by default (after initial creation).
35587 : They are preserved until explicitly turned off with another SetBC() call.
35588 :
35589 : INPUT PARAMETERS:
35590 : State - structure stores algorithm state
35591 : BndL - lower bounds, array[K].
35592 : If some (all) variables are unbounded, you may specify
35593 : very small number or -INF (latter is recommended because
35594 : it will allow solver to use better algorithm).
35595 : BndU - upper bounds, array[K].
35596 : If some (all) variables are unbounded, you may specify
35597 : very large number or +INF (latter is recommended because
35598 : it will allow solver to use better algorithm).
35599 :
35600 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
35601 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
35602 :
35603 : NOTE 2: unlike other constrained optimization algorithms, this solver has
35604 : following useful properties:
35605 : * bound constraints are always satisfied exactly
35606 : * function is evaluated only INSIDE area specified by bound constraints
35607 :
35608 : -- ALGLIB --
35609 : Copyright 14.01.2011 by Bochkanov Sergey
35610 : *************************************************************************/
35611 0 : void lsfitsetbc(lsfitstate* state,
35612 : /* Real */ ae_vector* bndl,
35613 : /* Real */ ae_vector* bndu,
35614 : ae_state *_state)
35615 : {
35616 : ae_int_t i;
35617 : ae_int_t k;
35618 :
35619 :
35620 0 : k = state->k;
35621 0 : ae_assert(bndl->cnt>=k, "LSFitSetBC: Length(BndL)<K", _state);
35622 0 : ae_assert(bndu->cnt>=k, "LSFitSetBC: Length(BndU)<K", _state);
35623 0 : for(i=0; i<=k-1; i++)
35624 : {
35625 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "LSFitSetBC: BndL contains NAN or +INF", _state);
35626 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "LSFitSetBC: BndU contains NAN or -INF", _state);
35627 0 : if( ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state) )
35628 : {
35629 0 : ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "LSFitSetBC: BndL[i]>BndU[i]", _state);
35630 : }
35631 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
35632 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
35633 : }
35634 0 : }
35635 :
35636 :
35637 : /*************************************************************************
35638 : This function sets linear constraints for underlying optimizer
35639 :
35640 : Linear constraints are inactive by default (after initial creation).
35641 : They are preserved until explicitly turned off with another SetLC() call.
35642 :
35643 : INPUT PARAMETERS:
35644 : State - structure stores algorithm state
35645 : C - linear constraints, array[K,N+1].
35646 : Each row of C represents one constraint, either equality
35647 : or inequality (see below):
35648 : * first N elements correspond to coefficients,
35649 : * last element corresponds to the right part.
35650 : All elements of C (including right part) must be finite.
35651 : CT - type of constraints, array[K]:
35652 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
35653 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
35654 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
35655 : K - number of equality/inequality constraints, K>=0:
35656 : * if given, only leading K elements of C/CT are used
35657 : * if not given, automatically determined from sizes of C/CT
35658 :
35659 : IMPORTANT: if you have linear constraints, it is strongly recommended to
35660 : set scale of variables with lsfitsetscale(). QP solver which is
35661 : used to calculate linearly constrained steps heavily relies on
35662 : good scaling of input problems.
35663 :
35664 : NOTE: linear (non-box) constraints are satisfied only approximately -
35665 : there always exists some violation due to numerical errors and
35666 : algorithmic limitations.
35667 :
35668 : NOTE: general linear constraints add significant overhead to solution
35669 : process. Although solver performs roughly same amount of iterations
35670 : (when compared with similar box-only constrained problem), each
35671 : iteration now involves solution of linearly constrained QP
35672 : subproblem, which requires ~3-5 times more Cholesky decompositions.
35673 : Thus, if you can reformulate your problem in such way this it has
35674 : only box constraints, it may be beneficial to do so.
35675 :
35676 : -- ALGLIB --
35677 : Copyright 29.04.2017 by Bochkanov Sergey
35678 : *************************************************************************/
35679 0 : void lsfitsetlc(lsfitstate* state,
35680 : /* Real */ ae_matrix* c,
35681 : /* Integer */ ae_vector* ct,
35682 : ae_int_t k,
35683 : ae_state *_state)
35684 : {
35685 : ae_int_t i;
35686 : ae_int_t n;
35687 :
35688 :
35689 0 : n = state->k;
35690 :
35691 : /*
35692 : * First, check for errors in the inputs
35693 : */
35694 0 : ae_assert(k>=0, "LSFitSetLC: K<0", _state);
35695 0 : ae_assert(c->cols>=n+1||k==0, "LSFitSetLC: Cols(C)<N+1", _state);
35696 0 : ae_assert(c->rows>=k, "LSFitSetLC: Rows(C)<K", _state);
35697 0 : ae_assert(ct->cnt>=k, "LSFitSetLC: Length(CT)<K", _state);
35698 0 : ae_assert(apservisfinitematrix(c, k, n+1, _state), "LSFitSetLC: C contains infinite or NaN values!", _state);
35699 :
35700 : /*
35701 : * Handle zero K
35702 : */
35703 0 : if( k==0 )
35704 : {
35705 0 : state->nec = 0;
35706 0 : state->nic = 0;
35707 0 : return;
35708 : }
35709 :
35710 : /*
35711 : * Equality constraints are stored first, in the upper
35712 : * NEC rows of State.CLEIC matrix. Inequality constraints
35713 : * are stored in the next NIC rows.
35714 : *
35715 : * NOTE: we convert inequality constraints to the form
35716 : * A*x<=b before copying them.
35717 : */
35718 0 : rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
35719 0 : state->nec = 0;
35720 0 : state->nic = 0;
35721 0 : for(i=0; i<=k-1; i++)
35722 : {
35723 0 : if( ct->ptr.p_int[i]==0 )
35724 : {
35725 0 : ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
35726 0 : state->nec = state->nec+1;
35727 : }
35728 : }
35729 0 : for(i=0; i<=k-1; i++)
35730 : {
35731 0 : if( ct->ptr.p_int[i]!=0 )
35732 : {
35733 0 : if( ct->ptr.p_int[i]>0 )
35734 : {
35735 0 : ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
35736 : }
35737 : else
35738 : {
35739 0 : ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
35740 : }
35741 0 : state->nic = state->nic+1;
35742 : }
35743 : }
35744 : }
35745 :
35746 :
35747 : /*************************************************************************
35748 : NOTES:
35749 :
35750 : 1. this algorithm is somewhat unusual because it works with parameterized
35751 : function f(C,X), where X is a function argument (we have many points
35752 : which are characterized by different argument values), and C is a
35753 : parameter to fit.
35754 :
35755 : For example, if we want to do linear fit by f(c0,c1,x) = c0*x+c1, then
35756 : x will be argument, and {c0,c1} will be parameters.
35757 :
35758 : It is important to understand that this algorithm finds minimum in the
35759 : space of function PARAMETERS (not arguments), so it needs derivatives
35760 : of f() with respect to C, not X.
35761 :
35762 : In the example above it will need f=c0*x+c1 and {df/dc0,df/dc1} = {x,1}
35763 : instead of {df/dx} = {c0}.
35764 :
35765 : 2. Callback functions accept C as the first parameter, and X as the second
35766 :
35767 : 3. If state was created with LSFitCreateFG(), algorithm needs just
35768 : function and its gradient, but if state was created with
35769 : LSFitCreateFGH(), algorithm will need function, gradient and Hessian.
35770 :
35771 : According to the said above, there ase several versions of this
35772 : function, which accept different sets of callbacks.
35773 :
35774 : This flexibility opens way to subtle errors - you may create state with
35775 : LSFitCreateFGH() (optimization using Hessian), but call function which
35776 : does not accept Hessian. So when algorithm will request Hessian, there
35777 : will be no callback to call. In this case exception will be thrown.
35778 :
35779 : Be careful to avoid such errors because there is no way to find them at
35780 : compile time - you can see them at runtime only.
35781 :
35782 : -- ALGLIB --
35783 : Copyright 17.08.2009 by Bochkanov Sergey
35784 : *************************************************************************/
35785 0 : ae_bool lsfititeration(lsfitstate* state, ae_state *_state)
35786 : {
35787 : double lx;
35788 : double lf;
35789 : double ld;
35790 : double rx;
35791 : double rf;
35792 : double rd;
35793 : ae_int_t n;
35794 : ae_int_t m;
35795 : ae_int_t k;
35796 : double v;
35797 : double vv;
35798 : double relcnt;
35799 : ae_int_t i;
35800 : ae_int_t j;
35801 : ae_int_t j1;
35802 : ae_int_t info;
35803 : ae_bool result;
35804 :
35805 :
35806 :
35807 : /*
35808 : * Reverse communication preparations
35809 : * I know it looks ugly, but it works the same way
35810 : * anywhere from C++ to Python.
35811 : *
35812 : * This code initializes locals by:
35813 : * * random values determined during code
35814 : * generation - on first subroutine call
35815 : * * values from previous call - on subsequent calls
35816 : */
35817 0 : if( state->rstate.stage>=0 )
35818 : {
35819 0 : n = state->rstate.ia.ptr.p_int[0];
35820 0 : m = state->rstate.ia.ptr.p_int[1];
35821 0 : k = state->rstate.ia.ptr.p_int[2];
35822 0 : i = state->rstate.ia.ptr.p_int[3];
35823 0 : j = state->rstate.ia.ptr.p_int[4];
35824 0 : j1 = state->rstate.ia.ptr.p_int[5];
35825 0 : info = state->rstate.ia.ptr.p_int[6];
35826 0 : lx = state->rstate.ra.ptr.p_double[0];
35827 0 : lf = state->rstate.ra.ptr.p_double[1];
35828 0 : ld = state->rstate.ra.ptr.p_double[2];
35829 0 : rx = state->rstate.ra.ptr.p_double[3];
35830 0 : rf = state->rstate.ra.ptr.p_double[4];
35831 0 : rd = state->rstate.ra.ptr.p_double[5];
35832 0 : v = state->rstate.ra.ptr.p_double[6];
35833 0 : vv = state->rstate.ra.ptr.p_double[7];
35834 0 : relcnt = state->rstate.ra.ptr.p_double[8];
35835 : }
35836 : else
35837 : {
35838 0 : n = 359;
35839 0 : m = -58;
35840 0 : k = -919;
35841 0 : i = -909;
35842 0 : j = 81;
35843 0 : j1 = 255;
35844 0 : info = 74;
35845 0 : lx = -788;
35846 0 : lf = 809;
35847 0 : ld = 205;
35848 0 : rx = -838;
35849 0 : rf = 939;
35850 0 : rd = -526;
35851 0 : v = 763;
35852 0 : vv = -541;
35853 0 : relcnt = -698;
35854 : }
35855 0 : if( state->rstate.stage==0 )
35856 : {
35857 0 : goto lbl_0;
35858 : }
35859 0 : if( state->rstate.stage==1 )
35860 : {
35861 0 : goto lbl_1;
35862 : }
35863 0 : if( state->rstate.stage==2 )
35864 : {
35865 0 : goto lbl_2;
35866 : }
35867 0 : if( state->rstate.stage==3 )
35868 : {
35869 0 : goto lbl_3;
35870 : }
35871 0 : if( state->rstate.stage==4 )
35872 : {
35873 0 : goto lbl_4;
35874 : }
35875 0 : if( state->rstate.stage==5 )
35876 : {
35877 0 : goto lbl_5;
35878 : }
35879 0 : if( state->rstate.stage==6 )
35880 : {
35881 0 : goto lbl_6;
35882 : }
35883 0 : if( state->rstate.stage==7 )
35884 : {
35885 0 : goto lbl_7;
35886 : }
35887 0 : if( state->rstate.stage==8 )
35888 : {
35889 0 : goto lbl_8;
35890 : }
35891 0 : if( state->rstate.stage==9 )
35892 : {
35893 0 : goto lbl_9;
35894 : }
35895 0 : if( state->rstate.stage==10 )
35896 : {
35897 0 : goto lbl_10;
35898 : }
35899 0 : if( state->rstate.stage==11 )
35900 : {
35901 0 : goto lbl_11;
35902 : }
35903 0 : if( state->rstate.stage==12 )
35904 : {
35905 0 : goto lbl_12;
35906 : }
35907 0 : if( state->rstate.stage==13 )
35908 : {
35909 0 : goto lbl_13;
35910 : }
35911 :
35912 : /*
35913 : * Routine body
35914 : */
35915 :
35916 : /*
35917 : * Init
35918 : */
35919 0 : if( state->wkind==1 )
35920 : {
35921 0 : ae_assert(state->npoints==state->nweights, "LSFitFit: number of points is not equal to the number of weights", _state);
35922 : }
35923 0 : state->repvaridx = -1;
35924 0 : n = state->npoints;
35925 0 : m = state->m;
35926 0 : k = state->k;
35927 0 : ivectorsetlengthatleast(&state->tmpct, state->nec+state->nic, _state);
35928 0 : for(i=0; i<=state->nec-1; i++)
35929 : {
35930 0 : state->tmpct.ptr.p_int[i] = 0;
35931 : }
35932 0 : for(i=0; i<=state->nic-1; i++)
35933 : {
35934 0 : state->tmpct.ptr.p_int[state->nec+i] = -1;
35935 : }
35936 0 : minlmsetcond(&state->optstate, state->epsx, state->maxits, _state);
35937 0 : minlmsetstpmax(&state->optstate, state->stpmax, _state);
35938 0 : minlmsetxrep(&state->optstate, state->xrep, _state);
35939 0 : minlmsetscale(&state->optstate, &state->s, _state);
35940 0 : minlmsetbc(&state->optstate, &state->bndl, &state->bndu, _state);
35941 0 : minlmsetlc(&state->optstate, &state->cleic, &state->tmpct, state->nec+state->nic, _state);
35942 :
35943 : /*
35944 : * Check that user-supplied gradient is correct
35945 : */
35946 0 : lsfit_lsfitclearrequestfields(state, _state);
35947 0 : if( !(ae_fp_greater(state->teststep,(double)(0))&&state->optalgo==1) )
35948 : {
35949 0 : goto lbl_14;
35950 : }
35951 0 : for(i=0; i<=k-1; i++)
35952 : {
35953 0 : state->c.ptr.p_double[i] = state->c0.ptr.p_double[i];
35954 0 : if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
35955 : {
35956 0 : state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
35957 : }
35958 0 : if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
35959 : {
35960 0 : state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
35961 : }
35962 : }
35963 0 : state->needfg = ae_true;
35964 0 : i = 0;
35965 0 : lbl_16:
35966 0 : if( i>k-1 )
35967 : {
35968 0 : goto lbl_18;
35969 : }
35970 0 : ae_assert(ae_fp_less_eq(state->bndl.ptr.p_double[i],state->c.ptr.p_double[i])&&ae_fp_less_eq(state->c.ptr.p_double[i],state->bndu.ptr.p_double[i]), "LSFitIteration: internal error(State.C is out of bounds)", _state);
35971 0 : v = state->c.ptr.p_double[i];
35972 0 : j = 0;
35973 0 : lbl_19:
35974 0 : if( j>n-1 )
35975 : {
35976 0 : goto lbl_21;
35977 : }
35978 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[j][0], 1, ae_v_len(0,m-1));
35979 0 : state->c.ptr.p_double[i] = v-state->teststep*state->s.ptr.p_double[i];
35980 0 : if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
35981 : {
35982 0 : state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
35983 : }
35984 0 : lx = state->c.ptr.p_double[i];
35985 0 : state->rstate.stage = 0;
35986 0 : goto lbl_rcomm;
35987 0 : lbl_0:
35988 0 : lf = state->f;
35989 0 : ld = state->g.ptr.p_double[i];
35990 0 : state->c.ptr.p_double[i] = v+state->teststep*state->s.ptr.p_double[i];
35991 0 : if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
35992 : {
35993 0 : state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
35994 : }
35995 0 : rx = state->c.ptr.p_double[i];
35996 0 : state->rstate.stage = 1;
35997 0 : goto lbl_rcomm;
35998 0 : lbl_1:
35999 0 : rf = state->f;
36000 0 : rd = state->g.ptr.p_double[i];
36001 0 : state->c.ptr.p_double[i] = (lx+rx)/2;
36002 0 : if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
36003 : {
36004 0 : state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
36005 : }
36006 0 : if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
36007 : {
36008 0 : state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
36009 : }
36010 0 : state->rstate.stage = 2;
36011 0 : goto lbl_rcomm;
36012 0 : lbl_2:
36013 0 : state->c.ptr.p_double[i] = v;
36014 0 : if( !derivativecheck(lf, ld, rf, rd, state->f, state->g.ptr.p_double[i], rx-lx, _state) )
36015 : {
36016 0 : state->repvaridx = i;
36017 0 : state->repterminationtype = -7;
36018 0 : result = ae_false;
36019 0 : return result;
36020 : }
36021 0 : j = j+1;
36022 0 : goto lbl_19;
36023 0 : lbl_21:
36024 0 : i = i+1;
36025 0 : goto lbl_16;
36026 0 : lbl_18:
36027 0 : state->needfg = ae_false;
36028 0 : lbl_14:
36029 :
36030 : /*
36031 : * Fill WCur by weights:
36032 : * * for WKind=0 unit weights are chosen
36033 : * * for WKind=1 we use user-supplied weights stored in State.TaskW
36034 : */
36035 0 : rvectorsetlengthatleast(&state->wcur, n, _state);
36036 0 : for(i=0; i<=n-1; i++)
36037 : {
36038 0 : state->wcur.ptr.p_double[i] = 1.0;
36039 0 : if( state->wkind==1 )
36040 : {
36041 0 : state->wcur.ptr.p_double[i] = state->taskw.ptr.p_double[i];
36042 : }
36043 : }
36044 :
36045 : /*
36046 : * Optimize
36047 : */
36048 0 : lbl_22:
36049 0 : if( !minlmiteration(&state->optstate, _state) )
36050 : {
36051 0 : goto lbl_23;
36052 : }
36053 0 : if( !state->optstate.needfi )
36054 : {
36055 0 : goto lbl_24;
36056 : }
36057 :
36058 : /*
36059 : * calculate f[] = wi*(f(xi,c)-yi)
36060 : */
36061 0 : i = 0;
36062 0 : lbl_26:
36063 0 : if( i>n-1 )
36064 : {
36065 0 : goto lbl_28;
36066 : }
36067 0 : ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
36068 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36069 0 : state->pointindex = i;
36070 0 : lsfit_lsfitclearrequestfields(state, _state);
36071 0 : state->needf = ae_true;
36072 0 : state->rstate.stage = 3;
36073 0 : goto lbl_rcomm;
36074 0 : lbl_3:
36075 0 : state->needf = ae_false;
36076 0 : vv = state->wcur.ptr.p_double[i];
36077 0 : state->optstate.fi.ptr.p_double[i] = vv*(state->f-state->tasky.ptr.p_double[i]);
36078 0 : i = i+1;
36079 0 : goto lbl_26;
36080 0 : lbl_28:
36081 0 : goto lbl_22;
36082 0 : lbl_24:
36083 0 : if( !state->optstate.needf )
36084 : {
36085 0 : goto lbl_29;
36086 : }
36087 :
36088 : /*
36089 : * calculate F = sum (wi*(f(xi,c)-yi))^2
36090 : */
36091 0 : state->optstate.f = (double)(0);
36092 0 : i = 0;
36093 0 : lbl_31:
36094 0 : if( i>n-1 )
36095 : {
36096 0 : goto lbl_33;
36097 : }
36098 0 : ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
36099 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36100 0 : state->pointindex = i;
36101 0 : lsfit_lsfitclearrequestfields(state, _state);
36102 0 : state->needf = ae_true;
36103 0 : state->rstate.stage = 4;
36104 0 : goto lbl_rcomm;
36105 0 : lbl_4:
36106 0 : state->needf = ae_false;
36107 0 : vv = state->wcur.ptr.p_double[i];
36108 0 : state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state);
36109 0 : i = i+1;
36110 0 : goto lbl_31;
36111 0 : lbl_33:
36112 0 : goto lbl_22;
36113 0 : lbl_29:
36114 0 : if( !state->optstate.needfg )
36115 : {
36116 0 : goto lbl_34;
36117 : }
36118 :
36119 : /*
36120 : * calculate F/gradF
36121 : */
36122 0 : state->optstate.f = (double)(0);
36123 0 : for(i=0; i<=k-1; i++)
36124 : {
36125 0 : state->optstate.g.ptr.p_double[i] = (double)(0);
36126 : }
36127 0 : i = 0;
36128 0 : lbl_36:
36129 0 : if( i>n-1 )
36130 : {
36131 0 : goto lbl_38;
36132 : }
36133 0 : ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
36134 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36135 0 : state->pointindex = i;
36136 0 : lsfit_lsfitclearrequestfields(state, _state);
36137 0 : state->needfg = ae_true;
36138 0 : state->rstate.stage = 5;
36139 0 : goto lbl_rcomm;
36140 0 : lbl_5:
36141 0 : state->needfg = ae_false;
36142 0 : vv = state->wcur.ptr.p_double[i];
36143 0 : state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state);
36144 0 : v = ae_sqr(vv, _state)*2*(state->f-state->tasky.ptr.p_double[i]);
36145 0 : ae_v_addd(&state->optstate.g.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), v);
36146 0 : i = i+1;
36147 0 : goto lbl_36;
36148 0 : lbl_38:
36149 0 : goto lbl_22;
36150 0 : lbl_34:
36151 0 : if( !state->optstate.needfij )
36152 : {
36153 0 : goto lbl_39;
36154 : }
36155 :
36156 : /*
36157 : * calculate Fi/jac(Fi)
36158 : */
36159 0 : i = 0;
36160 0 : lbl_41:
36161 0 : if( i>n-1 )
36162 : {
36163 0 : goto lbl_43;
36164 : }
36165 0 : ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
36166 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36167 0 : state->pointindex = i;
36168 0 : lsfit_lsfitclearrequestfields(state, _state);
36169 0 : state->needfg = ae_true;
36170 0 : state->rstate.stage = 6;
36171 0 : goto lbl_rcomm;
36172 0 : lbl_6:
36173 0 : state->needfg = ae_false;
36174 0 : vv = state->wcur.ptr.p_double[i];
36175 0 : state->optstate.fi.ptr.p_double[i] = vv*(state->f-state->tasky.ptr.p_double[i]);
36176 0 : ae_v_moved(&state->optstate.j.ptr.pp_double[i][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), vv);
36177 0 : i = i+1;
36178 0 : goto lbl_41;
36179 0 : lbl_43:
36180 0 : goto lbl_22;
36181 0 : lbl_39:
36182 0 : if( !state->optstate.needfgh )
36183 : {
36184 0 : goto lbl_44;
36185 : }
36186 :
36187 : /*
36188 : * calculate F/grad(F)/hess(F)
36189 : */
36190 0 : state->optstate.f = (double)(0);
36191 0 : for(i=0; i<=k-1; i++)
36192 : {
36193 0 : state->optstate.g.ptr.p_double[i] = (double)(0);
36194 : }
36195 0 : for(i=0; i<=k-1; i++)
36196 : {
36197 0 : for(j=0; j<=k-1; j++)
36198 : {
36199 0 : state->optstate.h.ptr.pp_double[i][j] = (double)(0);
36200 : }
36201 : }
36202 0 : i = 0;
36203 0 : lbl_46:
36204 0 : if( i>n-1 )
36205 : {
36206 0 : goto lbl_48;
36207 : }
36208 0 : ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
36209 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36210 0 : state->pointindex = i;
36211 0 : lsfit_lsfitclearrequestfields(state, _state);
36212 0 : state->needfgh = ae_true;
36213 0 : state->rstate.stage = 7;
36214 0 : goto lbl_rcomm;
36215 0 : lbl_7:
36216 0 : state->needfgh = ae_false;
36217 0 : vv = state->wcur.ptr.p_double[i];
36218 0 : state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state);
36219 0 : v = ae_sqr(vv, _state)*2*(state->f-state->tasky.ptr.p_double[i]);
36220 0 : ae_v_addd(&state->optstate.g.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), v);
36221 0 : for(j=0; j<=k-1; j++)
36222 : {
36223 0 : v = 2*ae_sqr(vv, _state)*state->g.ptr.p_double[j];
36224 0 : ae_v_addd(&state->optstate.h.ptr.pp_double[j][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,k-1), v);
36225 0 : v = 2*ae_sqr(vv, _state)*(state->f-state->tasky.ptr.p_double[i]);
36226 0 : ae_v_addd(&state->optstate.h.ptr.pp_double[j][0], 1, &state->h.ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v);
36227 : }
36228 0 : i = i+1;
36229 0 : goto lbl_46;
36230 0 : lbl_48:
36231 0 : goto lbl_22;
36232 0 : lbl_44:
36233 0 : if( !state->optstate.xupdated )
36234 : {
36235 0 : goto lbl_49;
36236 : }
36237 :
36238 : /*
36239 : * Report new iteration
36240 : */
36241 0 : ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
36242 0 : state->f = state->optstate.f;
36243 0 : lsfit_lsfitclearrequestfields(state, _state);
36244 0 : state->xupdated = ae_true;
36245 0 : state->rstate.stage = 8;
36246 0 : goto lbl_rcomm;
36247 0 : lbl_8:
36248 0 : state->xupdated = ae_false;
36249 0 : goto lbl_22;
36250 0 : lbl_49:
36251 0 : goto lbl_22;
36252 0 : lbl_23:
36253 :
36254 : /*
36255 : * Extract results
36256 : *
36257 : * NOTE: reverse communication protocol used by this unit does NOT
36258 : * allow us to reallocate State.C[] array. Thus, we extract
36259 : * results to the temporary variable in order to avoid possible
36260 : * reallocation.
36261 : */
36262 0 : minlmresults(&state->optstate, &state->c1, &state->optrep, _state);
36263 0 : state->repterminationtype = state->optrep.terminationtype;
36264 0 : state->repiterationscount = state->optrep.iterationscount;
36265 :
36266 : /*
36267 : * calculate errors
36268 : */
36269 0 : if( state->repterminationtype<=0 )
36270 : {
36271 0 : goto lbl_51;
36272 : }
36273 :
36274 : /*
36275 : * Calculate RMS/Avg/Max/... errors
36276 : */
36277 0 : state->reprmserror = (double)(0);
36278 0 : state->repwrmserror = (double)(0);
36279 0 : state->repavgerror = (double)(0);
36280 0 : state->repavgrelerror = (double)(0);
36281 0 : state->repmaxerror = (double)(0);
36282 0 : relcnt = (double)(0);
36283 0 : i = 0;
36284 0 : lbl_53:
36285 0 : if( i>n-1 )
36286 : {
36287 0 : goto lbl_55;
36288 : }
36289 0 : ae_v_move(&state->c.ptr.p_double[0], 1, &state->c1.ptr.p_double[0], 1, ae_v_len(0,k-1));
36290 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36291 0 : state->pointindex = i;
36292 0 : lsfit_lsfitclearrequestfields(state, _state);
36293 0 : state->needf = ae_true;
36294 0 : state->rstate.stage = 9;
36295 0 : goto lbl_rcomm;
36296 0 : lbl_9:
36297 0 : state->needf = ae_false;
36298 0 : v = state->f;
36299 0 : vv = state->wcur.ptr.p_double[i];
36300 0 : state->reprmserror = state->reprmserror+ae_sqr(v-state->tasky.ptr.p_double[i], _state);
36301 0 : state->repwrmserror = state->repwrmserror+ae_sqr(vv*(v-state->tasky.ptr.p_double[i]), _state);
36302 0 : state->repavgerror = state->repavgerror+ae_fabs(v-state->tasky.ptr.p_double[i], _state);
36303 0 : if( ae_fp_neq(state->tasky.ptr.p_double[i],(double)(0)) )
36304 : {
36305 0 : state->repavgrelerror = state->repavgrelerror+ae_fabs(v-state->tasky.ptr.p_double[i], _state)/ae_fabs(state->tasky.ptr.p_double[i], _state);
36306 0 : relcnt = relcnt+1;
36307 : }
36308 0 : state->repmaxerror = ae_maxreal(state->repmaxerror, ae_fabs(v-state->tasky.ptr.p_double[i], _state), _state);
36309 0 : i = i+1;
36310 0 : goto lbl_53;
36311 0 : lbl_55:
36312 0 : state->reprmserror = ae_sqrt(state->reprmserror/n, _state);
36313 0 : state->repwrmserror = ae_sqrt(state->repwrmserror/n, _state);
36314 0 : state->repavgerror = state->repavgerror/n;
36315 0 : if( ae_fp_neq(relcnt,(double)(0)) )
36316 : {
36317 0 : state->repavgrelerror = state->repavgrelerror/relcnt;
36318 : }
36319 :
36320 : /*
36321 : * Calculate covariance matrix
36322 : */
36323 0 : rmatrixsetlengthatleast(&state->tmpjac, n, k, _state);
36324 0 : rvectorsetlengthatleast(&state->tmpf, n, _state);
36325 0 : rvectorsetlengthatleast(&state->tmp, k, _state);
36326 0 : if( ae_fp_less_eq(state->diffstep,(double)(0)) )
36327 : {
36328 0 : goto lbl_56;
36329 : }
36330 :
36331 : /*
36332 : * Compute Jacobian by means of numerical differentiation
36333 : */
36334 0 : lsfit_lsfitclearrequestfields(state, _state);
36335 0 : state->needf = ae_true;
36336 0 : i = 0;
36337 0 : lbl_58:
36338 0 : if( i>n-1 )
36339 : {
36340 0 : goto lbl_60;
36341 : }
36342 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36343 0 : state->pointindex = i;
36344 0 : state->rstate.stage = 10;
36345 0 : goto lbl_rcomm;
36346 0 : lbl_10:
36347 0 : state->tmpf.ptr.p_double[i] = state->f;
36348 0 : j = 0;
36349 0 : lbl_61:
36350 0 : if( j>k-1 )
36351 : {
36352 0 : goto lbl_63;
36353 : }
36354 0 : v = state->c.ptr.p_double[j];
36355 0 : lx = v-state->diffstep*state->s.ptr.p_double[j];
36356 0 : state->c.ptr.p_double[j] = lx;
36357 0 : if( ae_isfinite(state->bndl.ptr.p_double[j], _state) )
36358 : {
36359 0 : state->c.ptr.p_double[j] = ae_maxreal(state->c.ptr.p_double[j], state->bndl.ptr.p_double[j], _state);
36360 : }
36361 0 : state->rstate.stage = 11;
36362 0 : goto lbl_rcomm;
36363 0 : lbl_11:
36364 0 : lf = state->f;
36365 0 : rx = v+state->diffstep*state->s.ptr.p_double[j];
36366 0 : state->c.ptr.p_double[j] = rx;
36367 0 : if( ae_isfinite(state->bndu.ptr.p_double[j], _state) )
36368 : {
36369 0 : state->c.ptr.p_double[j] = ae_minreal(state->c.ptr.p_double[j], state->bndu.ptr.p_double[j], _state);
36370 : }
36371 0 : state->rstate.stage = 12;
36372 0 : goto lbl_rcomm;
36373 0 : lbl_12:
36374 0 : rf = state->f;
36375 0 : state->c.ptr.p_double[j] = v;
36376 0 : if( ae_fp_neq(rx,lx) )
36377 : {
36378 0 : state->tmpjac.ptr.pp_double[i][j] = (rf-lf)/(rx-lx);
36379 : }
36380 : else
36381 : {
36382 0 : state->tmpjac.ptr.pp_double[i][j] = (double)(0);
36383 : }
36384 0 : j = j+1;
36385 0 : goto lbl_61;
36386 0 : lbl_63:
36387 0 : i = i+1;
36388 0 : goto lbl_58;
36389 0 : lbl_60:
36390 0 : state->needf = ae_false;
36391 0 : goto lbl_57;
36392 0 : lbl_56:
36393 :
36394 : /*
36395 : * Jacobian is calculated with user-provided analytic gradient
36396 : */
36397 0 : lsfit_lsfitclearrequestfields(state, _state);
36398 0 : state->needfg = ae_true;
36399 0 : i = 0;
36400 0 : lbl_64:
36401 0 : if( i>n-1 )
36402 : {
36403 0 : goto lbl_66;
36404 : }
36405 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
36406 0 : state->pointindex = i;
36407 0 : state->rstate.stage = 13;
36408 0 : goto lbl_rcomm;
36409 0 : lbl_13:
36410 0 : state->tmpf.ptr.p_double[i] = state->f;
36411 0 : for(j=0; j<=k-1; j++)
36412 : {
36413 0 : state->tmpjac.ptr.pp_double[i][j] = state->g.ptr.p_double[j];
36414 : }
36415 0 : i = i+1;
36416 0 : goto lbl_64;
36417 0 : lbl_66:
36418 0 : state->needfg = ae_false;
36419 0 : lbl_57:
36420 0 : for(i=0; i<=k-1; i++)
36421 : {
36422 0 : state->tmp.ptr.p_double[i] = 0.0;
36423 : }
36424 0 : lsfit_estimateerrors(&state->tmpjac, &state->tmpf, &state->tasky, &state->wcur, &state->tmp, &state->s, n, k, &state->rep, &state->tmpjacw, 0, _state);
36425 0 : lbl_51:
36426 0 : result = ae_false;
36427 0 : return result;
36428 :
36429 : /*
36430 : * Saving state
36431 : */
36432 0 : lbl_rcomm:
36433 0 : result = ae_true;
36434 0 : state->rstate.ia.ptr.p_int[0] = n;
36435 0 : state->rstate.ia.ptr.p_int[1] = m;
36436 0 : state->rstate.ia.ptr.p_int[2] = k;
36437 0 : state->rstate.ia.ptr.p_int[3] = i;
36438 0 : state->rstate.ia.ptr.p_int[4] = j;
36439 0 : state->rstate.ia.ptr.p_int[5] = j1;
36440 0 : state->rstate.ia.ptr.p_int[6] = info;
36441 0 : state->rstate.ra.ptr.p_double[0] = lx;
36442 0 : state->rstate.ra.ptr.p_double[1] = lf;
36443 0 : state->rstate.ra.ptr.p_double[2] = ld;
36444 0 : state->rstate.ra.ptr.p_double[3] = rx;
36445 0 : state->rstate.ra.ptr.p_double[4] = rf;
36446 0 : state->rstate.ra.ptr.p_double[5] = rd;
36447 0 : state->rstate.ra.ptr.p_double[6] = v;
36448 0 : state->rstate.ra.ptr.p_double[7] = vv;
36449 0 : state->rstate.ra.ptr.p_double[8] = relcnt;
36450 0 : return result;
36451 : }
36452 :
36453 :
36454 : /*************************************************************************
36455 : Nonlinear least squares fitting results.
36456 :
36457 : Called after return from LSFitFit().
36458 :
36459 : INPUT PARAMETERS:
36460 : State - algorithm state
36461 :
36462 : OUTPUT PARAMETERS:
36463 : Info - completion code:
36464 : * -8 optimizer detected NAN/INF in the target
36465 : function and/or gradient
36466 : * -7 gradient verification failed.
36467 : See LSFitSetGradientCheck() for more information.
36468 : * -3 inconsistent constraints
36469 : * 2 relative step is no more than EpsX.
36470 : * 5 MaxIts steps was taken
36471 : * 7 stopping conditions are too stringent,
36472 : further improvement is impossible
36473 : C - array[0..K-1], solution
36474 : Rep - optimization report. On success following fields are set:
36475 : * R2 non-adjusted coefficient of determination
36476 : (non-weighted)
36477 : * RMSError rms error on the (X,Y).
36478 : * AvgError average error on the (X,Y).
36479 : * AvgRelError average relative error on the non-zero Y
36480 : * MaxError maximum error
36481 : NON-WEIGHTED ERRORS ARE CALCULATED
36482 : * WRMSError weighted rms error on the (X,Y).
36483 :
36484 : ERRORS IN PARAMETERS
36485 :
36486 : This solver also calculates different kinds of errors in parameters and
36487 : fills corresponding fields of report:
36488 : * Rep.CovPar covariance matrix for parameters, array[K,K].
36489 : * Rep.ErrPar errors in parameters, array[K],
36490 : errpar = sqrt(diag(CovPar))
36491 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
36492 : best-fit curve from "ideal" best-fit curve built with
36493 : infinite number of samples, array[N].
36494 : errcurve = sqrt(diag(J*CovPar*J')),
36495 : where J is Jacobian matrix.
36496 : * Rep.Noise vector of per-point estimates of noise, array[N]
36497 :
36498 : IMPORTANT: errors in parameters are calculated without taking into
36499 : account boundary/linear constraints! Presence of constraints
36500 : changes distribution of errors, but there is no easy way to
36501 : account for constraints when you calculate covariance matrix.
36502 :
36503 : NOTE: noise in the data is estimated as follows:
36504 : * for fitting without user-supplied weights all points are
36505 : assumed to have same level of noise, which is estimated from
36506 : the data
36507 : * for fitting with user-supplied weights we assume that noise
36508 : level in I-th point is inversely proportional to Ith weight.
36509 : Coefficient of proportionality is estimated from the data.
36510 :
36511 : NOTE: we apply small amount of regularization when we invert squared
36512 : Jacobian and calculate covariance matrix. It guarantees that
36513 : algorithm won't divide by zero during inversion, but skews
36514 : error estimates a bit (fractional error is about 10^-9).
36515 :
36516 : However, we believe that this difference is insignificant for
36517 : all practical purposes except for the situation when you want
36518 : to compare ALGLIB results with "reference" implementation up
36519 : to the last significant digit.
36520 :
36521 : NOTE: covariance matrix is estimated using correction for degrees
36522 : of freedom (covariances are divided by N-M instead of dividing
36523 : by N).
36524 :
36525 : -- ALGLIB --
36526 : Copyright 17.08.2009 by Bochkanov Sergey
36527 : *************************************************************************/
36528 0 : void lsfitresults(lsfitstate* state,
36529 : ae_int_t* info,
36530 : /* Real */ ae_vector* c,
36531 : lsfitreport* rep,
36532 : ae_state *_state)
36533 : {
36534 : ae_int_t i;
36535 : ae_int_t j;
36536 :
36537 0 : *info = 0;
36538 0 : ae_vector_clear(c);
36539 0 : _lsfitreport_clear(rep);
36540 :
36541 0 : lsfit_clearreport(rep, _state);
36542 0 : *info = state->repterminationtype;
36543 0 : rep->varidx = state->repvaridx;
36544 0 : if( *info>0 )
36545 : {
36546 0 : ae_vector_set_length(c, state->k, _state);
36547 0 : ae_v_move(&c->ptr.p_double[0], 1, &state->c1.ptr.p_double[0], 1, ae_v_len(0,state->k-1));
36548 0 : rep->rmserror = state->reprmserror;
36549 0 : rep->wrmserror = state->repwrmserror;
36550 0 : rep->avgerror = state->repavgerror;
36551 0 : rep->avgrelerror = state->repavgrelerror;
36552 0 : rep->maxerror = state->repmaxerror;
36553 0 : rep->iterationscount = state->repiterationscount;
36554 0 : ae_matrix_set_length(&rep->covpar, state->k, state->k, _state);
36555 0 : ae_vector_set_length(&rep->errpar, state->k, _state);
36556 0 : ae_vector_set_length(&rep->errcurve, state->npoints, _state);
36557 0 : ae_vector_set_length(&rep->noise, state->npoints, _state);
36558 0 : rep->r2 = state->rep.r2;
36559 0 : for(i=0; i<=state->k-1; i++)
36560 : {
36561 0 : for(j=0; j<=state->k-1; j++)
36562 : {
36563 0 : rep->covpar.ptr.pp_double[i][j] = state->rep.covpar.ptr.pp_double[i][j];
36564 : }
36565 0 : rep->errpar.ptr.p_double[i] = state->rep.errpar.ptr.p_double[i];
36566 : }
36567 0 : for(i=0; i<=state->npoints-1; i++)
36568 : {
36569 0 : rep->errcurve.ptr.p_double[i] = state->rep.errcurve.ptr.p_double[i];
36570 0 : rep->noise.ptr.p_double[i] = state->rep.noise.ptr.p_double[i];
36571 : }
36572 : }
36573 0 : }
36574 :
36575 :
36576 : /*************************************************************************
36577 : This subroutine turns on verification of the user-supplied analytic
36578 : gradient:
36579 : * user calls this subroutine before fitting begins
36580 : * LSFitFit() is called
36581 : * prior to actual fitting, for each point in data set X_i and each
36582 : component of parameters being fited C_j algorithm performs following
36583 : steps:
36584 : * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j],
36585 : where C_j is j-th parameter and S[j] is a scale of j-th parameter
36586 : * if needed, steps are bounded with respect to constraints on C[]
36587 : * F(X_i|C) is evaluated at these trial points
36588 : * we perform one more evaluation in the middle point of the interval
36589 : * we build cubic model using function values and derivatives at trial
36590 : points and we compare its prediction with actual value in the middle
36591 : point
36592 : * in case difference between prediction and actual value is higher than
36593 : some predetermined threshold, algorithm stops with completion code -7;
36594 : Rep.VarIdx is set to index of the parameter with incorrect derivative.
36595 : * after verification is over, algorithm proceeds to the actual optimization.
36596 :
36597 : NOTE 1: verification needs N*K (points count * parameters count) gradient
36598 : evaluations. It is very costly and you should use it only for low
36599 : dimensional problems, when you want to be sure that you've
36600 : correctly calculated analytic derivatives. You should not use it
36601 : in the production code (unless you want to check derivatives
36602 : provided by some third party).
36603 :
36604 : NOTE 2: you should carefully choose TestStep. Value which is too large
36605 : (so large that function behaviour is significantly non-cubic) will
36606 : lead to false alarms. You may use different step for different
36607 : parameters by means of setting scale with LSFitSetScale().
36608 :
36609 : NOTE 3: this function may lead to false positives. In case it reports that
36610 : I-th derivative was calculated incorrectly, you may decrease test
36611 : step and try one more time - maybe your function changes too
36612 : sharply and your step is too large for such rapidly chanding
36613 : function.
36614 :
36615 : NOTE 4: this function works only for optimizers created with LSFitCreateWFG()
36616 : or LSFitCreateFG() constructors.
36617 :
36618 : INPUT PARAMETERS:
36619 : State - structure used to store algorithm state
36620 : TestStep - verification step:
36621 : * TestStep=0 turns verification off
36622 : * TestStep>0 activates verification
36623 :
36624 : -- ALGLIB --
36625 : Copyright 15.06.2012 by Bochkanov Sergey
36626 : *************************************************************************/
36627 0 : void lsfitsetgradientcheck(lsfitstate* state,
36628 : double teststep,
36629 : ae_state *_state)
36630 : {
36631 :
36632 :
36633 0 : ae_assert(ae_isfinite(teststep, _state), "LSFitSetGradientCheck: TestStep contains NaN or Infinite", _state);
36634 0 : ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "LSFitSetGradientCheck: invalid argument TestStep(TestStep<0)", _state);
36635 0 : state->teststep = teststep;
36636 0 : }
36637 :
36638 :
36639 : /*************************************************************************
36640 : This function analyzes section of curve for processing by RDP algorithm:
36641 : given set of points X,Y with indexes [I0,I1] it returns point with
36642 : worst deviation from linear model (non-parametric version which sees curve
36643 : as Y(x)).
36644 :
36645 : Input parameters:
36646 : X, Y - SORTED arrays.
36647 : I0,I1 - interval (boundaries included) to process
36648 : Eps - desired precision
36649 :
36650 : OUTPUT PARAMETERS:
36651 : WorstIdx - index of worst point
36652 : WorstError - error at worst point
36653 :
36654 : NOTE: this function guarantees that it returns exactly zero for a section
36655 : with less than 3 points.
36656 :
36657 : -- ALGLIB PROJECT --
36658 : Copyright 02.10.2014 by Bochkanov Sergey
36659 : *************************************************************************/
36660 0 : static void lsfit_rdpanalyzesection(/* Real */ ae_vector* x,
36661 : /* Real */ ae_vector* y,
36662 : ae_int_t i0,
36663 : ae_int_t i1,
36664 : ae_int_t* worstidx,
36665 : double* worsterror,
36666 : ae_state *_state)
36667 : {
36668 : ae_int_t i;
36669 : double xleft;
36670 : double xright;
36671 : double vx;
36672 : double ve;
36673 : double a;
36674 : double b;
36675 :
36676 0 : *worstidx = 0;
36677 0 : *worsterror = 0;
36678 :
36679 0 : xleft = x->ptr.p_double[i0];
36680 0 : xright = x->ptr.p_double[i1];
36681 0 : if( i1-i0+1<3||ae_fp_eq(xright,xleft) )
36682 : {
36683 0 : *worstidx = i0;
36684 0 : *worsterror = 0.0;
36685 0 : return;
36686 : }
36687 0 : a = (y->ptr.p_double[i1]-y->ptr.p_double[i0])/(xright-xleft);
36688 0 : b = (y->ptr.p_double[i0]*xright-y->ptr.p_double[i1]*xleft)/(xright-xleft);
36689 0 : *worstidx = -1;
36690 0 : *worsterror = (double)(0);
36691 0 : for(i=i0+1; i<=i1-1; i++)
36692 : {
36693 0 : vx = x->ptr.p_double[i];
36694 0 : ve = ae_fabs(a*vx+b-y->ptr.p_double[i], _state);
36695 0 : if( (ae_fp_greater(vx,xleft)&&ae_fp_less(vx,xright))&&ae_fp_greater(ve,*worsterror) )
36696 : {
36697 0 : *worsterror = ve;
36698 0 : *worstidx = i;
36699 : }
36700 : }
36701 : }
36702 :
36703 :
36704 : /*************************************************************************
36705 : Recursive splitting of interval [I0,I1] (right boundary included) with RDP
36706 : algorithm (non-parametric version which sees curve as Y(x)).
36707 :
36708 : Input parameters:
36709 : X, Y - SORTED arrays.
36710 : I0,I1 - interval (boundaries included) to process
36711 : Eps - desired precision
36712 : XOut,YOut - preallocated output arrays large enough to store result;
36713 : XOut[0..1], YOut[0..1] contain first and last points of
36714 : curve
36715 : NOut - must contain 2 on input
36716 :
36717 : OUTPUT PARAMETERS:
36718 : XOut, YOut - curve generated by RDP algorithm, UNSORTED
36719 : NOut - number of points in curve
36720 :
36721 : -- ALGLIB PROJECT --
36722 : Copyright 02.10.2014 by Bochkanov Sergey
36723 : *************************************************************************/
36724 0 : static void lsfit_rdprecursive(/* Real */ ae_vector* x,
36725 : /* Real */ ae_vector* y,
36726 : ae_int_t i0,
36727 : ae_int_t i1,
36728 : double eps,
36729 : /* Real */ ae_vector* xout,
36730 : /* Real */ ae_vector* yout,
36731 : ae_int_t* nout,
36732 : ae_state *_state)
36733 : {
36734 : ae_int_t worstidx;
36735 : double worsterror;
36736 :
36737 :
36738 0 : ae_assert(ae_fp_greater(eps,(double)(0)), "RDPRecursive: internal error, Eps<0", _state);
36739 0 : lsfit_rdpanalyzesection(x, y, i0, i1, &worstidx, &worsterror, _state);
36740 0 : if( ae_fp_less_eq(worsterror,eps) )
36741 : {
36742 0 : return;
36743 : }
36744 0 : xout->ptr.p_double[*nout] = x->ptr.p_double[worstidx];
36745 0 : yout->ptr.p_double[*nout] = y->ptr.p_double[worstidx];
36746 0 : *nout = *nout+1;
36747 0 : if( worstidx-i0<i1-worstidx )
36748 : {
36749 0 : lsfit_rdprecursive(x, y, i0, worstidx, eps, xout, yout, nout, _state);
36750 0 : lsfit_rdprecursive(x, y, worstidx, i1, eps, xout, yout, nout, _state);
36751 : }
36752 : else
36753 : {
36754 0 : lsfit_rdprecursive(x, y, worstidx, i1, eps, xout, yout, nout, _state);
36755 0 : lsfit_rdprecursive(x, y, i0, worstidx, eps, xout, yout, nout, _state);
36756 : }
36757 : }
36758 :
36759 :
36760 : /*************************************************************************
36761 : Internal 4PL/5PL fitting function.
36762 :
36763 : Accepts X, Y and already initialized and prepared MinLMState structure.
36764 : On input P1 contains initial guess, on output it contains solution. FLast
36765 : stores function value at P1.
36766 : *************************************************************************/
36767 0 : static void lsfit_logisticfitinternal(/* Real */ ae_vector* x,
36768 : /* Real */ ae_vector* y,
36769 : ae_int_t n,
36770 : ae_bool is4pl,
36771 : double lambdav,
36772 : minlmstate* state,
36773 : minlmreport* replm,
36774 : /* Real */ ae_vector* p1,
36775 : double* flast,
36776 : ae_state *_state)
36777 : {
36778 : ae_int_t i;
36779 : ae_int_t j;
36780 : double ta;
36781 : double tb;
36782 : double tc;
36783 : double td;
36784 : double tg;
36785 : double vp0;
36786 : double vp1;
36787 :
36788 0 : *flast = 0;
36789 :
36790 0 : minlmrestartfrom(state, p1, _state);
36791 0 : while(minlmiteration(state, _state))
36792 : {
36793 0 : ta = state->x.ptr.p_double[0];
36794 0 : tb = state->x.ptr.p_double[1];
36795 0 : tc = state->x.ptr.p_double[2];
36796 0 : td = state->x.ptr.p_double[3];
36797 0 : tg = state->x.ptr.p_double[4];
36798 0 : if( state->xupdated )
36799 : {
36800 :
36801 : /*
36802 : * Save best function value obtained so far.
36803 : */
36804 0 : *flast = state->f;
36805 0 : continue;
36806 : }
36807 0 : if( state->needfi||state->needfij )
36808 : {
36809 :
36810 : /*
36811 : * Function vector and Jacobian
36812 : */
36813 0 : for(i=0; i<=n-1; i++)
36814 : {
36815 0 : ae_assert(ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)), "LogisticFitInternal: integrity error", _state);
36816 :
36817 : /*
36818 : * Handle zero X
36819 : */
36820 0 : if( ae_fp_eq(x->ptr.p_double[i],(double)(0)) )
36821 : {
36822 0 : if( ae_fp_greater_eq(tb,(double)(0)) )
36823 : {
36824 :
36825 : /*
36826 : * Positive or zero TB, limit X^TB subject to X->+0 is equal to zero.
36827 : */
36828 0 : state->fi.ptr.p_double[i] = ta-y->ptr.p_double[i];
36829 0 : if( state->needfij )
36830 : {
36831 0 : state->j.ptr.pp_double[i][0] = (double)(1);
36832 0 : state->j.ptr.pp_double[i][1] = (double)(0);
36833 0 : state->j.ptr.pp_double[i][2] = (double)(0);
36834 0 : state->j.ptr.pp_double[i][3] = (double)(0);
36835 0 : state->j.ptr.pp_double[i][4] = (double)(0);
36836 : }
36837 : }
36838 : else
36839 : {
36840 :
36841 : /*
36842 : * Negative TB, limit X^TB subject to X->+0 is equal to +INF.
36843 : */
36844 0 : state->fi.ptr.p_double[i] = td-y->ptr.p_double[i];
36845 0 : if( state->needfij )
36846 : {
36847 0 : state->j.ptr.pp_double[i][0] = (double)(0);
36848 0 : state->j.ptr.pp_double[i][1] = (double)(0);
36849 0 : state->j.ptr.pp_double[i][2] = (double)(0);
36850 0 : state->j.ptr.pp_double[i][3] = (double)(1);
36851 0 : state->j.ptr.pp_double[i][4] = (double)(0);
36852 : }
36853 : }
36854 0 : continue;
36855 : }
36856 :
36857 : /*
36858 : * Positive X.
36859 : * Prepare VP0/VP1, it may become infinite or nearly overflow in some rare cases,
36860 : * handle these cases
36861 : */
36862 0 : vp0 = ae_pow(x->ptr.p_double[i]/tc, tb, _state);
36863 0 : if( is4pl )
36864 : {
36865 0 : vp1 = 1+vp0;
36866 : }
36867 : else
36868 : {
36869 0 : vp1 = ae_pow(1+vp0, tg, _state);
36870 : }
36871 0 : if( (!ae_isfinite(vp1, _state)||ae_fp_greater(vp0,1.0E50))||ae_fp_greater(vp1,1.0E50) )
36872 : {
36873 :
36874 : /*
36875 : * VP0/VP1 are not finite, assume that it is +INF or -INF
36876 : */
36877 0 : state->fi.ptr.p_double[i] = td-y->ptr.p_double[i];
36878 0 : if( state->needfij )
36879 : {
36880 0 : state->j.ptr.pp_double[i][0] = (double)(0);
36881 0 : state->j.ptr.pp_double[i][1] = (double)(0);
36882 0 : state->j.ptr.pp_double[i][2] = (double)(0);
36883 0 : state->j.ptr.pp_double[i][3] = (double)(1);
36884 0 : state->j.ptr.pp_double[i][4] = (double)(0);
36885 : }
36886 0 : continue;
36887 : }
36888 :
36889 : /*
36890 : * VP0/VP1 are finite, normal processing
36891 : */
36892 0 : if( is4pl )
36893 : {
36894 0 : state->fi.ptr.p_double[i] = td+(ta-td)/vp1-y->ptr.p_double[i];
36895 0 : if( state->needfij )
36896 : {
36897 0 : state->j.ptr.pp_double[i][0] = 1/vp1;
36898 0 : state->j.ptr.pp_double[i][1] = -(ta-td)*vp0*ae_log(x->ptr.p_double[i]/tc, _state)/ae_sqr(vp1, _state);
36899 0 : state->j.ptr.pp_double[i][2] = (ta-td)*(tb/tc)*vp0/ae_sqr(vp1, _state);
36900 0 : state->j.ptr.pp_double[i][3] = 1-1/vp1;
36901 0 : state->j.ptr.pp_double[i][4] = (double)(0);
36902 : }
36903 : }
36904 : else
36905 : {
36906 0 : state->fi.ptr.p_double[i] = td+(ta-td)/vp1-y->ptr.p_double[i];
36907 0 : if( state->needfij )
36908 : {
36909 0 : state->j.ptr.pp_double[i][0] = 1/vp1;
36910 0 : state->j.ptr.pp_double[i][1] = (ta-td)*(-tg)*ae_pow(1+vp0, -tg-1, _state)*vp0*ae_log(x->ptr.p_double[i]/tc, _state);
36911 0 : state->j.ptr.pp_double[i][2] = (ta-td)*(-tg)*ae_pow(1+vp0, -tg-1, _state)*vp0*(-tb/tc);
36912 0 : state->j.ptr.pp_double[i][3] = 1-1/vp1;
36913 0 : state->j.ptr.pp_double[i][4] = -(ta-td)/vp1*ae_log(1+vp0, _state);
36914 : }
36915 : }
36916 : }
36917 :
36918 : /*
36919 : * Add regularizer
36920 : */
36921 0 : for(i=0; i<=4; i++)
36922 : {
36923 0 : state->fi.ptr.p_double[n+i] = lambdav*state->x.ptr.p_double[i];
36924 0 : if( state->needfij )
36925 : {
36926 0 : for(j=0; j<=4; j++)
36927 : {
36928 0 : state->j.ptr.pp_double[n+i][j] = 0.0;
36929 : }
36930 0 : state->j.ptr.pp_double[n+i][i] = lambdav;
36931 : }
36932 : }
36933 :
36934 : /*
36935 : * Done
36936 : */
36937 0 : continue;
36938 : }
36939 0 : ae_assert(ae_false, "LogisticFitX: internal error", _state);
36940 : }
36941 0 : minlmresultsbuf(state, p1, replm, _state);
36942 0 : ae_assert(replm->terminationtype>0, "LogisticFitX: internal error", _state);
36943 0 : }
36944 :
36945 :
36946 : /*************************************************************************
36947 : Calculate errors for 4PL/5PL fit.
36948 : Leaves other fields of Rep unchanged, so caller should properly initialize
36949 : it with ClearRep() call.
36950 :
36951 : -- ALGLIB PROJECT --
36952 : Copyright 28.04.2017 by Bochkanov Sergey
36953 : *************************************************************************/
36954 0 : static void lsfit_logisticfit45errors(/* Real */ ae_vector* x,
36955 : /* Real */ ae_vector* y,
36956 : ae_int_t n,
36957 : double a,
36958 : double b,
36959 : double c,
36960 : double d,
36961 : double g,
36962 : lsfitreport* rep,
36963 : ae_state *_state)
36964 : {
36965 : ae_int_t i;
36966 : ae_int_t k;
36967 : double v;
36968 : double rss;
36969 : double tss;
36970 : double meany;
36971 :
36972 :
36973 :
36974 : /*
36975 : * Calculate errors
36976 : */
36977 0 : rep->rmserror = (double)(0);
36978 0 : rep->avgerror = (double)(0);
36979 0 : rep->avgrelerror = (double)(0);
36980 0 : rep->maxerror = (double)(0);
36981 0 : k = 0;
36982 0 : rss = 0.0;
36983 0 : tss = 0.0;
36984 0 : meany = 0.0;
36985 0 : for(i=0; i<=n-1; i++)
36986 : {
36987 0 : meany = meany+y->ptr.p_double[i];
36988 : }
36989 0 : meany = meany/n;
36990 0 : for(i=0; i<=n-1; i++)
36991 : {
36992 :
36993 : /*
36994 : * Calculate residual from regression
36995 : */
36996 0 : if( ae_fp_greater(x->ptr.p_double[i],(double)(0)) )
36997 : {
36998 0 : v = d+(a-d)/ae_pow(1.0+ae_pow(x->ptr.p_double[i]/c, b, _state), g, _state)-y->ptr.p_double[i];
36999 : }
37000 : else
37001 : {
37002 0 : if( ae_fp_greater_eq(b,(double)(0)) )
37003 : {
37004 0 : v = a-y->ptr.p_double[i];
37005 : }
37006 : else
37007 : {
37008 0 : v = d-y->ptr.p_double[i];
37009 : }
37010 : }
37011 :
37012 : /*
37013 : * Update RSS (residual sum of squares) and TSS (total sum of squares)
37014 : * which are used to calculate coefficient of determination.
37015 : *
37016 : * NOTE: we use formula R2 = 1-RSS/TSS because it has nice property of
37017 : * being equal to 0.0 if and only if model perfectly fits data.
37018 : *
37019 : * When we fit nonlinear models, there are exist multiple ways of
37020 : * determining R2, each of them giving different results. Formula
37021 : * above is the most intuitive one.
37022 : */
37023 0 : rss = rss+v*v;
37024 0 : tss = tss+ae_sqr(y->ptr.p_double[i]-meany, _state);
37025 :
37026 : /*
37027 : * Update errors
37028 : */
37029 0 : rep->rmserror = rep->rmserror+ae_sqr(v, _state);
37030 0 : rep->avgerror = rep->avgerror+ae_fabs(v, _state);
37031 0 : if( ae_fp_neq(y->ptr.p_double[i],(double)(0)) )
37032 : {
37033 0 : rep->avgrelerror = rep->avgrelerror+ae_fabs(v/y->ptr.p_double[i], _state);
37034 0 : k = k+1;
37035 : }
37036 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state);
37037 : }
37038 0 : rep->rmserror = ae_sqrt(rep->rmserror/n, _state);
37039 0 : rep->avgerror = rep->avgerror/n;
37040 0 : if( k>0 )
37041 : {
37042 0 : rep->avgrelerror = rep->avgrelerror/k;
37043 : }
37044 0 : rep->r2 = 1.0-rss/tss;
37045 0 : }
37046 :
37047 :
37048 : /*************************************************************************
37049 : Internal spline fitting subroutine
37050 :
37051 : -- ALGLIB PROJECT --
37052 : Copyright 08.09.2009 by Bochkanov Sergey
37053 : *************************************************************************/
37054 0 : static void lsfit_spline1dfitinternal(ae_int_t st,
37055 : /* Real */ ae_vector* x,
37056 : /* Real */ ae_vector* y,
37057 : /* Real */ ae_vector* w,
37058 : ae_int_t n,
37059 : /* Real */ ae_vector* xc,
37060 : /* Real */ ae_vector* yc,
37061 : /* Integer */ ae_vector* dc,
37062 : ae_int_t k,
37063 : ae_int_t m,
37064 : ae_int_t* info,
37065 : spline1dinterpolant* s,
37066 : spline1dfitreport* rep,
37067 : ae_state *_state)
37068 : {
37069 : ae_frame _frame_block;
37070 : ae_vector _x;
37071 : ae_vector _y;
37072 : ae_vector _w;
37073 : ae_vector _xc;
37074 : ae_vector _yc;
37075 : ae_matrix fmatrix;
37076 : ae_matrix cmatrix;
37077 : ae_vector y2;
37078 : ae_vector w2;
37079 : ae_vector sx;
37080 : ae_vector sy;
37081 : ae_vector sd;
37082 : ae_vector tmp;
37083 : ae_vector xoriginal;
37084 : ae_vector yoriginal;
37085 : lsfitreport lrep;
37086 : double v0;
37087 : double v1;
37088 : double v2;
37089 : double mx;
37090 : spline1dinterpolant s2;
37091 : ae_int_t i;
37092 : ae_int_t j;
37093 : ae_int_t relcnt;
37094 : double xa;
37095 : double xb;
37096 : double sa;
37097 : double sb;
37098 : double bl;
37099 : double br;
37100 : double decay;
37101 :
37102 0 : ae_frame_make(_state, &_frame_block);
37103 0 : memset(&_x, 0, sizeof(_x));
37104 0 : memset(&_y, 0, sizeof(_y));
37105 0 : memset(&_w, 0, sizeof(_w));
37106 0 : memset(&_xc, 0, sizeof(_xc));
37107 0 : memset(&_yc, 0, sizeof(_yc));
37108 0 : memset(&fmatrix, 0, sizeof(fmatrix));
37109 0 : memset(&cmatrix, 0, sizeof(cmatrix));
37110 0 : memset(&y2, 0, sizeof(y2));
37111 0 : memset(&w2, 0, sizeof(w2));
37112 0 : memset(&sx, 0, sizeof(sx));
37113 0 : memset(&sy, 0, sizeof(sy));
37114 0 : memset(&sd, 0, sizeof(sd));
37115 0 : memset(&tmp, 0, sizeof(tmp));
37116 0 : memset(&xoriginal, 0, sizeof(xoriginal));
37117 0 : memset(&yoriginal, 0, sizeof(yoriginal));
37118 0 : memset(&lrep, 0, sizeof(lrep));
37119 0 : memset(&s2, 0, sizeof(s2));
37120 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
37121 0 : x = &_x;
37122 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
37123 0 : y = &_y;
37124 0 : ae_vector_init_copy(&_w, w, _state, ae_true);
37125 0 : w = &_w;
37126 0 : ae_vector_init_copy(&_xc, xc, _state, ae_true);
37127 0 : xc = &_xc;
37128 0 : ae_vector_init_copy(&_yc, yc, _state, ae_true);
37129 0 : yc = &_yc;
37130 0 : *info = 0;
37131 0 : _spline1dinterpolant_clear(s);
37132 0 : _spline1dfitreport_clear(rep);
37133 0 : ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
37134 0 : ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true);
37135 0 : ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
37136 0 : ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
37137 0 : ae_vector_init(&sx, 0, DT_REAL, _state, ae_true);
37138 0 : ae_vector_init(&sy, 0, DT_REAL, _state, ae_true);
37139 0 : ae_vector_init(&sd, 0, DT_REAL, _state, ae_true);
37140 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
37141 0 : ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
37142 0 : ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
37143 0 : _lsfitreport_init(&lrep, _state, ae_true);
37144 0 : _spline1dinterpolant_init(&s2, _state, ae_true);
37145 :
37146 0 : ae_assert(st==0||st==1, "Spline1DFit: internal error!", _state);
37147 0 : if( st==0&&m<4 )
37148 : {
37149 0 : *info = -1;
37150 0 : ae_frame_leave(_state);
37151 0 : return;
37152 : }
37153 0 : if( st==1&&m<4 )
37154 : {
37155 0 : *info = -1;
37156 0 : ae_frame_leave(_state);
37157 0 : return;
37158 : }
37159 0 : if( (n<1||k<0)||k>=m )
37160 : {
37161 0 : *info = -1;
37162 0 : ae_frame_leave(_state);
37163 0 : return;
37164 : }
37165 0 : for(i=0; i<=k-1; i++)
37166 : {
37167 0 : *info = 0;
37168 0 : if( dc->ptr.p_int[i]<0 )
37169 : {
37170 0 : *info = -1;
37171 : }
37172 0 : if( dc->ptr.p_int[i]>1 )
37173 : {
37174 0 : *info = -1;
37175 : }
37176 0 : if( *info<0 )
37177 : {
37178 0 : ae_frame_leave(_state);
37179 0 : return;
37180 : }
37181 : }
37182 0 : if( st==1&&m%2!=0 )
37183 : {
37184 :
37185 : /*
37186 : * Hermite fitter must have even number of basis functions
37187 : */
37188 0 : *info = -2;
37189 0 : ae_frame_leave(_state);
37190 0 : return;
37191 : }
37192 :
37193 : /*
37194 : * weight decay for correct handling of task which becomes
37195 : * degenerate after constraints are applied
37196 : */
37197 0 : decay = 10000*ae_machineepsilon;
37198 :
37199 : /*
37200 : * Scale X, Y, XC, YC
37201 : */
37202 0 : lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
37203 :
37204 : /*
37205 : * allocate space, initialize:
37206 : * * SX - grid for basis functions
37207 : * * SY - values of basis functions at grid points
37208 : * * FMatrix- values of basis functions at X[]
37209 : * * CMatrix- values (derivatives) of basis functions at XC[]
37210 : */
37211 0 : ae_vector_set_length(&y2, n+m, _state);
37212 0 : ae_vector_set_length(&w2, n+m, _state);
37213 0 : ae_matrix_set_length(&fmatrix, n+m, m, _state);
37214 0 : if( k>0 )
37215 : {
37216 0 : ae_matrix_set_length(&cmatrix, k, m+1, _state);
37217 : }
37218 0 : if( st==0 )
37219 : {
37220 :
37221 : /*
37222 : * allocate space for cubic spline
37223 : */
37224 0 : ae_vector_set_length(&sx, m-2, _state);
37225 0 : ae_vector_set_length(&sy, m-2, _state);
37226 0 : for(j=0; j<=m-2-1; j++)
37227 : {
37228 0 : sx.ptr.p_double[j] = (double)(2*j)/(double)(m-2-1)-1;
37229 : }
37230 : }
37231 0 : if( st==1 )
37232 : {
37233 :
37234 : /*
37235 : * allocate space for Hermite spline
37236 : */
37237 0 : ae_vector_set_length(&sx, m/2, _state);
37238 0 : ae_vector_set_length(&sy, m/2, _state);
37239 0 : ae_vector_set_length(&sd, m/2, _state);
37240 0 : for(j=0; j<=m/2-1; j++)
37241 : {
37242 0 : sx.ptr.p_double[j] = (double)(2*j)/(double)(m/2-1)-1;
37243 : }
37244 : }
37245 :
37246 : /*
37247 : * Prepare design and constraints matrices:
37248 : * * fill constraints matrix
37249 : * * fill first N rows of design matrix with values
37250 : * * fill next M rows of design matrix with regularizing term
37251 : * * append M zeros to Y
37252 : * * append M elements, mean(abs(W)) each, to W
37253 : */
37254 0 : for(j=0; j<=m-1; j++)
37255 : {
37256 :
37257 : /*
37258 : * prepare Jth basis function
37259 : */
37260 0 : if( st==0 )
37261 : {
37262 :
37263 : /*
37264 : * cubic spline basis
37265 : */
37266 0 : for(i=0; i<=m-2-1; i++)
37267 : {
37268 0 : sy.ptr.p_double[i] = (double)(0);
37269 : }
37270 0 : bl = (double)(0);
37271 0 : br = (double)(0);
37272 0 : if( j<m-2 )
37273 : {
37274 0 : sy.ptr.p_double[j] = (double)(1);
37275 : }
37276 0 : if( j==m-2 )
37277 : {
37278 0 : bl = (double)(1);
37279 : }
37280 0 : if( j==m-1 )
37281 : {
37282 0 : br = (double)(1);
37283 : }
37284 0 : spline1dbuildcubic(&sx, &sy, m-2, 1, bl, 1, br, &s2, _state);
37285 : }
37286 0 : if( st==1 )
37287 : {
37288 :
37289 : /*
37290 : * Hermite basis
37291 : */
37292 0 : for(i=0; i<=m/2-1; i++)
37293 : {
37294 0 : sy.ptr.p_double[i] = (double)(0);
37295 0 : sd.ptr.p_double[i] = (double)(0);
37296 : }
37297 0 : if( j%2==0 )
37298 : {
37299 0 : sy.ptr.p_double[j/2] = (double)(1);
37300 : }
37301 : else
37302 : {
37303 0 : sd.ptr.p_double[j/2] = (double)(1);
37304 : }
37305 0 : spline1dbuildhermite(&sx, &sy, &sd, m/2, &s2, _state);
37306 : }
37307 :
37308 : /*
37309 : * values at X[], XC[]
37310 : */
37311 0 : for(i=0; i<=n-1; i++)
37312 : {
37313 0 : fmatrix.ptr.pp_double[i][j] = spline1dcalc(&s2, x->ptr.p_double[i], _state);
37314 : }
37315 0 : for(i=0; i<=k-1; i++)
37316 : {
37317 0 : ae_assert(dc->ptr.p_int[i]>=0&&dc->ptr.p_int[i]<=2, "Spline1DFit: internal error!", _state);
37318 0 : spline1ddiff(&s2, xc->ptr.p_double[i], &v0, &v1, &v2, _state);
37319 0 : if( dc->ptr.p_int[i]==0 )
37320 : {
37321 0 : cmatrix.ptr.pp_double[i][j] = v0;
37322 : }
37323 0 : if( dc->ptr.p_int[i]==1 )
37324 : {
37325 0 : cmatrix.ptr.pp_double[i][j] = v1;
37326 : }
37327 0 : if( dc->ptr.p_int[i]==2 )
37328 : {
37329 0 : cmatrix.ptr.pp_double[i][j] = v2;
37330 : }
37331 : }
37332 : }
37333 0 : for(i=0; i<=k-1; i++)
37334 : {
37335 0 : cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i];
37336 : }
37337 0 : for(i=0; i<=m-1; i++)
37338 : {
37339 0 : for(j=0; j<=m-1; j++)
37340 : {
37341 0 : if( i==j )
37342 : {
37343 0 : fmatrix.ptr.pp_double[n+i][j] = decay;
37344 : }
37345 : else
37346 : {
37347 0 : fmatrix.ptr.pp_double[n+i][j] = (double)(0);
37348 : }
37349 : }
37350 : }
37351 0 : ae_vector_set_length(&y2, n+m, _state);
37352 0 : ae_vector_set_length(&w2, n+m, _state);
37353 0 : ae_v_move(&y2.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
37354 0 : ae_v_move(&w2.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
37355 0 : mx = (double)(0);
37356 0 : for(i=0; i<=n-1; i++)
37357 : {
37358 0 : mx = mx+ae_fabs(w->ptr.p_double[i], _state);
37359 : }
37360 0 : mx = mx/n;
37361 0 : for(i=0; i<=m-1; i++)
37362 : {
37363 0 : y2.ptr.p_double[n+i] = (double)(0);
37364 0 : w2.ptr.p_double[n+i] = mx;
37365 : }
37366 :
37367 : /*
37368 : * Solve constrained task
37369 : */
37370 0 : if( k>0 )
37371 : {
37372 :
37373 : /*
37374 : * solve using regularization
37375 : */
37376 0 : lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, &tmp, &lrep, _state);
37377 : }
37378 : else
37379 : {
37380 :
37381 : /*
37382 : * no constraints, no regularization needed
37383 : */
37384 0 : lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, k, info, &tmp, &lrep, _state);
37385 : }
37386 0 : if( *info<0 )
37387 : {
37388 0 : ae_frame_leave(_state);
37389 0 : return;
37390 : }
37391 :
37392 : /*
37393 : * Generate spline and scale it
37394 : */
37395 0 : if( st==0 )
37396 : {
37397 :
37398 : /*
37399 : * cubic spline basis
37400 : */
37401 0 : ae_v_move(&sy.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-2-1));
37402 0 : spline1dbuildcubic(&sx, &sy, m-2, 1, tmp.ptr.p_double[m-2], 1, tmp.ptr.p_double[m-1], s, _state);
37403 : }
37404 0 : if( st==1 )
37405 : {
37406 :
37407 : /*
37408 : * Hermite basis
37409 : */
37410 0 : for(i=0; i<=m/2-1; i++)
37411 : {
37412 0 : sy.ptr.p_double[i] = tmp.ptr.p_double[2*i];
37413 0 : sd.ptr.p_double[i] = tmp.ptr.p_double[2*i+1];
37414 : }
37415 0 : spline1dbuildhermite(&sx, &sy, &sd, m/2, s, _state);
37416 : }
37417 0 : spline1dlintransx(s, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
37418 0 : spline1dlintransy(s, sb-sa, sa, _state);
37419 :
37420 : /*
37421 : * Scale absolute errors obtained from LSFitLinearW.
37422 : * Relative error should be calculated separately
37423 : * (because of shifting/scaling of the task)
37424 : */
37425 0 : rep->taskrcond = lrep.taskrcond;
37426 0 : rep->rmserror = lrep.rmserror*(sb-sa);
37427 0 : rep->avgerror = lrep.avgerror*(sb-sa);
37428 0 : rep->maxerror = lrep.maxerror*(sb-sa);
37429 0 : rep->avgrelerror = (double)(0);
37430 0 : relcnt = 0;
37431 0 : for(i=0; i<=n-1; i++)
37432 : {
37433 0 : if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) )
37434 : {
37435 0 : rep->avgrelerror = rep->avgrelerror+ae_fabs(spline1dcalc(s, xoriginal.ptr.p_double[i], _state)-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state);
37436 0 : relcnt = relcnt+1;
37437 : }
37438 : }
37439 0 : if( relcnt!=0 )
37440 : {
37441 0 : rep->avgrelerror = rep->avgrelerror/relcnt;
37442 : }
37443 0 : ae_frame_leave(_state);
37444 : }
37445 :
37446 :
37447 : /*************************************************************************
37448 : Internal fitting subroutine
37449 : *************************************************************************/
37450 0 : static void lsfit_lsfitlinearinternal(/* Real */ ae_vector* y,
37451 : /* Real */ ae_vector* w,
37452 : /* Real */ ae_matrix* fmatrix,
37453 : ae_int_t n,
37454 : ae_int_t m,
37455 : ae_int_t* info,
37456 : /* Real */ ae_vector* c,
37457 : lsfitreport* rep,
37458 : ae_state *_state)
37459 : {
37460 : ae_frame _frame_block;
37461 : double threshold;
37462 : ae_matrix ft;
37463 : ae_matrix q;
37464 : ae_matrix l;
37465 : ae_matrix r;
37466 : ae_vector b;
37467 : ae_vector wmod;
37468 : ae_vector tau;
37469 : ae_vector nzeros;
37470 : ae_vector s;
37471 : ae_int_t i;
37472 : ae_int_t j;
37473 : double v;
37474 : ae_vector sv;
37475 : ae_matrix u;
37476 : ae_matrix vt;
37477 : ae_vector tmp;
37478 : ae_vector utb;
37479 : ae_vector sutb;
37480 : ae_int_t relcnt;
37481 :
37482 0 : ae_frame_make(_state, &_frame_block);
37483 0 : memset(&ft, 0, sizeof(ft));
37484 0 : memset(&q, 0, sizeof(q));
37485 0 : memset(&l, 0, sizeof(l));
37486 0 : memset(&r, 0, sizeof(r));
37487 0 : memset(&b, 0, sizeof(b));
37488 0 : memset(&wmod, 0, sizeof(wmod));
37489 0 : memset(&tau, 0, sizeof(tau));
37490 0 : memset(&nzeros, 0, sizeof(nzeros));
37491 0 : memset(&s, 0, sizeof(s));
37492 0 : memset(&sv, 0, sizeof(sv));
37493 0 : memset(&u, 0, sizeof(u));
37494 0 : memset(&vt, 0, sizeof(vt));
37495 0 : memset(&tmp, 0, sizeof(tmp));
37496 0 : memset(&utb, 0, sizeof(utb));
37497 0 : memset(&sutb, 0, sizeof(sutb));
37498 0 : *info = 0;
37499 0 : ae_vector_clear(c);
37500 0 : _lsfitreport_clear(rep);
37501 0 : ae_matrix_init(&ft, 0, 0, DT_REAL, _state, ae_true);
37502 0 : ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
37503 0 : ae_matrix_init(&l, 0, 0, DT_REAL, _state, ae_true);
37504 0 : ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true);
37505 0 : ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
37506 0 : ae_vector_init(&wmod, 0, DT_REAL, _state, ae_true);
37507 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
37508 0 : ae_vector_init(&nzeros, 0, DT_REAL, _state, ae_true);
37509 0 : ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
37510 0 : ae_vector_init(&sv, 0, DT_REAL, _state, ae_true);
37511 0 : ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
37512 0 : ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
37513 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
37514 0 : ae_vector_init(&utb, 0, DT_REAL, _state, ae_true);
37515 0 : ae_vector_init(&sutb, 0, DT_REAL, _state, ae_true);
37516 :
37517 0 : lsfit_clearreport(rep, _state);
37518 0 : if( n<1||m<1 )
37519 : {
37520 0 : *info = -1;
37521 0 : ae_frame_leave(_state);
37522 0 : return;
37523 : }
37524 0 : *info = 1;
37525 0 : threshold = ae_sqrt(ae_machineepsilon, _state);
37526 :
37527 : /*
37528 : * Degenerate case, needs special handling
37529 : */
37530 0 : if( n<m )
37531 : {
37532 :
37533 : /*
37534 : * Create design matrix.
37535 : */
37536 0 : ae_matrix_set_length(&ft, n, m, _state);
37537 0 : ae_vector_set_length(&b, n, _state);
37538 0 : ae_vector_set_length(&wmod, n, _state);
37539 0 : for(j=0; j<=n-1; j++)
37540 : {
37541 0 : v = w->ptr.p_double[j];
37542 0 : ae_v_moved(&ft.ptr.pp_double[j][0], 1, &fmatrix->ptr.pp_double[j][0], 1, ae_v_len(0,m-1), v);
37543 0 : b.ptr.p_double[j] = w->ptr.p_double[j]*y->ptr.p_double[j];
37544 0 : wmod.ptr.p_double[j] = (double)(1);
37545 : }
37546 :
37547 : /*
37548 : * LQ decomposition and reduction to M=N
37549 : */
37550 0 : ae_vector_set_length(c, m, _state);
37551 0 : for(i=0; i<=m-1; i++)
37552 : {
37553 0 : c->ptr.p_double[i] = (double)(0);
37554 : }
37555 0 : rep->taskrcond = (double)(0);
37556 0 : rmatrixlq(&ft, n, m, &tau, _state);
37557 0 : rmatrixlqunpackq(&ft, n, m, &tau, n, &q, _state);
37558 0 : rmatrixlqunpackl(&ft, n, m, &l, _state);
37559 0 : lsfit_lsfitlinearinternal(&b, &wmod, &l, n, n, info, &tmp, rep, _state);
37560 0 : if( *info<=0 )
37561 : {
37562 0 : ae_frame_leave(_state);
37563 0 : return;
37564 : }
37565 0 : for(i=0; i<=n-1; i++)
37566 : {
37567 0 : v = tmp.ptr.p_double[i];
37568 0 : ae_v_addd(&c->ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
37569 : }
37570 0 : ae_frame_leave(_state);
37571 0 : return;
37572 : }
37573 :
37574 : /*
37575 : * N>=M. Generate design matrix and reduce to N=M using
37576 : * QR decomposition.
37577 : */
37578 0 : ae_matrix_set_length(&ft, n, m, _state);
37579 0 : ae_vector_set_length(&b, n, _state);
37580 0 : for(j=0; j<=n-1; j++)
37581 : {
37582 0 : v = w->ptr.p_double[j];
37583 0 : ae_v_moved(&ft.ptr.pp_double[j][0], 1, &fmatrix->ptr.pp_double[j][0], 1, ae_v_len(0,m-1), v);
37584 0 : b.ptr.p_double[j] = w->ptr.p_double[j]*y->ptr.p_double[j];
37585 : }
37586 0 : rmatrixqr(&ft, n, m, &tau, _state);
37587 0 : rmatrixqrunpackq(&ft, n, m, &tau, m, &q, _state);
37588 0 : rmatrixqrunpackr(&ft, n, m, &r, _state);
37589 0 : ae_vector_set_length(&tmp, m, _state);
37590 0 : for(i=0; i<=m-1; i++)
37591 : {
37592 0 : tmp.ptr.p_double[i] = (double)(0);
37593 : }
37594 0 : for(i=0; i<=n-1; i++)
37595 : {
37596 0 : v = b.ptr.p_double[i];
37597 0 : ae_v_addd(&tmp.ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
37598 : }
37599 0 : ae_vector_set_length(&b, m, _state);
37600 0 : ae_v_move(&b.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
37601 :
37602 : /*
37603 : * R contains reduced MxM design upper triangular matrix,
37604 : * B contains reduced Mx1 right part.
37605 : *
37606 : * Determine system condition number and decide
37607 : * should we use triangular solver (faster) or
37608 : * SVD-based solver (more stable).
37609 : *
37610 : * We can use LU-based RCond estimator for this task.
37611 : */
37612 0 : rep->taskrcond = rmatrixlurcondinf(&r, m, _state);
37613 0 : if( ae_fp_greater(rep->taskrcond,threshold) )
37614 : {
37615 :
37616 : /*
37617 : * use QR-based solver
37618 : */
37619 0 : ae_vector_set_length(c, m, _state);
37620 0 : c->ptr.p_double[m-1] = b.ptr.p_double[m-1]/r.ptr.pp_double[m-1][m-1];
37621 0 : for(i=m-2; i>=0; i--)
37622 : {
37623 0 : v = ae_v_dotproduct(&r.ptr.pp_double[i][i+1], 1, &c->ptr.p_double[i+1], 1, ae_v_len(i+1,m-1));
37624 0 : c->ptr.p_double[i] = (b.ptr.p_double[i]-v)/r.ptr.pp_double[i][i];
37625 : }
37626 : }
37627 : else
37628 : {
37629 :
37630 : /*
37631 : * use SVD-based solver
37632 : */
37633 0 : if( !rmatrixsvd(&r, m, m, 1, 1, 2, &sv, &u, &vt, _state) )
37634 : {
37635 0 : *info = -4;
37636 0 : ae_frame_leave(_state);
37637 0 : return;
37638 : }
37639 0 : ae_vector_set_length(&utb, m, _state);
37640 0 : ae_vector_set_length(&sutb, m, _state);
37641 0 : for(i=0; i<=m-1; i++)
37642 : {
37643 0 : utb.ptr.p_double[i] = (double)(0);
37644 : }
37645 0 : for(i=0; i<=m-1; i++)
37646 : {
37647 0 : v = b.ptr.p_double[i];
37648 0 : ae_v_addd(&utb.ptr.p_double[0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
37649 : }
37650 0 : if( ae_fp_greater(sv.ptr.p_double[0],(double)(0)) )
37651 : {
37652 0 : rep->taskrcond = sv.ptr.p_double[m-1]/sv.ptr.p_double[0];
37653 0 : for(i=0; i<=m-1; i++)
37654 : {
37655 0 : if( ae_fp_greater(sv.ptr.p_double[i],threshold*sv.ptr.p_double[0]) )
37656 : {
37657 0 : sutb.ptr.p_double[i] = utb.ptr.p_double[i]/sv.ptr.p_double[i];
37658 : }
37659 : else
37660 : {
37661 0 : sutb.ptr.p_double[i] = (double)(0);
37662 : }
37663 : }
37664 : }
37665 : else
37666 : {
37667 0 : rep->taskrcond = (double)(0);
37668 0 : for(i=0; i<=m-1; i++)
37669 : {
37670 0 : sutb.ptr.p_double[i] = (double)(0);
37671 : }
37672 : }
37673 0 : ae_vector_set_length(c, m, _state);
37674 0 : for(i=0; i<=m-1; i++)
37675 : {
37676 0 : c->ptr.p_double[i] = (double)(0);
37677 : }
37678 0 : for(i=0; i<=m-1; i++)
37679 : {
37680 0 : v = sutb.ptr.p_double[i];
37681 0 : ae_v_addd(&c->ptr.p_double[0], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
37682 : }
37683 : }
37684 :
37685 : /*
37686 : * calculate errors
37687 : */
37688 0 : rep->rmserror = (double)(0);
37689 0 : rep->avgerror = (double)(0);
37690 0 : rep->avgrelerror = (double)(0);
37691 0 : rep->maxerror = (double)(0);
37692 0 : relcnt = 0;
37693 0 : for(i=0; i<=n-1; i++)
37694 : {
37695 0 : v = ae_v_dotproduct(&fmatrix->ptr.pp_double[i][0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1));
37696 0 : rep->rmserror = rep->rmserror+ae_sqr(v-y->ptr.p_double[i], _state);
37697 0 : rep->avgerror = rep->avgerror+ae_fabs(v-y->ptr.p_double[i], _state);
37698 0 : if( ae_fp_neq(y->ptr.p_double[i],(double)(0)) )
37699 : {
37700 0 : rep->avgrelerror = rep->avgrelerror+ae_fabs(v-y->ptr.p_double[i], _state)/ae_fabs(y->ptr.p_double[i], _state);
37701 0 : relcnt = relcnt+1;
37702 : }
37703 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v-y->ptr.p_double[i], _state), _state);
37704 : }
37705 0 : rep->rmserror = ae_sqrt(rep->rmserror/n, _state);
37706 0 : rep->avgerror = rep->avgerror/n;
37707 0 : if( relcnt!=0 )
37708 : {
37709 0 : rep->avgrelerror = rep->avgrelerror/relcnt;
37710 : }
37711 0 : ae_vector_set_length(&nzeros, n, _state);
37712 0 : ae_vector_set_length(&s, m, _state);
37713 0 : for(i=0; i<=m-1; i++)
37714 : {
37715 0 : s.ptr.p_double[i] = (double)(0);
37716 : }
37717 0 : for(i=0; i<=n-1; i++)
37718 : {
37719 0 : for(j=0; j<=m-1; j++)
37720 : {
37721 0 : s.ptr.p_double[j] = s.ptr.p_double[j]+ae_sqr(fmatrix->ptr.pp_double[i][j], _state);
37722 : }
37723 0 : nzeros.ptr.p_double[i] = (double)(0);
37724 : }
37725 0 : for(i=0; i<=m-1; i++)
37726 : {
37727 0 : if( ae_fp_neq(s.ptr.p_double[i],(double)(0)) )
37728 : {
37729 0 : s.ptr.p_double[i] = ae_sqrt(1/s.ptr.p_double[i], _state);
37730 : }
37731 : else
37732 : {
37733 0 : s.ptr.p_double[i] = (double)(1);
37734 : }
37735 : }
37736 0 : lsfit_estimateerrors(fmatrix, &nzeros, y, w, c, &s, n, m, rep, &r, 1, _state);
37737 0 : ae_frame_leave(_state);
37738 : }
37739 :
37740 :
37741 : /*************************************************************************
37742 : Internal subroutine
37743 : *************************************************************************/
37744 0 : static void lsfit_lsfitclearrequestfields(lsfitstate* state,
37745 : ae_state *_state)
37746 : {
37747 :
37748 :
37749 0 : state->needf = ae_false;
37750 0 : state->needfg = ae_false;
37751 0 : state->needfgh = ae_false;
37752 0 : state->xupdated = ae_false;
37753 0 : }
37754 :
37755 :
37756 : /*************************************************************************
37757 : Internal subroutine, calculates barycentric basis functions.
37758 : Used for efficient simultaneous calculation of N basis functions.
37759 :
37760 : -- ALGLIB --
37761 : Copyright 17.08.2009 by Bochkanov Sergey
37762 : *************************************************************************/
37763 0 : static void lsfit_barycentriccalcbasis(barycentricinterpolant* b,
37764 : double t,
37765 : /* Real */ ae_vector* y,
37766 : ae_state *_state)
37767 : {
37768 : double s2;
37769 : double s;
37770 : double v;
37771 : ae_int_t i;
37772 : ae_int_t j;
37773 :
37774 :
37775 :
37776 : /*
37777 : * special case: N=1
37778 : */
37779 0 : if( b->n==1 )
37780 : {
37781 0 : y->ptr.p_double[0] = (double)(1);
37782 0 : return;
37783 : }
37784 :
37785 : /*
37786 : * Here we assume that task is normalized, i.e.:
37787 : * 1. abs(Y[i])<=1
37788 : * 2. abs(W[i])<=1
37789 : * 3. X[] is ordered
37790 : *
37791 : * First, we decide: should we use "safe" formula (guarded
37792 : * against overflow) or fast one?
37793 : */
37794 0 : s = ae_fabs(t-b->x.ptr.p_double[0], _state);
37795 0 : for(i=0; i<=b->n-1; i++)
37796 : {
37797 0 : v = b->x.ptr.p_double[i];
37798 0 : if( ae_fp_eq(v,t) )
37799 : {
37800 0 : for(j=0; j<=b->n-1; j++)
37801 : {
37802 0 : y->ptr.p_double[j] = (double)(0);
37803 : }
37804 0 : y->ptr.p_double[i] = (double)(1);
37805 0 : return;
37806 : }
37807 0 : v = ae_fabs(t-v, _state);
37808 0 : if( ae_fp_less(v,s) )
37809 : {
37810 0 : s = v;
37811 : }
37812 : }
37813 0 : s2 = (double)(0);
37814 0 : for(i=0; i<=b->n-1; i++)
37815 : {
37816 0 : v = s/(t-b->x.ptr.p_double[i]);
37817 0 : v = v*b->w.ptr.p_double[i];
37818 0 : y->ptr.p_double[i] = v;
37819 0 : s2 = s2+v;
37820 : }
37821 0 : v = 1/s2;
37822 0 : ae_v_muld(&y->ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
37823 : }
37824 :
37825 :
37826 : /*************************************************************************
37827 : This is internal function for Chebyshev fitting.
37828 :
37829 : It assumes that input data are normalized:
37830 : * X/XC belong to [-1,+1],
37831 : * mean(Y)=0, stddev(Y)=1.
37832 :
37833 : It does not checks inputs for errors.
37834 :
37835 : This function is used to fit general (shifted) Chebyshev models, power
37836 : basis models or barycentric models.
37837 :
37838 : INPUT PARAMETERS:
37839 : X - points, array[0..N-1].
37840 : Y - function values, array[0..N-1].
37841 : W - weights, array[0..N-1]
37842 : N - number of points, N>0.
37843 : XC - points where polynomial values/derivatives are constrained,
37844 : array[0..K-1].
37845 : YC - values of constraints, array[0..K-1]
37846 : DC - array[0..K-1], types of constraints:
37847 : * DC[i]=0 means that P(XC[i])=YC[i]
37848 : * DC[i]=1 means that P'(XC[i])=YC[i]
37849 : K - number of constraints, 0<=K<M.
37850 : K=0 means no constraints (XC/YC/DC are not used in such cases)
37851 : M - number of basis functions (= polynomial_degree + 1), M>=1
37852 :
37853 : OUTPUT PARAMETERS:
37854 : Info- same format as in LSFitLinearW() subroutine:
37855 : * Info>0 task is solved
37856 : * Info<=0 an error occured:
37857 : -4 means inconvergence of internal SVD
37858 : -3 means inconsistent constraints
37859 : C - interpolant in Chebyshev form; [-1,+1] is used as base interval
37860 : Rep - report, same format as in LSFitLinearW() subroutine.
37861 : Following fields are set:
37862 : * RMSError rms error on the (X,Y).
37863 : * AvgError average error on the (X,Y).
37864 : * AvgRelError average relative error on the non-zero Y
37865 : * MaxError maximum error
37866 : NON-WEIGHTED ERRORS ARE CALCULATED
37867 :
37868 : IMPORTANT:
37869 : this subroitine doesn't calculate task's condition number for K<>0.
37870 :
37871 : -- ALGLIB PROJECT --
37872 : Copyright 10.12.2009 by Bochkanov Sergey
37873 : *************************************************************************/
37874 0 : static void lsfit_internalchebyshevfit(/* Real */ ae_vector* x,
37875 : /* Real */ ae_vector* y,
37876 : /* Real */ ae_vector* w,
37877 : ae_int_t n,
37878 : /* Real */ ae_vector* xc,
37879 : /* Real */ ae_vector* yc,
37880 : /* Integer */ ae_vector* dc,
37881 : ae_int_t k,
37882 : ae_int_t m,
37883 : ae_int_t* info,
37884 : /* Real */ ae_vector* c,
37885 : lsfitreport* rep,
37886 : ae_state *_state)
37887 : {
37888 : ae_frame _frame_block;
37889 : ae_vector _xc;
37890 : ae_vector _yc;
37891 : ae_vector y2;
37892 : ae_vector w2;
37893 : ae_vector tmp;
37894 : ae_vector tmp2;
37895 : ae_vector tmpdiff;
37896 : ae_vector bx;
37897 : ae_vector by;
37898 : ae_vector bw;
37899 : ae_matrix fmatrix;
37900 : ae_matrix cmatrix;
37901 : ae_int_t i;
37902 : ae_int_t j;
37903 : double mx;
37904 : double decay;
37905 :
37906 0 : ae_frame_make(_state, &_frame_block);
37907 0 : memset(&_xc, 0, sizeof(_xc));
37908 0 : memset(&_yc, 0, sizeof(_yc));
37909 0 : memset(&y2, 0, sizeof(y2));
37910 0 : memset(&w2, 0, sizeof(w2));
37911 0 : memset(&tmp, 0, sizeof(tmp));
37912 0 : memset(&tmp2, 0, sizeof(tmp2));
37913 0 : memset(&tmpdiff, 0, sizeof(tmpdiff));
37914 0 : memset(&bx, 0, sizeof(bx));
37915 0 : memset(&by, 0, sizeof(by));
37916 0 : memset(&bw, 0, sizeof(bw));
37917 0 : memset(&fmatrix, 0, sizeof(fmatrix));
37918 0 : memset(&cmatrix, 0, sizeof(cmatrix));
37919 0 : ae_vector_init_copy(&_xc, xc, _state, ae_true);
37920 0 : xc = &_xc;
37921 0 : ae_vector_init_copy(&_yc, yc, _state, ae_true);
37922 0 : yc = &_yc;
37923 0 : *info = 0;
37924 0 : ae_vector_clear(c);
37925 0 : _lsfitreport_clear(rep);
37926 0 : ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
37927 0 : ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
37928 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
37929 0 : ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
37930 0 : ae_vector_init(&tmpdiff, 0, DT_REAL, _state, ae_true);
37931 0 : ae_vector_init(&bx, 0, DT_REAL, _state, ae_true);
37932 0 : ae_vector_init(&by, 0, DT_REAL, _state, ae_true);
37933 0 : ae_vector_init(&bw, 0, DT_REAL, _state, ae_true);
37934 0 : ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
37935 0 : ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true);
37936 :
37937 0 : lsfit_clearreport(rep, _state);
37938 :
37939 : /*
37940 : * weight decay for correct handling of task which becomes
37941 : * degenerate after constraints are applied
37942 : */
37943 0 : decay = 10000*ae_machineepsilon;
37944 :
37945 : /*
37946 : * allocate space, initialize/fill:
37947 : * * FMatrix- values of basis functions at X[]
37948 : * * CMatrix- values (derivatives) of basis functions at XC[]
37949 : * * fill constraints matrix
37950 : * * fill first N rows of design matrix with values
37951 : * * fill next M rows of design matrix with regularizing term
37952 : * * append M zeros to Y
37953 : * * append M elements, mean(abs(W)) each, to W
37954 : */
37955 0 : ae_vector_set_length(&y2, n+m, _state);
37956 0 : ae_vector_set_length(&w2, n+m, _state);
37957 0 : ae_vector_set_length(&tmp, m, _state);
37958 0 : ae_vector_set_length(&tmpdiff, m, _state);
37959 0 : ae_matrix_set_length(&fmatrix, n+m, m, _state);
37960 0 : if( k>0 )
37961 : {
37962 0 : ae_matrix_set_length(&cmatrix, k, m+1, _state);
37963 : }
37964 :
37965 : /*
37966 : * Fill design matrix, Y2, W2:
37967 : * * first N rows with basis functions for original points
37968 : * * next M rows with decay terms
37969 : */
37970 0 : for(i=0; i<=n-1; i++)
37971 : {
37972 :
37973 : /*
37974 : * prepare Ith row
37975 : * use Tmp for calculations to avoid multidimensional arrays overhead
37976 : */
37977 0 : for(j=0; j<=m-1; j++)
37978 : {
37979 0 : if( j==0 )
37980 : {
37981 0 : tmp.ptr.p_double[j] = (double)(1);
37982 : }
37983 : else
37984 : {
37985 0 : if( j==1 )
37986 : {
37987 0 : tmp.ptr.p_double[j] = x->ptr.p_double[i];
37988 : }
37989 : else
37990 : {
37991 0 : tmp.ptr.p_double[j] = 2*x->ptr.p_double[i]*tmp.ptr.p_double[j-1]-tmp.ptr.p_double[j-2];
37992 : }
37993 : }
37994 : }
37995 0 : ae_v_move(&fmatrix.ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
37996 : }
37997 0 : for(i=0; i<=m-1; i++)
37998 : {
37999 0 : for(j=0; j<=m-1; j++)
38000 : {
38001 0 : if( i==j )
38002 : {
38003 0 : fmatrix.ptr.pp_double[n+i][j] = decay;
38004 : }
38005 : else
38006 : {
38007 0 : fmatrix.ptr.pp_double[n+i][j] = (double)(0);
38008 : }
38009 : }
38010 : }
38011 0 : ae_v_move(&y2.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
38012 0 : ae_v_move(&w2.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
38013 0 : mx = (double)(0);
38014 0 : for(i=0; i<=n-1; i++)
38015 : {
38016 0 : mx = mx+ae_fabs(w->ptr.p_double[i], _state);
38017 : }
38018 0 : mx = mx/n;
38019 0 : for(i=0; i<=m-1; i++)
38020 : {
38021 0 : y2.ptr.p_double[n+i] = (double)(0);
38022 0 : w2.ptr.p_double[n+i] = mx;
38023 : }
38024 :
38025 : /*
38026 : * fill constraints matrix
38027 : */
38028 0 : for(i=0; i<=k-1; i++)
38029 : {
38030 :
38031 : /*
38032 : * prepare Ith row
38033 : * use Tmp for basis function values,
38034 : * TmpDiff for basos function derivatives
38035 : */
38036 0 : for(j=0; j<=m-1; j++)
38037 : {
38038 0 : if( j==0 )
38039 : {
38040 0 : tmp.ptr.p_double[j] = (double)(1);
38041 0 : tmpdiff.ptr.p_double[j] = (double)(0);
38042 : }
38043 : else
38044 : {
38045 0 : if( j==1 )
38046 : {
38047 0 : tmp.ptr.p_double[j] = xc->ptr.p_double[i];
38048 0 : tmpdiff.ptr.p_double[j] = (double)(1);
38049 : }
38050 : else
38051 : {
38052 0 : tmp.ptr.p_double[j] = 2*xc->ptr.p_double[i]*tmp.ptr.p_double[j-1]-tmp.ptr.p_double[j-2];
38053 0 : tmpdiff.ptr.p_double[j] = 2*(tmp.ptr.p_double[j-1]+xc->ptr.p_double[i]*tmpdiff.ptr.p_double[j-1])-tmpdiff.ptr.p_double[j-2];
38054 : }
38055 : }
38056 : }
38057 0 : if( dc->ptr.p_int[i]==0 )
38058 : {
38059 0 : ae_v_move(&cmatrix.ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
38060 : }
38061 0 : if( dc->ptr.p_int[i]==1 )
38062 : {
38063 0 : ae_v_move(&cmatrix.ptr.pp_double[i][0], 1, &tmpdiff.ptr.p_double[0], 1, ae_v_len(0,m-1));
38064 : }
38065 0 : cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i];
38066 : }
38067 :
38068 : /*
38069 : * Solve constrained task
38070 : */
38071 0 : if( k>0 )
38072 : {
38073 :
38074 : /*
38075 : * solve using regularization
38076 : */
38077 0 : lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, c, rep, _state);
38078 : }
38079 : else
38080 : {
38081 :
38082 : /*
38083 : * no constraints, no regularization needed
38084 : */
38085 0 : lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, 0, info, c, rep, _state);
38086 : }
38087 0 : if( *info<0 )
38088 : {
38089 0 : ae_frame_leave(_state);
38090 0 : return;
38091 : }
38092 0 : ae_frame_leave(_state);
38093 : }
38094 :
38095 :
38096 : /*************************************************************************
38097 : Internal Floater-Hormann fitting subroutine for fixed D
38098 : *************************************************************************/
38099 0 : static void lsfit_barycentricfitwcfixedd(/* Real */ ae_vector* x,
38100 : /* Real */ ae_vector* y,
38101 : /* Real */ ae_vector* w,
38102 : ae_int_t n,
38103 : /* Real */ ae_vector* xc,
38104 : /* Real */ ae_vector* yc,
38105 : /* Integer */ ae_vector* dc,
38106 : ae_int_t k,
38107 : ae_int_t m,
38108 : ae_int_t d,
38109 : ae_int_t* info,
38110 : barycentricinterpolant* b,
38111 : barycentricfitreport* rep,
38112 : ae_state *_state)
38113 : {
38114 : ae_frame _frame_block;
38115 : ae_vector _x;
38116 : ae_vector _y;
38117 : ae_vector _w;
38118 : ae_vector _xc;
38119 : ae_vector _yc;
38120 : ae_matrix fmatrix;
38121 : ae_matrix cmatrix;
38122 : ae_vector y2;
38123 : ae_vector w2;
38124 : ae_vector sx;
38125 : ae_vector sy;
38126 : ae_vector sbf;
38127 : ae_vector xoriginal;
38128 : ae_vector yoriginal;
38129 : ae_vector tmp;
38130 : lsfitreport lrep;
38131 : double v0;
38132 : double v1;
38133 : double mx;
38134 : barycentricinterpolant b2;
38135 : ae_int_t i;
38136 : ae_int_t j;
38137 : ae_int_t relcnt;
38138 : double xa;
38139 : double xb;
38140 : double sa;
38141 : double sb;
38142 : double decay;
38143 :
38144 0 : ae_frame_make(_state, &_frame_block);
38145 0 : memset(&_x, 0, sizeof(_x));
38146 0 : memset(&_y, 0, sizeof(_y));
38147 0 : memset(&_w, 0, sizeof(_w));
38148 0 : memset(&_xc, 0, sizeof(_xc));
38149 0 : memset(&_yc, 0, sizeof(_yc));
38150 0 : memset(&fmatrix, 0, sizeof(fmatrix));
38151 0 : memset(&cmatrix, 0, sizeof(cmatrix));
38152 0 : memset(&y2, 0, sizeof(y2));
38153 0 : memset(&w2, 0, sizeof(w2));
38154 0 : memset(&sx, 0, sizeof(sx));
38155 0 : memset(&sy, 0, sizeof(sy));
38156 0 : memset(&sbf, 0, sizeof(sbf));
38157 0 : memset(&xoriginal, 0, sizeof(xoriginal));
38158 0 : memset(&yoriginal, 0, sizeof(yoriginal));
38159 0 : memset(&tmp, 0, sizeof(tmp));
38160 0 : memset(&lrep, 0, sizeof(lrep));
38161 0 : memset(&b2, 0, sizeof(b2));
38162 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
38163 0 : x = &_x;
38164 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
38165 0 : y = &_y;
38166 0 : ae_vector_init_copy(&_w, w, _state, ae_true);
38167 0 : w = &_w;
38168 0 : ae_vector_init_copy(&_xc, xc, _state, ae_true);
38169 0 : xc = &_xc;
38170 0 : ae_vector_init_copy(&_yc, yc, _state, ae_true);
38171 0 : yc = &_yc;
38172 0 : *info = 0;
38173 0 : _barycentricinterpolant_clear(b);
38174 0 : _barycentricfitreport_clear(rep);
38175 0 : ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
38176 0 : ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true);
38177 0 : ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
38178 0 : ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
38179 0 : ae_vector_init(&sx, 0, DT_REAL, _state, ae_true);
38180 0 : ae_vector_init(&sy, 0, DT_REAL, _state, ae_true);
38181 0 : ae_vector_init(&sbf, 0, DT_REAL, _state, ae_true);
38182 0 : ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
38183 0 : ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
38184 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
38185 0 : _lsfitreport_init(&lrep, _state, ae_true);
38186 0 : _barycentricinterpolant_init(&b2, _state, ae_true);
38187 :
38188 0 : if( ((n<1||m<2)||k<0)||k>=m )
38189 : {
38190 0 : *info = -1;
38191 0 : ae_frame_leave(_state);
38192 0 : return;
38193 : }
38194 0 : for(i=0; i<=k-1; i++)
38195 : {
38196 0 : *info = 0;
38197 0 : if( dc->ptr.p_int[i]<0 )
38198 : {
38199 0 : *info = -1;
38200 : }
38201 0 : if( dc->ptr.p_int[i]>1 )
38202 : {
38203 0 : *info = -1;
38204 : }
38205 0 : if( *info<0 )
38206 : {
38207 0 : ae_frame_leave(_state);
38208 0 : return;
38209 : }
38210 : }
38211 :
38212 : /*
38213 : * weight decay for correct handling of task which becomes
38214 : * degenerate after constraints are applied
38215 : */
38216 0 : decay = 10000*ae_machineepsilon;
38217 :
38218 : /*
38219 : * Scale X, Y, XC, YC
38220 : */
38221 0 : lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
38222 :
38223 : /*
38224 : * allocate space, initialize:
38225 : * * FMatrix- values of basis functions at X[]
38226 : * * CMatrix- values (derivatives) of basis functions at XC[]
38227 : */
38228 0 : ae_vector_set_length(&y2, n+m, _state);
38229 0 : ae_vector_set_length(&w2, n+m, _state);
38230 0 : ae_matrix_set_length(&fmatrix, n+m, m, _state);
38231 0 : if( k>0 )
38232 : {
38233 0 : ae_matrix_set_length(&cmatrix, k, m+1, _state);
38234 : }
38235 0 : ae_vector_set_length(&y2, n+m, _state);
38236 0 : ae_vector_set_length(&w2, n+m, _state);
38237 :
38238 : /*
38239 : * Prepare design and constraints matrices:
38240 : * * fill constraints matrix
38241 : * * fill first N rows of design matrix with values
38242 : * * fill next M rows of design matrix with regularizing term
38243 : * * append M zeros to Y
38244 : * * append M elements, mean(abs(W)) each, to W
38245 : */
38246 0 : ae_vector_set_length(&sx, m, _state);
38247 0 : ae_vector_set_length(&sy, m, _state);
38248 0 : ae_vector_set_length(&sbf, m, _state);
38249 0 : for(j=0; j<=m-1; j++)
38250 : {
38251 0 : sx.ptr.p_double[j] = (double)(2*j)/(double)(m-1)-1;
38252 : }
38253 0 : for(i=0; i<=m-1; i++)
38254 : {
38255 0 : sy.ptr.p_double[i] = (double)(1);
38256 : }
38257 0 : barycentricbuildfloaterhormann(&sx, &sy, m, d, &b2, _state);
38258 0 : mx = (double)(0);
38259 0 : for(i=0; i<=n-1; i++)
38260 : {
38261 0 : lsfit_barycentriccalcbasis(&b2, x->ptr.p_double[i], &sbf, _state);
38262 0 : ae_v_move(&fmatrix.ptr.pp_double[i][0], 1, &sbf.ptr.p_double[0], 1, ae_v_len(0,m-1));
38263 0 : y2.ptr.p_double[i] = y->ptr.p_double[i];
38264 0 : w2.ptr.p_double[i] = w->ptr.p_double[i];
38265 0 : mx = mx+ae_fabs(w->ptr.p_double[i], _state)/n;
38266 : }
38267 0 : for(i=0; i<=m-1; i++)
38268 : {
38269 0 : for(j=0; j<=m-1; j++)
38270 : {
38271 0 : if( i==j )
38272 : {
38273 0 : fmatrix.ptr.pp_double[n+i][j] = decay;
38274 : }
38275 : else
38276 : {
38277 0 : fmatrix.ptr.pp_double[n+i][j] = (double)(0);
38278 : }
38279 : }
38280 0 : y2.ptr.p_double[n+i] = (double)(0);
38281 0 : w2.ptr.p_double[n+i] = mx;
38282 : }
38283 0 : if( k>0 )
38284 : {
38285 0 : for(j=0; j<=m-1; j++)
38286 : {
38287 0 : for(i=0; i<=m-1; i++)
38288 : {
38289 0 : sy.ptr.p_double[i] = (double)(0);
38290 : }
38291 0 : sy.ptr.p_double[j] = (double)(1);
38292 0 : barycentricbuildfloaterhormann(&sx, &sy, m, d, &b2, _state);
38293 0 : for(i=0; i<=k-1; i++)
38294 : {
38295 0 : ae_assert(dc->ptr.p_int[i]>=0&&dc->ptr.p_int[i]<=1, "BarycentricFit: internal error!", _state);
38296 0 : barycentricdiff1(&b2, xc->ptr.p_double[i], &v0, &v1, _state);
38297 0 : if( dc->ptr.p_int[i]==0 )
38298 : {
38299 0 : cmatrix.ptr.pp_double[i][j] = v0;
38300 : }
38301 0 : if( dc->ptr.p_int[i]==1 )
38302 : {
38303 0 : cmatrix.ptr.pp_double[i][j] = v1;
38304 : }
38305 : }
38306 : }
38307 0 : for(i=0; i<=k-1; i++)
38308 : {
38309 0 : cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i];
38310 : }
38311 : }
38312 :
38313 : /*
38314 : * Solve constrained task
38315 : */
38316 0 : if( k>0 )
38317 : {
38318 :
38319 : /*
38320 : * solve using regularization
38321 : */
38322 0 : lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, &tmp, &lrep, _state);
38323 : }
38324 : else
38325 : {
38326 :
38327 : /*
38328 : * no constraints, no regularization needed
38329 : */
38330 0 : lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, k, info, &tmp, &lrep, _state);
38331 : }
38332 0 : if( *info<0 )
38333 : {
38334 0 : ae_frame_leave(_state);
38335 0 : return;
38336 : }
38337 :
38338 : /*
38339 : * Generate interpolant and scale it
38340 : */
38341 0 : ae_v_move(&sy.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
38342 0 : barycentricbuildfloaterhormann(&sx, &sy, m, d, b, _state);
38343 0 : barycentriclintransx(b, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
38344 0 : barycentriclintransy(b, sb-sa, sa, _state);
38345 :
38346 : /*
38347 : * Scale absolute errors obtained from LSFitLinearW.
38348 : * Relative error should be calculated separately
38349 : * (because of shifting/scaling of the task)
38350 : */
38351 0 : rep->taskrcond = lrep.taskrcond;
38352 0 : rep->rmserror = lrep.rmserror*(sb-sa);
38353 0 : rep->avgerror = lrep.avgerror*(sb-sa);
38354 0 : rep->maxerror = lrep.maxerror*(sb-sa);
38355 0 : rep->avgrelerror = (double)(0);
38356 0 : relcnt = 0;
38357 0 : for(i=0; i<=n-1; i++)
38358 : {
38359 0 : if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) )
38360 : {
38361 0 : rep->avgrelerror = rep->avgrelerror+ae_fabs(barycentriccalc(b, xoriginal.ptr.p_double[i], _state)-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state);
38362 0 : relcnt = relcnt+1;
38363 : }
38364 : }
38365 0 : if( relcnt!=0 )
38366 : {
38367 0 : rep->avgrelerror = rep->avgrelerror/relcnt;
38368 : }
38369 0 : ae_frame_leave(_state);
38370 : }
38371 :
38372 :
38373 0 : static void lsfit_clearreport(lsfitreport* rep, ae_state *_state)
38374 : {
38375 :
38376 :
38377 0 : rep->taskrcond = (double)(0);
38378 0 : rep->iterationscount = 0;
38379 0 : rep->varidx = -1;
38380 0 : rep->rmserror = (double)(0);
38381 0 : rep->avgerror = (double)(0);
38382 0 : rep->avgrelerror = (double)(0);
38383 0 : rep->maxerror = (double)(0);
38384 0 : rep->wrmserror = (double)(0);
38385 0 : rep->r2 = (double)(0);
38386 0 : ae_matrix_set_length(&rep->covpar, 0, 0, _state);
38387 0 : ae_vector_set_length(&rep->errpar, 0, _state);
38388 0 : ae_vector_set_length(&rep->errcurve, 0, _state);
38389 0 : ae_vector_set_length(&rep->noise, 0, _state);
38390 0 : }
38391 :
38392 :
38393 : /*************************************************************************
38394 : This internal function estimates covariance matrix and other error-related
38395 : information for linear/nonlinear least squares model.
38396 :
38397 : It has a bit awkward interface, but it can be used for both linear and
38398 : nonlinear problems.
38399 :
38400 : INPUT PARAMETERS:
38401 : F1 - array[0..N-1,0..K-1]:
38402 : * for linear problems - matrix of function values
38403 : * for nonlinear problems - Jacobian matrix
38404 : F0 - array[0..N-1]:
38405 : * for linear problems - must be filled with zeros
38406 : * for nonlinear problems - must store values of function being
38407 : fitted
38408 : Y - array[0..N-1]:
38409 : * for linear and nonlinear problems - must store target values
38410 : W - weights, array[0..N-1]:
38411 : * for linear and nonlinear problems - weights
38412 : X - array[0..K-1]:
38413 : * for linear and nonlinear problems - current solution
38414 : S - array[0..K-1]:
38415 : * its components should be strictly positive
38416 : * squared inverse of this diagonal matrix is used as damping
38417 : factor for covariance matrix (linear and nonlinear problems)
38418 : * for nonlinear problems, when scale of the variables is usually
38419 : explicitly given by user, you may use scale vector for this
38420 : parameter
38421 : * for linear problems you may set this parameter to
38422 : S=sqrt(1/diag(F'*F))
38423 : * this parameter is automatically rescaled by this function,
38424 : only relative magnitudes of its components (with respect to
38425 : each other) matter.
38426 : N - number of points, N>0.
38427 : K - number of dimensions
38428 : Rep - structure which is used to store results
38429 : Z - additional matrix which, depending on ZKind, may contain some
38430 : information used to accelerate calculations - or just can be
38431 : temporary buffer:
38432 : * for ZKind=0 Z contains no information, just temporary
38433 : buffer which can be resized and used as needed
38434 : * for ZKind=1 Z contains triangular matrix from QR
38435 : decomposition of W*F1. This matrix can be used
38436 : to speedup calculation of covariance matrix.
38437 : It should not be changed by algorithm.
38438 : ZKind- contents of Z
38439 :
38440 : OUTPUT PARAMETERS:
38441 :
38442 : * Rep.CovPar covariance matrix for parameters, array[K,K].
38443 : * Rep.ErrPar errors in parameters, array[K],
38444 : errpar = sqrt(diag(CovPar))
38445 : * Rep.ErrCurve vector of fit errors - standard deviations of empirical
38446 : best-fit curve from "ideal" best-fit curve built with
38447 : infinite number of samples, array[N].
38448 : errcurve = sqrt(diag(J*CovPar*J')),
38449 : where J is Jacobian matrix.
38450 : * Rep.Noise vector of per-point estimates of noise, array[N]
38451 : * Rep.R2 coefficient of determination (non-weighted)
38452 :
38453 : Other fields of Rep are not changed.
38454 :
38455 : IMPORTANT: errors in parameters are calculated without taking into
38456 : account boundary/linear constraints! Presence of constraints
38457 : changes distribution of errors, but there is no easy way to
38458 : account for constraints when you calculate covariance matrix.
38459 :
38460 : NOTE: noise in the data is estimated as follows:
38461 : * for fitting without user-supplied weights all points are
38462 : assumed to have same level of noise, which is estimated from
38463 : the data
38464 : * for fitting with user-supplied weights we assume that noise
38465 : level in I-th point is inversely proportional to Ith weight.
38466 : Coefficient of proportionality is estimated from the data.
38467 :
38468 : NOTE: we apply small amount of regularization when we invert squared
38469 : Jacobian and calculate covariance matrix. It guarantees that
38470 : algorithm won't divide by zero during inversion, but skews
38471 : error estimates a bit (fractional error is about 10^-9).
38472 :
38473 : However, we believe that this difference is insignificant for
38474 : all practical purposes except for the situation when you want
38475 : to compare ALGLIB results with "reference" implementation up
38476 : to the last significant digit.
38477 :
38478 : -- ALGLIB PROJECT --
38479 : Copyright 10.12.2009 by Bochkanov Sergey
38480 : *************************************************************************/
38481 0 : static void lsfit_estimateerrors(/* Real */ ae_matrix* f1,
38482 : /* Real */ ae_vector* f0,
38483 : /* Real */ ae_vector* y,
38484 : /* Real */ ae_vector* w,
38485 : /* Real */ ae_vector* x,
38486 : /* Real */ ae_vector* s,
38487 : ae_int_t n,
38488 : ae_int_t k,
38489 : lsfitreport* rep,
38490 : /* Real */ ae_matrix* z,
38491 : ae_int_t zkind,
38492 : ae_state *_state)
38493 : {
38494 : ae_frame _frame_block;
38495 : ae_vector _s;
38496 : ae_int_t i;
38497 : ae_int_t j;
38498 : ae_int_t j1;
38499 : double v;
38500 : double noisec;
38501 : ae_int_t info;
38502 : matinvreport invrep;
38503 : ae_int_t nzcnt;
38504 : double avg;
38505 : double rss;
38506 : double tss;
38507 : double sz;
38508 : double ss;
38509 :
38510 0 : ae_frame_make(_state, &_frame_block);
38511 0 : memset(&_s, 0, sizeof(_s));
38512 0 : memset(&invrep, 0, sizeof(invrep));
38513 0 : ae_vector_init_copy(&_s, s, _state, ae_true);
38514 0 : s = &_s;
38515 0 : _matinvreport_init(&invrep, _state, ae_true);
38516 :
38517 :
38518 : /*
38519 : * Compute NZCnt - count of non-zero weights
38520 : */
38521 0 : nzcnt = 0;
38522 0 : for(i=0; i<=n-1; i++)
38523 : {
38524 0 : if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) )
38525 : {
38526 0 : nzcnt = nzcnt+1;
38527 : }
38528 : }
38529 :
38530 : /*
38531 : * Compute R2
38532 : */
38533 0 : if( nzcnt>0 )
38534 : {
38535 0 : avg = 0.0;
38536 0 : for(i=0; i<=n-1; i++)
38537 : {
38538 0 : if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) )
38539 : {
38540 0 : avg = avg+y->ptr.p_double[i];
38541 : }
38542 : }
38543 0 : avg = avg/nzcnt;
38544 0 : rss = 0.0;
38545 0 : tss = 0.0;
38546 0 : for(i=0; i<=n-1; i++)
38547 : {
38548 0 : if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) )
38549 : {
38550 0 : v = ae_v_dotproduct(&f1->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,k-1));
38551 0 : v = v+f0->ptr.p_double[i];
38552 0 : rss = rss+ae_sqr(v-y->ptr.p_double[i], _state);
38553 0 : tss = tss+ae_sqr(y->ptr.p_double[i]-avg, _state);
38554 : }
38555 : }
38556 0 : if( ae_fp_neq(tss,(double)(0)) )
38557 : {
38558 0 : rep->r2 = ae_maxreal(1.0-rss/tss, 0.0, _state);
38559 : }
38560 : else
38561 : {
38562 0 : rep->r2 = 1.0;
38563 : }
38564 : }
38565 : else
38566 : {
38567 0 : rep->r2 = (double)(0);
38568 : }
38569 :
38570 : /*
38571 : * Compute estimate of proportionality between noise in the data and weights:
38572 : * NoiseC = mean(per-point-noise*per-point-weight)
38573 : * Noise level (standard deviation) at each point is equal to NoiseC/W[I].
38574 : */
38575 0 : if( nzcnt>k )
38576 : {
38577 0 : noisec = 0.0;
38578 0 : for(i=0; i<=n-1; i++)
38579 : {
38580 0 : if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) )
38581 : {
38582 0 : v = ae_v_dotproduct(&f1->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,k-1));
38583 0 : v = v+f0->ptr.p_double[i];
38584 0 : noisec = noisec+ae_sqr((v-y->ptr.p_double[i])*w->ptr.p_double[i], _state);
38585 : }
38586 : }
38587 0 : noisec = ae_sqrt(noisec/(nzcnt-k), _state);
38588 : }
38589 : else
38590 : {
38591 0 : noisec = 0.0;
38592 : }
38593 :
38594 : /*
38595 : * Two branches on noise level:
38596 : * * NoiseC>0 normal situation
38597 : * * NoiseC=0 degenerate case CovPar is filled by zeros
38598 : */
38599 0 : rmatrixsetlengthatleast(&rep->covpar, k, k, _state);
38600 0 : if( ae_fp_greater(noisec,(double)(0)) )
38601 : {
38602 :
38603 : /*
38604 : * Normal situation: non-zero noise level
38605 : */
38606 0 : ae_assert(zkind==0||zkind==1, "LSFit: internal error in EstimateErrors() function", _state);
38607 0 : if( zkind==0 )
38608 : {
38609 :
38610 : /*
38611 : * Z contains no additional information which can be used to speed up
38612 : * calculations. We have to calculate covariance matrix on our own:
38613 : * * Compute scaled Jacobian N*J, where N[i,i]=WCur[I]/NoiseC, store in Z
38614 : * * Compute Z'*Z, store in CovPar
38615 : * * Apply moderate regularization to CovPar and compute matrix inverse.
38616 : * In case inverse failed, increase regularization parameter and try
38617 : * again.
38618 : */
38619 0 : rmatrixsetlengthatleast(z, n, k, _state);
38620 0 : for(i=0; i<=n-1; i++)
38621 : {
38622 0 : v = w->ptr.p_double[i]/noisec;
38623 0 : ae_v_moved(&z->ptr.pp_double[i][0], 1, &f1->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
38624 : }
38625 :
38626 : /*
38627 : * Convert S to automatically scaled damped matrix:
38628 : * * calculate SZ - sum of diagonal elements of Z'*Z
38629 : * * calculate SS - sum of diagonal elements of S^(-2)
38630 : * * overwrite S by (SZ/SS)*S^(-2)
38631 : * * now S has approximately same magnitude as giagonal of Z'*Z
38632 : */
38633 0 : sz = (double)(0);
38634 0 : for(i=0; i<=n-1; i++)
38635 : {
38636 0 : for(j=0; j<=k-1; j++)
38637 : {
38638 0 : sz = sz+z->ptr.pp_double[i][j]*z->ptr.pp_double[i][j];
38639 : }
38640 : }
38641 0 : if( ae_fp_eq(sz,(double)(0)) )
38642 : {
38643 0 : sz = (double)(1);
38644 : }
38645 0 : ss = (double)(0);
38646 0 : for(j=0; j<=k-1; j++)
38647 : {
38648 0 : ss = ss+1/ae_sqr(s->ptr.p_double[j], _state);
38649 : }
38650 0 : for(j=0; j<=k-1; j++)
38651 : {
38652 0 : s->ptr.p_double[j] = sz/ss/ae_sqr(s->ptr.p_double[j], _state);
38653 : }
38654 :
38655 : /*
38656 : * Calculate damped inverse inv(Z'*Z+S).
38657 : * We increase damping factor V until Z'*Z become well-conditioned.
38658 : */
38659 0 : v = 1.0E3*ae_machineepsilon;
38660 0 : do
38661 : {
38662 0 : rmatrixsyrk(k, n, 1.0, z, 0, 0, 2, 0.0, &rep->covpar, 0, 0, ae_true, _state);
38663 0 : for(i=0; i<=k-1; i++)
38664 : {
38665 0 : rep->covpar.ptr.pp_double[i][i] = rep->covpar.ptr.pp_double[i][i]+v*s->ptr.p_double[i];
38666 : }
38667 0 : spdmatrixinverse(&rep->covpar, k, ae_true, &info, &invrep, _state);
38668 0 : v = 10*v;
38669 : }
38670 0 : while(info<=0);
38671 0 : for(i=0; i<=k-1; i++)
38672 : {
38673 0 : for(j=i+1; j<=k-1; j++)
38674 : {
38675 0 : rep->covpar.ptr.pp_double[j][i] = rep->covpar.ptr.pp_double[i][j];
38676 : }
38677 : }
38678 : }
38679 0 : if( zkind==1 )
38680 : {
38681 :
38682 : /*
38683 : * We can reuse additional information:
38684 : * * Z contains R matrix from QR decomposition of W*F1
38685 : * * After multiplication by 1/NoiseC we get Z_mod = N*F1, where diag(N)=w[i]/NoiseC
38686 : * * Such triangular Z_mod is a Cholesky factor from decomposition of J'*N'*N*J.
38687 : * Thus, we can calculate covariance matrix as inverse of the matrix given by
38688 : * its Cholesky decomposition. It allow us to avoid time-consuming calculation
38689 : * of J'*N'*N*J in CovPar - complexity is reduced from O(N*K^2) to O(K^3), which
38690 : * is quite good because K is usually orders of magnitude smaller than N.
38691 : *
38692 : * First, convert S to automatically scaled damped matrix:
38693 : * * calculate SZ - sum of magnitudes of diagonal elements of Z/NoiseC
38694 : * * calculate SS - sum of diagonal elements of S^(-1)
38695 : * * overwrite S by (SZ/SS)*S^(-1)
38696 : * * now S has approximately same magnitude as giagonal of Z'*Z
38697 : */
38698 0 : sz = (double)(0);
38699 0 : for(j=0; j<=k-1; j++)
38700 : {
38701 0 : sz = sz+ae_fabs(z->ptr.pp_double[j][j]/noisec, _state);
38702 : }
38703 0 : if( ae_fp_eq(sz,(double)(0)) )
38704 : {
38705 0 : sz = (double)(1);
38706 : }
38707 0 : ss = (double)(0);
38708 0 : for(j=0; j<=k-1; j++)
38709 : {
38710 0 : ss = ss+1/s->ptr.p_double[j];
38711 : }
38712 0 : for(j=0; j<=k-1; j++)
38713 : {
38714 0 : s->ptr.p_double[j] = sz/ss/s->ptr.p_double[j];
38715 : }
38716 :
38717 : /*
38718 : * Calculate damped inverse of inv((Z+v*S)'*(Z+v*S))
38719 : * We increase damping factor V until matrix become well-conditioned.
38720 : */
38721 0 : v = 1.0E3*ae_machineepsilon;
38722 0 : do
38723 : {
38724 0 : for(i=0; i<=k-1; i++)
38725 : {
38726 0 : for(j=i; j<=k-1; j++)
38727 : {
38728 0 : rep->covpar.ptr.pp_double[i][j] = z->ptr.pp_double[i][j]/noisec;
38729 : }
38730 0 : rep->covpar.ptr.pp_double[i][i] = rep->covpar.ptr.pp_double[i][i]+v*s->ptr.p_double[i];
38731 : }
38732 0 : spdmatrixcholeskyinverse(&rep->covpar, k, ae_true, &info, &invrep, _state);
38733 0 : v = 10*v;
38734 : }
38735 0 : while(info<=0);
38736 0 : for(i=0; i<=k-1; i++)
38737 : {
38738 0 : for(j=i+1; j<=k-1; j++)
38739 : {
38740 0 : rep->covpar.ptr.pp_double[j][i] = rep->covpar.ptr.pp_double[i][j];
38741 : }
38742 : }
38743 : }
38744 : }
38745 : else
38746 : {
38747 :
38748 : /*
38749 : * Degenerate situation: zero noise level, covariance matrix is zero.
38750 : */
38751 0 : for(i=0; i<=k-1; i++)
38752 : {
38753 0 : for(j=0; j<=k-1; j++)
38754 : {
38755 0 : rep->covpar.ptr.pp_double[j][i] = (double)(0);
38756 : }
38757 : }
38758 : }
38759 :
38760 : /*
38761 : * Estimate erorrs in parameters, curve and per-point noise
38762 : */
38763 0 : rvectorsetlengthatleast(&rep->errpar, k, _state);
38764 0 : rvectorsetlengthatleast(&rep->errcurve, n, _state);
38765 0 : rvectorsetlengthatleast(&rep->noise, n, _state);
38766 0 : for(i=0; i<=k-1; i++)
38767 : {
38768 0 : rep->errpar.ptr.p_double[i] = ae_sqrt(rep->covpar.ptr.pp_double[i][i], _state);
38769 : }
38770 0 : for(i=0; i<=n-1; i++)
38771 : {
38772 :
38773 : /*
38774 : * ErrCurve[I] is sqrt(P[i,i]) where P=J*CovPar*J'
38775 : */
38776 0 : v = 0.0;
38777 0 : for(j=0; j<=k-1; j++)
38778 : {
38779 0 : for(j1=0; j1<=k-1; j1++)
38780 : {
38781 0 : v = v+f1->ptr.pp_double[i][j]*rep->covpar.ptr.pp_double[j][j1]*f1->ptr.pp_double[i][j1];
38782 : }
38783 : }
38784 0 : rep->errcurve.ptr.p_double[i] = ae_sqrt(v, _state);
38785 :
38786 : /*
38787 : * Noise[i] is filled using weights and current estimate of noise level
38788 : */
38789 0 : if( ae_fp_neq(w->ptr.p_double[i],(double)(0)) )
38790 : {
38791 0 : rep->noise.ptr.p_double[i] = noisec/w->ptr.p_double[i];
38792 : }
38793 : else
38794 : {
38795 0 : rep->noise.ptr.p_double[i] = (double)(0);
38796 : }
38797 : }
38798 0 : ae_frame_leave(_state);
38799 0 : }
38800 :
38801 :
38802 0 : void _polynomialfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
38803 : {
38804 0 : polynomialfitreport *p = (polynomialfitreport*)_p;
38805 0 : ae_touch_ptr((void*)p);
38806 0 : }
38807 :
38808 :
38809 0 : void _polynomialfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
38810 : {
38811 0 : polynomialfitreport *dst = (polynomialfitreport*)_dst;
38812 0 : polynomialfitreport *src = (polynomialfitreport*)_src;
38813 0 : dst->taskrcond = src->taskrcond;
38814 0 : dst->rmserror = src->rmserror;
38815 0 : dst->avgerror = src->avgerror;
38816 0 : dst->avgrelerror = src->avgrelerror;
38817 0 : dst->maxerror = src->maxerror;
38818 0 : }
38819 :
38820 :
38821 0 : void _polynomialfitreport_clear(void* _p)
38822 : {
38823 0 : polynomialfitreport *p = (polynomialfitreport*)_p;
38824 0 : ae_touch_ptr((void*)p);
38825 0 : }
38826 :
38827 :
38828 0 : void _polynomialfitreport_destroy(void* _p)
38829 : {
38830 0 : polynomialfitreport *p = (polynomialfitreport*)_p;
38831 0 : ae_touch_ptr((void*)p);
38832 0 : }
38833 :
38834 :
38835 0 : void _barycentricfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
38836 : {
38837 0 : barycentricfitreport *p = (barycentricfitreport*)_p;
38838 0 : ae_touch_ptr((void*)p);
38839 0 : }
38840 :
38841 :
38842 0 : void _barycentricfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
38843 : {
38844 0 : barycentricfitreport *dst = (barycentricfitreport*)_dst;
38845 0 : barycentricfitreport *src = (barycentricfitreport*)_src;
38846 0 : dst->taskrcond = src->taskrcond;
38847 0 : dst->dbest = src->dbest;
38848 0 : dst->rmserror = src->rmserror;
38849 0 : dst->avgerror = src->avgerror;
38850 0 : dst->avgrelerror = src->avgrelerror;
38851 0 : dst->maxerror = src->maxerror;
38852 0 : }
38853 :
38854 :
38855 0 : void _barycentricfitreport_clear(void* _p)
38856 : {
38857 0 : barycentricfitreport *p = (barycentricfitreport*)_p;
38858 0 : ae_touch_ptr((void*)p);
38859 0 : }
38860 :
38861 :
38862 0 : void _barycentricfitreport_destroy(void* _p)
38863 : {
38864 0 : barycentricfitreport *p = (barycentricfitreport*)_p;
38865 0 : ae_touch_ptr((void*)p);
38866 0 : }
38867 :
38868 :
38869 0 : void _lsfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
38870 : {
38871 0 : lsfitreport *p = (lsfitreport*)_p;
38872 0 : ae_touch_ptr((void*)p);
38873 0 : ae_matrix_init(&p->covpar, 0, 0, DT_REAL, _state, make_automatic);
38874 0 : ae_vector_init(&p->errpar, 0, DT_REAL, _state, make_automatic);
38875 0 : ae_vector_init(&p->errcurve, 0, DT_REAL, _state, make_automatic);
38876 0 : ae_vector_init(&p->noise, 0, DT_REAL, _state, make_automatic);
38877 0 : }
38878 :
38879 :
38880 0 : void _lsfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
38881 : {
38882 0 : lsfitreport *dst = (lsfitreport*)_dst;
38883 0 : lsfitreport *src = (lsfitreport*)_src;
38884 0 : dst->taskrcond = src->taskrcond;
38885 0 : dst->iterationscount = src->iterationscount;
38886 0 : dst->varidx = src->varidx;
38887 0 : dst->rmserror = src->rmserror;
38888 0 : dst->avgerror = src->avgerror;
38889 0 : dst->avgrelerror = src->avgrelerror;
38890 0 : dst->maxerror = src->maxerror;
38891 0 : dst->wrmserror = src->wrmserror;
38892 0 : ae_matrix_init_copy(&dst->covpar, &src->covpar, _state, make_automatic);
38893 0 : ae_vector_init_copy(&dst->errpar, &src->errpar, _state, make_automatic);
38894 0 : ae_vector_init_copy(&dst->errcurve, &src->errcurve, _state, make_automatic);
38895 0 : ae_vector_init_copy(&dst->noise, &src->noise, _state, make_automatic);
38896 0 : dst->r2 = src->r2;
38897 0 : }
38898 :
38899 :
38900 0 : void _lsfitreport_clear(void* _p)
38901 : {
38902 0 : lsfitreport *p = (lsfitreport*)_p;
38903 0 : ae_touch_ptr((void*)p);
38904 0 : ae_matrix_clear(&p->covpar);
38905 0 : ae_vector_clear(&p->errpar);
38906 0 : ae_vector_clear(&p->errcurve);
38907 0 : ae_vector_clear(&p->noise);
38908 0 : }
38909 :
38910 :
38911 0 : void _lsfitreport_destroy(void* _p)
38912 : {
38913 0 : lsfitreport *p = (lsfitreport*)_p;
38914 0 : ae_touch_ptr((void*)p);
38915 0 : ae_matrix_destroy(&p->covpar);
38916 0 : ae_vector_destroy(&p->errpar);
38917 0 : ae_vector_destroy(&p->errcurve);
38918 0 : ae_vector_destroy(&p->noise);
38919 0 : }
38920 :
38921 :
38922 0 : void _lsfitstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
38923 : {
38924 0 : lsfitstate *p = (lsfitstate*)_p;
38925 0 : ae_touch_ptr((void*)p);
38926 0 : ae_vector_init(&p->c0, 0, DT_REAL, _state, make_automatic);
38927 0 : ae_vector_init(&p->c1, 0, DT_REAL, _state, make_automatic);
38928 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
38929 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
38930 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
38931 0 : ae_matrix_init(&p->taskx, 0, 0, DT_REAL, _state, make_automatic);
38932 0 : ae_vector_init(&p->tasky, 0, DT_REAL, _state, make_automatic);
38933 0 : ae_vector_init(&p->taskw, 0, DT_REAL, _state, make_automatic);
38934 0 : ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic);
38935 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
38936 0 : ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic);
38937 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
38938 0 : ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic);
38939 0 : ae_vector_init(&p->wcur, 0, DT_REAL, _state, make_automatic);
38940 0 : ae_vector_init(&p->tmpct, 0, DT_INT, _state, make_automatic);
38941 0 : ae_vector_init(&p->tmp, 0, DT_REAL, _state, make_automatic);
38942 0 : ae_vector_init(&p->tmpf, 0, DT_REAL, _state, make_automatic);
38943 0 : ae_matrix_init(&p->tmpjac, 0, 0, DT_REAL, _state, make_automatic);
38944 0 : ae_matrix_init(&p->tmpjacw, 0, 0, DT_REAL, _state, make_automatic);
38945 0 : _matinvreport_init(&p->invrep, _state, make_automatic);
38946 0 : _lsfitreport_init(&p->rep, _state, make_automatic);
38947 0 : _minlmstate_init(&p->optstate, _state, make_automatic);
38948 0 : _minlmreport_init(&p->optrep, _state, make_automatic);
38949 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
38950 0 : }
38951 :
38952 :
38953 0 : void _lsfitstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
38954 : {
38955 0 : lsfitstate *dst = (lsfitstate*)_dst;
38956 0 : lsfitstate *src = (lsfitstate*)_src;
38957 0 : dst->optalgo = src->optalgo;
38958 0 : dst->m = src->m;
38959 0 : dst->k = src->k;
38960 0 : dst->epsx = src->epsx;
38961 0 : dst->maxits = src->maxits;
38962 0 : dst->stpmax = src->stpmax;
38963 0 : dst->xrep = src->xrep;
38964 0 : ae_vector_init_copy(&dst->c0, &src->c0, _state, make_automatic);
38965 0 : ae_vector_init_copy(&dst->c1, &src->c1, _state, make_automatic);
38966 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
38967 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
38968 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
38969 0 : ae_matrix_init_copy(&dst->taskx, &src->taskx, _state, make_automatic);
38970 0 : ae_vector_init_copy(&dst->tasky, &src->tasky, _state, make_automatic);
38971 0 : dst->npoints = src->npoints;
38972 0 : ae_vector_init_copy(&dst->taskw, &src->taskw, _state, make_automatic);
38973 0 : dst->nweights = src->nweights;
38974 0 : dst->wkind = src->wkind;
38975 0 : dst->wits = src->wits;
38976 0 : dst->diffstep = src->diffstep;
38977 0 : dst->teststep = src->teststep;
38978 0 : ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic);
38979 0 : dst->nec = src->nec;
38980 0 : dst->nic = src->nic;
38981 0 : dst->xupdated = src->xupdated;
38982 0 : dst->needf = src->needf;
38983 0 : dst->needfg = src->needfg;
38984 0 : dst->needfgh = src->needfgh;
38985 0 : dst->pointindex = src->pointindex;
38986 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
38987 0 : ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic);
38988 0 : dst->f = src->f;
38989 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
38990 0 : ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic);
38991 0 : ae_vector_init_copy(&dst->wcur, &src->wcur, _state, make_automatic);
38992 0 : ae_vector_init_copy(&dst->tmpct, &src->tmpct, _state, make_automatic);
38993 0 : ae_vector_init_copy(&dst->tmp, &src->tmp, _state, make_automatic);
38994 0 : ae_vector_init_copy(&dst->tmpf, &src->tmpf, _state, make_automatic);
38995 0 : ae_matrix_init_copy(&dst->tmpjac, &src->tmpjac, _state, make_automatic);
38996 0 : ae_matrix_init_copy(&dst->tmpjacw, &src->tmpjacw, _state, make_automatic);
38997 0 : dst->tmpnoise = src->tmpnoise;
38998 0 : _matinvreport_init_copy(&dst->invrep, &src->invrep, _state, make_automatic);
38999 0 : dst->repiterationscount = src->repiterationscount;
39000 0 : dst->repterminationtype = src->repterminationtype;
39001 0 : dst->repvaridx = src->repvaridx;
39002 0 : dst->reprmserror = src->reprmserror;
39003 0 : dst->repavgerror = src->repavgerror;
39004 0 : dst->repavgrelerror = src->repavgrelerror;
39005 0 : dst->repmaxerror = src->repmaxerror;
39006 0 : dst->repwrmserror = src->repwrmserror;
39007 0 : _lsfitreport_init_copy(&dst->rep, &src->rep, _state, make_automatic);
39008 0 : _minlmstate_init_copy(&dst->optstate, &src->optstate, _state, make_automatic);
39009 0 : _minlmreport_init_copy(&dst->optrep, &src->optrep, _state, make_automatic);
39010 0 : dst->prevnpt = src->prevnpt;
39011 0 : dst->prevalgo = src->prevalgo;
39012 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
39013 0 : }
39014 :
39015 :
39016 0 : void _lsfitstate_clear(void* _p)
39017 : {
39018 0 : lsfitstate *p = (lsfitstate*)_p;
39019 0 : ae_touch_ptr((void*)p);
39020 0 : ae_vector_clear(&p->c0);
39021 0 : ae_vector_clear(&p->c1);
39022 0 : ae_vector_clear(&p->s);
39023 0 : ae_vector_clear(&p->bndl);
39024 0 : ae_vector_clear(&p->bndu);
39025 0 : ae_matrix_clear(&p->taskx);
39026 0 : ae_vector_clear(&p->tasky);
39027 0 : ae_vector_clear(&p->taskw);
39028 0 : ae_matrix_clear(&p->cleic);
39029 0 : ae_vector_clear(&p->x);
39030 0 : ae_vector_clear(&p->c);
39031 0 : ae_vector_clear(&p->g);
39032 0 : ae_matrix_clear(&p->h);
39033 0 : ae_vector_clear(&p->wcur);
39034 0 : ae_vector_clear(&p->tmpct);
39035 0 : ae_vector_clear(&p->tmp);
39036 0 : ae_vector_clear(&p->tmpf);
39037 0 : ae_matrix_clear(&p->tmpjac);
39038 0 : ae_matrix_clear(&p->tmpjacw);
39039 0 : _matinvreport_clear(&p->invrep);
39040 0 : _lsfitreport_clear(&p->rep);
39041 0 : _minlmstate_clear(&p->optstate);
39042 0 : _minlmreport_clear(&p->optrep);
39043 0 : _rcommstate_clear(&p->rstate);
39044 0 : }
39045 :
39046 :
39047 0 : void _lsfitstate_destroy(void* _p)
39048 : {
39049 0 : lsfitstate *p = (lsfitstate*)_p;
39050 0 : ae_touch_ptr((void*)p);
39051 0 : ae_vector_destroy(&p->c0);
39052 0 : ae_vector_destroy(&p->c1);
39053 0 : ae_vector_destroy(&p->s);
39054 0 : ae_vector_destroy(&p->bndl);
39055 0 : ae_vector_destroy(&p->bndu);
39056 0 : ae_matrix_destroy(&p->taskx);
39057 0 : ae_vector_destroy(&p->tasky);
39058 0 : ae_vector_destroy(&p->taskw);
39059 0 : ae_matrix_destroy(&p->cleic);
39060 0 : ae_vector_destroy(&p->x);
39061 0 : ae_vector_destroy(&p->c);
39062 0 : ae_vector_destroy(&p->g);
39063 0 : ae_matrix_destroy(&p->h);
39064 0 : ae_vector_destroy(&p->wcur);
39065 0 : ae_vector_destroy(&p->tmpct);
39066 0 : ae_vector_destroy(&p->tmp);
39067 0 : ae_vector_destroy(&p->tmpf);
39068 0 : ae_matrix_destroy(&p->tmpjac);
39069 0 : ae_matrix_destroy(&p->tmpjacw);
39070 0 : _matinvreport_destroy(&p->invrep);
39071 0 : _lsfitreport_destroy(&p->rep);
39072 0 : _minlmstate_destroy(&p->optstate);
39073 0 : _minlmreport_destroy(&p->optrep);
39074 0 : _rcommstate_destroy(&p->rstate);
39075 0 : }
39076 :
39077 :
39078 : #endif
39079 : #if defined(AE_COMPILE_RBFV2) || !defined(AE_PARTIAL_BUILD)
39080 :
39081 :
39082 : /*************************************************************************
39083 : This function creates RBF model for a scalar (NY=1) or vector (NY>1)
39084 : function in a NX-dimensional space (NX=2 or NX=3).
39085 :
39086 : INPUT PARAMETERS:
39087 : NX - dimension of the space, NX=2 or NX=3
39088 : NY - function dimension, NY>=1
39089 :
39090 : OUTPUT PARAMETERS:
39091 : S - RBF model (initially equals to zero)
39092 :
39093 : -- ALGLIB --
39094 : Copyright 13.12.2011 by Bochkanov Sergey
39095 : *************************************************************************/
39096 0 : void rbfv2create(ae_int_t nx,
39097 : ae_int_t ny,
39098 : rbfv2model* s,
39099 : ae_state *_state)
39100 : {
39101 : ae_int_t i;
39102 : ae_int_t j;
39103 :
39104 0 : _rbfv2model_clear(s);
39105 :
39106 0 : ae_assert(nx>=1, "RBFCreate: NX<1", _state);
39107 0 : ae_assert(ny>=1, "RBFCreate: NY<1", _state);
39108 :
39109 : /*
39110 : * Serializable parameters
39111 : */
39112 0 : s->nx = nx;
39113 0 : s->ny = ny;
39114 0 : s->bf = 0;
39115 0 : s->nh = 0;
39116 0 : ae_matrix_set_length(&s->v, ny, nx+1, _state);
39117 0 : for(i=0; i<=ny-1; i++)
39118 : {
39119 0 : for(j=0; j<=nx; j++)
39120 : {
39121 0 : s->v.ptr.pp_double[i][j] = (double)(0);
39122 : }
39123 : }
39124 :
39125 : /*
39126 : * Non-serializable parameters
39127 : */
39128 0 : s->lambdareg = rbfv2_defaultlambdareg;
39129 0 : s->maxits = rbfv2_defaultmaxits;
39130 0 : s->supportr = rbfv2_defaultsupportr;
39131 0 : s->basisfunction = rbfv2_defaultbf;
39132 0 : }
39133 :
39134 :
39135 : /*************************************************************************
39136 : This function creates buffer structure which can be used to perform
39137 : parallel RBF model evaluations (with one RBF model instance being
39138 : used from multiple threads, as long as different threads use different
39139 : instances of buffer).
39140 :
39141 : This buffer object can be used with rbftscalcbuf() function (here "ts"
39142 : stands for "thread-safe", "buf" is a suffix which denotes function which
39143 : reuses previously allocated output space).
39144 :
39145 : How to use it:
39146 : * create RBF model structure with rbfcreate()
39147 : * load data, tune parameters
39148 : * call rbfbuildmodel()
39149 : * call rbfcreatecalcbuffer(), once per thread working with RBF model (you
39150 : should call this function only AFTER call to rbfbuildmodel(), see below
39151 : for more information)
39152 : * call rbftscalcbuf() from different threads, with each thread working
39153 : with its own copy of buffer object.
39154 :
39155 : INPUT PARAMETERS
39156 : S - RBF model
39157 :
39158 : OUTPUT PARAMETERS
39159 : Buf - external buffer.
39160 :
39161 :
39162 : IMPORTANT: buffer object should be used only with RBF model object which
39163 : was used to initialize buffer. Any attempt to use buffer with
39164 : different object is dangerous - you may get memory violation
39165 : error because sizes of internal arrays do not fit to dimensions
39166 : of RBF structure.
39167 :
39168 : IMPORTANT: you should call this function only for model which was built
39169 : with rbfbuildmodel() function, after successful invocation of
39170 : rbfbuildmodel(). Sizes of some internal structures are
39171 : determined only after model is built, so buffer object created
39172 : before model construction stage will be useless (and any
39173 : attempt to use it will result in exception).
39174 :
39175 : -- ALGLIB --
39176 : Copyright 02.04.2016 by Sergey Bochkanov
39177 : *************************************************************************/
39178 0 : void rbfv2createcalcbuffer(rbfv2model* s,
39179 : rbfv2calcbuffer* buf,
39180 : ae_state *_state)
39181 : {
39182 :
39183 0 : _rbfv2calcbuffer_clear(buf);
39184 :
39185 0 : rbfv2_allocatecalcbuffer(s, buf, _state);
39186 0 : }
39187 :
39188 :
39189 : /*************************************************************************
39190 : This function builds hierarchical RBF model.
39191 :
39192 : INPUT PARAMETERS:
39193 : X - array[N,S.NX], X-values
39194 : Y - array[N,S.NY], Y-values
39195 : ScaleVec- array[S.NX], vector of per-dimension scales
39196 : N - points count
39197 : ATerm - linear term type, 1 for linear, 2 for constant, 3 for zero.
39198 : NH - hierarchy height
39199 : RBase - base RBF radius
39200 : BF - basis function type: 0 for Gaussian, 1 for compact
39201 : LambdaNS- non-smoothness penalty coefficient. Exactly zero value means
39202 : that no penalty is applied, and even system matrix does not
39203 : contain penalty-related rows. Value of 1 means
39204 : S - RBF model, initialized by RBFCreate() call.
39205 : progress10000- variable used for progress reports, it is regularly set
39206 : to the current progress multiplied by 10000, in order to
39207 : get value in [0,10000] range. The rationale for such scaling
39208 : is that it allows us to use integer type to store progress,
39209 : which has less potential for non-atomic corruption on unprotected
39210 : reads from another threads.
39211 : You can read this variable from some other thread to get
39212 : estimate of the current progress.
39213 : Initial value of this variable is ignored, it is written by
39214 : this function, but not read.
39215 : terminationrequest - variable used for termination requests; its initial
39216 : value must be False, and you can set it to True from some
39217 : other thread. This routine regularly checks this variable
39218 : and will terminate model construction shortly upon discovering
39219 : that termination was requested.
39220 :
39221 : OUTPUT PARAMETERS:
39222 : S - updated model (for rep.terminationtype>0, unchanged otherwise)
39223 : Rep - report:
39224 : * Rep.TerminationType:
39225 : * -5 - non-distinct basis function centers were detected,
39226 : interpolation aborted
39227 : * -4 - nonconvergence of the internal SVD solver
39228 : * 1 - successful termination
39229 : * 8 terminated by user via rbfrequesttermination()
39230 : Fields are used for debugging purposes:
39231 : * Rep.IterationsCount - iterations count of the LSQR solver
39232 : * Rep.NMV - number of matrix-vector products
39233 : * Rep.ARows - rows count for the system matrix
39234 : * Rep.ACols - columns count for the system matrix
39235 : * Rep.ANNZ - number of significantly non-zero elements
39236 : (elements above some algorithm-determined threshold)
39237 :
39238 : NOTE: failure to build model will leave current state of the structure
39239 : unchanged.
39240 :
39241 : -- ALGLIB --
39242 : Copyright 20.06.2016 by Bochkanov Sergey
39243 : *************************************************************************/
39244 0 : void rbfv2buildhierarchical(/* Real */ ae_matrix* x,
39245 : /* Real */ ae_matrix* y,
39246 : ae_int_t n,
39247 : /* Real */ ae_vector* scalevec,
39248 : ae_int_t aterm,
39249 : ae_int_t nh,
39250 : double rbase,
39251 : double lambdans,
39252 : rbfv2model* s,
39253 : ae_int_t* progress10000,
39254 : ae_bool* terminationrequest,
39255 : rbfv2report* rep,
39256 : ae_state *_state)
39257 : {
39258 : ae_frame _frame_block;
39259 : ae_int_t nx;
39260 : ae_int_t ny;
39261 : ae_int_t bf;
39262 : ae_matrix rhs;
39263 : ae_matrix residualy;
39264 : ae_matrix v;
39265 : ae_int_t rowsperpoint;
39266 : ae_vector hidx;
39267 : ae_vector xr;
39268 : ae_vector ri;
39269 : ae_vector kdroots;
39270 : ae_vector kdnodes;
39271 : ae_vector kdsplits;
39272 : ae_vector kdboxmin;
39273 : ae_vector kdboxmax;
39274 : ae_vector cw;
39275 : ae_vector cwrange;
39276 : ae_matrix curxy;
39277 : ae_int_t curn;
39278 : ae_int_t nbasis;
39279 : kdtree curtree;
39280 : kdtree globaltree;
39281 : ae_vector x0;
39282 : ae_vector x1;
39283 : ae_vector tags;
39284 : ae_vector dist;
39285 : ae_vector nncnt;
39286 : ae_vector rowsizes;
39287 : ae_vector diagata;
39288 : ae_vector prec;
39289 : ae_vector tmpx;
39290 : ae_int_t i;
39291 : ae_int_t j;
39292 : ae_int_t k;
39293 : ae_int_t k2;
39294 : ae_int_t levelidx;
39295 : ae_int_t offsi;
39296 : ae_int_t offsj;
39297 : double val;
39298 : double criticalr;
39299 : ae_int_t cnt;
39300 : double avgdiagata;
39301 : ae_vector avgrowsize;
39302 : double sumrowsize;
39303 : double rprogress;
39304 : ae_int_t maxits;
39305 : linlsqrstate linstate;
39306 : linlsqrreport lsqrrep;
39307 : sparsematrix sparseacrs;
39308 : ae_vector densew1;
39309 : ae_vector denseb1;
39310 : rbfv2calcbuffer calcbuf;
39311 : ae_vector vr2;
39312 : ae_vector voffs;
39313 : ae_vector rowindexes;
39314 : ae_vector rowvals;
39315 : double penalty;
39316 :
39317 0 : ae_frame_make(_state, &_frame_block);
39318 0 : memset(&rhs, 0, sizeof(rhs));
39319 0 : memset(&residualy, 0, sizeof(residualy));
39320 0 : memset(&v, 0, sizeof(v));
39321 0 : memset(&hidx, 0, sizeof(hidx));
39322 0 : memset(&xr, 0, sizeof(xr));
39323 0 : memset(&ri, 0, sizeof(ri));
39324 0 : memset(&kdroots, 0, sizeof(kdroots));
39325 0 : memset(&kdnodes, 0, sizeof(kdnodes));
39326 0 : memset(&kdsplits, 0, sizeof(kdsplits));
39327 0 : memset(&kdboxmin, 0, sizeof(kdboxmin));
39328 0 : memset(&kdboxmax, 0, sizeof(kdboxmax));
39329 0 : memset(&cw, 0, sizeof(cw));
39330 0 : memset(&cwrange, 0, sizeof(cwrange));
39331 0 : memset(&curxy, 0, sizeof(curxy));
39332 0 : memset(&curtree, 0, sizeof(curtree));
39333 0 : memset(&globaltree, 0, sizeof(globaltree));
39334 0 : memset(&x0, 0, sizeof(x0));
39335 0 : memset(&x1, 0, sizeof(x1));
39336 0 : memset(&tags, 0, sizeof(tags));
39337 0 : memset(&dist, 0, sizeof(dist));
39338 0 : memset(&nncnt, 0, sizeof(nncnt));
39339 0 : memset(&rowsizes, 0, sizeof(rowsizes));
39340 0 : memset(&diagata, 0, sizeof(diagata));
39341 0 : memset(&prec, 0, sizeof(prec));
39342 0 : memset(&tmpx, 0, sizeof(tmpx));
39343 0 : memset(&avgrowsize, 0, sizeof(avgrowsize));
39344 0 : memset(&linstate, 0, sizeof(linstate));
39345 0 : memset(&lsqrrep, 0, sizeof(lsqrrep));
39346 0 : memset(&sparseacrs, 0, sizeof(sparseacrs));
39347 0 : memset(&densew1, 0, sizeof(densew1));
39348 0 : memset(&denseb1, 0, sizeof(denseb1));
39349 0 : memset(&calcbuf, 0, sizeof(calcbuf));
39350 0 : memset(&vr2, 0, sizeof(vr2));
39351 0 : memset(&voffs, 0, sizeof(voffs));
39352 0 : memset(&rowindexes, 0, sizeof(rowindexes));
39353 0 : memset(&rowvals, 0, sizeof(rowvals));
39354 0 : _rbfv2report_clear(rep);
39355 0 : ae_matrix_init(&rhs, 0, 0, DT_REAL, _state, ae_true);
39356 0 : ae_matrix_init(&residualy, 0, 0, DT_REAL, _state, ae_true);
39357 0 : ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
39358 0 : ae_vector_init(&hidx, 0, DT_INT, _state, ae_true);
39359 0 : ae_vector_init(&xr, 0, DT_REAL, _state, ae_true);
39360 0 : ae_vector_init(&ri, 0, DT_REAL, _state, ae_true);
39361 0 : ae_vector_init(&kdroots, 0, DT_INT, _state, ae_true);
39362 0 : ae_vector_init(&kdnodes, 0, DT_INT, _state, ae_true);
39363 0 : ae_vector_init(&kdsplits, 0, DT_REAL, _state, ae_true);
39364 0 : ae_vector_init(&kdboxmin, 0, DT_REAL, _state, ae_true);
39365 0 : ae_vector_init(&kdboxmax, 0, DT_REAL, _state, ae_true);
39366 0 : ae_vector_init(&cw, 0, DT_REAL, _state, ae_true);
39367 0 : ae_vector_init(&cwrange, 0, DT_INT, _state, ae_true);
39368 0 : ae_matrix_init(&curxy, 0, 0, DT_REAL, _state, ae_true);
39369 0 : _kdtree_init(&curtree, _state, ae_true);
39370 0 : _kdtree_init(&globaltree, _state, ae_true);
39371 0 : ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
39372 0 : ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
39373 0 : ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
39374 0 : ae_vector_init(&dist, 0, DT_REAL, _state, ae_true);
39375 0 : ae_vector_init(&nncnt, 0, DT_INT, _state, ae_true);
39376 0 : ae_vector_init(&rowsizes, 0, DT_INT, _state, ae_true);
39377 0 : ae_vector_init(&diagata, 0, DT_REAL, _state, ae_true);
39378 0 : ae_vector_init(&prec, 0, DT_REAL, _state, ae_true);
39379 0 : ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true);
39380 0 : ae_vector_init(&avgrowsize, 0, DT_REAL, _state, ae_true);
39381 0 : _linlsqrstate_init(&linstate, _state, ae_true);
39382 0 : _linlsqrreport_init(&lsqrrep, _state, ae_true);
39383 0 : _sparsematrix_init(&sparseacrs, _state, ae_true);
39384 0 : ae_vector_init(&densew1, 0, DT_REAL, _state, ae_true);
39385 0 : ae_vector_init(&denseb1, 0, DT_REAL, _state, ae_true);
39386 0 : _rbfv2calcbuffer_init(&calcbuf, _state, ae_true);
39387 0 : ae_vector_init(&vr2, 0, DT_REAL, _state, ae_true);
39388 0 : ae_vector_init(&voffs, 0, DT_INT, _state, ae_true);
39389 0 : ae_vector_init(&rowindexes, 0, DT_INT, _state, ae_true);
39390 0 : ae_vector_init(&rowvals, 0, DT_REAL, _state, ae_true);
39391 :
39392 0 : ae_assert(s->nx>0, "RBFV2BuildHierarchical: incorrect NX", _state);
39393 0 : ae_assert(s->ny>0, "RBFV2BuildHierarchical: incorrect NY", _state);
39394 0 : ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "RBFV2BuildHierarchical: incorrect LambdaNS", _state);
39395 0 : for(j=0; j<=s->nx-1; j++)
39396 : {
39397 0 : ae_assert(ae_fp_greater(scalevec->ptr.p_double[j],(double)(0)), "RBFV2BuildHierarchical: incorrect ScaleVec", _state);
39398 : }
39399 0 : nx = s->nx;
39400 0 : ny = s->ny;
39401 0 : bf = s->basisfunction;
39402 0 : ae_assert(bf==0||bf==1, "RBFV2BuildHierarchical: incorrect BF", _state);
39403 :
39404 : /*
39405 : * Clean up communication and report fields
39406 : */
39407 0 : *progress10000 = 0;
39408 0 : rep->maxerror = (double)(0);
39409 0 : rep->rmserror = (double)(0);
39410 :
39411 : /*
39412 : * Quick exit when we have no points
39413 : */
39414 0 : if( n==0 )
39415 : {
39416 0 : rbfv2_zerofill(s, nx, ny, bf, _state);
39417 0 : rep->terminationtype = 1;
39418 0 : *progress10000 = 10000;
39419 0 : ae_frame_leave(_state);
39420 0 : return;
39421 : }
39422 :
39423 : /*
39424 : * First model in a sequence - linear model.
39425 : * Residuals from linear regression are stored in the ResidualY variable
39426 : * (used later to build RBF models).
39427 : */
39428 0 : ae_matrix_set_length(&residualy, n, ny, _state);
39429 0 : for(i=0; i<=n-1; i++)
39430 : {
39431 0 : for(j=0; j<=ny-1; j++)
39432 : {
39433 0 : residualy.ptr.pp_double[i][j] = y->ptr.pp_double[i][j];
39434 : }
39435 : }
39436 0 : if( !rbfv2_rbfv2buildlinearmodel(x, &residualy, n, nx, ny, aterm, &v, _state) )
39437 : {
39438 0 : rbfv2_zerofill(s, nx, ny, bf, _state);
39439 0 : rep->terminationtype = -5;
39440 0 : *progress10000 = 10000;
39441 0 : ae_frame_leave(_state);
39442 0 : return;
39443 : }
39444 :
39445 : /*
39446 : * Handle special case: multilayer model with NLayers=0.
39447 : * Quick exit.
39448 : */
39449 0 : if( nh==0 )
39450 : {
39451 0 : rep->terminationtype = 1;
39452 0 : rbfv2_zerofill(s, nx, ny, bf, _state);
39453 0 : for(i=0; i<=ny-1; i++)
39454 : {
39455 0 : for(j=0; j<=nx; j++)
39456 : {
39457 0 : s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j];
39458 : }
39459 : }
39460 0 : rep->maxerror = (double)(0);
39461 0 : rep->rmserror = (double)(0);
39462 0 : for(i=0; i<=n-1; i++)
39463 : {
39464 0 : for(j=0; j<=ny-1; j++)
39465 : {
39466 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(residualy.ptr.pp_double[i][j], _state), _state);
39467 0 : rep->rmserror = rep->rmserror+ae_sqr(residualy.ptr.pp_double[i][j], _state);
39468 : }
39469 : }
39470 0 : rep->rmserror = ae_sqrt(rep->rmserror/(n*ny), _state);
39471 0 : *progress10000 = 10000;
39472 0 : ae_frame_leave(_state);
39473 0 : return;
39474 : }
39475 :
39476 : /*
39477 : * Penalty coefficient is set to LambdaNS*RBase^2.
39478 : *
39479 : * We use such normalization because VALUES of radial basis
39480 : * functions have roughly unit magnitude, but their DERIVATIVES
39481 : * are (roughly) inversely proportional to the radius. Thus,
39482 : * without additional scaling, regularization coefficient
39483 : * looses invariancy w.r.t. scaling of variables.
39484 : */
39485 0 : if( ae_fp_eq(lambdans,(double)(0)) )
39486 : {
39487 0 : rowsperpoint = 1;
39488 : }
39489 : else
39490 : {
39491 :
39492 : /*
39493 : * NOTE: simplified penalty function is used, which does not provide rotation invariance
39494 : */
39495 0 : rowsperpoint = 1+nx;
39496 : }
39497 0 : penalty = lambdans*ae_sqr(rbase, _state);
39498 :
39499 : /*
39500 : * Prepare temporary structures
39501 : */
39502 0 : ae_matrix_set_length(&rhs, n*rowsperpoint, ny, _state);
39503 0 : ae_matrix_set_length(&curxy, n, nx+ny, _state);
39504 0 : ae_vector_set_length(&x0, nx, _state);
39505 0 : ae_vector_set_length(&x1, nx, _state);
39506 0 : ae_vector_set_length(&tags, n, _state);
39507 0 : ae_vector_set_length(&dist, n, _state);
39508 0 : ae_vector_set_length(&vr2, n, _state);
39509 0 : ae_vector_set_length(&voffs, n, _state);
39510 0 : ae_vector_set_length(&nncnt, n, _state);
39511 0 : ae_vector_set_length(&rowsizes, n*rowsperpoint, _state);
39512 0 : ae_vector_set_length(&denseb1, n*rowsperpoint, _state);
39513 0 : for(i=0; i<=n*rowsperpoint-1; i++)
39514 : {
39515 0 : for(j=0; j<=ny-1; j++)
39516 : {
39517 0 : rhs.ptr.pp_double[i][j] = (double)(0);
39518 : }
39519 : }
39520 0 : for(i=0; i<=n-1; i++)
39521 : {
39522 0 : for(j=0; j<=nx-1; j++)
39523 : {
39524 0 : curxy.ptr.pp_double[i][j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j];
39525 : }
39526 0 : for(j=0; j<=ny-1; j++)
39527 : {
39528 0 : rhs.ptr.pp_double[i*rowsperpoint][j] = residualy.ptr.pp_double[i][j];
39529 : }
39530 0 : tags.ptr.p_int[i] = i;
39531 : }
39532 0 : kdtreebuildtagged(&curxy, &tags, n, nx, 0, 2, &globaltree, _state);
39533 :
39534 : /*
39535 : * Generate sequence of layer radii.
39536 : * Prepare assignment of different levels to points.
39537 : */
39538 0 : ae_assert(n>0, "RBFV2BuildHierarchical: integrity check failed", _state);
39539 0 : ae_vector_set_length(&ri, nh, _state);
39540 0 : for(levelidx=0; levelidx<=nh-1; levelidx++)
39541 : {
39542 0 : ri.ptr.p_double[levelidx] = rbase*ae_pow((double)(2), (double)(-levelidx), _state);
39543 : }
39544 0 : ae_vector_set_length(&hidx, n, _state);
39545 0 : ae_vector_set_length(&xr, n, _state);
39546 0 : for(i=0; i<=n-1; i++)
39547 : {
39548 0 : hidx.ptr.p_int[i] = nh;
39549 0 : xr.ptr.p_double[i] = ae_maxrealnumber;
39550 0 : ae_assert(ae_fp_greater(xr.ptr.p_double[i],ri.ptr.p_double[0]), "RBFV2BuildHierarchical: integrity check failed", _state);
39551 : }
39552 0 : for(levelidx=0; levelidx<=nh-1; levelidx++)
39553 : {
39554 :
39555 : /*
39556 : * Scan dataset points, for each such point that distance to nearest
39557 : * "support" point is larger than SupportR*Ri[LevelIdx] we:
39558 : * * set distance of current point to 0 (it is support now) and update HIdx
39559 : * * perform R-NN request with radius SupportR*Ri[LevelIdx]
39560 : * * for each point in request update its distance
39561 : */
39562 0 : criticalr = s->supportr*ri.ptr.p_double[levelidx];
39563 0 : for(i=0; i<=n-1; i++)
39564 : {
39565 0 : if( ae_fp_greater(xr.ptr.p_double[i],criticalr) )
39566 : {
39567 :
39568 : /*
39569 : * Mark point as support
39570 : */
39571 0 : ae_assert(hidx.ptr.p_int[i]==nh, "RBFV2BuildHierarchical: integrity check failed", _state);
39572 0 : hidx.ptr.p_int[i] = levelidx;
39573 0 : xr.ptr.p_double[i] = (double)(0);
39574 :
39575 : /*
39576 : * Update neighbors
39577 : */
39578 0 : for(j=0; j<=nx-1; j++)
39579 : {
39580 0 : x0.ptr.p_double[j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j];
39581 : }
39582 0 : k = kdtreequeryrnn(&globaltree, &x0, criticalr, ae_true, _state);
39583 0 : kdtreequeryresultstags(&globaltree, &tags, _state);
39584 0 : kdtreequeryresultsdistances(&globaltree, &dist, _state);
39585 0 : for(j=0; j<=k-1; j++)
39586 : {
39587 0 : xr.ptr.p_double[tags.ptr.p_int[j]] = ae_minreal(xr.ptr.p_double[tags.ptr.p_int[j]], dist.ptr.p_double[j], _state);
39588 : }
39589 : }
39590 : }
39591 : }
39592 :
39593 : /*
39594 : * Build multitree (with zero weights) according to hierarchy.
39595 : *
39596 : * NOTE: this code assumes that during every iteration kdNodes,
39597 : * kdSplits and CW have size which EXACTLY fits their
39598 : * contents, and that these variables are resized at each
39599 : * iteration when we add new hierarchical model.
39600 : */
39601 0 : ae_vector_set_length(&kdroots, nh+1, _state);
39602 0 : ae_vector_set_length(&kdnodes, 0, _state);
39603 0 : ae_vector_set_length(&kdsplits, 0, _state);
39604 0 : ae_vector_set_length(&kdboxmin, nx, _state);
39605 0 : ae_vector_set_length(&kdboxmax, nx, _state);
39606 0 : ae_vector_set_length(&cw, 0, _state);
39607 0 : ae_vector_set_length(&cwrange, nh+1, _state);
39608 0 : kdtreeexplorebox(&globaltree, &kdboxmin, &kdboxmax, _state);
39609 0 : cwrange.ptr.p_int[0] = 0;
39610 0 : for(levelidx=0; levelidx<=nh-1; levelidx++)
39611 : {
39612 :
39613 : /*
39614 : * Prepare radius and root offset
39615 : */
39616 0 : kdroots.ptr.p_int[levelidx] = kdnodes.cnt;
39617 :
39618 : /*
39619 : * Generate LevelIdx-th tree and append to multi-tree
39620 : */
39621 0 : curn = 0;
39622 0 : for(i=0; i<=n-1; i++)
39623 : {
39624 0 : if( hidx.ptr.p_int[i]<=levelidx )
39625 : {
39626 0 : for(j=0; j<=nx-1; j++)
39627 : {
39628 0 : curxy.ptr.pp_double[curn][j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j];
39629 : }
39630 0 : for(j=0; j<=ny-1; j++)
39631 : {
39632 0 : curxy.ptr.pp_double[curn][nx+j] = (double)(0);
39633 : }
39634 0 : inc(&curn, _state);
39635 : }
39636 : }
39637 0 : ae_assert(curn>0, "RBFV2BuildHierarchical: integrity check failed", _state);
39638 0 : kdtreebuild(&curxy, curn, nx, ny, 2, &curtree, _state);
39639 0 : rbfv2_convertandappendtree(&curtree, curn, nx, ny, &kdnodes, &kdsplits, &cw, _state);
39640 :
39641 : /*
39642 : * Fill entry of CWRange (we assume that length of CW exactly fits its actual size)
39643 : */
39644 0 : cwrange.ptr.p_int[levelidx+1] = cw.cnt;
39645 : }
39646 0 : kdroots.ptr.p_int[nh] = kdnodes.cnt;
39647 :
39648 : /*
39649 : * Prepare buffer and scaled dataset
39650 : */
39651 0 : rbfv2_allocatecalcbuffer(s, &calcbuf, _state);
39652 0 : for(i=0; i<=n-1; i++)
39653 : {
39654 0 : for(j=0; j<=nx-1; j++)
39655 : {
39656 0 : curxy.ptr.pp_double[i][j] = x->ptr.pp_double[i][j]/scalevec->ptr.p_double[j];
39657 : }
39658 : }
39659 :
39660 : /*
39661 : * Calculate average row sizes for each layer; these values are used
39662 : * for smooth progress reporting (it adds some overhead, but in most
39663 : * cases - insignificant one).
39664 : */
39665 0 : rvectorsetlengthatleast(&avgrowsize, nh, _state);
39666 0 : sumrowsize = (double)(0);
39667 0 : for(levelidx=0; levelidx<=nh-1; levelidx++)
39668 : {
39669 0 : cnt = 0;
39670 0 : for(i=0; i<=n-1; i++)
39671 : {
39672 0 : for(j=0; j<=nx-1; j++)
39673 : {
39674 0 : x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j];
39675 : }
39676 0 : cnt = cnt+rbfv2_designmatrixrowsize(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, nx, ny, nh, levelidx, rbfv2nearradius(bf, _state), &x0, &calcbuf, _state);
39677 : }
39678 0 : avgrowsize.ptr.p_double[levelidx] = coalesce((double)(cnt), (double)(1), _state)/coalesce((double)(n), (double)(1), _state);
39679 0 : sumrowsize = sumrowsize+avgrowsize.ptr.p_double[levelidx];
39680 : }
39681 :
39682 : /*
39683 : * Build unconstrained model with LSQR solver, applied layer by layer
39684 : */
39685 0 : for(levelidx=0; levelidx<=nh-1; levelidx++)
39686 : {
39687 :
39688 : /*
39689 : * Generate A - matrix of basis functions (near radius is used)
39690 : *
39691 : * NOTE: AvgDiagATA is average value of diagonal element of A^T*A.
39692 : * It is used to calculate value of Tikhonov regularization
39693 : * coefficient.
39694 : */
39695 0 : nbasis = (cwrange.ptr.p_int[levelidx+1]-cwrange.ptr.p_int[levelidx])/(nx+ny);
39696 0 : ae_assert(cwrange.ptr.p_int[levelidx+1]-cwrange.ptr.p_int[levelidx]==nbasis*(nx+ny), "Assertion failed", _state);
39697 0 : for(i=0; i<=n-1; i++)
39698 : {
39699 0 : for(j=0; j<=nx-1; j++)
39700 : {
39701 0 : x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j];
39702 : }
39703 0 : cnt = rbfv2_designmatrixrowsize(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, nx, ny, nh, levelidx, rbfv2nearradius(bf, _state), &x0, &calcbuf, _state);
39704 0 : nncnt.ptr.p_int[i] = cnt;
39705 0 : for(j=0; j<=rowsperpoint-1; j++)
39706 : {
39707 0 : rowsizes.ptr.p_int[i*rowsperpoint+j] = cnt;
39708 : }
39709 : }
39710 0 : ivectorsetlengthatleast(&rowindexes, nbasis, _state);
39711 0 : rvectorsetlengthatleast(&rowvals, nbasis*rowsperpoint, _state);
39712 0 : rvectorsetlengthatleast(&diagata, nbasis, _state);
39713 0 : sparsecreatecrsbuf(n*rowsperpoint, nbasis, &rowsizes, &sparseacrs, _state);
39714 0 : avgdiagata = 0.0;
39715 0 : for(j=0; j<=nbasis-1; j++)
39716 : {
39717 0 : diagata.ptr.p_double[j] = (double)(0);
39718 : }
39719 0 : for(i=0; i<=n-1; i++)
39720 : {
39721 :
39722 : /*
39723 : * Fill design matrix row, diagonal of A^T*A
39724 : */
39725 0 : for(j=0; j<=nx-1; j++)
39726 : {
39727 0 : x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j];
39728 : }
39729 0 : rbfv2_designmatrixgeneraterow(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, &cwrange, nx, ny, nh, levelidx, bf, rbfv2nearradius(bf, _state), rowsperpoint, penalty, &x0, &calcbuf, &vr2, &voffs, &rowindexes, &rowvals, &cnt, _state);
39730 0 : ae_assert(cnt==nncnt.ptr.p_int[i], "RBFV2BuildHierarchical: integrity check failed", _state);
39731 0 : for(k=0; k<=rowsperpoint-1; k++)
39732 : {
39733 0 : for(j=0; j<=cnt-1; j++)
39734 : {
39735 0 : val = rowvals.ptr.p_double[j*rowsperpoint+k];
39736 0 : sparseset(&sparseacrs, i*rowsperpoint+k, rowindexes.ptr.p_int[j], val, _state);
39737 0 : avgdiagata = avgdiagata+ae_sqr(val, _state);
39738 0 : diagata.ptr.p_double[rowindexes.ptr.p_int[j]] = diagata.ptr.p_double[rowindexes.ptr.p_int[j]]+ae_sqr(val, _state);
39739 : }
39740 : }
39741 :
39742 : /*
39743 : * Handle possible termination requests
39744 : */
39745 0 : if( *terminationrequest )
39746 : {
39747 :
39748 : /*
39749 : * Request for termination was submitted, terminate immediately
39750 : */
39751 0 : rbfv2_zerofill(s, nx, ny, bf, _state);
39752 0 : rep->terminationtype = 8;
39753 0 : *progress10000 = 10000;
39754 0 : ae_frame_leave(_state);
39755 0 : return;
39756 : }
39757 : }
39758 0 : avgdiagata = avgdiagata/nbasis;
39759 0 : rvectorsetlengthatleast(&prec, nbasis, _state);
39760 0 : for(j=0; j<=nbasis-1; j++)
39761 : {
39762 0 : prec.ptr.p_double[j] = 1/coalesce(ae_sqrt(diagata.ptr.p_double[j], _state), (double)(1), _state);
39763 : }
39764 :
39765 : /*
39766 : * solve
39767 : */
39768 0 : maxits = coalescei(s->maxits, rbfv2_defaultmaxits, _state);
39769 0 : rvectorsetlengthatleast(&tmpx, nbasis, _state);
39770 0 : linlsqrcreate(n*rowsperpoint, nbasis, &linstate, _state);
39771 0 : linlsqrsetcond(&linstate, 0.0, 0.0, maxits, _state);
39772 0 : linlsqrsetlambdai(&linstate, ae_sqrt(s->lambdareg*avgdiagata, _state), _state);
39773 0 : for(j=0; j<=ny-1; j++)
39774 : {
39775 0 : for(i=0; i<=n*rowsperpoint-1; i++)
39776 : {
39777 0 : denseb1.ptr.p_double[i] = rhs.ptr.pp_double[i][j];
39778 : }
39779 0 : linlsqrsetb(&linstate, &denseb1, _state);
39780 0 : linlsqrrestart(&linstate, _state);
39781 0 : linlsqrsetxrep(&linstate, ae_true, _state);
39782 0 : while(linlsqriteration(&linstate, _state))
39783 : {
39784 0 : if( *terminationrequest )
39785 : {
39786 :
39787 : /*
39788 : * Request for termination was submitted, terminate immediately
39789 : */
39790 0 : rbfv2_zerofill(s, nx, ny, bf, _state);
39791 0 : rep->terminationtype = 8;
39792 0 : *progress10000 = 10000;
39793 0 : ae_frame_leave(_state);
39794 0 : return;
39795 : }
39796 0 : if( linstate.needmv )
39797 : {
39798 0 : for(i=0; i<=nbasis-1; i++)
39799 : {
39800 0 : tmpx.ptr.p_double[i] = prec.ptr.p_double[i]*linstate.x.ptr.p_double[i];
39801 : }
39802 0 : sparsemv(&sparseacrs, &tmpx, &linstate.mv, _state);
39803 0 : continue;
39804 : }
39805 0 : if( linstate.needmtv )
39806 : {
39807 0 : sparsemtv(&sparseacrs, &linstate.x, &linstate.mtv, _state);
39808 0 : for(i=0; i<=nbasis-1; i++)
39809 : {
39810 0 : linstate.mtv.ptr.p_double[i] = prec.ptr.p_double[i]*linstate.mtv.ptr.p_double[i];
39811 : }
39812 0 : continue;
39813 : }
39814 0 : if( linstate.xupdated )
39815 : {
39816 0 : rprogress = (double)(0);
39817 0 : for(i=0; i<=levelidx-1; i++)
39818 : {
39819 0 : rprogress = rprogress+maxits*ny*avgrowsize.ptr.p_double[i];
39820 : }
39821 0 : rprogress = rprogress+(linlsqrpeekiterationscount(&linstate, _state)+j*maxits)*avgrowsize.ptr.p_double[levelidx];
39822 0 : rprogress = rprogress/(sumrowsize*maxits*ny);
39823 0 : rprogress = 10000*rprogress;
39824 0 : rprogress = ae_maxreal(rprogress, (double)(0), _state);
39825 0 : rprogress = ae_minreal(rprogress, (double)(10000), _state);
39826 0 : ae_assert(*progress10000<=ae_round(rprogress, _state)+1, "HRBF: integrity check failed (progress indicator) even after +1 safeguard correction", _state);
39827 0 : *progress10000 = ae_round(rprogress, _state);
39828 0 : continue;
39829 : }
39830 0 : ae_assert(ae_false, "HRBF: unexpected request from LSQR solver", _state);
39831 : }
39832 0 : linlsqrresults(&linstate, &densew1, &lsqrrep, _state);
39833 0 : ae_assert(lsqrrep.terminationtype>0, "RBFV2BuildHierarchical: integrity check failed", _state);
39834 0 : for(i=0; i<=nbasis-1; i++)
39835 : {
39836 0 : densew1.ptr.p_double[i] = prec.ptr.p_double[i]*densew1.ptr.p_double[i];
39837 : }
39838 0 : for(i=0; i<=nbasis-1; i++)
39839 : {
39840 0 : offsi = cwrange.ptr.p_int[levelidx]+(nx+ny)*i;
39841 0 : cw.ptr.p_double[offsi+nx+j] = densew1.ptr.p_double[i];
39842 : }
39843 : }
39844 :
39845 : /*
39846 : * Update residuals (far radius is used)
39847 : */
39848 0 : for(i=0; i<=n-1; i++)
39849 : {
39850 0 : for(j=0; j<=nx-1; j++)
39851 : {
39852 0 : x0.ptr.p_double[j] = curxy.ptr.pp_double[i][j];
39853 : }
39854 0 : rbfv2_designmatrixgeneraterow(&kdnodes, &kdsplits, &cw, &ri, &kdroots, &kdboxmin, &kdboxmax, &cwrange, nx, ny, nh, levelidx, bf, rbfv2farradius(bf, _state), rowsperpoint, penalty, &x0, &calcbuf, &vr2, &voffs, &rowindexes, &rowvals, &cnt, _state);
39855 0 : for(j=0; j<=cnt-1; j++)
39856 : {
39857 0 : offsj = cwrange.ptr.p_int[levelidx]+(nx+ny)*rowindexes.ptr.p_int[j]+nx;
39858 0 : for(k=0; k<=rowsperpoint-1; k++)
39859 : {
39860 0 : val = rowvals.ptr.p_double[j*rowsperpoint+k];
39861 0 : for(k2=0; k2<=ny-1; k2++)
39862 : {
39863 0 : rhs.ptr.pp_double[i*rowsperpoint+k][k2] = rhs.ptr.pp_double[i*rowsperpoint+k][k2]-val*cw.ptr.p_double[offsj+k2];
39864 : }
39865 : }
39866 : }
39867 : }
39868 : }
39869 :
39870 : /*
39871 : * Model is built.
39872 : *
39873 : * Copy local variables by swapping, global ones (ScaleVec) are copied
39874 : * explicitly.
39875 : */
39876 0 : s->bf = bf;
39877 0 : s->nh = nh;
39878 0 : ae_swap_vectors(&s->ri, &ri);
39879 0 : ae_swap_vectors(&s->kdroots, &kdroots);
39880 0 : ae_swap_vectors(&s->kdnodes, &kdnodes);
39881 0 : ae_swap_vectors(&s->kdsplits, &kdsplits);
39882 0 : ae_swap_vectors(&s->kdboxmin, &kdboxmin);
39883 0 : ae_swap_vectors(&s->kdboxmax, &kdboxmax);
39884 0 : ae_swap_vectors(&s->cw, &cw);
39885 0 : ae_swap_matrices(&s->v, &v);
39886 0 : ae_vector_set_length(&s->s, nx, _state);
39887 0 : for(i=0; i<=nx-1; i++)
39888 : {
39889 0 : s->s.ptr.p_double[i] = scalevec->ptr.p_double[i];
39890 : }
39891 0 : rep->terminationtype = 1;
39892 :
39893 : /*
39894 : * Calculate maximum and RMS errors
39895 : */
39896 0 : rep->maxerror = (double)(0);
39897 0 : rep->rmserror = (double)(0);
39898 0 : for(i=0; i<=n-1; i++)
39899 : {
39900 0 : for(j=0; j<=ny-1; j++)
39901 : {
39902 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(rhs.ptr.pp_double[i*rowsperpoint][j], _state), _state);
39903 0 : rep->rmserror = rep->rmserror+ae_sqr(rhs.ptr.pp_double[i*rowsperpoint][j], _state);
39904 : }
39905 : }
39906 0 : rep->rmserror = ae_sqrt(rep->rmserror/(n*ny), _state);
39907 :
39908 : /*
39909 : * Update progress reports
39910 : */
39911 0 : *progress10000 = 10000;
39912 0 : ae_frame_leave(_state);
39913 : }
39914 :
39915 :
39916 : /*************************************************************************
39917 : Serializer: allocation
39918 :
39919 : -- ALGLIB --
39920 : Copyright 02.02.2012 by Bochkanov Sergey
39921 : *************************************************************************/
39922 0 : void rbfv2alloc(ae_serializer* s, rbfv2model* model, ae_state *_state)
39923 : {
39924 :
39925 :
39926 :
39927 : /*
39928 : * Data
39929 : */
39930 0 : ae_serializer_alloc_entry(s);
39931 0 : ae_serializer_alloc_entry(s);
39932 0 : ae_serializer_alloc_entry(s);
39933 0 : ae_serializer_alloc_entry(s);
39934 0 : allocrealarray(s, &model->ri, -1, _state);
39935 0 : allocrealarray(s, &model->s, -1, _state);
39936 0 : allocintegerarray(s, &model->kdroots, -1, _state);
39937 0 : allocintegerarray(s, &model->kdnodes, -1, _state);
39938 0 : allocrealarray(s, &model->kdsplits, -1, _state);
39939 0 : allocrealarray(s, &model->kdboxmin, -1, _state);
39940 0 : allocrealarray(s, &model->kdboxmax, -1, _state);
39941 0 : allocrealarray(s, &model->cw, -1, _state);
39942 0 : allocrealmatrix(s, &model->v, -1, -1, _state);
39943 0 : }
39944 :
39945 :
39946 : /*************************************************************************
39947 : Serializer: serialization
39948 :
39949 : -- ALGLIB --
39950 : Copyright 02.02.2012 by Bochkanov Sergey
39951 : *************************************************************************/
39952 0 : void rbfv2serialize(ae_serializer* s, rbfv2model* model, ae_state *_state)
39953 : {
39954 :
39955 :
39956 :
39957 : /*
39958 : * Data
39959 : */
39960 0 : ae_serializer_serialize_int(s, model->nx, _state);
39961 0 : ae_serializer_serialize_int(s, model->ny, _state);
39962 0 : ae_serializer_serialize_int(s, model->nh, _state);
39963 0 : ae_serializer_serialize_int(s, model->bf, _state);
39964 0 : serializerealarray(s, &model->ri, -1, _state);
39965 0 : serializerealarray(s, &model->s, -1, _state);
39966 0 : serializeintegerarray(s, &model->kdroots, -1, _state);
39967 0 : serializeintegerarray(s, &model->kdnodes, -1, _state);
39968 0 : serializerealarray(s, &model->kdsplits, -1, _state);
39969 0 : serializerealarray(s, &model->kdboxmin, -1, _state);
39970 0 : serializerealarray(s, &model->kdboxmax, -1, _state);
39971 0 : serializerealarray(s, &model->cw, -1, _state);
39972 0 : serializerealmatrix(s, &model->v, -1, -1, _state);
39973 0 : }
39974 :
39975 :
39976 : /*************************************************************************
39977 : Serializer: unserialization
39978 :
39979 : -- ALGLIB --
39980 : Copyright 02.02.2012 by Bochkanov Sergey
39981 : *************************************************************************/
39982 0 : void rbfv2unserialize(ae_serializer* s,
39983 : rbfv2model* model,
39984 : ae_state *_state)
39985 : {
39986 : ae_int_t nx;
39987 : ae_int_t ny;
39988 :
39989 0 : _rbfv2model_clear(model);
39990 :
39991 :
39992 : /*
39993 : * Unserialize primary model parameters, initialize model.
39994 : *
39995 : * It is necessary to call RBFCreate() because some internal fields
39996 : * which are NOT unserialized will need initialization.
39997 : */
39998 0 : ae_serializer_unserialize_int(s, &nx, _state);
39999 0 : ae_serializer_unserialize_int(s, &ny, _state);
40000 0 : rbfv2create(nx, ny, model, _state);
40001 0 : ae_serializer_unserialize_int(s, &model->nh, _state);
40002 0 : ae_serializer_unserialize_int(s, &model->bf, _state);
40003 0 : unserializerealarray(s, &model->ri, _state);
40004 0 : unserializerealarray(s, &model->s, _state);
40005 0 : unserializeintegerarray(s, &model->kdroots, _state);
40006 0 : unserializeintegerarray(s, &model->kdnodes, _state);
40007 0 : unserializerealarray(s, &model->kdsplits, _state);
40008 0 : unserializerealarray(s, &model->kdboxmin, _state);
40009 0 : unserializerealarray(s, &model->kdboxmax, _state);
40010 0 : unserializerealarray(s, &model->cw, _state);
40011 0 : unserializerealmatrix(s, &model->v, _state);
40012 0 : }
40013 :
40014 :
40015 : /*************************************************************************
40016 : Returns far radius for basis function type
40017 : *************************************************************************/
40018 0 : double rbfv2farradius(ae_int_t bf, ae_state *_state)
40019 : {
40020 : double result;
40021 :
40022 :
40023 0 : result = (double)(1);
40024 0 : if( bf==0 )
40025 : {
40026 0 : result = 5.0;
40027 : }
40028 0 : if( bf==1 )
40029 : {
40030 0 : result = (double)(3);
40031 : }
40032 0 : return result;
40033 : }
40034 :
40035 :
40036 : /*************************************************************************
40037 : Returns near radius for basis function type
40038 : *************************************************************************/
40039 0 : double rbfv2nearradius(ae_int_t bf, ae_state *_state)
40040 : {
40041 : double result;
40042 :
40043 :
40044 0 : result = (double)(1);
40045 0 : if( bf==0 )
40046 : {
40047 0 : result = 3.0;
40048 : }
40049 0 : if( bf==1 )
40050 : {
40051 0 : result = (double)(3);
40052 : }
40053 0 : return result;
40054 : }
40055 :
40056 :
40057 : /*************************************************************************
40058 : Returns basis function value.
40059 : Assumes that D2>=0
40060 : *************************************************************************/
40061 0 : double rbfv2basisfunc(ae_int_t bf, double d2, ae_state *_state)
40062 : {
40063 : double v;
40064 : double result;
40065 :
40066 :
40067 0 : result = (double)(0);
40068 0 : if( bf==0 )
40069 : {
40070 0 : result = ae_exp(-d2, _state);
40071 0 : return result;
40072 : }
40073 0 : if( bf==1 )
40074 : {
40075 :
40076 : /*
40077 : * if D2<3:
40078 : * Exp(1)*Exp(-D2)*Exp(-1/(1-D2/9))
40079 : * else:
40080 : * 0
40081 : */
40082 0 : v = 1-d2/9;
40083 0 : if( ae_fp_less_eq(v,(double)(0)) )
40084 : {
40085 0 : result = (double)(0);
40086 0 : return result;
40087 : }
40088 0 : result = 2.718281828459045*ae_exp(-d2, _state)*ae_exp(-1/v, _state);
40089 0 : return result;
40090 : }
40091 0 : ae_assert(ae_false, "RBFV2BasisFunc: unknown BF type", _state);
40092 0 : return result;
40093 : }
40094 :
40095 :
40096 : /*************************************************************************
40097 : Returns basis function value, first and second derivatives
40098 : Assumes that D2>=0
40099 : *************************************************************************/
40100 0 : void rbfv2basisfuncdiff2(ae_int_t bf,
40101 : double d2,
40102 : double* f,
40103 : double* df,
40104 : double* d2f,
40105 : ae_state *_state)
40106 : {
40107 : double v;
40108 :
40109 0 : *f = 0;
40110 0 : *df = 0;
40111 0 : *d2f = 0;
40112 :
40113 0 : if( bf==0 )
40114 : {
40115 0 : *f = ae_exp(-d2, _state);
40116 0 : *df = -*f;
40117 0 : *d2f = *f;
40118 0 : return;
40119 : }
40120 0 : if( bf==1 )
40121 : {
40122 :
40123 : /*
40124 : * if D2<3:
40125 : * F = Exp(1)*Exp(-D2)*Exp(-1/(1-D2/9))
40126 : * dF = -F * [pow(D2/9-1,-2)/9 + 1]
40127 : * d2F = -dF * [pow(D2/9-1,-2)/9 + 1] + F*(2/81)*pow(D2/9-1,-3)
40128 : * else:
40129 : * 0
40130 : */
40131 0 : v = 1-d2/9;
40132 0 : if( ae_fp_less_eq(v,(double)(0)) )
40133 : {
40134 0 : *f = (double)(0);
40135 0 : *df = (double)(0);
40136 0 : *d2f = (double)(0);
40137 0 : return;
40138 : }
40139 0 : *f = ae_exp((double)(1), _state)*ae_exp(-d2, _state)*ae_exp(-1/v, _state);
40140 0 : *df = -*f*(1/(9*v*v)+1);
40141 0 : *d2f = -*df*(1/(9*v*v)+1)+*f*((double)2/(double)81)/(v*v*v);
40142 0 : return;
40143 : }
40144 0 : ae_assert(ae_false, "RBFV2BasisFuncDiff2: unknown BF type", _state);
40145 : }
40146 :
40147 :
40148 : /*************************************************************************
40149 : This function calculates values of the RBF model in the given point.
40150 :
40151 : This function should be used when we have NY=1 (scalar function) and NX=1
40152 : (1-dimensional space).
40153 :
40154 : This function returns 0.0 when:
40155 : * model is not initialized
40156 : * NX<>1
40157 : *NY<>1
40158 :
40159 : INPUT PARAMETERS:
40160 : S - RBF model
40161 : X0 - X-coordinate, finite number
40162 :
40163 : RESULT:
40164 : value of the model or 0.0 (as defined above)
40165 :
40166 : -- ALGLIB --
40167 : Copyright 13.12.2011 by Bochkanov Sergey
40168 : *************************************************************************/
40169 0 : double rbfv2calc1(rbfv2model* s, double x0, ae_state *_state)
40170 : {
40171 : double result;
40172 :
40173 :
40174 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc1: invalid value for X0 (X0 is Inf)!", _state);
40175 0 : if( s->ny!=1||s->nx!=1 )
40176 : {
40177 0 : result = (double)(0);
40178 0 : return result;
40179 : }
40180 0 : result = s->v.ptr.pp_double[0][0]*x0-s->v.ptr.pp_double[0][1];
40181 0 : if( s->nh==0 )
40182 : {
40183 0 : return result;
40184 : }
40185 0 : rbfv2_allocatecalcbuffer(s, &s->calcbuf, _state);
40186 0 : s->calcbuf.x123.ptr.p_double[0] = x0;
40187 0 : rbfv2tscalcbuf(s, &s->calcbuf, &s->calcbuf.x123, &s->calcbuf.y123, _state);
40188 0 : result = s->calcbuf.y123.ptr.p_double[0];
40189 0 : return result;
40190 : }
40191 :
40192 :
40193 : /*************************************************************************
40194 : This function calculates values of the RBF model in the given point.
40195 :
40196 : This function should be used when we have NY=1 (scalar function) and NX=2
40197 : (2-dimensional space). If you have 3-dimensional space, use RBFCalc3(). If
40198 : you have general situation (NX-dimensional space, NY-dimensional function)
40199 : you should use general, less efficient implementation RBFCalc().
40200 :
40201 : If you want to calculate function values many times, consider using
40202 : RBFGridCalc2(), which is far more efficient than many subsequent calls to
40203 : RBFCalc2().
40204 :
40205 : This function returns 0.0 when:
40206 : * model is not initialized
40207 : * NX<>2
40208 : *NY<>1
40209 :
40210 : INPUT PARAMETERS:
40211 : S - RBF model
40212 : X0 - first coordinate, finite number
40213 : X1 - second coordinate, finite number
40214 :
40215 : RESULT:
40216 : value of the model or 0.0 (as defined above)
40217 :
40218 : -- ALGLIB --
40219 : Copyright 13.12.2011 by Bochkanov Sergey
40220 : *************************************************************************/
40221 0 : double rbfv2calc2(rbfv2model* s, double x0, double x1, ae_state *_state)
40222 : {
40223 : double result;
40224 :
40225 :
40226 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc2: invalid value for X0 (X0 is Inf)!", _state);
40227 0 : ae_assert(ae_isfinite(x1, _state), "RBFCalc2: invalid value for X1 (X1 is Inf)!", _state);
40228 0 : if( s->ny!=1||s->nx!=2 )
40229 : {
40230 0 : result = (double)(0);
40231 0 : return result;
40232 : }
40233 0 : result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][2];
40234 0 : if( s->nh==0 )
40235 : {
40236 0 : return result;
40237 : }
40238 0 : rbfv2_allocatecalcbuffer(s, &s->calcbuf, _state);
40239 0 : s->calcbuf.x123.ptr.p_double[0] = x0;
40240 0 : s->calcbuf.x123.ptr.p_double[1] = x1;
40241 0 : rbfv2tscalcbuf(s, &s->calcbuf, &s->calcbuf.x123, &s->calcbuf.y123, _state);
40242 0 : result = s->calcbuf.y123.ptr.p_double[0];
40243 0 : return result;
40244 : }
40245 :
40246 :
40247 : /*************************************************************************
40248 : This function calculates values of the RBF model in the given point.
40249 :
40250 : This function should be used when we have NY=1 (scalar function) and NX=3
40251 : (3-dimensional space). If you have 2-dimensional space, use RBFCalc2(). If
40252 : you have general situation (NX-dimensional space, NY-dimensional function)
40253 : you should use general, less efficient implementation RBFCalc().
40254 :
40255 : This function returns 0.0 when:
40256 : * model is not initialized
40257 : * NX<>3
40258 : *NY<>1
40259 :
40260 : INPUT PARAMETERS:
40261 : S - RBF model
40262 : X0 - first coordinate, finite number
40263 : X1 - second coordinate, finite number
40264 : X2 - third coordinate, finite number
40265 :
40266 : RESULT:
40267 : value of the model or 0.0 (as defined above)
40268 :
40269 : -- ALGLIB --
40270 : Copyright 13.12.2011 by Bochkanov Sergey
40271 : *************************************************************************/
40272 0 : double rbfv2calc3(rbfv2model* s,
40273 : double x0,
40274 : double x1,
40275 : double x2,
40276 : ae_state *_state)
40277 : {
40278 : double result;
40279 :
40280 :
40281 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc3: invalid value for X0 (X0 is Inf or NaN)!", _state);
40282 0 : ae_assert(ae_isfinite(x1, _state), "RBFCalc3: invalid value for X1 (X1 is Inf or NaN)!", _state);
40283 0 : ae_assert(ae_isfinite(x2, _state), "RBFCalc3: invalid value for X2 (X2 is Inf or NaN)!", _state);
40284 0 : if( s->ny!=1||s->nx!=3 )
40285 : {
40286 0 : result = (double)(0);
40287 0 : return result;
40288 : }
40289 0 : result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][2]*x2+s->v.ptr.pp_double[0][3];
40290 0 : if( s->nh==0 )
40291 : {
40292 0 : return result;
40293 : }
40294 0 : rbfv2_allocatecalcbuffer(s, &s->calcbuf, _state);
40295 0 : s->calcbuf.x123.ptr.p_double[0] = x0;
40296 0 : s->calcbuf.x123.ptr.p_double[1] = x1;
40297 0 : s->calcbuf.x123.ptr.p_double[2] = x2;
40298 0 : rbfv2tscalcbuf(s, &s->calcbuf, &s->calcbuf.x123, &s->calcbuf.y123, _state);
40299 0 : result = s->calcbuf.y123.ptr.p_double[0];
40300 0 : return result;
40301 : }
40302 :
40303 :
40304 : /*************************************************************************
40305 : This function calculates values of the RBF model at the given point.
40306 :
40307 : Same as RBFCalc(), but does not reallocate Y when in is large enough to
40308 : store function values.
40309 :
40310 : INPUT PARAMETERS:
40311 : S - RBF model
40312 : X - coordinates, array[NX].
40313 : X may have more than NX elements, in this case only
40314 : leading NX will be used.
40315 : Y - possibly preallocated array
40316 :
40317 : OUTPUT PARAMETERS:
40318 : Y - function value, array[NY]. Y is not reallocated when it
40319 : is larger than NY.
40320 :
40321 : -- ALGLIB --
40322 : Copyright 13.12.2011 by Bochkanov Sergey
40323 : *************************************************************************/
40324 0 : void rbfv2calcbuf(rbfv2model* s,
40325 : /* Real */ ae_vector* x,
40326 : /* Real */ ae_vector* y,
40327 : ae_state *_state)
40328 : {
40329 :
40330 :
40331 0 : rbfv2tscalcbuf(s, &s->calcbuf, x, y, _state);
40332 0 : }
40333 :
40334 :
40335 : /*************************************************************************
40336 : This function calculates values of the RBF model at the given point, using
40337 : external buffer object (internal temporaries of RBF model are not
40338 : modified).
40339 :
40340 : This function allows to use same RBF model object in different threads,
40341 : assuming that different threads use different instances of buffer
40342 : structure.
40343 :
40344 : INPUT PARAMETERS:
40345 : S - RBF model, may be shared between different threads
40346 : Buf - buffer object created for this particular instance of RBF
40347 : model with rbfcreatecalcbuffer().
40348 : X - coordinates, array[NX].
40349 : X may have more than NX elements, in this case only
40350 : leading NX will be used.
40351 : Y - possibly preallocated array
40352 :
40353 : OUTPUT PARAMETERS:
40354 : Y - function value, array[NY]. Y is not reallocated when it
40355 : is larger than NY.
40356 :
40357 : -- ALGLIB --
40358 : Copyright 13.12.2011 by Bochkanov Sergey
40359 : *************************************************************************/
40360 0 : void rbfv2tscalcbuf(rbfv2model* s,
40361 : rbfv2calcbuffer* buf,
40362 : /* Real */ ae_vector* x,
40363 : /* Real */ ae_vector* y,
40364 : ae_state *_state)
40365 : {
40366 : ae_int_t i;
40367 : ae_int_t j;
40368 : ae_int_t levelidx;
40369 : double rcur;
40370 : double rquery2;
40371 : double invrc2;
40372 : ae_int_t nx;
40373 : ae_int_t ny;
40374 :
40375 :
40376 0 : ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)<NX", _state);
40377 0 : ae_assert(isfinitevector(x, s->nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state);
40378 0 : nx = s->nx;
40379 0 : ny = s->ny;
40380 :
40381 : /*
40382 : * Handle linear term
40383 : */
40384 0 : if( y->cnt<ny )
40385 : {
40386 0 : ae_vector_set_length(y, ny, _state);
40387 : }
40388 0 : for(i=0; i<=ny-1; i++)
40389 : {
40390 0 : y->ptr.p_double[i] = s->v.ptr.pp_double[i][nx];
40391 0 : for(j=0; j<=nx-1; j++)
40392 : {
40393 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+s->v.ptr.pp_double[i][j]*x->ptr.p_double[j];
40394 : }
40395 : }
40396 0 : if( s->nh==0 )
40397 : {
40398 0 : return;
40399 : }
40400 :
40401 : /*
40402 : * Handle nonlinear term
40403 : */
40404 0 : rbfv2_allocatecalcbuffer(s, buf, _state);
40405 0 : for(j=0; j<=nx-1; j++)
40406 : {
40407 0 : buf->x.ptr.p_double[j] = x->ptr.p_double[j]/s->s.ptr.p_double[j];
40408 : }
40409 0 : for(levelidx=0; levelidx<=s->nh-1; levelidx++)
40410 : {
40411 :
40412 : /*
40413 : * Prepare fields of Buf required by PartialCalcRec()
40414 : */
40415 0 : buf->curdist2 = (double)(0);
40416 0 : for(j=0; j<=nx-1; j++)
40417 : {
40418 0 : buf->curboxmin.ptr.p_double[j] = s->kdboxmin.ptr.p_double[j];
40419 0 : buf->curboxmax.ptr.p_double[j] = s->kdboxmax.ptr.p_double[j];
40420 0 : if( ae_fp_less(buf->x.ptr.p_double[j],buf->curboxmin.ptr.p_double[j]) )
40421 : {
40422 0 : buf->curdist2 = buf->curdist2+ae_sqr(buf->curboxmin.ptr.p_double[j]-buf->x.ptr.p_double[j], _state);
40423 : }
40424 : else
40425 : {
40426 0 : if( ae_fp_greater(buf->x.ptr.p_double[j],buf->curboxmax.ptr.p_double[j]) )
40427 : {
40428 0 : buf->curdist2 = buf->curdist2+ae_sqr(buf->x.ptr.p_double[j]-buf->curboxmax.ptr.p_double[j], _state);
40429 : }
40430 : }
40431 : }
40432 :
40433 : /*
40434 : * Call PartialCalcRec()
40435 : */
40436 0 : rcur = s->ri.ptr.p_double[levelidx];
40437 0 : invrc2 = 1/(rcur*rcur);
40438 0 : rquery2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state);
40439 0 : rbfv2_partialcalcrec(s, buf, s->kdroots.ptr.p_int[levelidx], invrc2, rquery2, &buf->x, y, _state);
40440 : }
40441 : }
40442 :
40443 :
40444 : /*************************************************************************
40445 : This function calculates values of the RBF model at the regular grid.
40446 :
40447 : Grid have N0*N1 points, with Point[I,J] = (X0[I], X1[J])
40448 :
40449 : This function returns 0.0 when:
40450 : * model is not initialized
40451 : * NX<>2
40452 : *NY<>1
40453 :
40454 : INPUT PARAMETERS:
40455 : S - RBF model
40456 : X0 - array of grid nodes, first coordinates, array[N0]
40457 : N0 - grid size (number of nodes) in the first dimension
40458 : X1 - array of grid nodes, second coordinates, array[N1]
40459 : N1 - grid size (number of nodes) in the second dimension
40460 :
40461 : OUTPUT PARAMETERS:
40462 : Y - function values, array[N0,N1]. Y is out-variable and
40463 : is reallocated by this function.
40464 :
40465 : NOTE: as a special exception, this function supports unordered arrays X0
40466 : and X1. However, future versions may be more efficient for X0/X1
40467 : ordered by ascending.
40468 :
40469 : -- ALGLIB --
40470 : Copyright 13.12.2011 by Bochkanov Sergey
40471 : *************************************************************************/
40472 0 : void rbfv2gridcalc2(rbfv2model* s,
40473 : /* Real */ ae_vector* x0,
40474 : ae_int_t n0,
40475 : /* Real */ ae_vector* x1,
40476 : ae_int_t n1,
40477 : /* Real */ ae_matrix* y,
40478 : ae_state *_state)
40479 : {
40480 : ae_frame _frame_block;
40481 : ae_vector cpx0;
40482 : ae_vector cpx1;
40483 : ae_vector dummyx2;
40484 : ae_vector dummyx3;
40485 : ae_vector dummyflag;
40486 : ae_vector p01;
40487 : ae_vector p11;
40488 : ae_vector p2;
40489 : ae_vector vy;
40490 : ae_int_t i;
40491 : ae_int_t j;
40492 :
40493 0 : ae_frame_make(_state, &_frame_block);
40494 0 : memset(&cpx0, 0, sizeof(cpx0));
40495 0 : memset(&cpx1, 0, sizeof(cpx1));
40496 0 : memset(&dummyx2, 0, sizeof(dummyx2));
40497 0 : memset(&dummyx3, 0, sizeof(dummyx3));
40498 0 : memset(&dummyflag, 0, sizeof(dummyflag));
40499 0 : memset(&p01, 0, sizeof(p01));
40500 0 : memset(&p11, 0, sizeof(p11));
40501 0 : memset(&p2, 0, sizeof(p2));
40502 0 : memset(&vy, 0, sizeof(vy));
40503 0 : ae_matrix_clear(y);
40504 0 : ae_vector_init(&cpx0, 0, DT_REAL, _state, ae_true);
40505 0 : ae_vector_init(&cpx1, 0, DT_REAL, _state, ae_true);
40506 0 : ae_vector_init(&dummyx2, 0, DT_REAL, _state, ae_true);
40507 0 : ae_vector_init(&dummyx3, 0, DT_REAL, _state, ae_true);
40508 0 : ae_vector_init(&dummyflag, 0, DT_BOOL, _state, ae_true);
40509 0 : ae_vector_init(&p01, 0, DT_INT, _state, ae_true);
40510 0 : ae_vector_init(&p11, 0, DT_INT, _state, ae_true);
40511 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
40512 0 : ae_vector_init(&vy, 0, DT_REAL, _state, ae_true);
40513 :
40514 0 : ae_assert(n0>0, "RBFGridCalc2: invalid value for N0 (N0<=0)!", _state);
40515 0 : ae_assert(n1>0, "RBFGridCalc2: invalid value for N1 (N1<=0)!", _state);
40516 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc2: Length(X0)<N0", _state);
40517 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc2: Length(X1)<N1", _state);
40518 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc2: X0 contains infinite or NaN values!", _state);
40519 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc2: X1 contains infinite or NaN values!", _state);
40520 0 : ae_matrix_set_length(y, n0, n1, _state);
40521 0 : for(i=0; i<=n0-1; i++)
40522 : {
40523 0 : for(j=0; j<=n1-1; j++)
40524 : {
40525 0 : y->ptr.pp_double[i][j] = (double)(0);
40526 : }
40527 : }
40528 0 : if( s->ny!=1||s->nx!=2 )
40529 : {
40530 0 : ae_frame_leave(_state);
40531 0 : return;
40532 : }
40533 :
40534 : /*
40535 : *create and sort arrays
40536 : */
40537 0 : ae_vector_set_length(&cpx0, n0, _state);
40538 0 : for(i=0; i<=n0-1; i++)
40539 : {
40540 0 : cpx0.ptr.p_double[i] = x0->ptr.p_double[i];
40541 : }
40542 0 : tagsort(&cpx0, n0, &p01, &p2, _state);
40543 0 : ae_vector_set_length(&cpx1, n1, _state);
40544 0 : for(i=0; i<=n1-1; i++)
40545 : {
40546 0 : cpx1.ptr.p_double[i] = x1->ptr.p_double[i];
40547 : }
40548 0 : tagsort(&cpx1, n1, &p11, &p2, _state);
40549 0 : ae_vector_set_length(&dummyx2, 1, _state);
40550 0 : dummyx2.ptr.p_double[0] = (double)(0);
40551 0 : ae_vector_set_length(&dummyx3, 1, _state);
40552 0 : dummyx3.ptr.p_double[0] = (double)(0);
40553 0 : ae_vector_set_length(&vy, n0*n1, _state);
40554 0 : rbfv2gridcalcvx(s, &cpx0, n0, &cpx1, n1, &dummyx2, 1, &dummyx3, 1, &dummyflag, ae_false, &vy, _state);
40555 0 : for(i=0; i<=n0-1; i++)
40556 : {
40557 0 : for(j=0; j<=n1-1; j++)
40558 : {
40559 0 : y->ptr.pp_double[i][j] = vy.ptr.p_double[i+j*n0];
40560 : }
40561 : }
40562 0 : ae_frame_leave(_state);
40563 : }
40564 :
40565 :
40566 : /*************************************************************************
40567 : This function is used to perform gridded calculation for 2D, 3D or 4D
40568 : problems. It accepts parameters X0...X3 and counters N0...N3. If RBF model
40569 : has dimensionality less than 4, corresponding arrays should contain just
40570 : one element equal to zero, and corresponding N's should be equal to 1.
40571 :
40572 : NOTE: array Y should be preallocated by caller.
40573 :
40574 : -- ALGLIB --
40575 : Copyright 12.07.2016 by Bochkanov Sergey
40576 : *************************************************************************/
40577 0 : void rbfv2gridcalcvx(rbfv2model* s,
40578 : /* Real */ ae_vector* x0,
40579 : ae_int_t n0,
40580 : /* Real */ ae_vector* x1,
40581 : ae_int_t n1,
40582 : /* Real */ ae_vector* x2,
40583 : ae_int_t n2,
40584 : /* Real */ ae_vector* x3,
40585 : ae_int_t n3,
40586 : /* Boolean */ ae_vector* flagy,
40587 : ae_bool sparsey,
40588 : /* Real */ ae_vector* y,
40589 : ae_state *_state)
40590 : {
40591 : ae_frame _frame_block;
40592 : ae_int_t nx;
40593 : ae_int_t ny;
40594 : ae_int_t i;
40595 : ae_int_t j;
40596 : ae_int_t k;
40597 : ae_vector tx;
40598 : ae_vector ty;
40599 : ae_vector z;
40600 : ae_int_t dstoffs;
40601 : ae_int_t dummy;
40602 : rbfv2gridcalcbuffer bufseedv2;
40603 : ae_shared_pool bufpool;
40604 : ae_int_t rowidx;
40605 : ae_int_t rowcnt;
40606 : double v;
40607 : double rcur;
40608 : ae_int_t levelidx;
40609 : double searchradius2;
40610 : ae_int_t ntrials;
40611 : double avgfuncpernode;
40612 : hqrndstate rs;
40613 : ae_vector blocks0;
40614 : ae_vector blocks1;
40615 : ae_vector blocks2;
40616 : ae_vector blocks3;
40617 : ae_int_t blockscnt0;
40618 : ae_int_t blockscnt1;
40619 : ae_int_t blockscnt2;
40620 : ae_int_t blockscnt3;
40621 : double blockwidth0;
40622 : double blockwidth1;
40623 : double blockwidth2;
40624 : double blockwidth3;
40625 : ae_int_t maxblocksize;
40626 :
40627 0 : ae_frame_make(_state, &_frame_block);
40628 0 : memset(&tx, 0, sizeof(tx));
40629 0 : memset(&ty, 0, sizeof(ty));
40630 0 : memset(&z, 0, sizeof(z));
40631 0 : memset(&bufseedv2, 0, sizeof(bufseedv2));
40632 0 : memset(&bufpool, 0, sizeof(bufpool));
40633 0 : memset(&rs, 0, sizeof(rs));
40634 0 : memset(&blocks0, 0, sizeof(blocks0));
40635 0 : memset(&blocks1, 0, sizeof(blocks1));
40636 0 : memset(&blocks2, 0, sizeof(blocks2));
40637 0 : memset(&blocks3, 0, sizeof(blocks3));
40638 0 : ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
40639 0 : ae_vector_init(&ty, 0, DT_REAL, _state, ae_true);
40640 0 : ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
40641 0 : _rbfv2gridcalcbuffer_init(&bufseedv2, _state, ae_true);
40642 0 : ae_shared_pool_init(&bufpool, _state, ae_true);
40643 0 : _hqrndstate_init(&rs, _state, ae_true);
40644 0 : ae_vector_init(&blocks0, 0, DT_INT, _state, ae_true);
40645 0 : ae_vector_init(&blocks1, 0, DT_INT, _state, ae_true);
40646 0 : ae_vector_init(&blocks2, 0, DT_INT, _state, ae_true);
40647 0 : ae_vector_init(&blocks3, 0, DT_INT, _state, ae_true);
40648 :
40649 0 : nx = s->nx;
40650 0 : ny = s->ny;
40651 0 : hqrndseed(532, 54734, &rs, _state);
40652 :
40653 : /*
40654 : * Perform integrity checks
40655 : */
40656 0 : ae_assert(s->nx==2||s->nx==3, "RBFGridCalcVX: integrity check failed", _state);
40657 0 : ae_assert(s->nx>=4||((x3->cnt>=1&&ae_fp_eq(x3->ptr.p_double[0],(double)(0)))&&n3==1), "RBFGridCalcVX: integrity check failed", _state);
40658 0 : ae_assert(s->nx>=3||((x2->cnt>=1&&ae_fp_eq(x2->ptr.p_double[0],(double)(0)))&&n2==1), "RBFGridCalcVX: integrity check failed", _state);
40659 0 : ae_assert(s->nx>=2||((x1->cnt>=1&&ae_fp_eq(x1->ptr.p_double[0],(double)(0)))&&n1==1), "RBFGridCalcVX: integrity check failed", _state);
40660 :
40661 : /*
40662 : * Allocate arrays
40663 : */
40664 0 : ae_assert(s->nx<=4, "RBFGridCalcVX: integrity check failed", _state);
40665 0 : ae_vector_set_length(&z, ny, _state);
40666 0 : ae_vector_set_length(&tx, 4, _state);
40667 0 : ae_vector_set_length(&ty, ny, _state);
40668 :
40669 : /*
40670 : * Calculate linear term
40671 : */
40672 0 : rowcnt = n1*n2*n3;
40673 0 : for(rowidx=0; rowidx<=rowcnt-1; rowidx++)
40674 : {
40675 :
40676 : /*
40677 : * Calculate TX - current position
40678 : */
40679 0 : k = rowidx;
40680 0 : tx.ptr.p_double[0] = (double)(0);
40681 0 : tx.ptr.p_double[1] = x1->ptr.p_double[k%n1];
40682 0 : k = k/n1;
40683 0 : tx.ptr.p_double[2] = x2->ptr.p_double[k%n2];
40684 0 : k = k/n2;
40685 0 : tx.ptr.p_double[3] = x3->ptr.p_double[k%n3];
40686 0 : k = k/n3;
40687 0 : ae_assert(k==0, "RBFGridCalcVX: integrity check failed", _state);
40688 0 : for(j=0; j<=ny-1; j++)
40689 : {
40690 0 : v = s->v.ptr.pp_double[j][nx];
40691 0 : for(k=1; k<=nx-1; k++)
40692 : {
40693 0 : v = v+tx.ptr.p_double[k]*s->v.ptr.pp_double[j][k];
40694 : }
40695 0 : z.ptr.p_double[j] = v;
40696 : }
40697 0 : for(i=0; i<=n0-1; i++)
40698 : {
40699 0 : dstoffs = ny*(rowidx*n0+i);
40700 0 : if( sparsey&&!flagy->ptr.p_bool[rowidx*n0+i] )
40701 : {
40702 0 : for(j=0; j<=ny-1; j++)
40703 : {
40704 0 : y->ptr.p_double[j+dstoffs] = (double)(0);
40705 : }
40706 0 : continue;
40707 : }
40708 0 : v = x0->ptr.p_double[i];
40709 0 : for(j=0; j<=ny-1; j++)
40710 : {
40711 0 : y->ptr.p_double[j+dstoffs] = z.ptr.p_double[j]+v*s->v.ptr.pp_double[j][0];
40712 : }
40713 : }
40714 : }
40715 0 : if( s->nh==0 )
40716 : {
40717 0 : ae_frame_leave(_state);
40718 0 : return;
40719 : }
40720 :
40721 : /*
40722 : * Process RBF terms, layer by layer
40723 : */
40724 0 : for(levelidx=0; levelidx<=s->nh-1; levelidx++)
40725 : {
40726 0 : rcur = s->ri.ptr.p_double[levelidx];
40727 0 : blockwidth0 = (double)(1);
40728 0 : blockwidth1 = (double)(1);
40729 0 : blockwidth2 = (double)(1);
40730 0 : blockwidth3 = (double)(1);
40731 0 : if( nx>=1 )
40732 : {
40733 0 : blockwidth0 = rcur*s->s.ptr.p_double[0];
40734 : }
40735 0 : if( nx>=2 )
40736 : {
40737 0 : blockwidth1 = rcur*s->s.ptr.p_double[1];
40738 : }
40739 0 : if( nx>=3 )
40740 : {
40741 0 : blockwidth2 = rcur*s->s.ptr.p_double[2];
40742 : }
40743 0 : if( nx>=4 )
40744 : {
40745 0 : blockwidth3 = rcur*s->s.ptr.p_double[3];
40746 : }
40747 0 : maxblocksize = 8;
40748 :
40749 : /*
40750 : * Group grid nodes into blocks according to current radius
40751 : */
40752 0 : ae_vector_set_length(&blocks0, n0+1, _state);
40753 0 : blockscnt0 = 0;
40754 0 : blocks0.ptr.p_int[0] = 0;
40755 0 : for(i=1; i<=n0-1; i++)
40756 : {
40757 0 : if( ae_fp_greater(x0->ptr.p_double[i]-x0->ptr.p_double[blocks0.ptr.p_int[blockscnt0]],blockwidth0)||i-blocks0.ptr.p_int[blockscnt0]>=maxblocksize )
40758 : {
40759 0 : inc(&blockscnt0, _state);
40760 0 : blocks0.ptr.p_int[blockscnt0] = i;
40761 : }
40762 : }
40763 0 : inc(&blockscnt0, _state);
40764 0 : blocks0.ptr.p_int[blockscnt0] = n0;
40765 0 : ae_vector_set_length(&blocks1, n1+1, _state);
40766 0 : blockscnt1 = 0;
40767 0 : blocks1.ptr.p_int[0] = 0;
40768 0 : for(i=1; i<=n1-1; i++)
40769 : {
40770 0 : if( ae_fp_greater(x1->ptr.p_double[i]-x1->ptr.p_double[blocks1.ptr.p_int[blockscnt1]],blockwidth1)||i-blocks1.ptr.p_int[blockscnt1]>=maxblocksize )
40771 : {
40772 0 : inc(&blockscnt1, _state);
40773 0 : blocks1.ptr.p_int[blockscnt1] = i;
40774 : }
40775 : }
40776 0 : inc(&blockscnt1, _state);
40777 0 : blocks1.ptr.p_int[blockscnt1] = n1;
40778 0 : ae_vector_set_length(&blocks2, n2+1, _state);
40779 0 : blockscnt2 = 0;
40780 0 : blocks2.ptr.p_int[0] = 0;
40781 0 : for(i=1; i<=n2-1; i++)
40782 : {
40783 0 : if( ae_fp_greater(x2->ptr.p_double[i]-x2->ptr.p_double[blocks2.ptr.p_int[blockscnt2]],blockwidth2)||i-blocks2.ptr.p_int[blockscnt2]>=maxblocksize )
40784 : {
40785 0 : inc(&blockscnt2, _state);
40786 0 : blocks2.ptr.p_int[blockscnt2] = i;
40787 : }
40788 : }
40789 0 : inc(&blockscnt2, _state);
40790 0 : blocks2.ptr.p_int[blockscnt2] = n2;
40791 0 : ae_vector_set_length(&blocks3, n3+1, _state);
40792 0 : blockscnt3 = 0;
40793 0 : blocks3.ptr.p_int[0] = 0;
40794 0 : for(i=1; i<=n3-1; i++)
40795 : {
40796 0 : if( ae_fp_greater(x3->ptr.p_double[i]-x3->ptr.p_double[blocks3.ptr.p_int[blockscnt3]],blockwidth3)||i-blocks3.ptr.p_int[blockscnt3]>=maxblocksize )
40797 : {
40798 0 : inc(&blockscnt3, _state);
40799 0 : blocks3.ptr.p_int[blockscnt3] = i;
40800 : }
40801 : }
40802 0 : inc(&blockscnt3, _state);
40803 0 : blocks3.ptr.p_int[blockscnt3] = n3;
40804 :
40805 : /*
40806 : * Prepare seed for shared pool
40807 : */
40808 0 : rbfv2_allocatecalcbuffer(s, &bufseedv2.calcbuf, _state);
40809 0 : ae_shared_pool_set_seed(&bufpool, &bufseedv2, sizeof(bufseedv2), _rbfv2gridcalcbuffer_init, _rbfv2gridcalcbuffer_init_copy, _rbfv2gridcalcbuffer_destroy, _state);
40810 :
40811 : /*
40812 : * Determine average number of neighbor per node
40813 : */
40814 0 : searchradius2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state);
40815 0 : ntrials = 100;
40816 0 : avgfuncpernode = 0.0;
40817 0 : for(i=0; i<=ntrials-1; i++)
40818 : {
40819 0 : tx.ptr.p_double[0] = x0->ptr.p_double[hqrnduniformi(&rs, n0, _state)];
40820 0 : tx.ptr.p_double[1] = x1->ptr.p_double[hqrnduniformi(&rs, n1, _state)];
40821 0 : tx.ptr.p_double[2] = x2->ptr.p_double[hqrnduniformi(&rs, n2, _state)];
40822 0 : tx.ptr.p_double[3] = x3->ptr.p_double[hqrnduniformi(&rs, n3, _state)];
40823 0 : rbfv2_preparepartialquery(&tx, &s->kdboxmin, &s->kdboxmax, nx, &bufseedv2.calcbuf, &dummy, _state);
40824 0 : avgfuncpernode = avgfuncpernode+(double)rbfv2_partialcountrec(&s->kdnodes, &s->kdsplits, &s->cw, nx, ny, &bufseedv2.calcbuf, s->kdroots.ptr.p_int[levelidx], searchradius2, &tx, _state)/(double)ntrials;
40825 : }
40826 :
40827 : /*
40828 : * Perform calculation in multithreaded mode
40829 : */
40830 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, &blocks0, 0, blockscnt0, &blocks1, 0, blockscnt1, &blocks2, 0, blockscnt2, &blocks3, 0, blockscnt3, flagy, sparsey, levelidx, avgfuncpernode, &bufpool, y, _state);
40831 : }
40832 0 : ae_frame_leave(_state);
40833 : }
40834 :
40835 :
40836 0 : void rbfv2partialgridcalcrec(rbfv2model* s,
40837 : /* Real */ ae_vector* x0,
40838 : ae_int_t n0,
40839 : /* Real */ ae_vector* x1,
40840 : ae_int_t n1,
40841 : /* Real */ ae_vector* x2,
40842 : ae_int_t n2,
40843 : /* Real */ ae_vector* x3,
40844 : ae_int_t n3,
40845 : /* Integer */ ae_vector* blocks0,
40846 : ae_int_t block0a,
40847 : ae_int_t block0b,
40848 : /* Integer */ ae_vector* blocks1,
40849 : ae_int_t block1a,
40850 : ae_int_t block1b,
40851 : /* Integer */ ae_vector* blocks2,
40852 : ae_int_t block2a,
40853 : ae_int_t block2b,
40854 : /* Integer */ ae_vector* blocks3,
40855 : ae_int_t block3a,
40856 : ae_int_t block3b,
40857 : /* Boolean */ ae_vector* flagy,
40858 : ae_bool sparsey,
40859 : ae_int_t levelidx,
40860 : double avgfuncpernode,
40861 : ae_shared_pool* bufpool,
40862 : /* Real */ ae_vector* y,
40863 : ae_state *_state)
40864 : {
40865 : ae_frame _frame_block;
40866 : ae_int_t nx;
40867 : ae_int_t ny;
40868 : ae_int_t k;
40869 : ae_int_t l;
40870 : ae_int_t blkidx;
40871 : ae_int_t blkcnt;
40872 : ae_int_t nodeidx;
40873 : ae_int_t nodescnt;
40874 : ae_int_t rowidx;
40875 : ae_int_t rowscnt;
40876 : ae_int_t i0;
40877 : ae_int_t i1;
40878 : ae_int_t i2;
40879 : ae_int_t i3;
40880 : ae_int_t j0;
40881 : ae_int_t j1;
40882 : ae_int_t j2;
40883 : ae_int_t j3;
40884 : double rcur;
40885 : double invrc2;
40886 : double rquery2;
40887 : double rfar2;
40888 : ae_int_t dstoffs;
40889 : ae_int_t srcoffs;
40890 : ae_int_t dummy;
40891 : double rowwidth;
40892 : double maxrowwidth;
40893 : double problemcost;
40894 : ae_int_t maxbs;
40895 : ae_int_t midpoint;
40896 : ae_bool emptyrow;
40897 : rbfv2gridcalcbuffer *buf;
40898 : ae_smart_ptr _buf;
40899 :
40900 0 : ae_frame_make(_state, &_frame_block);
40901 0 : memset(&_buf, 0, sizeof(_buf));
40902 0 : ae_smart_ptr_init(&_buf, (void**)&buf, _state, ae_true);
40903 :
40904 0 : nx = s->nx;
40905 0 : ny = s->ny;
40906 :
40907 : /*
40908 : * Integrity checks
40909 : */
40910 0 : ae_assert(s->nx==2||s->nx==3, "RBFV2PartialGridCalcRec: integrity check failed", _state);
40911 :
40912 : /*
40913 : * Try to split large problem
40914 : */
40915 0 : problemcost = s->ny*2*(avgfuncpernode+1);
40916 0 : problemcost = problemcost*(blocks0->ptr.p_int[block0b]-blocks0->ptr.p_int[block0a]);
40917 0 : problemcost = problemcost*(blocks1->ptr.p_int[block1b]-blocks1->ptr.p_int[block1a]);
40918 0 : problemcost = problemcost*(blocks2->ptr.p_int[block2b]-blocks2->ptr.p_int[block2a]);
40919 0 : problemcost = problemcost*(blocks3->ptr.p_int[block3b]-blocks3->ptr.p_int[block3a]);
40920 0 : maxbs = 0;
40921 0 : maxbs = ae_maxint(maxbs, block0b-block0a, _state);
40922 0 : maxbs = ae_maxint(maxbs, block1b-block1a, _state);
40923 0 : maxbs = ae_maxint(maxbs, block2b-block2a, _state);
40924 0 : maxbs = ae_maxint(maxbs, block3b-block3a, _state);
40925 0 : if( ae_fp_greater_eq(problemcost*rbfv2_complexitymultiplier,smpactivationlevel(_state)) )
40926 : {
40927 0 : if( _trypexec_rbfv2partialgridcalcrec(s,x0,n0,x1,n1,x2,n2,x3,n3,blocks0,block0a,block0b,blocks1,block1a,block1b,blocks2,block2a,block2b,blocks3,block3a,block3b,flagy,sparsey,levelidx,avgfuncpernode,bufpool,y, _state) )
40928 : {
40929 0 : ae_frame_leave(_state);
40930 0 : return;
40931 : }
40932 : }
40933 0 : if( ae_fp_greater_eq(problemcost*rbfv2_complexitymultiplier,spawnlevel(_state))&&maxbs>=2 )
40934 : {
40935 0 : if( block0b-block0a==maxbs )
40936 : {
40937 0 : midpoint = block0a+maxbs/2;
40938 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, midpoint, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40939 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, midpoint, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40940 0 : ae_frame_leave(_state);
40941 0 : return;
40942 : }
40943 0 : if( block1b-block1a==maxbs )
40944 : {
40945 0 : midpoint = block1a+maxbs/2;
40946 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, midpoint, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40947 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, midpoint, block1b, blocks2, block2a, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40948 0 : ae_frame_leave(_state);
40949 0 : return;
40950 : }
40951 0 : if( block2b-block2a==maxbs )
40952 : {
40953 0 : midpoint = block2a+maxbs/2;
40954 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, midpoint, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40955 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, midpoint, block2b, blocks3, block3a, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40956 0 : ae_frame_leave(_state);
40957 0 : return;
40958 : }
40959 0 : if( block3b-block3a==maxbs )
40960 : {
40961 0 : midpoint = block3a+maxbs/2;
40962 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, block3a, midpoint, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40963 0 : rbfv2partialgridcalcrec(s, x0, n0, x1, n1, x2, n2, x3, n3, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, blocks3, midpoint, block3b, flagy, sparsey, levelidx, avgfuncpernode, bufpool, y, _state);
40964 0 : ae_frame_leave(_state);
40965 0 : return;
40966 : }
40967 0 : ae_assert(ae_false, "RBFV2PartialGridCalcRec: integrity check failed", _state);
40968 : }
40969 :
40970 : /*
40971 : * Retrieve buffer object from pool (it will be returned later)
40972 : */
40973 0 : ae_shared_pool_retrieve(bufpool, &_buf, _state);
40974 :
40975 : /*
40976 : * Calculate RBF model
40977 : */
40978 0 : ae_assert(nx<=4, "RBFV2PartialGridCalcRec: integrity check failed", _state);
40979 0 : ae_vector_set_length(&buf->tx, 4, _state);
40980 0 : ae_vector_set_length(&buf->cx, 4, _state);
40981 0 : ae_vector_set_length(&buf->ty, ny, _state);
40982 0 : rcur = s->ri.ptr.p_double[levelidx];
40983 0 : invrc2 = 1/(rcur*rcur);
40984 0 : blkcnt = (block3b-block3a)*(block2b-block2a)*(block1b-block1a)*(block0b-block0a);
40985 0 : for(blkidx=0; blkidx<=blkcnt-1; blkidx++)
40986 : {
40987 :
40988 : /*
40989 : * Select block (I0,I1,I2,I3).
40990 : *
40991 : * NOTE: for problems with NX<4 corresponding I_? are zero.
40992 : */
40993 0 : k = blkidx;
40994 0 : i0 = block0a+k%(block0b-block0a);
40995 0 : k = k/(block0b-block0a);
40996 0 : i1 = block1a+k%(block1b-block1a);
40997 0 : k = k/(block1b-block1a);
40998 0 : i2 = block2a+k%(block2b-block2a);
40999 0 : k = k/(block2b-block2a);
41000 0 : i3 = block3a+k%(block3b-block3a);
41001 0 : k = k/(block3b-block3a);
41002 0 : ae_assert(k==0, "RBFV2PartialGridCalcRec: integrity check failed", _state);
41003 :
41004 : /*
41005 : * We partitioned grid into blocks and selected block with
41006 : * index (I0,I1,I2,I3). This block is a 4D cube (some dimensions
41007 : * may be zero) of nodes with indexes (J0,J1,J2,J3), which is
41008 : * further partitioned into a set of rows, each row corresponding
41009 : * to indexes J1...J3 being fixed.
41010 : *
41011 : * We process block row by row, and each row may be handled
41012 : * by either "generic" (nodes are processed separately) or
41013 : * batch algorithm (that's the reason to use rows, after all).
41014 : *
41015 : *
41016 : * Process nodes of the block
41017 : */
41018 0 : rowscnt = (blocks3->ptr.p_int[i3+1]-blocks3->ptr.p_int[i3])*(blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2])*(blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1]);
41019 0 : for(rowidx=0; rowidx<=rowscnt-1; rowidx++)
41020 : {
41021 :
41022 : /*
41023 : * Find out node indexes (*,J1,J2,J3).
41024 : *
41025 : * NOTE: for problems with NX<4 corresponding J_? are zero.
41026 : */
41027 0 : k = rowidx;
41028 0 : j1 = blocks1->ptr.p_int[i1]+k%(blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1]);
41029 0 : k = k/(blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1]);
41030 0 : j2 = blocks2->ptr.p_int[i2]+k%(blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2]);
41031 0 : k = k/(blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2]);
41032 0 : j3 = blocks3->ptr.p_int[i3]+k%(blocks3->ptr.p_int[i3+1]-blocks3->ptr.p_int[i3]);
41033 0 : k = k/(blocks3->ptr.p_int[i3+1]-blocks3->ptr.p_int[i3]);
41034 0 : ae_assert(k==0, "RBFV2PartialGridCalcRec: integrity check failed", _state);
41035 :
41036 : /*
41037 : * Analyze row, skip completely empty rows
41038 : */
41039 0 : nodescnt = blocks0->ptr.p_int[i0+1]-blocks0->ptr.p_int[i0];
41040 0 : srcoffs = blocks0->ptr.p_int[i0]+(j1+(j2+j3*n2)*n1)*n0;
41041 0 : emptyrow = ae_true;
41042 0 : for(nodeidx=0; nodeidx<=nodescnt-1; nodeidx++)
41043 : {
41044 0 : emptyrow = emptyrow&&(sparsey&&!flagy->ptr.p_bool[srcoffs+nodeidx]);
41045 : }
41046 0 : if( emptyrow )
41047 : {
41048 0 : continue;
41049 : }
41050 :
41051 : /*
41052 : * Process row - use either "batch" (rowsize>1) or "generic"
41053 : * (row size is 1) algorithm.
41054 : *
41055 : * NOTE: "generic" version may also be used as fallback code for
41056 : * situations when we do not want to use batch code.
41057 : */
41058 0 : maxrowwidth = 0.5*rbfv2nearradius(s->bf, _state)*rcur*s->s.ptr.p_double[0];
41059 0 : rowwidth = x0->ptr.p_double[blocks0->ptr.p_int[i0+1]-1]-x0->ptr.p_double[blocks0->ptr.p_int[i0]];
41060 0 : if( nodescnt>1&&ae_fp_less_eq(rowwidth,maxrowwidth) )
41061 : {
41062 :
41063 : /*
41064 : * "Batch" code which processes entire row at once, saving
41065 : * some time in kd-tree search code.
41066 : */
41067 0 : rquery2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state)+0.5*rowwidth/s->s.ptr.p_double[0], _state);
41068 0 : rfar2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state);
41069 0 : j0 = blocks0->ptr.p_int[i0];
41070 0 : if( nx>0 )
41071 : {
41072 0 : buf->cx.ptr.p_double[0] = (x0->ptr.p_double[j0]+0.5*rowwidth)/s->s.ptr.p_double[0];
41073 : }
41074 0 : if( nx>1 )
41075 : {
41076 0 : buf->cx.ptr.p_double[1] = x1->ptr.p_double[j1]/s->s.ptr.p_double[1];
41077 : }
41078 0 : if( nx>2 )
41079 : {
41080 0 : buf->cx.ptr.p_double[2] = x2->ptr.p_double[j2]/s->s.ptr.p_double[2];
41081 : }
41082 0 : if( nx>3 )
41083 : {
41084 0 : buf->cx.ptr.p_double[3] = x3->ptr.p_double[j3]/s->s.ptr.p_double[3];
41085 : }
41086 0 : srcoffs = j0+(j1+(j2+j3*n2)*n1)*n0;
41087 0 : dstoffs = ny*srcoffs;
41088 0 : rvectorsetlengthatleast(&buf->rx, nodescnt, _state);
41089 0 : bvectorsetlengthatleast(&buf->rf, nodescnt, _state);
41090 0 : rvectorsetlengthatleast(&buf->ry, nodescnt*ny, _state);
41091 0 : for(nodeidx=0; nodeidx<=nodescnt-1; nodeidx++)
41092 : {
41093 0 : buf->rx.ptr.p_double[nodeidx] = x0->ptr.p_double[j0+nodeidx]/s->s.ptr.p_double[0];
41094 0 : buf->rf.ptr.p_bool[nodeidx] = !sparsey||flagy->ptr.p_bool[srcoffs+nodeidx];
41095 : }
41096 0 : for(k=0; k<=nodescnt*ny-1; k++)
41097 : {
41098 0 : buf->ry.ptr.p_double[k] = (double)(0);
41099 : }
41100 0 : rbfv2_preparepartialquery(&buf->cx, &s->kdboxmin, &s->kdboxmax, nx, &buf->calcbuf, &dummy, _state);
41101 0 : rbfv2_partialrowcalcrec(s, &buf->calcbuf, s->kdroots.ptr.p_int[levelidx], invrc2, rquery2, rfar2, &buf->cx, &buf->rx, &buf->rf, nodescnt, &buf->ry, _state);
41102 0 : for(k=0; k<=nodescnt*ny-1; k++)
41103 : {
41104 0 : y->ptr.p_double[dstoffs+k] = y->ptr.p_double[dstoffs+k]+buf->ry.ptr.p_double[k];
41105 : }
41106 : }
41107 : else
41108 : {
41109 :
41110 : /*
41111 : * "Generic" code. Although we usually move here
41112 : * only when NodesCnt=1, we still use a loop on
41113 : * NodeIdx just to be able to use this branch as
41114 : * fallback code without any modifications.
41115 : */
41116 0 : rquery2 = ae_sqr(rcur*rbfv2farradius(s->bf, _state), _state);
41117 0 : for(nodeidx=0; nodeidx<=nodescnt-1; nodeidx++)
41118 : {
41119 :
41120 : /*
41121 : * Prepare TX - current point
41122 : */
41123 0 : j0 = blocks0->ptr.p_int[i0]+nodeidx;
41124 0 : if( nx>0 )
41125 : {
41126 0 : buf->tx.ptr.p_double[0] = x0->ptr.p_double[j0]/s->s.ptr.p_double[0];
41127 : }
41128 0 : if( nx>1 )
41129 : {
41130 0 : buf->tx.ptr.p_double[1] = x1->ptr.p_double[j1]/s->s.ptr.p_double[1];
41131 : }
41132 0 : if( nx>2 )
41133 : {
41134 0 : buf->tx.ptr.p_double[2] = x2->ptr.p_double[j2]/s->s.ptr.p_double[2];
41135 : }
41136 0 : if( nx>3 )
41137 : {
41138 0 : buf->tx.ptr.p_double[3] = x3->ptr.p_double[j3]/s->s.ptr.p_double[3];
41139 : }
41140 :
41141 : /*
41142 : * Evaluate and add to Y
41143 : */
41144 0 : srcoffs = j0+(j1+(j2+j3*n2)*n1)*n0;
41145 0 : dstoffs = ny*srcoffs;
41146 0 : for(l=0; l<=ny-1; l++)
41147 : {
41148 0 : buf->ty.ptr.p_double[l] = (double)(0);
41149 : }
41150 0 : if( !sparsey||flagy->ptr.p_bool[srcoffs] )
41151 : {
41152 0 : rbfv2_preparepartialquery(&buf->tx, &s->kdboxmin, &s->kdboxmax, nx, &buf->calcbuf, &dummy, _state);
41153 0 : rbfv2_partialcalcrec(s, &buf->calcbuf, s->kdroots.ptr.p_int[levelidx], invrc2, rquery2, &buf->tx, &buf->ty, _state);
41154 : }
41155 0 : for(l=0; l<=ny-1; l++)
41156 : {
41157 0 : y->ptr.p_double[dstoffs+l] = y->ptr.p_double[dstoffs+l]+buf->ty.ptr.p_double[l];
41158 : }
41159 : }
41160 : }
41161 : }
41162 : }
41163 :
41164 : /*
41165 : * Recycle buffer object back to pool
41166 : */
41167 0 : ae_shared_pool_recycle(bufpool, &_buf, _state);
41168 0 : ae_frame_leave(_state);
41169 : }
41170 :
41171 :
41172 : /*************************************************************************
41173 : Serial stub for GPL edition.
41174 : *************************************************************************/
41175 0 : ae_bool _trypexec_rbfv2partialgridcalcrec(rbfv2model* s,
41176 : /* Real */ ae_vector* x0,
41177 : ae_int_t n0,
41178 : /* Real */ ae_vector* x1,
41179 : ae_int_t n1,
41180 : /* Real */ ae_vector* x2,
41181 : ae_int_t n2,
41182 : /* Real */ ae_vector* x3,
41183 : ae_int_t n3,
41184 : /* Integer */ ae_vector* blocks0,
41185 : ae_int_t block0a,
41186 : ae_int_t block0b,
41187 : /* Integer */ ae_vector* blocks1,
41188 : ae_int_t block1a,
41189 : ae_int_t block1b,
41190 : /* Integer */ ae_vector* blocks2,
41191 : ae_int_t block2a,
41192 : ae_int_t block2b,
41193 : /* Integer */ ae_vector* blocks3,
41194 : ae_int_t block3a,
41195 : ae_int_t block3b,
41196 : /* Boolean */ ae_vector* flagy,
41197 : ae_bool sparsey,
41198 : ae_int_t levelidx,
41199 : double avgfuncpernode,
41200 : ae_shared_pool* bufpool,
41201 : /* Real */ ae_vector* y,
41202 : ae_state *_state)
41203 : {
41204 0 : return ae_false;
41205 : }
41206 :
41207 :
41208 : /*************************************************************************
41209 : This function "unpacks" RBF model by extracting its coefficients.
41210 :
41211 : INPUT PARAMETERS:
41212 : S - RBF model
41213 :
41214 : OUTPUT PARAMETERS:
41215 : NX - dimensionality of argument
41216 : NY - dimensionality of the target function
41217 : XWR - model information, array[NC,NX+NY+1].
41218 : One row of the array corresponds to one basis function:
41219 : * first NX columns - coordinates of the center
41220 : * next NY columns - weights, one per dimension of the
41221 : function being modelled
41222 : * last NX columns - radii, per dimension
41223 : NC - number of the centers
41224 : V - polynomial term , array[NY,NX+1]. One row per one
41225 : dimension of the function being modelled. First NX
41226 : elements are linear coefficients, V[NX] is equal to the
41227 : constant part.
41228 :
41229 : -- ALGLIB --
41230 : Copyright 13.12.2011 by Bochkanov Sergey
41231 : *************************************************************************/
41232 0 : void rbfv2unpack(rbfv2model* s,
41233 : ae_int_t* nx,
41234 : ae_int_t* ny,
41235 : /* Real */ ae_matrix* xwr,
41236 : ae_int_t* nc,
41237 : /* Real */ ae_matrix* v,
41238 : ae_state *_state)
41239 : {
41240 : ae_int_t i;
41241 : ae_int_t ncactual;
41242 :
41243 0 : *nx = 0;
41244 0 : *ny = 0;
41245 0 : ae_matrix_clear(xwr);
41246 0 : *nc = 0;
41247 0 : ae_matrix_clear(v);
41248 :
41249 0 : *nx = s->nx;
41250 0 : *ny = s->ny;
41251 0 : *nc = 0;
41252 :
41253 : /*
41254 : * Fill V
41255 : */
41256 0 : ae_matrix_set_length(v, s->ny, s->nx+1, _state);
41257 0 : for(i=0; i<=s->ny-1; i++)
41258 : {
41259 0 : ae_v_move(&v->ptr.pp_double[i][0], 1, &s->v.ptr.pp_double[i][0], 1, ae_v_len(0,s->nx));
41260 : }
41261 :
41262 : /*
41263 : * Fill XWR
41264 : */
41265 0 : ae_assert(s->cw.cnt%(s->nx+s->ny)==0, "RBFV2Unpack: integrity error", _state);
41266 0 : *nc = s->cw.cnt/(s->nx+s->ny);
41267 0 : ncactual = 0;
41268 0 : if( *nc>0 )
41269 : {
41270 0 : ae_matrix_set_length(xwr, *nc, s->nx+s->ny+s->nx, _state);
41271 0 : for(i=0; i<=s->nh-1; i++)
41272 : {
41273 0 : rbfv2_partialunpackrec(&s->kdnodes, &s->kdsplits, &s->cw, &s->s, s->nx, s->ny, s->kdroots.ptr.p_int[i], s->ri.ptr.p_double[i], xwr, &ncactual, _state);
41274 : }
41275 : }
41276 0 : ae_assert(*nc==ncactual, "RBFV2Unpack: integrity error", _state);
41277 0 : }
41278 :
41279 :
41280 0 : static ae_bool rbfv2_rbfv2buildlinearmodel(/* Real */ ae_matrix* x,
41281 : /* Real */ ae_matrix* y,
41282 : ae_int_t n,
41283 : ae_int_t nx,
41284 : ae_int_t ny,
41285 : ae_int_t modeltype,
41286 : /* Real */ ae_matrix* v,
41287 : ae_state *_state)
41288 : {
41289 : ae_frame _frame_block;
41290 : ae_vector tmpy;
41291 : ae_matrix a;
41292 : double scaling;
41293 : ae_vector shifting;
41294 : double mn;
41295 : double mx;
41296 : ae_vector c;
41297 : lsfitreport rep;
41298 : ae_int_t i;
41299 : ae_int_t j;
41300 : ae_int_t k;
41301 : ae_int_t info;
41302 : ae_bool result;
41303 :
41304 0 : ae_frame_make(_state, &_frame_block);
41305 0 : memset(&tmpy, 0, sizeof(tmpy));
41306 0 : memset(&a, 0, sizeof(a));
41307 0 : memset(&shifting, 0, sizeof(shifting));
41308 0 : memset(&c, 0, sizeof(c));
41309 0 : memset(&rep, 0, sizeof(rep));
41310 0 : ae_matrix_clear(v);
41311 0 : ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
41312 0 : ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
41313 0 : ae_vector_init(&shifting, 0, DT_REAL, _state, ae_true);
41314 0 : ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
41315 0 : _lsfitreport_init(&rep, _state, ae_true);
41316 :
41317 0 : ae_assert(n>=0, "BuildLinearModel: N<0", _state);
41318 0 : ae_assert(nx>0, "BuildLinearModel: NX<=0", _state);
41319 0 : ae_assert(ny>0, "BuildLinearModel: NY<=0", _state);
41320 :
41321 : /*
41322 : * Handle degenerate case (N=0)
41323 : */
41324 0 : result = ae_true;
41325 0 : ae_matrix_set_length(v, ny, nx+1, _state);
41326 0 : if( n==0 )
41327 : {
41328 0 : for(j=0; j<=nx; j++)
41329 : {
41330 0 : for(i=0; i<=ny-1; i++)
41331 : {
41332 0 : v->ptr.pp_double[i][j] = (double)(0);
41333 : }
41334 : }
41335 0 : ae_frame_leave(_state);
41336 0 : return result;
41337 : }
41338 :
41339 : /*
41340 : * Allocate temporaries
41341 : */
41342 0 : ae_vector_set_length(&tmpy, n, _state);
41343 :
41344 : /*
41345 : * General linear model.
41346 : */
41347 0 : if( modeltype==1 )
41348 : {
41349 :
41350 : /*
41351 : * Calculate scaling/shifting, transform variables, prepare LLS problem
41352 : */
41353 0 : ae_matrix_set_length(&a, n, nx+1, _state);
41354 0 : ae_vector_set_length(&shifting, nx, _state);
41355 0 : scaling = (double)(0);
41356 0 : for(i=0; i<=nx-1; i++)
41357 : {
41358 0 : mn = x->ptr.pp_double[0][i];
41359 0 : mx = mn;
41360 0 : for(j=1; j<=n-1; j++)
41361 : {
41362 0 : if( ae_fp_greater(mn,x->ptr.pp_double[j][i]) )
41363 : {
41364 0 : mn = x->ptr.pp_double[j][i];
41365 : }
41366 0 : if( ae_fp_less(mx,x->ptr.pp_double[j][i]) )
41367 : {
41368 0 : mx = x->ptr.pp_double[j][i];
41369 : }
41370 : }
41371 0 : scaling = ae_maxreal(scaling, mx-mn, _state);
41372 0 : shifting.ptr.p_double[i] = 0.5*(mx+mn);
41373 : }
41374 0 : if( ae_fp_eq(scaling,(double)(0)) )
41375 : {
41376 0 : scaling = (double)(1);
41377 : }
41378 : else
41379 : {
41380 0 : scaling = 0.5*scaling;
41381 : }
41382 0 : for(i=0; i<=n-1; i++)
41383 : {
41384 0 : for(j=0; j<=nx-1; j++)
41385 : {
41386 0 : a.ptr.pp_double[i][j] = (x->ptr.pp_double[i][j]-shifting.ptr.p_double[j])/scaling;
41387 : }
41388 : }
41389 0 : for(i=0; i<=n-1; i++)
41390 : {
41391 0 : a.ptr.pp_double[i][nx] = (double)(1);
41392 : }
41393 :
41394 : /*
41395 : * Solve linear system in transformed variables, make backward
41396 : */
41397 0 : for(i=0; i<=ny-1; i++)
41398 : {
41399 0 : for(j=0; j<=n-1; j++)
41400 : {
41401 0 : tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i];
41402 : }
41403 0 : lsfitlinear(&tmpy, &a, n, nx+1, &info, &c, &rep, _state);
41404 0 : if( info<=0 )
41405 : {
41406 0 : result = ae_false;
41407 0 : ae_frame_leave(_state);
41408 0 : return result;
41409 : }
41410 0 : for(j=0; j<=nx-1; j++)
41411 : {
41412 0 : v->ptr.pp_double[i][j] = c.ptr.p_double[j]/scaling;
41413 : }
41414 0 : v->ptr.pp_double[i][nx] = c.ptr.p_double[nx];
41415 0 : for(j=0; j<=nx-1; j++)
41416 : {
41417 0 : v->ptr.pp_double[i][nx] = v->ptr.pp_double[i][nx]-shifting.ptr.p_double[j]*v->ptr.pp_double[i][j];
41418 : }
41419 0 : for(j=0; j<=n-1; j++)
41420 : {
41421 0 : for(k=0; k<=nx-1; k++)
41422 : {
41423 0 : y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-x->ptr.pp_double[j][k]*v->ptr.pp_double[i][k];
41424 : }
41425 0 : y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][nx];
41426 : }
41427 : }
41428 0 : ae_frame_leave(_state);
41429 0 : return result;
41430 : }
41431 :
41432 : /*
41433 : * Constant model, very simple
41434 : */
41435 0 : if( modeltype==2 )
41436 : {
41437 0 : for(i=0; i<=ny-1; i++)
41438 : {
41439 0 : for(j=0; j<=nx; j++)
41440 : {
41441 0 : v->ptr.pp_double[i][j] = (double)(0);
41442 : }
41443 0 : for(j=0; j<=n-1; j++)
41444 : {
41445 0 : v->ptr.pp_double[i][nx] = v->ptr.pp_double[i][nx]+y->ptr.pp_double[j][i];
41446 : }
41447 0 : if( n>0 )
41448 : {
41449 0 : v->ptr.pp_double[i][nx] = v->ptr.pp_double[i][nx]/n;
41450 : }
41451 0 : for(j=0; j<=n-1; j++)
41452 : {
41453 0 : y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][nx];
41454 : }
41455 : }
41456 0 : ae_frame_leave(_state);
41457 0 : return result;
41458 : }
41459 :
41460 : /*
41461 : * Zero model
41462 : */
41463 0 : ae_assert(modeltype==3, "BuildLinearModel: unknown model type", _state);
41464 0 : for(i=0; i<=ny-1; i++)
41465 : {
41466 0 : for(j=0; j<=nx; j++)
41467 : {
41468 0 : v->ptr.pp_double[i][j] = (double)(0);
41469 : }
41470 : }
41471 0 : ae_frame_leave(_state);
41472 0 : return result;
41473 : }
41474 :
41475 :
41476 : /*************************************************************************
41477 : Reallocates calcBuf if necessary, reuses previously allocated space if
41478 : possible.
41479 :
41480 : -- ALGLIB --
41481 : Copyright 20.06.2016 by Sergey Bochkanov
41482 : *************************************************************************/
41483 0 : static void rbfv2_allocatecalcbuffer(rbfv2model* s,
41484 : rbfv2calcbuffer* buf,
41485 : ae_state *_state)
41486 : {
41487 :
41488 :
41489 0 : if( buf->x.cnt<s->nx )
41490 : {
41491 0 : ae_vector_set_length(&buf->x, s->nx, _state);
41492 : }
41493 0 : if( buf->curboxmin.cnt<s->nx )
41494 : {
41495 0 : ae_vector_set_length(&buf->curboxmin, s->nx, _state);
41496 : }
41497 0 : if( buf->curboxmax.cnt<s->nx )
41498 : {
41499 0 : ae_vector_set_length(&buf->curboxmax, s->nx, _state);
41500 : }
41501 0 : if( buf->x123.cnt<s->nx )
41502 : {
41503 0 : ae_vector_set_length(&buf->x123, s->nx, _state);
41504 : }
41505 0 : if( buf->y123.cnt<s->ny )
41506 : {
41507 0 : ae_vector_set_length(&buf->y123, s->ny, _state);
41508 : }
41509 0 : }
41510 :
41511 :
41512 : /*************************************************************************
41513 : Extracts structure (and XY-values too) from kd-tree built for a small
41514 : subset of points and appends it to multi-tree.
41515 :
41516 :
41517 : -- ALGLIB --
41518 : Copyright 20.06.2016 by Sergey Bochkanov
41519 : *************************************************************************/
41520 0 : static void rbfv2_convertandappendtree(kdtree* curtree,
41521 : ae_int_t n,
41522 : ae_int_t nx,
41523 : ae_int_t ny,
41524 : /* Integer */ ae_vector* kdnodes,
41525 : /* Real */ ae_vector* kdsplits,
41526 : /* Real */ ae_vector* cw,
41527 : ae_state *_state)
41528 : {
41529 : ae_frame _frame_block;
41530 : ae_int_t nodesbase;
41531 : ae_int_t splitsbase;
41532 : ae_int_t cwbase;
41533 : ae_vector localnodes;
41534 : ae_vector localsplits;
41535 : ae_vector localcw;
41536 : ae_matrix xybuf;
41537 : ae_int_t localnodessize;
41538 : ae_int_t localsplitssize;
41539 : ae_int_t localcwsize;
41540 : ae_int_t i;
41541 :
41542 0 : ae_frame_make(_state, &_frame_block);
41543 0 : memset(&localnodes, 0, sizeof(localnodes));
41544 0 : memset(&localsplits, 0, sizeof(localsplits));
41545 0 : memset(&localcw, 0, sizeof(localcw));
41546 0 : memset(&xybuf, 0, sizeof(xybuf));
41547 0 : ae_vector_init(&localnodes, 0, DT_INT, _state, ae_true);
41548 0 : ae_vector_init(&localsplits, 0, DT_REAL, _state, ae_true);
41549 0 : ae_vector_init(&localcw, 0, DT_REAL, _state, ae_true);
41550 0 : ae_matrix_init(&xybuf, 0, 0, DT_REAL, _state, ae_true);
41551 :
41552 :
41553 : /*
41554 : * Calculate base offsets
41555 : */
41556 0 : nodesbase = kdnodes->cnt;
41557 0 : splitsbase = kdsplits->cnt;
41558 0 : cwbase = cw->cnt;
41559 :
41560 : /*
41561 : * Prepare local copy of tree
41562 : */
41563 0 : ae_vector_set_length(&localnodes, n*rbfv2_maxnodesize, _state);
41564 0 : ae_vector_set_length(&localsplits, n, _state);
41565 0 : ae_vector_set_length(&localcw, (nx+ny)*n, _state);
41566 0 : localnodessize = 0;
41567 0 : localsplitssize = 0;
41568 0 : localcwsize = 0;
41569 0 : rbfv2_converttreerec(curtree, n, nx, ny, 0, nodesbase, splitsbase, cwbase, &localnodes, &localnodessize, &localsplits, &localsplitssize, &localcw, &localcwsize, &xybuf, _state);
41570 :
41571 : /*
41572 : * Append to multi-tree
41573 : */
41574 0 : ivectorresize(kdnodes, kdnodes->cnt+localnodessize, _state);
41575 0 : rvectorresize(kdsplits, kdsplits->cnt+localsplitssize, _state);
41576 0 : rvectorresize(cw, cw->cnt+localcwsize, _state);
41577 0 : for(i=0; i<=localnodessize-1; i++)
41578 : {
41579 0 : kdnodes->ptr.p_int[nodesbase+i] = localnodes.ptr.p_int[i];
41580 : }
41581 0 : for(i=0; i<=localsplitssize-1; i++)
41582 : {
41583 0 : kdsplits->ptr.p_double[splitsbase+i] = localsplits.ptr.p_double[i];
41584 : }
41585 0 : for(i=0; i<=localcwsize-1; i++)
41586 : {
41587 0 : cw->ptr.p_double[cwbase+i] = localcw.ptr.p_double[i];
41588 : }
41589 0 : ae_frame_leave(_state);
41590 0 : }
41591 :
41592 :
41593 : /*************************************************************************
41594 : Recurrent tree conversion
41595 :
41596 : CurTree - tree to convert
41597 : N, NX, NY - dataset metrics
41598 : NodeOffset - offset of current tree node, 0 for root
41599 : NodesBase - a value which is added to intra-tree node indexes;
41600 : although this tree is stored in separate array, it
41601 : is intended to be stored in the larger tree, with
41602 : localNodes being moved to offset NodesBase.
41603 : SplitsBase - similarly, offset of localSplits in the final tree
41604 : CWBase - similarly, offset of localCW in the final tree
41605 : *************************************************************************/
41606 0 : static void rbfv2_converttreerec(kdtree* curtree,
41607 : ae_int_t n,
41608 : ae_int_t nx,
41609 : ae_int_t ny,
41610 : ae_int_t nodeoffset,
41611 : ae_int_t nodesbase,
41612 : ae_int_t splitsbase,
41613 : ae_int_t cwbase,
41614 : /* Integer */ ae_vector* localnodes,
41615 : ae_int_t* localnodessize,
41616 : /* Real */ ae_vector* localsplits,
41617 : ae_int_t* localsplitssize,
41618 : /* Real */ ae_vector* localcw,
41619 : ae_int_t* localcwsize,
41620 : /* Real */ ae_matrix* xybuf,
41621 : ae_state *_state)
41622 : {
41623 : ae_int_t i;
41624 : ae_int_t j;
41625 : ae_int_t nodetype;
41626 : ae_int_t cnt;
41627 : ae_int_t d;
41628 : double s;
41629 : ae_int_t nodele;
41630 : ae_int_t nodege;
41631 : ae_int_t oldnodessize;
41632 :
41633 :
41634 0 : kdtreeexplorenodetype(curtree, nodeoffset, &nodetype, _state);
41635 :
41636 : /*
41637 : * Leaf node
41638 : */
41639 0 : if( nodetype==0 )
41640 : {
41641 0 : kdtreeexploreleaf(curtree, nodeoffset, xybuf, &cnt, _state);
41642 0 : ae_assert(localnodes->cnt>=*localnodessize+2, "ConvertTreeRec: integrity check failed", _state);
41643 0 : ae_assert(localcw->cnt>=*localcwsize+cnt*(nx+ny), "ConvertTreeRec: integrity check failed", _state);
41644 0 : localnodes->ptr.p_int[*localnodessize+0] = cnt;
41645 0 : localnodes->ptr.p_int[*localnodessize+1] = cwbase+(*localcwsize);
41646 0 : *localnodessize = *localnodessize+2;
41647 0 : for(i=0; i<=cnt-1; i++)
41648 : {
41649 0 : for(j=0; j<=nx+ny-1; j++)
41650 : {
41651 0 : localcw->ptr.p_double[*localcwsize+i*(nx+ny)+j] = xybuf->ptr.pp_double[i][j];
41652 : }
41653 : }
41654 0 : *localcwsize = *localcwsize+cnt*(nx+ny);
41655 0 : return;
41656 : }
41657 :
41658 : /*
41659 : * Split node
41660 : */
41661 0 : if( nodetype==1 )
41662 : {
41663 0 : kdtreeexploresplit(curtree, nodeoffset, &d, &s, &nodele, &nodege, _state);
41664 0 : ae_assert(localnodes->cnt>=*localnodessize+rbfv2_maxnodesize, "ConvertTreeRec: integrity check failed", _state);
41665 0 : ae_assert(localsplits->cnt>=*localsplitssize+1, "ConvertTreeRec: integrity check failed", _state);
41666 0 : oldnodessize = *localnodessize;
41667 0 : localnodes->ptr.p_int[*localnodessize+0] = 0;
41668 0 : localnodes->ptr.p_int[*localnodessize+1] = d;
41669 0 : localnodes->ptr.p_int[*localnodessize+2] = splitsbase+(*localsplitssize);
41670 0 : localnodes->ptr.p_int[*localnodessize+3] = -1;
41671 0 : localnodes->ptr.p_int[*localnodessize+4] = -1;
41672 0 : *localnodessize = *localnodessize+5;
41673 0 : localsplits->ptr.p_double[*localsplitssize+0] = s;
41674 0 : *localsplitssize = *localsplitssize+1;
41675 0 : localnodes->ptr.p_int[oldnodessize+3] = nodesbase+(*localnodessize);
41676 0 : rbfv2_converttreerec(curtree, n, nx, ny, nodele, nodesbase, splitsbase, cwbase, localnodes, localnodessize, localsplits, localsplitssize, localcw, localcwsize, xybuf, _state);
41677 0 : localnodes->ptr.p_int[oldnodessize+4] = nodesbase+(*localnodessize);
41678 0 : rbfv2_converttreerec(curtree, n, nx, ny, nodege, nodesbase, splitsbase, cwbase, localnodes, localnodessize, localsplits, localsplitssize, localcw, localcwsize, xybuf, _state);
41679 0 : return;
41680 : }
41681 :
41682 : /*
41683 : * Integrity error
41684 : */
41685 0 : ae_assert(ae_false, "ConvertTreeRec: integrity check failed", _state);
41686 : }
41687 :
41688 :
41689 : /*************************************************************************
41690 : This function performs partial calculation of hierarchical model: given
41691 : evaluation point X and partially computed value Y, it updates Y by values
41692 : computed using part of multi-tree given by RootIdx.
41693 :
41694 : INPUT PARAMETERS:
41695 : S - V2 model
41696 : Buf - calc-buffer, this function uses following fields:
41697 : * Buf.CurBoxMin - should be set by caller
41698 : * Buf.CurBoxMax - should be set by caller
41699 : * Buf.CurDist2 - squared distance from X to current bounding box,
41700 : should be set by caller
41701 : RootIdx - offset of partial kd-tree
41702 : InvR2 - 1/R^2, where R is basis function radius
41703 : QueryR2 - squared query radius, usually it is (R*FarRadius(BasisFunction))^2
41704 : X - evaluation point, array[NX]
41705 : Y - partial value, array[NY]
41706 :
41707 : OUTPUT PARAMETERS
41708 : Y - updated partial value
41709 :
41710 : -- ALGLIB --
41711 : Copyright 20.06.2016 by Bochkanov Sergey
41712 : *************************************************************************/
41713 0 : static void rbfv2_partialcalcrec(rbfv2model* s,
41714 : rbfv2calcbuffer* buf,
41715 : ae_int_t rootidx,
41716 : double invr2,
41717 : double queryr2,
41718 : /* Real */ ae_vector* x,
41719 : /* Real */ ae_vector* y,
41720 : ae_state *_state)
41721 : {
41722 : ae_int_t i;
41723 : ae_int_t j;
41724 : double ptdist2;
41725 : double v;
41726 : double v0;
41727 : double v1;
41728 : ae_int_t cwoffs;
41729 : ae_int_t cwcnt;
41730 : ae_int_t itemoffs;
41731 : double arg;
41732 : double val;
41733 : ae_int_t d;
41734 : double split;
41735 : ae_int_t childle;
41736 : ae_int_t childge;
41737 : ae_int_t childoffs;
41738 : ae_bool updatemin;
41739 : double prevdist2;
41740 : double t1;
41741 : ae_int_t nx;
41742 : ae_int_t ny;
41743 :
41744 :
41745 0 : nx = s->nx;
41746 0 : ny = s->ny;
41747 :
41748 : /*
41749 : * Helps to avoid spurious warnings
41750 : */
41751 0 : val = (double)(0);
41752 :
41753 : /*
41754 : * Leaf node.
41755 : */
41756 0 : if( s->kdnodes.ptr.p_int[rootidx]>0 )
41757 : {
41758 0 : cwcnt = s->kdnodes.ptr.p_int[rootidx+0];
41759 0 : cwoffs = s->kdnodes.ptr.p_int[rootidx+1];
41760 0 : for(i=0; i<=cwcnt-1; i++)
41761 : {
41762 :
41763 : /*
41764 : * Calculate distance
41765 : */
41766 0 : itemoffs = cwoffs+i*(nx+ny);
41767 0 : ptdist2 = (double)(0);
41768 0 : for(j=0; j<=nx-1; j++)
41769 : {
41770 0 : v = s->cw.ptr.p_double[itemoffs+j]-x->ptr.p_double[j];
41771 0 : ptdist2 = ptdist2+v*v;
41772 : }
41773 :
41774 : /*
41775 : * Skip points if distance too large
41776 : */
41777 0 : if( ptdist2>=queryr2 )
41778 : {
41779 0 : continue;
41780 : }
41781 :
41782 : /*
41783 : * Update Y
41784 : */
41785 0 : arg = ptdist2*invr2;
41786 0 : if( s->bf==0 )
41787 : {
41788 0 : val = ae_exp(-arg, _state);
41789 : }
41790 : else
41791 : {
41792 0 : if( s->bf==1 )
41793 : {
41794 0 : val = rbfv2basisfunc(s->bf, arg, _state);
41795 : }
41796 : else
41797 : {
41798 0 : ae_assert(ae_false, "PartialCalcRec: integrity check failed", _state);
41799 : }
41800 : }
41801 0 : itemoffs = itemoffs+nx;
41802 0 : for(j=0; j<=ny-1; j++)
41803 : {
41804 0 : y->ptr.p_double[j] = y->ptr.p_double[j]+val*s->cw.ptr.p_double[itemoffs+j];
41805 : }
41806 : }
41807 0 : return;
41808 : }
41809 :
41810 : /*
41811 : * Simple split
41812 : */
41813 0 : if( s->kdnodes.ptr.p_int[rootidx]==0 )
41814 : {
41815 :
41816 : /*
41817 : * Load:
41818 : * * D dimension to split
41819 : * * Split split position
41820 : * * ChildLE, ChildGE - indexes of childs
41821 : */
41822 0 : d = s->kdnodes.ptr.p_int[rootidx+1];
41823 0 : split = s->kdsplits.ptr.p_double[s->kdnodes.ptr.p_int[rootidx+2]];
41824 0 : childle = s->kdnodes.ptr.p_int[rootidx+3];
41825 0 : childge = s->kdnodes.ptr.p_int[rootidx+4];
41826 :
41827 : /*
41828 : * Navigate through childs
41829 : */
41830 0 : for(i=0; i<=1; i++)
41831 : {
41832 :
41833 : /*
41834 : * Select child to process:
41835 : * * ChildOffs current child offset in Nodes[]
41836 : * * UpdateMin whether minimum or maximum value
41837 : * of bounding box is changed on update
41838 : */
41839 0 : updatemin = i!=0;
41840 0 : if( i==0 )
41841 : {
41842 0 : childoffs = childle;
41843 : }
41844 : else
41845 : {
41846 0 : childoffs = childge;
41847 : }
41848 :
41849 : /*
41850 : * Update bounding box and current distance
41851 : */
41852 0 : prevdist2 = buf->curdist2;
41853 0 : t1 = x->ptr.p_double[d];
41854 0 : if( updatemin )
41855 : {
41856 0 : v = buf->curboxmin.ptr.p_double[d];
41857 0 : if( t1<=split )
41858 : {
41859 0 : v0 = v-t1;
41860 0 : if( v0<0 )
41861 : {
41862 0 : v0 = (double)(0);
41863 : }
41864 0 : v1 = split-t1;
41865 0 : buf->curdist2 = buf->curdist2-v0*v0+v1*v1;
41866 : }
41867 0 : buf->curboxmin.ptr.p_double[d] = split;
41868 : }
41869 : else
41870 : {
41871 0 : v = buf->curboxmax.ptr.p_double[d];
41872 0 : if( t1>=split )
41873 : {
41874 0 : v0 = t1-v;
41875 0 : if( v0<0 )
41876 : {
41877 0 : v0 = (double)(0);
41878 : }
41879 0 : v1 = t1-split;
41880 0 : buf->curdist2 = buf->curdist2-v0*v0+v1*v1;
41881 : }
41882 0 : buf->curboxmax.ptr.p_double[d] = split;
41883 : }
41884 :
41885 : /*
41886 : * Decide: to dive into cell or not to dive
41887 : */
41888 0 : if( buf->curdist2<queryr2 )
41889 : {
41890 0 : rbfv2_partialcalcrec(s, buf, childoffs, invr2, queryr2, x, y, _state);
41891 : }
41892 :
41893 : /*
41894 : * Restore bounding box and distance
41895 : */
41896 0 : if( updatemin )
41897 : {
41898 0 : buf->curboxmin.ptr.p_double[d] = v;
41899 : }
41900 : else
41901 : {
41902 0 : buf->curboxmax.ptr.p_double[d] = v;
41903 : }
41904 0 : buf->curdist2 = prevdist2;
41905 : }
41906 0 : return;
41907 : }
41908 :
41909 : /*
41910 : * Integrity failure
41911 : */
41912 0 : ae_assert(ae_false, "PartialCalcRec: integrity check failed", _state);
41913 : }
41914 :
41915 :
41916 : /*************************************************************************
41917 : This function performs same operation as partialcalcrec(), but for entire
41918 : row of the grid. "Row" is a set of nodes (x0,x1,x2,x3) which share x1..x3,
41919 : but have different x0's. (note: for 2D/3D problems x2..x3 are zero).
41920 :
41921 : Row is given by:
41922 : * central point XC, which is located at the center of the row, and used to
41923 : perform kd-tree requests
41924 : * set of x0 coordinates stored in RX array (array may be unordered, but it
41925 : is expected that spread of x0 is no more than R; function may be
41926 : inefficient for larger spreads).
41927 : * set of YFlag values stored in RF
41928 :
41929 : INPUT PARAMETERS:
41930 : S - V2 model
41931 : Buf - calc-buffer, this function uses following fields:
41932 : * Buf.CurBoxMin - should be set by caller
41933 : * Buf.CurBoxMax - should be set by caller
41934 : * Buf.CurDist2 - squared distance from X to current bounding box,
41935 : should be set by caller
41936 : RootIdx - offset of partial kd-tree
41937 : InvR2 - 1/R^2, where R is basis function radius
41938 : RQuery2 - squared query radius, usually it is (R*FarRadius(BasisFunction)+0.5*RowWidth)^2,
41939 : where RowWidth is its spatial extent (after scaling of
41940 : variables). This radius is used to perform initial query
41941 : for neighbors of CX.
41942 : RFar2 - squared far radius; far radius is used to perform actual
41943 : filtering of results of query made with RQuery2.
41944 : CX - central point, array[NX], used for queries
41945 : RX - x0 coordinates, array[RowSize]
41946 : RF - sparsity flags, array[RowSize]
41947 : RowSize - row size in elements
41948 : RY - input partial value, array[NY]
41949 :
41950 : OUTPUT PARAMETERS
41951 : RY - updated partial value (function adds its results to RY)
41952 :
41953 : -- ALGLIB --
41954 : Copyright 20.06.2016 by Bochkanov Sergey
41955 : *************************************************************************/
41956 0 : static void rbfv2_partialrowcalcrec(rbfv2model* s,
41957 : rbfv2calcbuffer* buf,
41958 : ae_int_t rootidx,
41959 : double invr2,
41960 : double rquery2,
41961 : double rfar2,
41962 : /* Real */ ae_vector* cx,
41963 : /* Real */ ae_vector* rx,
41964 : /* Boolean */ ae_vector* rf,
41965 : ae_int_t rowsize,
41966 : /* Real */ ae_vector* ry,
41967 : ae_state *_state)
41968 : {
41969 : ae_int_t i;
41970 : ae_int_t j;
41971 : ae_int_t i0;
41972 : ae_int_t i1;
41973 : double partialptdist2;
41974 : double ptdist2;
41975 : double v;
41976 : double v0;
41977 : double v1;
41978 : ae_int_t cwoffs;
41979 : ae_int_t cwcnt;
41980 : ae_int_t itemoffs;
41981 : ae_int_t woffs;
41982 : double val;
41983 : ae_int_t d;
41984 : double split;
41985 : ae_int_t childle;
41986 : ae_int_t childge;
41987 : ae_int_t childoffs;
41988 : ae_bool updatemin;
41989 : double prevdist2;
41990 : double t1;
41991 : ae_int_t nx;
41992 : ae_int_t ny;
41993 :
41994 :
41995 0 : nx = s->nx;
41996 0 : ny = s->ny;
41997 :
41998 : /*
41999 : * Leaf node.
42000 : */
42001 0 : if( s->kdnodes.ptr.p_int[rootidx]>0 )
42002 : {
42003 0 : cwcnt = s->kdnodes.ptr.p_int[rootidx+0];
42004 0 : cwoffs = s->kdnodes.ptr.p_int[rootidx+1];
42005 0 : for(i0=0; i0<=cwcnt-1; i0++)
42006 : {
42007 :
42008 : /*
42009 : * Calculate partial distance (components from 1 to NX-1)
42010 : */
42011 0 : itemoffs = cwoffs+i0*(nx+ny);
42012 0 : partialptdist2 = (double)(0);
42013 0 : for(j=1; j<=nx-1; j++)
42014 : {
42015 0 : v = s->cw.ptr.p_double[itemoffs+j]-cx->ptr.p_double[j];
42016 0 : partialptdist2 = partialptdist2+v*v;
42017 : }
42018 :
42019 : /*
42020 : * Process each element of the row
42021 : */
42022 0 : for(i1=0; i1<=rowsize-1; i1++)
42023 : {
42024 0 : if( rf->ptr.p_bool[i1] )
42025 : {
42026 :
42027 : /*
42028 : * Calculate distance
42029 : */
42030 0 : v = s->cw.ptr.p_double[itemoffs]-rx->ptr.p_double[i1];
42031 0 : ptdist2 = partialptdist2+v*v;
42032 :
42033 : /*
42034 : * Skip points if distance too large
42035 : */
42036 0 : if( ptdist2>=rfar2 )
42037 : {
42038 0 : continue;
42039 : }
42040 :
42041 : /*
42042 : * Update Y
42043 : */
42044 0 : val = rbfv2basisfunc(s->bf, ptdist2*invr2, _state);
42045 0 : woffs = itemoffs+nx;
42046 0 : for(j=0; j<=ny-1; j++)
42047 : {
42048 0 : ry->ptr.p_double[j+i1*ny] = ry->ptr.p_double[j+i1*ny]+val*s->cw.ptr.p_double[woffs+j];
42049 : }
42050 : }
42051 : }
42052 : }
42053 0 : return;
42054 : }
42055 :
42056 : /*
42057 : * Simple split
42058 : */
42059 0 : if( s->kdnodes.ptr.p_int[rootidx]==0 )
42060 : {
42061 :
42062 : /*
42063 : * Load:
42064 : * * D dimension to split
42065 : * * Split split position
42066 : * * ChildLE, ChildGE - indexes of childs
42067 : */
42068 0 : d = s->kdnodes.ptr.p_int[rootidx+1];
42069 0 : split = s->kdsplits.ptr.p_double[s->kdnodes.ptr.p_int[rootidx+2]];
42070 0 : childle = s->kdnodes.ptr.p_int[rootidx+3];
42071 0 : childge = s->kdnodes.ptr.p_int[rootidx+4];
42072 :
42073 : /*
42074 : * Navigate through childs
42075 : */
42076 0 : for(i=0; i<=1; i++)
42077 : {
42078 :
42079 : /*
42080 : * Select child to process:
42081 : * * ChildOffs current child offset in Nodes[]
42082 : * * UpdateMin whether minimum or maximum value
42083 : * of bounding box is changed on update
42084 : */
42085 0 : updatemin = i!=0;
42086 0 : if( i==0 )
42087 : {
42088 0 : childoffs = childle;
42089 : }
42090 : else
42091 : {
42092 0 : childoffs = childge;
42093 : }
42094 :
42095 : /*
42096 : * Update bounding box and current distance
42097 : */
42098 0 : prevdist2 = buf->curdist2;
42099 0 : t1 = cx->ptr.p_double[d];
42100 0 : if( updatemin )
42101 : {
42102 0 : v = buf->curboxmin.ptr.p_double[d];
42103 0 : if( t1<=split )
42104 : {
42105 0 : v0 = v-t1;
42106 0 : if( v0<0 )
42107 : {
42108 0 : v0 = (double)(0);
42109 : }
42110 0 : v1 = split-t1;
42111 0 : buf->curdist2 = buf->curdist2-v0*v0+v1*v1;
42112 : }
42113 0 : buf->curboxmin.ptr.p_double[d] = split;
42114 : }
42115 : else
42116 : {
42117 0 : v = buf->curboxmax.ptr.p_double[d];
42118 0 : if( t1>=split )
42119 : {
42120 0 : v0 = t1-v;
42121 0 : if( v0<0 )
42122 : {
42123 0 : v0 = (double)(0);
42124 : }
42125 0 : v1 = t1-split;
42126 0 : buf->curdist2 = buf->curdist2-v0*v0+v1*v1;
42127 : }
42128 0 : buf->curboxmax.ptr.p_double[d] = split;
42129 : }
42130 :
42131 : /*
42132 : * Decide: to dive into cell or not to dive
42133 : */
42134 0 : if( buf->curdist2<rquery2 )
42135 : {
42136 0 : rbfv2_partialrowcalcrec(s, buf, childoffs, invr2, rquery2, rfar2, cx, rx, rf, rowsize, ry, _state);
42137 : }
42138 :
42139 : /*
42140 : * Restore bounding box and distance
42141 : */
42142 0 : if( updatemin )
42143 : {
42144 0 : buf->curboxmin.ptr.p_double[d] = v;
42145 : }
42146 : else
42147 : {
42148 0 : buf->curboxmax.ptr.p_double[d] = v;
42149 : }
42150 0 : buf->curdist2 = prevdist2;
42151 : }
42152 0 : return;
42153 : }
42154 :
42155 : /*
42156 : * Integrity failure
42157 : */
42158 0 : ae_assert(ae_false, "PartialCalcRec: integrity check failed", _state);
42159 : }
42160 :
42161 :
42162 : /*************************************************************************
42163 : This function prepares partial query
42164 :
42165 : INPUT PARAMETERS:
42166 : X - query point
42167 : kdBoxMin, kdBoxMax - current bounding box
42168 : NX - problem size
42169 : Buf - preallocated buffer; this function just loads data, but
42170 : does not allocate place for them.
42171 : Cnt - counter variable which is set to zery by this function, as
42172 : convenience, and to remember about necessity to zero counter
42173 : prior to calling partialqueryrec().
42174 :
42175 : OUTPUT PARAMETERS
42176 : Buf - calc-buffer:
42177 : * Buf.CurBoxMin - current box
42178 : * Buf.CurBoxMax - current box
42179 : * Buf.CurDist2 - squared distance from X to current box
42180 : Cnt - set to zero
42181 :
42182 : -- ALGLIB --
42183 : Copyright 20.06.2016 by Bochkanov Sergey
42184 : *************************************************************************/
42185 0 : static void rbfv2_preparepartialquery(/* Real */ ae_vector* x,
42186 : /* Real */ ae_vector* kdboxmin,
42187 : /* Real */ ae_vector* kdboxmax,
42188 : ae_int_t nx,
42189 : rbfv2calcbuffer* buf,
42190 : ae_int_t* cnt,
42191 : ae_state *_state)
42192 : {
42193 : ae_int_t j;
42194 :
42195 :
42196 0 : *cnt = 0;
42197 0 : buf->curdist2 = (double)(0);
42198 0 : for(j=0; j<=nx-1; j++)
42199 : {
42200 0 : buf->curboxmin.ptr.p_double[j] = kdboxmin->ptr.p_double[j];
42201 0 : buf->curboxmax.ptr.p_double[j] = kdboxmax->ptr.p_double[j];
42202 0 : if( ae_fp_less(x->ptr.p_double[j],buf->curboxmin.ptr.p_double[j]) )
42203 : {
42204 0 : buf->curdist2 = buf->curdist2+ae_sqr(buf->curboxmin.ptr.p_double[j]-x->ptr.p_double[j], _state);
42205 : }
42206 : else
42207 : {
42208 0 : if( ae_fp_greater(x->ptr.p_double[j],buf->curboxmax.ptr.p_double[j]) )
42209 : {
42210 0 : buf->curdist2 = buf->curdist2+ae_sqr(x->ptr.p_double[j]-buf->curboxmax.ptr.p_double[j], _state);
42211 : }
42212 : }
42213 : }
42214 0 : }
42215 :
42216 :
42217 : /*************************************************************************
42218 : This function performs partial (for just one subtree of multi-tree) query
42219 : for neighbors located in R-sphere around X. It returns squared distances
42220 : from X to points and offsets in S.CW[] array for points being found.
42221 :
42222 : INPUT PARAMETERS:
42223 : kdNodes, kdSplits, CW, NX, NY - corresponding fields of V2 model
42224 : Buf - calc-buffer, this function uses following fields:
42225 : * Buf.CurBoxMin - should be set by caller
42226 : * Buf.CurBoxMax - should be set by caller
42227 : * Buf.CurDist2 - squared distance from X to current
42228 : bounding box, should be set by caller
42229 : You may use preparepartialquery() function to initialize
42230 : these fields.
42231 : RootIdx - offset of partial kd-tree
42232 : QueryR2 - squared query radius
42233 : X - array[NX], point being queried
42234 : R2 - preallocated output buffer; it is caller's responsibility
42235 : to make sure that R2 has enough space.
42236 : Offs - preallocated output buffer; it is caller's responsibility
42237 : to make sure that Offs has enough space.
42238 : K - MUST BE ZERO ON INITIAL CALL. This variable is incremented,
42239 : not set. So, any no-zero value will result in the incorrect
42240 : points count being returned.
42241 :
42242 : OUTPUT PARAMETERS
42243 : R2 - squared distances in first K elements
42244 : Offs - offsets in S.CW in first K elements
42245 : K - points count
42246 :
42247 : -- ALGLIB --
42248 : Copyright 20.06.2016 by Bochkanov Sergey
42249 : *************************************************************************/
42250 0 : static void rbfv2_partialqueryrec(/* Integer */ ae_vector* kdnodes,
42251 : /* Real */ ae_vector* kdsplits,
42252 : /* Real */ ae_vector* cw,
42253 : ae_int_t nx,
42254 : ae_int_t ny,
42255 : rbfv2calcbuffer* buf,
42256 : ae_int_t rootidx,
42257 : double queryr2,
42258 : /* Real */ ae_vector* x,
42259 : /* Real */ ae_vector* r2,
42260 : /* Integer */ ae_vector* offs,
42261 : ae_int_t* k,
42262 : ae_state *_state)
42263 : {
42264 : ae_int_t i;
42265 : ae_int_t j;
42266 : double ptdist2;
42267 : double v;
42268 : ae_int_t cwoffs;
42269 : ae_int_t cwcnt;
42270 : ae_int_t itemoffs;
42271 : ae_int_t d;
42272 : double split;
42273 : ae_int_t childle;
42274 : ae_int_t childge;
42275 : ae_int_t childoffs;
42276 : ae_bool updatemin;
42277 : double prevdist2;
42278 : double t1;
42279 :
42280 :
42281 :
42282 : /*
42283 : * Leaf node.
42284 : */
42285 0 : if( kdnodes->ptr.p_int[rootidx]>0 )
42286 : {
42287 0 : cwcnt = kdnodes->ptr.p_int[rootidx+0];
42288 0 : cwoffs = kdnodes->ptr.p_int[rootidx+1];
42289 0 : for(i=0; i<=cwcnt-1; i++)
42290 : {
42291 :
42292 : /*
42293 : * Calculate distance
42294 : */
42295 0 : itemoffs = cwoffs+i*(nx+ny);
42296 0 : ptdist2 = (double)(0);
42297 0 : for(j=0; j<=nx-1; j++)
42298 : {
42299 0 : v = cw->ptr.p_double[itemoffs+j]-x->ptr.p_double[j];
42300 0 : ptdist2 = ptdist2+v*v;
42301 : }
42302 :
42303 : /*
42304 : * Skip points if distance too large
42305 : */
42306 0 : if( ae_fp_greater_eq(ptdist2,queryr2) )
42307 : {
42308 0 : continue;
42309 : }
42310 :
42311 : /*
42312 : * Output
42313 : */
42314 0 : r2->ptr.p_double[*k] = ptdist2;
42315 0 : offs->ptr.p_int[*k] = itemoffs;
42316 0 : *k = *k+1;
42317 : }
42318 0 : return;
42319 : }
42320 :
42321 : /*
42322 : * Simple split
42323 : */
42324 0 : if( kdnodes->ptr.p_int[rootidx]==0 )
42325 : {
42326 :
42327 : /*
42328 : * Load:
42329 : * * D dimension to split
42330 : * * Split split position
42331 : * * ChildLE, ChildGE - indexes of childs
42332 : */
42333 0 : d = kdnodes->ptr.p_int[rootidx+1];
42334 0 : split = kdsplits->ptr.p_double[kdnodes->ptr.p_int[rootidx+2]];
42335 0 : childle = kdnodes->ptr.p_int[rootidx+3];
42336 0 : childge = kdnodes->ptr.p_int[rootidx+4];
42337 :
42338 : /*
42339 : * Navigate through childs
42340 : */
42341 0 : for(i=0; i<=1; i++)
42342 : {
42343 :
42344 : /*
42345 : * Select child to process:
42346 : * * ChildOffs current child offset in Nodes[]
42347 : * * UpdateMin whether minimum or maximum value
42348 : * of bounding box is changed on update
42349 : */
42350 0 : updatemin = i!=0;
42351 0 : if( i==0 )
42352 : {
42353 0 : childoffs = childle;
42354 : }
42355 : else
42356 : {
42357 0 : childoffs = childge;
42358 : }
42359 :
42360 : /*
42361 : * Update bounding box and current distance
42362 : */
42363 0 : prevdist2 = buf->curdist2;
42364 0 : t1 = x->ptr.p_double[d];
42365 0 : if( updatemin )
42366 : {
42367 0 : v = buf->curboxmin.ptr.p_double[d];
42368 0 : if( ae_fp_less_eq(t1,split) )
42369 : {
42370 0 : buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(v-t1, (double)(0), _state), _state)+ae_sqr(split-t1, _state);
42371 : }
42372 0 : buf->curboxmin.ptr.p_double[d] = split;
42373 : }
42374 : else
42375 : {
42376 0 : v = buf->curboxmax.ptr.p_double[d];
42377 0 : if( ae_fp_greater_eq(t1,split) )
42378 : {
42379 0 : buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(t1-v, (double)(0), _state), _state)+ae_sqr(t1-split, _state);
42380 : }
42381 0 : buf->curboxmax.ptr.p_double[d] = split;
42382 : }
42383 :
42384 : /*
42385 : * Decide: to dive into cell or not to dive
42386 : */
42387 0 : if( ae_fp_less(buf->curdist2,queryr2) )
42388 : {
42389 0 : rbfv2_partialqueryrec(kdnodes, kdsplits, cw, nx, ny, buf, childoffs, queryr2, x, r2, offs, k, _state);
42390 : }
42391 :
42392 : /*
42393 : * Restore bounding box and distance
42394 : */
42395 0 : if( updatemin )
42396 : {
42397 0 : buf->curboxmin.ptr.p_double[d] = v;
42398 : }
42399 : else
42400 : {
42401 0 : buf->curboxmax.ptr.p_double[d] = v;
42402 : }
42403 0 : buf->curdist2 = prevdist2;
42404 : }
42405 0 : return;
42406 : }
42407 :
42408 : /*
42409 : * Integrity failure
42410 : */
42411 0 : ae_assert(ae_false, "PartialQueryRec: integrity check failed", _state);
42412 : }
42413 :
42414 :
42415 : /*************************************************************************
42416 : This function performs partial (for just one subtree of multi-tree)
42417 : counting of neighbors located in R-sphere around X.
42418 :
42419 : This function does not guarantee consistency of results with other partial
42420 : queries, it should be used only to get approximate estimates (well, we do
42421 : not use approximate algorithms, but rounding errors may give us
42422 : inconsistent results in just-at-the-boundary cases).
42423 :
42424 : INPUT PARAMETERS:
42425 : kdNodes, kdSplits, CW, NX, NY - corresponding fields of V2 model
42426 : Buf - calc-buffer, this function uses following fields:
42427 : * Buf.CurBoxMin - should be set by caller
42428 : * Buf.CurBoxMax - should be set by caller
42429 : * Buf.CurDist2 - squared distance from X to current
42430 : bounding box, should be set by caller
42431 : You may use preparepartialquery() function to initialize
42432 : these fields.
42433 : RootIdx - offset of partial kd-tree
42434 : QueryR2 - squared query radius
42435 : X - array[NX], point being queried
42436 :
42437 : RESULT:
42438 : points count
42439 :
42440 : -- ALGLIB --
42441 : Copyright 20.06.2016 by Bochkanov Sergey
42442 : *************************************************************************/
42443 0 : static ae_int_t rbfv2_partialcountrec(/* Integer */ ae_vector* kdnodes,
42444 : /* Real */ ae_vector* kdsplits,
42445 : /* Real */ ae_vector* cw,
42446 : ae_int_t nx,
42447 : ae_int_t ny,
42448 : rbfv2calcbuffer* buf,
42449 : ae_int_t rootidx,
42450 : double queryr2,
42451 : /* Real */ ae_vector* x,
42452 : ae_state *_state)
42453 : {
42454 : ae_int_t i;
42455 : ae_int_t j;
42456 : double ptdist2;
42457 : double v;
42458 : ae_int_t cwoffs;
42459 : ae_int_t cwcnt;
42460 : ae_int_t itemoffs;
42461 : ae_int_t d;
42462 : double split;
42463 : ae_int_t childle;
42464 : ae_int_t childge;
42465 : ae_int_t childoffs;
42466 : ae_bool updatemin;
42467 : double prevdist2;
42468 : double t1;
42469 : ae_int_t result;
42470 :
42471 :
42472 0 : result = 0;
42473 :
42474 : /*
42475 : * Leaf node.
42476 : */
42477 0 : if( kdnodes->ptr.p_int[rootidx]>0 )
42478 : {
42479 0 : cwcnt = kdnodes->ptr.p_int[rootidx+0];
42480 0 : cwoffs = kdnodes->ptr.p_int[rootidx+1];
42481 0 : for(i=0; i<=cwcnt-1; i++)
42482 : {
42483 :
42484 : /*
42485 : * Calculate distance
42486 : */
42487 0 : itemoffs = cwoffs+i*(nx+ny);
42488 0 : ptdist2 = (double)(0);
42489 0 : for(j=0; j<=nx-1; j++)
42490 : {
42491 0 : v = cw->ptr.p_double[itemoffs+j]-x->ptr.p_double[j];
42492 0 : ptdist2 = ptdist2+v*v;
42493 : }
42494 :
42495 : /*
42496 : * Skip points if distance too large
42497 : */
42498 0 : if( ae_fp_greater_eq(ptdist2,queryr2) )
42499 : {
42500 0 : continue;
42501 : }
42502 :
42503 : /*
42504 : * Output
42505 : */
42506 0 : result = result+1;
42507 : }
42508 0 : return result;
42509 : }
42510 :
42511 : /*
42512 : * Simple split
42513 : */
42514 0 : if( kdnodes->ptr.p_int[rootidx]==0 )
42515 : {
42516 :
42517 : /*
42518 : * Load:
42519 : * * D dimension to split
42520 : * * Split split position
42521 : * * ChildLE, ChildGE - indexes of childs
42522 : */
42523 0 : d = kdnodes->ptr.p_int[rootidx+1];
42524 0 : split = kdsplits->ptr.p_double[kdnodes->ptr.p_int[rootidx+2]];
42525 0 : childle = kdnodes->ptr.p_int[rootidx+3];
42526 0 : childge = kdnodes->ptr.p_int[rootidx+4];
42527 :
42528 : /*
42529 : * Navigate through childs
42530 : */
42531 0 : for(i=0; i<=1; i++)
42532 : {
42533 :
42534 : /*
42535 : * Select child to process:
42536 : * * ChildOffs current child offset in Nodes[]
42537 : * * UpdateMin whether minimum or maximum value
42538 : * of bounding box is changed on update
42539 : */
42540 0 : updatemin = i!=0;
42541 0 : if( i==0 )
42542 : {
42543 0 : childoffs = childle;
42544 : }
42545 : else
42546 : {
42547 0 : childoffs = childge;
42548 : }
42549 :
42550 : /*
42551 : * Update bounding box and current distance
42552 : */
42553 0 : prevdist2 = buf->curdist2;
42554 0 : t1 = x->ptr.p_double[d];
42555 0 : if( updatemin )
42556 : {
42557 0 : v = buf->curboxmin.ptr.p_double[d];
42558 0 : if( ae_fp_less_eq(t1,split) )
42559 : {
42560 0 : buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(v-t1, (double)(0), _state), _state)+ae_sqr(split-t1, _state);
42561 : }
42562 0 : buf->curboxmin.ptr.p_double[d] = split;
42563 : }
42564 : else
42565 : {
42566 0 : v = buf->curboxmax.ptr.p_double[d];
42567 0 : if( ae_fp_greater_eq(t1,split) )
42568 : {
42569 0 : buf->curdist2 = buf->curdist2-ae_sqr(ae_maxreal(t1-v, (double)(0), _state), _state)+ae_sqr(t1-split, _state);
42570 : }
42571 0 : buf->curboxmax.ptr.p_double[d] = split;
42572 : }
42573 :
42574 : /*
42575 : * Decide: to dive into cell or not to dive
42576 : */
42577 0 : if( ae_fp_less(buf->curdist2,queryr2) )
42578 : {
42579 0 : result = result+rbfv2_partialcountrec(kdnodes, kdsplits, cw, nx, ny, buf, childoffs, queryr2, x, _state);
42580 : }
42581 :
42582 : /*
42583 : * Restore bounding box and distance
42584 : */
42585 0 : if( updatemin )
42586 : {
42587 0 : buf->curboxmin.ptr.p_double[d] = v;
42588 : }
42589 : else
42590 : {
42591 0 : buf->curboxmax.ptr.p_double[d] = v;
42592 : }
42593 0 : buf->curdist2 = prevdist2;
42594 : }
42595 0 : return result;
42596 : }
42597 :
42598 : /*
42599 : * Integrity failure
42600 : */
42601 0 : ae_assert(ae_false, "PartialCountRec: integrity check failed", _state);
42602 0 : return result;
42603 : }
42604 :
42605 :
42606 : /*************************************************************************
42607 : This function performs partial (for just one subtree of multi-tree) unpack
42608 : for RBF model. It appends center coordinates, weights and per-dimension
42609 : radii (according to current scaling) to preallocated output array.
42610 :
42611 : INPUT PARAMETERS:
42612 : kdNodes, kdSplits, CW, S, NX, NY - corresponding fields of V2 model
42613 : RootIdx - offset of partial kd-tree
42614 : R - radius for current partial tree
42615 : XWR - preallocated output buffer; it is caller's responsibility
42616 : to make sure that XWR has enough space. First K rows are
42617 : already occupied.
42618 : K - number of already occupied rows in XWR.
42619 :
42620 : OUTPUT PARAMETERS
42621 : XWR - updated XWR
42622 : K - updated rows count
42623 :
42624 : -- ALGLIB --
42625 : Copyright 20.06.2016 by Bochkanov Sergey
42626 : *************************************************************************/
42627 0 : static void rbfv2_partialunpackrec(/* Integer */ ae_vector* kdnodes,
42628 : /* Real */ ae_vector* kdsplits,
42629 : /* Real */ ae_vector* cw,
42630 : /* Real */ ae_vector* s,
42631 : ae_int_t nx,
42632 : ae_int_t ny,
42633 : ae_int_t rootidx,
42634 : double r,
42635 : /* Real */ ae_matrix* xwr,
42636 : ae_int_t* k,
42637 : ae_state *_state)
42638 : {
42639 : ae_int_t i;
42640 : ae_int_t j;
42641 : ae_int_t childle;
42642 : ae_int_t childge;
42643 : ae_int_t itemoffs;
42644 : ae_int_t cwoffs;
42645 : ae_int_t cwcnt;
42646 :
42647 :
42648 :
42649 : /*
42650 : * Leaf node.
42651 : */
42652 0 : if( kdnodes->ptr.p_int[rootidx]>0 )
42653 : {
42654 0 : cwcnt = kdnodes->ptr.p_int[rootidx+0];
42655 0 : cwoffs = kdnodes->ptr.p_int[rootidx+1];
42656 0 : for(i=0; i<=cwcnt-1; i++)
42657 : {
42658 0 : itemoffs = cwoffs+i*(nx+ny);
42659 0 : for(j=0; j<=nx+ny-1; j++)
42660 : {
42661 0 : xwr->ptr.pp_double[*k][j] = cw->ptr.p_double[itemoffs+j];
42662 : }
42663 0 : for(j=0; j<=nx-1; j++)
42664 : {
42665 0 : xwr->ptr.pp_double[*k][j] = xwr->ptr.pp_double[*k][j]*s->ptr.p_double[j];
42666 : }
42667 0 : for(j=0; j<=nx-1; j++)
42668 : {
42669 0 : xwr->ptr.pp_double[*k][nx+ny+j] = r*s->ptr.p_double[j];
42670 : }
42671 0 : *k = *k+1;
42672 : }
42673 0 : return;
42674 : }
42675 :
42676 : /*
42677 : * Simple split
42678 : */
42679 0 : if( kdnodes->ptr.p_int[rootidx]==0 )
42680 : {
42681 :
42682 : /*
42683 : * Load:
42684 : * * ChildLE, ChildGE - indexes of childs
42685 : */
42686 0 : childle = kdnodes->ptr.p_int[rootidx+3];
42687 0 : childge = kdnodes->ptr.p_int[rootidx+4];
42688 :
42689 : /*
42690 : * Process both parts of split
42691 : */
42692 0 : rbfv2_partialunpackrec(kdnodes, kdsplits, cw, s, nx, ny, childle, r, xwr, k, _state);
42693 0 : rbfv2_partialunpackrec(kdnodes, kdsplits, cw, s, nx, ny, childge, r, xwr, k, _state);
42694 0 : return;
42695 : }
42696 :
42697 : /*
42698 : * Integrity failure
42699 : */
42700 0 : ae_assert(ae_false, "PartialUnpackRec: integrity check failed", _state);
42701 : }
42702 :
42703 :
42704 : /*************************************************************************
42705 : This function returns size of design matrix row for evaluation point X0,
42706 : given:
42707 : * query radius multiplier (either RBFV2NearRadius() or RBFV2FarRadius())
42708 : * hierarchy level: value in [0,NH) for single-level model, or negative
42709 : value for multilevel model (all levels of hierarchy in single matrix,
42710 : like one used by nonnegative RBF)
42711 :
42712 : INPUT PARAMETERS:
42713 : kdNodes, kdSplits, CW, Ri, kdRoots, kdBoxMin, kdBoxMax, NX, NY, NH - corresponding fields of V2 model
42714 : Level - value in [0,NH) for single-level design matrix, negative
42715 : value for multilevel design matrix
42716 : RCoeff - radius coefficient, either RBFV2NearRadius() or RBFV2FarRadius()
42717 : X0 - query point
42718 : CalcBuf - buffer for PreparePartialQuery(), allocated by caller
42719 :
42720 : RESULT:
42721 : row size
42722 :
42723 : -- ALGLIB --
42724 : Copyright 28.09.2016 by Bochkanov Sergey
42725 : *************************************************************************/
42726 0 : static ae_int_t rbfv2_designmatrixrowsize(/* Integer */ ae_vector* kdnodes,
42727 : /* Real */ ae_vector* kdsplits,
42728 : /* Real */ ae_vector* cw,
42729 : /* Real */ ae_vector* ri,
42730 : /* Integer */ ae_vector* kdroots,
42731 : /* Real */ ae_vector* kdboxmin,
42732 : /* Real */ ae_vector* kdboxmax,
42733 : ae_int_t nx,
42734 : ae_int_t ny,
42735 : ae_int_t nh,
42736 : ae_int_t level,
42737 : double rcoeff,
42738 : /* Real */ ae_vector* x0,
42739 : rbfv2calcbuffer* calcbuf,
42740 : ae_state *_state)
42741 : {
42742 : ae_int_t dummy;
42743 : ae_int_t levelidx;
42744 : ae_int_t level0;
42745 : ae_int_t level1;
42746 : double curradius2;
42747 : ae_int_t result;
42748 :
42749 :
42750 0 : ae_assert(nh>0, "DesignMatrixRowSize: integrity failure", _state);
42751 0 : if( level>=0 )
42752 : {
42753 0 : level0 = level;
42754 0 : level1 = level;
42755 : }
42756 : else
42757 : {
42758 0 : level0 = 0;
42759 0 : level1 = nh-1;
42760 : }
42761 0 : result = 0;
42762 0 : for(levelidx=level0; levelidx<=level1; levelidx++)
42763 : {
42764 0 : curradius2 = ae_sqr(ri->ptr.p_double[levelidx]*rcoeff, _state);
42765 0 : rbfv2_preparepartialquery(x0, kdboxmin, kdboxmax, nx, calcbuf, &dummy, _state);
42766 0 : result = result+rbfv2_partialcountrec(kdnodes, kdsplits, cw, nx, ny, calcbuf, kdroots->ptr.p_int[levelidx], curradius2, x0, _state);
42767 : }
42768 0 : return result;
42769 : }
42770 :
42771 :
42772 : /*************************************************************************
42773 : This function generates design matrix row for evaluation point X0, given:
42774 : * query radius multiplier (either RBFV2NearRadius() or RBFV2FarRadius())
42775 : * hierarchy level: value in [0,NH) for single-level model, or negative
42776 : value for multilevel model (all levels of hierarchy in single matrix,
42777 : like one used by nonnegative RBF)
42778 :
42779 : INPUT PARAMETERS:
42780 : kdNodes, kdSplits, CW, Ri, kdRoots, kdBoxMin, kdBoxMax, NX, NY, NH - corresponding fields of V2 model
42781 :
42782 : CWRange - internal array[NH+1] used by RBF construction function,
42783 : stores ranges of CW occupied by NH trees.
42784 : Level - value in [0,NH) for single-level design matrix, negative
42785 : value for multilevel design matrix
42786 : BF - basis function type
42787 : RCoeff - radius coefficient, either RBFV2NearRadius() or RBFV2FarRadius()
42788 : RowsPerPoint-equal to:
42789 : * 1 for unpenalized regression model
42790 : * 1+NX for basic form of nonsmoothness penalty
42791 : Penalty - nonsmoothness penalty coefficient
42792 :
42793 : X0 - query point
42794 :
42795 : CalcBuf - buffer for PreparePartialQuery(), allocated by caller
42796 : R2 - preallocated temporary buffer, size is at least NPoints;
42797 : it is caller's responsibility to make sure that R2 has enough space.
42798 : Offs - preallocated temporary buffer; size is at least NPoints;
42799 : it is caller's responsibility to make sure that Offs has enough space.
42800 : K - MUST BE ZERO ON INITIAL CALL. This variable is incremented,
42801 : not set. So, any no-zero value will result in the incorrect
42802 : points count being returned.
42803 : RowIdx - preallocated array, at least RowSize elements
42804 : RowVal - preallocated array, at least RowSize*RowsPerPoint elements
42805 :
42806 : RESULT:
42807 : RowIdx - RowSize elements are filled with column indexes of non-zero
42808 : design matrix entries
42809 : RowVal - RowSize*RowsPerPoint elements are filled with design matrix
42810 : values, with column RowIdx[0] being stored in first RowsPerPoint
42811 : elements of RowVal, column RowIdx[1] being stored in next
42812 : RowsPerPoint elements, and so on.
42813 :
42814 : First element in contiguous set of RowsPerPoint elements
42815 : corresponds to
42816 :
42817 : RowSize - number of columns per row
42818 :
42819 : -- ALGLIB --
42820 : Copyright 28.09.2016 by Bochkanov Sergey
42821 : *************************************************************************/
42822 0 : static void rbfv2_designmatrixgeneraterow(/* Integer */ ae_vector* kdnodes,
42823 : /* Real */ ae_vector* kdsplits,
42824 : /* Real */ ae_vector* cw,
42825 : /* Real */ ae_vector* ri,
42826 : /* Integer */ ae_vector* kdroots,
42827 : /* Real */ ae_vector* kdboxmin,
42828 : /* Real */ ae_vector* kdboxmax,
42829 : /* Integer */ ae_vector* cwrange,
42830 : ae_int_t nx,
42831 : ae_int_t ny,
42832 : ae_int_t nh,
42833 : ae_int_t level,
42834 : ae_int_t bf,
42835 : double rcoeff,
42836 : ae_int_t rowsperpoint,
42837 : double penalty,
42838 : /* Real */ ae_vector* x0,
42839 : rbfv2calcbuffer* calcbuf,
42840 : /* Real */ ae_vector* tmpr2,
42841 : /* Integer */ ae_vector* tmpoffs,
42842 : /* Integer */ ae_vector* rowidx,
42843 : /* Real */ ae_vector* rowval,
42844 : ae_int_t* rowsize,
42845 : ae_state *_state)
42846 : {
42847 : ae_int_t j;
42848 : ae_int_t k;
42849 : ae_int_t cnt;
42850 : ae_int_t levelidx;
42851 : ae_int_t level0;
42852 : ae_int_t level1;
42853 : double invri2;
42854 : double curradius2;
42855 : double val;
42856 : double dval;
42857 : double d2val;
42858 :
42859 0 : *rowsize = 0;
42860 :
42861 0 : ae_assert(nh>0, "DesignMatrixGenerateRow: integrity failure (a)", _state);
42862 0 : ae_assert(rowsperpoint==1||rowsperpoint==1+nx, "DesignMatrixGenerateRow: integrity failure (b)", _state);
42863 0 : if( level>=0 )
42864 : {
42865 0 : level0 = level;
42866 0 : level1 = level;
42867 : }
42868 : else
42869 : {
42870 0 : level0 = 0;
42871 0 : level1 = nh-1;
42872 : }
42873 0 : *rowsize = 0;
42874 0 : for(levelidx=level0; levelidx<=level1; levelidx++)
42875 : {
42876 0 : curradius2 = ae_sqr(ri->ptr.p_double[levelidx]*rcoeff, _state);
42877 0 : invri2 = 1/ae_sqr(ri->ptr.p_double[levelidx], _state);
42878 0 : rbfv2_preparepartialquery(x0, kdboxmin, kdboxmax, nx, calcbuf, &cnt, _state);
42879 0 : rbfv2_partialqueryrec(kdnodes, kdsplits, cw, nx, ny, calcbuf, kdroots->ptr.p_int[levelidx], curradius2, x0, tmpr2, tmpoffs, &cnt, _state);
42880 0 : ae_assert(tmpr2->cnt>=cnt, "DesignMatrixRowSize: integrity failure (c)", _state);
42881 0 : ae_assert(tmpoffs->cnt>=cnt, "DesignMatrixRowSize: integrity failure (d)", _state);
42882 0 : ae_assert(rowidx->cnt>=*rowsize+cnt, "DesignMatrixRowSize: integrity failure (e)", _state);
42883 0 : ae_assert(rowval->cnt>=rowsperpoint*(*rowsize+cnt), "DesignMatrixRowSize: integrity failure (f)", _state);
42884 0 : for(j=0; j<=cnt-1; j++)
42885 : {
42886 :
42887 : /*
42888 : * Generate element corresponding to fitting error.
42889 : * Store derivative information which may be required later.
42890 : */
42891 0 : ae_assert((tmpoffs->ptr.p_int[j]-cwrange->ptr.p_int[level0])%(nx+ny)==0, "DesignMatrixRowSize: integrity failure (g)", _state);
42892 0 : rbfv2basisfuncdiff2(bf, tmpr2->ptr.p_double[j]*invri2, &val, &dval, &d2val, _state);
42893 0 : rowidx->ptr.p_int[*rowsize+j] = (tmpoffs->ptr.p_int[j]-cwrange->ptr.p_int[level0])/(nx+ny);
42894 0 : rowval->ptr.p_double[(*rowsize+j)*rowsperpoint+0] = val;
42895 0 : if( rowsperpoint==1 )
42896 : {
42897 0 : continue;
42898 : }
42899 :
42900 : /*
42901 : * Generate elements corresponding to nonsmoothness penalty
42902 : */
42903 0 : ae_assert(rowsperpoint==1+nx, "DesignMatrixRowSize: integrity failure (h)", _state);
42904 0 : for(k=0; k<=nx-1; k++)
42905 : {
42906 0 : rowval->ptr.p_double[(*rowsize+j)*rowsperpoint+1+k] = penalty*(dval*2*invri2+d2val*ae_sqr(2*(x0->ptr.p_double[k]-cw->ptr.p_double[tmpoffs->ptr.p_int[j]+k])*invri2, _state));
42907 : }
42908 : }
42909 :
42910 : /*
42911 : * Update columns counter
42912 : */
42913 0 : *rowsize = *rowsize+cnt;
42914 : }
42915 0 : }
42916 :
42917 :
42918 : /*************************************************************************
42919 : This function fills RBF model by zeros.
42920 :
42921 : -- ALGLIB --
42922 : Copyright 17.11.2018 by Bochkanov Sergey
42923 : *************************************************************************/
42924 0 : static void rbfv2_zerofill(rbfv2model* s,
42925 : ae_int_t nx,
42926 : ae_int_t ny,
42927 : ae_int_t bf,
42928 : ae_state *_state)
42929 : {
42930 : ae_int_t i;
42931 : ae_int_t j;
42932 :
42933 :
42934 0 : s->bf = bf;
42935 0 : s->nh = 0;
42936 0 : ae_vector_set_length(&s->ri, 0, _state);
42937 0 : ae_vector_set_length(&s->s, 0, _state);
42938 0 : ae_vector_set_length(&s->kdroots, 0, _state);
42939 0 : ae_vector_set_length(&s->kdnodes, 0, _state);
42940 0 : ae_vector_set_length(&s->kdsplits, 0, _state);
42941 0 : ae_vector_set_length(&s->kdboxmin, 0, _state);
42942 0 : ae_vector_set_length(&s->kdboxmax, 0, _state);
42943 0 : ae_vector_set_length(&s->cw, 0, _state);
42944 0 : ae_matrix_set_length(&s->v, ny, nx+1, _state);
42945 0 : for(i=0; i<=ny-1; i++)
42946 : {
42947 0 : for(j=0; j<=nx; j++)
42948 : {
42949 0 : s->v.ptr.pp_double[i][j] = (double)(0);
42950 : }
42951 : }
42952 0 : }
42953 :
42954 :
42955 0 : void _rbfv2calcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic)
42956 : {
42957 0 : rbfv2calcbuffer *p = (rbfv2calcbuffer*)_p;
42958 0 : ae_touch_ptr((void*)p);
42959 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
42960 0 : ae_vector_init(&p->curboxmin, 0, DT_REAL, _state, make_automatic);
42961 0 : ae_vector_init(&p->curboxmax, 0, DT_REAL, _state, make_automatic);
42962 0 : ae_vector_init(&p->x123, 0, DT_REAL, _state, make_automatic);
42963 0 : ae_vector_init(&p->y123, 0, DT_REAL, _state, make_automatic);
42964 0 : }
42965 :
42966 :
42967 0 : void _rbfv2calcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
42968 : {
42969 0 : rbfv2calcbuffer *dst = (rbfv2calcbuffer*)_dst;
42970 0 : rbfv2calcbuffer *src = (rbfv2calcbuffer*)_src;
42971 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
42972 0 : ae_vector_init_copy(&dst->curboxmin, &src->curboxmin, _state, make_automatic);
42973 0 : ae_vector_init_copy(&dst->curboxmax, &src->curboxmax, _state, make_automatic);
42974 0 : dst->curdist2 = src->curdist2;
42975 0 : ae_vector_init_copy(&dst->x123, &src->x123, _state, make_automatic);
42976 0 : ae_vector_init_copy(&dst->y123, &src->y123, _state, make_automatic);
42977 0 : }
42978 :
42979 :
42980 0 : void _rbfv2calcbuffer_clear(void* _p)
42981 : {
42982 0 : rbfv2calcbuffer *p = (rbfv2calcbuffer*)_p;
42983 0 : ae_touch_ptr((void*)p);
42984 0 : ae_vector_clear(&p->x);
42985 0 : ae_vector_clear(&p->curboxmin);
42986 0 : ae_vector_clear(&p->curboxmax);
42987 0 : ae_vector_clear(&p->x123);
42988 0 : ae_vector_clear(&p->y123);
42989 0 : }
42990 :
42991 :
42992 0 : void _rbfv2calcbuffer_destroy(void* _p)
42993 : {
42994 0 : rbfv2calcbuffer *p = (rbfv2calcbuffer*)_p;
42995 0 : ae_touch_ptr((void*)p);
42996 0 : ae_vector_destroy(&p->x);
42997 0 : ae_vector_destroy(&p->curboxmin);
42998 0 : ae_vector_destroy(&p->curboxmax);
42999 0 : ae_vector_destroy(&p->x123);
43000 0 : ae_vector_destroy(&p->y123);
43001 0 : }
43002 :
43003 :
43004 0 : void _rbfv2model_init(void* _p, ae_state *_state, ae_bool make_automatic)
43005 : {
43006 0 : rbfv2model *p = (rbfv2model*)_p;
43007 0 : ae_touch_ptr((void*)p);
43008 0 : ae_vector_init(&p->ri, 0, DT_REAL, _state, make_automatic);
43009 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
43010 0 : ae_vector_init(&p->kdroots, 0, DT_INT, _state, make_automatic);
43011 0 : ae_vector_init(&p->kdnodes, 0, DT_INT, _state, make_automatic);
43012 0 : ae_vector_init(&p->kdsplits, 0, DT_REAL, _state, make_automatic);
43013 0 : ae_vector_init(&p->kdboxmin, 0, DT_REAL, _state, make_automatic);
43014 0 : ae_vector_init(&p->kdboxmax, 0, DT_REAL, _state, make_automatic);
43015 0 : ae_vector_init(&p->cw, 0, DT_REAL, _state, make_automatic);
43016 0 : ae_matrix_init(&p->v, 0, 0, DT_REAL, _state, make_automatic);
43017 0 : _rbfv2calcbuffer_init(&p->calcbuf, _state, make_automatic);
43018 0 : }
43019 :
43020 :
43021 0 : void _rbfv2model_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43022 : {
43023 0 : rbfv2model *dst = (rbfv2model*)_dst;
43024 0 : rbfv2model *src = (rbfv2model*)_src;
43025 0 : dst->ny = src->ny;
43026 0 : dst->nx = src->nx;
43027 0 : dst->bf = src->bf;
43028 0 : dst->nh = src->nh;
43029 0 : ae_vector_init_copy(&dst->ri, &src->ri, _state, make_automatic);
43030 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
43031 0 : ae_vector_init_copy(&dst->kdroots, &src->kdroots, _state, make_automatic);
43032 0 : ae_vector_init_copy(&dst->kdnodes, &src->kdnodes, _state, make_automatic);
43033 0 : ae_vector_init_copy(&dst->kdsplits, &src->kdsplits, _state, make_automatic);
43034 0 : ae_vector_init_copy(&dst->kdboxmin, &src->kdboxmin, _state, make_automatic);
43035 0 : ae_vector_init_copy(&dst->kdboxmax, &src->kdboxmax, _state, make_automatic);
43036 0 : ae_vector_init_copy(&dst->cw, &src->cw, _state, make_automatic);
43037 0 : ae_matrix_init_copy(&dst->v, &src->v, _state, make_automatic);
43038 0 : dst->lambdareg = src->lambdareg;
43039 0 : dst->maxits = src->maxits;
43040 0 : dst->supportr = src->supportr;
43041 0 : dst->basisfunction = src->basisfunction;
43042 0 : _rbfv2calcbuffer_init_copy(&dst->calcbuf, &src->calcbuf, _state, make_automatic);
43043 0 : }
43044 :
43045 :
43046 0 : void _rbfv2model_clear(void* _p)
43047 : {
43048 0 : rbfv2model *p = (rbfv2model*)_p;
43049 0 : ae_touch_ptr((void*)p);
43050 0 : ae_vector_clear(&p->ri);
43051 0 : ae_vector_clear(&p->s);
43052 0 : ae_vector_clear(&p->kdroots);
43053 0 : ae_vector_clear(&p->kdnodes);
43054 0 : ae_vector_clear(&p->kdsplits);
43055 0 : ae_vector_clear(&p->kdboxmin);
43056 0 : ae_vector_clear(&p->kdboxmax);
43057 0 : ae_vector_clear(&p->cw);
43058 0 : ae_matrix_clear(&p->v);
43059 0 : _rbfv2calcbuffer_clear(&p->calcbuf);
43060 0 : }
43061 :
43062 :
43063 0 : void _rbfv2model_destroy(void* _p)
43064 : {
43065 0 : rbfv2model *p = (rbfv2model*)_p;
43066 0 : ae_touch_ptr((void*)p);
43067 0 : ae_vector_destroy(&p->ri);
43068 0 : ae_vector_destroy(&p->s);
43069 0 : ae_vector_destroy(&p->kdroots);
43070 0 : ae_vector_destroy(&p->kdnodes);
43071 0 : ae_vector_destroy(&p->kdsplits);
43072 0 : ae_vector_destroy(&p->kdboxmin);
43073 0 : ae_vector_destroy(&p->kdboxmax);
43074 0 : ae_vector_destroy(&p->cw);
43075 0 : ae_matrix_destroy(&p->v);
43076 0 : _rbfv2calcbuffer_destroy(&p->calcbuf);
43077 0 : }
43078 :
43079 :
43080 0 : void _rbfv2gridcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic)
43081 : {
43082 0 : rbfv2gridcalcbuffer *p = (rbfv2gridcalcbuffer*)_p;
43083 0 : ae_touch_ptr((void*)p);
43084 0 : _rbfv2calcbuffer_init(&p->calcbuf, _state, make_automatic);
43085 0 : ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic);
43086 0 : ae_vector_init(&p->rx, 0, DT_REAL, _state, make_automatic);
43087 0 : ae_vector_init(&p->ry, 0, DT_REAL, _state, make_automatic);
43088 0 : ae_vector_init(&p->tx, 0, DT_REAL, _state, make_automatic);
43089 0 : ae_vector_init(&p->ty, 0, DT_REAL, _state, make_automatic);
43090 0 : ae_vector_init(&p->rf, 0, DT_BOOL, _state, make_automatic);
43091 0 : }
43092 :
43093 :
43094 0 : void _rbfv2gridcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43095 : {
43096 0 : rbfv2gridcalcbuffer *dst = (rbfv2gridcalcbuffer*)_dst;
43097 0 : rbfv2gridcalcbuffer *src = (rbfv2gridcalcbuffer*)_src;
43098 0 : _rbfv2calcbuffer_init_copy(&dst->calcbuf, &src->calcbuf, _state, make_automatic);
43099 0 : ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic);
43100 0 : ae_vector_init_copy(&dst->rx, &src->rx, _state, make_automatic);
43101 0 : ae_vector_init_copy(&dst->ry, &src->ry, _state, make_automatic);
43102 0 : ae_vector_init_copy(&dst->tx, &src->tx, _state, make_automatic);
43103 0 : ae_vector_init_copy(&dst->ty, &src->ty, _state, make_automatic);
43104 0 : ae_vector_init_copy(&dst->rf, &src->rf, _state, make_automatic);
43105 0 : }
43106 :
43107 :
43108 0 : void _rbfv2gridcalcbuffer_clear(void* _p)
43109 : {
43110 0 : rbfv2gridcalcbuffer *p = (rbfv2gridcalcbuffer*)_p;
43111 0 : ae_touch_ptr((void*)p);
43112 0 : _rbfv2calcbuffer_clear(&p->calcbuf);
43113 0 : ae_vector_clear(&p->cx);
43114 0 : ae_vector_clear(&p->rx);
43115 0 : ae_vector_clear(&p->ry);
43116 0 : ae_vector_clear(&p->tx);
43117 0 : ae_vector_clear(&p->ty);
43118 0 : ae_vector_clear(&p->rf);
43119 0 : }
43120 :
43121 :
43122 0 : void _rbfv2gridcalcbuffer_destroy(void* _p)
43123 : {
43124 0 : rbfv2gridcalcbuffer *p = (rbfv2gridcalcbuffer*)_p;
43125 0 : ae_touch_ptr((void*)p);
43126 0 : _rbfv2calcbuffer_destroy(&p->calcbuf);
43127 0 : ae_vector_destroy(&p->cx);
43128 0 : ae_vector_destroy(&p->rx);
43129 0 : ae_vector_destroy(&p->ry);
43130 0 : ae_vector_destroy(&p->tx);
43131 0 : ae_vector_destroy(&p->ty);
43132 0 : ae_vector_destroy(&p->rf);
43133 0 : }
43134 :
43135 :
43136 0 : void _rbfv2report_init(void* _p, ae_state *_state, ae_bool make_automatic)
43137 : {
43138 0 : rbfv2report *p = (rbfv2report*)_p;
43139 0 : ae_touch_ptr((void*)p);
43140 0 : }
43141 :
43142 :
43143 0 : void _rbfv2report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43144 : {
43145 0 : rbfv2report *dst = (rbfv2report*)_dst;
43146 0 : rbfv2report *src = (rbfv2report*)_src;
43147 0 : dst->terminationtype = src->terminationtype;
43148 0 : dst->maxerror = src->maxerror;
43149 0 : dst->rmserror = src->rmserror;
43150 0 : }
43151 :
43152 :
43153 0 : void _rbfv2report_clear(void* _p)
43154 : {
43155 0 : rbfv2report *p = (rbfv2report*)_p;
43156 0 : ae_touch_ptr((void*)p);
43157 0 : }
43158 :
43159 :
43160 0 : void _rbfv2report_destroy(void* _p)
43161 : {
43162 0 : rbfv2report *p = (rbfv2report*)_p;
43163 0 : ae_touch_ptr((void*)p);
43164 0 : }
43165 :
43166 :
43167 : #endif
43168 : #if defined(AE_COMPILE_SPLINE2D) || !defined(AE_PARTIAL_BUILD)
43169 :
43170 :
43171 : /*************************************************************************
43172 : This subroutine calculates the value of the bilinear or bicubic spline at
43173 : the given point X.
43174 :
43175 : Input parameters:
43176 : C - 2D spline object.
43177 : Built by spline2dbuildbilinearv or spline2dbuildbicubicv.
43178 : X, Y- point
43179 :
43180 : Result:
43181 : S(x,y)
43182 :
43183 : -- ALGLIB PROJECT --
43184 : Copyright 05.07.2007 by Bochkanov Sergey
43185 : *************************************************************************/
43186 0 : double spline2dcalc(spline2dinterpolant* c,
43187 : double x,
43188 : double y,
43189 : ae_state *_state)
43190 : {
43191 : ae_int_t ix;
43192 : ae_int_t iy;
43193 : ae_int_t l;
43194 : ae_int_t r;
43195 : ae_int_t h;
43196 : double t;
43197 : double dt;
43198 : double u;
43199 : double du;
43200 : double y1;
43201 : double y2;
43202 : double y3;
43203 : double y4;
43204 : ae_int_t s1;
43205 : ae_int_t s2;
43206 : ae_int_t s3;
43207 : ae_int_t s4;
43208 : ae_int_t sfx;
43209 : ae_int_t sfy;
43210 : ae_int_t sfxy;
43211 : double t2;
43212 : double t3;
43213 : double u2;
43214 : double u3;
43215 : double ht00;
43216 : double ht01;
43217 : double ht10;
43218 : double ht11;
43219 : double hu00;
43220 : double hu01;
43221 : double hu10;
43222 : double hu11;
43223 : double result;
43224 :
43225 :
43226 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalc: incorrect C (incorrect parameter C.SType)", _state);
43227 0 : ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalc: X or Y contains NaN or Infinite value", _state);
43228 0 : if( c->d!=1 )
43229 : {
43230 0 : result = (double)(0);
43231 0 : return result;
43232 : }
43233 :
43234 : /*
43235 : * Determine evaluation interval
43236 : */
43237 0 : l = 0;
43238 0 : r = c->n-1;
43239 0 : while(l!=r-1)
43240 : {
43241 0 : h = (l+r)/2;
43242 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
43243 : {
43244 0 : r = h;
43245 : }
43246 : else
43247 : {
43248 0 : l = h;
43249 : }
43250 : }
43251 0 : dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
43252 0 : t = (x-c->x.ptr.p_double[l])*dt;
43253 0 : ix = l;
43254 0 : l = 0;
43255 0 : r = c->m-1;
43256 0 : while(l!=r-1)
43257 : {
43258 0 : h = (l+r)/2;
43259 0 : if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
43260 : {
43261 0 : r = h;
43262 : }
43263 : else
43264 : {
43265 0 : l = h;
43266 : }
43267 : }
43268 0 : du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
43269 0 : u = (y-c->y.ptr.p_double[l])*du;
43270 0 : iy = l;
43271 :
43272 : /*
43273 : * Bilinear interpolation
43274 : */
43275 0 : if( c->stype==-1 )
43276 : {
43277 0 : y1 = c->f.ptr.p_double[c->n*iy+ix];
43278 0 : y2 = c->f.ptr.p_double[c->n*iy+(ix+1)];
43279 0 : y3 = c->f.ptr.p_double[c->n*(iy+1)+(ix+1)];
43280 0 : y4 = c->f.ptr.p_double[c->n*(iy+1)+ix];
43281 0 : result = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
43282 0 : return result;
43283 : }
43284 :
43285 : /*
43286 : * Bicubic interpolation:
43287 : * * calculate Hermite basis for dimensions X and Y (variables T and U),
43288 : * here HTij means basis function whose I-th derivative has value 1 at T=J.
43289 : * Same for HUij.
43290 : * * after initial calculation, apply scaling by DT/DU to the basis
43291 : * * calculate using stored table of second derivatives
43292 : */
43293 0 : ae_assert(c->stype==-3, "Spline2DCalc: integrity check failed", _state);
43294 0 : sfx = c->n*c->m;
43295 0 : sfy = 2*c->n*c->m;
43296 0 : sfxy = 3*c->n*c->m;
43297 0 : s1 = c->n*iy+ix;
43298 0 : s2 = c->n*iy+(ix+1);
43299 0 : s3 = c->n*(iy+1)+ix;
43300 0 : s4 = c->n*(iy+1)+(ix+1);
43301 0 : t2 = t*t;
43302 0 : t3 = t*t2;
43303 0 : u2 = u*u;
43304 0 : u3 = u*u2;
43305 0 : ht00 = 2*t3-3*t2+1;
43306 0 : ht10 = t3-2*t2+t;
43307 0 : ht01 = -2*t3+3*t2;
43308 0 : ht11 = t3-t2;
43309 0 : hu00 = 2*u3-3*u2+1;
43310 0 : hu10 = u3-2*u2+u;
43311 0 : hu01 = -2*u3+3*u2;
43312 0 : hu11 = u3-u2;
43313 0 : ht10 = ht10/dt;
43314 0 : ht11 = ht11/dt;
43315 0 : hu10 = hu10/du;
43316 0 : hu11 = hu11/du;
43317 0 : result = (double)(0);
43318 0 : result = result+c->f.ptr.p_double[s1]*ht00*hu00+c->f.ptr.p_double[s2]*ht01*hu00+c->f.ptr.p_double[s3]*ht00*hu01+c->f.ptr.p_double[s4]*ht01*hu01;
43319 0 : result = result+c->f.ptr.p_double[sfx+s1]*ht10*hu00+c->f.ptr.p_double[sfx+s2]*ht11*hu00+c->f.ptr.p_double[sfx+s3]*ht10*hu01+c->f.ptr.p_double[sfx+s4]*ht11*hu01;
43320 0 : result = result+c->f.ptr.p_double[sfy+s1]*ht00*hu10+c->f.ptr.p_double[sfy+s2]*ht01*hu10+c->f.ptr.p_double[sfy+s3]*ht00*hu11+c->f.ptr.p_double[sfy+s4]*ht01*hu11;
43321 0 : result = result+c->f.ptr.p_double[sfxy+s1]*ht10*hu10+c->f.ptr.p_double[sfxy+s2]*ht11*hu10+c->f.ptr.p_double[sfxy+s3]*ht10*hu11+c->f.ptr.p_double[sfxy+s4]*ht11*hu11;
43322 0 : return result;
43323 : }
43324 :
43325 :
43326 : /*************************************************************************
43327 : This subroutine calculates the value of the bilinear or bicubic spline at
43328 : the given point X and its derivatives.
43329 :
43330 : Input parameters:
43331 : C - spline interpolant.
43332 : X, Y- point
43333 :
43334 : Output parameters:
43335 : F - S(x,y)
43336 : FX - dS(x,y)/dX
43337 : FY - dS(x,y)/dY
43338 : FXY - d2S(x,y)/dXdY
43339 :
43340 : -- ALGLIB PROJECT --
43341 : Copyright 05.07.2007 by Bochkanov Sergey
43342 : *************************************************************************/
43343 0 : void spline2ddiff(spline2dinterpolant* c,
43344 : double x,
43345 : double y,
43346 : double* f,
43347 : double* fx,
43348 : double* fy,
43349 : double* fxy,
43350 : ae_state *_state)
43351 : {
43352 : double t;
43353 : double dt;
43354 : double u;
43355 : double du;
43356 : ae_int_t ix;
43357 : ae_int_t iy;
43358 : ae_int_t l;
43359 : ae_int_t r;
43360 : ae_int_t h;
43361 : ae_int_t s1;
43362 : ae_int_t s2;
43363 : ae_int_t s3;
43364 : ae_int_t s4;
43365 : ae_int_t sfx;
43366 : ae_int_t sfy;
43367 : ae_int_t sfxy;
43368 : double y1;
43369 : double y2;
43370 : double y3;
43371 : double y4;
43372 : double v0;
43373 : double v1;
43374 : double v2;
43375 : double v3;
43376 : double t2;
43377 : double t3;
43378 : double u2;
43379 : double u3;
43380 : double ht00;
43381 : double ht01;
43382 : double ht10;
43383 : double ht11;
43384 : double hu00;
43385 : double hu01;
43386 : double hu10;
43387 : double hu11;
43388 : double dht00;
43389 : double dht01;
43390 : double dht10;
43391 : double dht11;
43392 : double dhu00;
43393 : double dhu01;
43394 : double dhu10;
43395 : double dhu11;
43396 :
43397 0 : *f = 0;
43398 0 : *fx = 0;
43399 0 : *fy = 0;
43400 0 : *fxy = 0;
43401 :
43402 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline2DDiff: incorrect C (incorrect parameter C.SType)", _state);
43403 0 : ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DDiff: X or Y contains NaN or Infinite value", _state);
43404 :
43405 : /*
43406 : * Prepare F, dF/dX, dF/dY, d2F/dXdY
43407 : */
43408 0 : *f = (double)(0);
43409 0 : *fx = (double)(0);
43410 0 : *fy = (double)(0);
43411 0 : *fxy = (double)(0);
43412 0 : if( c->d!=1 )
43413 : {
43414 0 : return;
43415 : }
43416 :
43417 : /*
43418 : * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
43419 : */
43420 0 : l = 0;
43421 0 : r = c->n-1;
43422 0 : while(l!=r-1)
43423 : {
43424 0 : h = (l+r)/2;
43425 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
43426 : {
43427 0 : r = h;
43428 : }
43429 : else
43430 : {
43431 0 : l = h;
43432 : }
43433 : }
43434 0 : t = (x-c->x.ptr.p_double[l])/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
43435 0 : dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
43436 0 : ix = l;
43437 :
43438 : /*
43439 : * Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included)
43440 : */
43441 0 : l = 0;
43442 0 : r = c->m-1;
43443 0 : while(l!=r-1)
43444 : {
43445 0 : h = (l+r)/2;
43446 0 : if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
43447 : {
43448 0 : r = h;
43449 : }
43450 : else
43451 : {
43452 0 : l = h;
43453 : }
43454 : }
43455 0 : u = (y-c->y.ptr.p_double[l])/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
43456 0 : du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
43457 0 : iy = l;
43458 :
43459 : /*
43460 : * Bilinear interpolation
43461 : */
43462 0 : if( c->stype==-1 )
43463 : {
43464 0 : y1 = c->f.ptr.p_double[c->n*iy+ix];
43465 0 : y2 = c->f.ptr.p_double[c->n*iy+(ix+1)];
43466 0 : y3 = c->f.ptr.p_double[c->n*(iy+1)+(ix+1)];
43467 0 : y4 = c->f.ptr.p_double[c->n*(iy+1)+ix];
43468 0 : *f = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
43469 0 : *fx = (-(1-u)*y1+(1-u)*y2+u*y3-u*y4)*dt;
43470 0 : *fy = (-(1-t)*y1-t*y2+t*y3+(1-t)*y4)*du;
43471 0 : *fxy = (y1-y2+y3-y4)*du*dt;
43472 0 : return;
43473 : }
43474 :
43475 : /*
43476 : * Bicubic interpolation
43477 : */
43478 0 : if( c->stype==-3 )
43479 : {
43480 0 : sfx = c->n*c->m;
43481 0 : sfy = 2*c->n*c->m;
43482 0 : sfxy = 3*c->n*c->m;
43483 0 : s1 = c->n*iy+ix;
43484 0 : s2 = c->n*iy+(ix+1);
43485 0 : s3 = c->n*(iy+1)+ix;
43486 0 : s4 = c->n*(iy+1)+(ix+1);
43487 0 : t2 = t*t;
43488 0 : t3 = t*t2;
43489 0 : u2 = u*u;
43490 0 : u3 = u*u2;
43491 0 : ht00 = 2*t3-3*t2+1;
43492 0 : ht10 = t3-2*t2+t;
43493 0 : ht01 = -2*t3+3*t2;
43494 0 : ht11 = t3-t2;
43495 0 : hu00 = 2*u3-3*u2+1;
43496 0 : hu10 = u3-2*u2+u;
43497 0 : hu01 = -2*u3+3*u2;
43498 0 : hu11 = u3-u2;
43499 0 : ht10 = ht10/dt;
43500 0 : ht11 = ht11/dt;
43501 0 : hu10 = hu10/du;
43502 0 : hu11 = hu11/du;
43503 0 : dht00 = 6*t2-6*t;
43504 0 : dht10 = 3*t2-4*t+1;
43505 0 : dht01 = -6*t2+6*t;
43506 0 : dht11 = 3*t2-2*t;
43507 0 : dhu00 = 6*u2-6*u;
43508 0 : dhu10 = 3*u2-4*u+1;
43509 0 : dhu01 = -6*u2+6*u;
43510 0 : dhu11 = 3*u2-2*u;
43511 0 : dht00 = dht00*dt;
43512 0 : dht01 = dht01*dt;
43513 0 : dhu00 = dhu00*du;
43514 0 : dhu01 = dhu01*du;
43515 0 : *f = (double)(0);
43516 0 : *fx = (double)(0);
43517 0 : *fy = (double)(0);
43518 0 : *fxy = (double)(0);
43519 0 : v0 = c->f.ptr.p_double[s1];
43520 0 : v1 = c->f.ptr.p_double[s2];
43521 0 : v2 = c->f.ptr.p_double[s3];
43522 0 : v3 = c->f.ptr.p_double[s4];
43523 0 : *f = *f+v0*ht00*hu00+v1*ht01*hu00+v2*ht00*hu01+v3*ht01*hu01;
43524 0 : *fx = *fx+v0*dht00*hu00+v1*dht01*hu00+v2*dht00*hu01+v3*dht01*hu01;
43525 0 : *fy = *fy+v0*ht00*dhu00+v1*ht01*dhu00+v2*ht00*dhu01+v3*ht01*dhu01;
43526 0 : *fxy = *fxy+v0*dht00*dhu00+v1*dht01*dhu00+v2*dht00*dhu01+v3*dht01*dhu01;
43527 0 : v0 = c->f.ptr.p_double[sfx+s1];
43528 0 : v1 = c->f.ptr.p_double[sfx+s2];
43529 0 : v2 = c->f.ptr.p_double[sfx+s3];
43530 0 : v3 = c->f.ptr.p_double[sfx+s4];
43531 0 : *f = *f+v0*ht10*hu00+v1*ht11*hu00+v2*ht10*hu01+v3*ht11*hu01;
43532 0 : *fx = *fx+v0*dht10*hu00+v1*dht11*hu00+v2*dht10*hu01+v3*dht11*hu01;
43533 0 : *fy = *fy+v0*ht10*dhu00+v1*ht11*dhu00+v2*ht10*dhu01+v3*ht11*dhu01;
43534 0 : *fxy = *fxy+v0*dht10*dhu00+v1*dht11*dhu00+v2*dht10*dhu01+v3*dht11*dhu01;
43535 0 : v0 = c->f.ptr.p_double[sfy+s1];
43536 0 : v1 = c->f.ptr.p_double[sfy+s2];
43537 0 : v2 = c->f.ptr.p_double[sfy+s3];
43538 0 : v3 = c->f.ptr.p_double[sfy+s4];
43539 0 : *f = *f+v0*ht00*hu10+v1*ht01*hu10+v2*ht00*hu11+v3*ht01*hu11;
43540 0 : *fx = *fx+v0*dht00*hu10+v1*dht01*hu10+v2*dht00*hu11+v3*dht01*hu11;
43541 0 : *fy = *fy+v0*ht00*dhu10+v1*ht01*dhu10+v2*ht00*dhu11+v3*ht01*dhu11;
43542 0 : *fxy = *fxy+v0*dht00*dhu10+v1*dht01*dhu10+v2*dht00*dhu11+v3*dht01*dhu11;
43543 0 : v0 = c->f.ptr.p_double[sfxy+s1];
43544 0 : v1 = c->f.ptr.p_double[sfxy+s2];
43545 0 : v2 = c->f.ptr.p_double[sfxy+s3];
43546 0 : v3 = c->f.ptr.p_double[sfxy+s4];
43547 0 : *f = *f+v0*ht10*hu10+v1*ht11*hu10+v2*ht10*hu11+v3*ht11*hu11;
43548 0 : *fx = *fx+v0*dht10*hu10+v1*dht11*hu10+v2*dht10*hu11+v3*dht11*hu11;
43549 0 : *fy = *fy+v0*ht10*dhu10+v1*ht11*dhu10+v2*ht10*dhu11+v3*ht11*dhu11;
43550 0 : *fxy = *fxy+v0*dht10*dhu10+v1*dht11*dhu10+v2*dht10*dhu11+v3*dht11*dhu11;
43551 0 : return;
43552 : }
43553 : }
43554 :
43555 :
43556 : /*************************************************************************
43557 : This subroutine calculates bilinear or bicubic vector-valued spline at the
43558 : given point (X,Y).
43559 :
43560 : If you need just some specific component of vector-valued spline, you can
43561 : use spline2dcalcvi() function.
43562 :
43563 : INPUT PARAMETERS:
43564 : C - spline interpolant.
43565 : X, Y- point
43566 : F - output buffer, possibly preallocated array. In case array size
43567 : is large enough to store result, it is not reallocated. Array
43568 : which is too short will be reallocated
43569 :
43570 : OUTPUT PARAMETERS:
43571 : F - array[D] (or larger) which stores function values
43572 :
43573 : -- ALGLIB PROJECT --
43574 : Copyright 01.02.2018 by Bochkanov Sergey
43575 : *************************************************************************/
43576 0 : void spline2dcalcvbuf(spline2dinterpolant* c,
43577 : double x,
43578 : double y,
43579 : /* Real */ ae_vector* f,
43580 : ae_state *_state)
43581 : {
43582 : ae_int_t ix;
43583 : ae_int_t iy;
43584 : ae_int_t l;
43585 : ae_int_t r;
43586 : ae_int_t h;
43587 : ae_int_t i;
43588 : double t;
43589 : double dt;
43590 : double u;
43591 : double du;
43592 : double y1;
43593 : double y2;
43594 : double y3;
43595 : double y4;
43596 : ae_int_t s1;
43597 : ae_int_t s2;
43598 : ae_int_t s3;
43599 : ae_int_t s4;
43600 : ae_int_t sfx;
43601 : ae_int_t sfy;
43602 : ae_int_t sfxy;
43603 : double t2;
43604 : double t3;
43605 : double u2;
43606 : double u3;
43607 : double ht00;
43608 : double ht01;
43609 : double ht10;
43610 : double ht11;
43611 : double hu00;
43612 : double hu01;
43613 : double hu10;
43614 : double hu11;
43615 :
43616 :
43617 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcVBuf: incorrect C (incorrect parameter C.SType)", _state);
43618 0 : ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcVBuf: X or Y contains NaN or Infinite value", _state);
43619 :
43620 : /*
43621 : * Allocate place for output
43622 : */
43623 0 : rvectorsetlengthatleast(f, c->d, _state);
43624 :
43625 : /*
43626 : * Determine evaluation interval
43627 : */
43628 0 : l = 0;
43629 0 : r = c->n-1;
43630 0 : while(l!=r-1)
43631 : {
43632 0 : h = (l+r)/2;
43633 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
43634 : {
43635 0 : r = h;
43636 : }
43637 : else
43638 : {
43639 0 : l = h;
43640 : }
43641 : }
43642 0 : dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
43643 0 : t = (x-c->x.ptr.p_double[l])*dt;
43644 0 : ix = l;
43645 0 : l = 0;
43646 0 : r = c->m-1;
43647 0 : while(l!=r-1)
43648 : {
43649 0 : h = (l+r)/2;
43650 0 : if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
43651 : {
43652 0 : r = h;
43653 : }
43654 : else
43655 : {
43656 0 : l = h;
43657 : }
43658 : }
43659 0 : du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
43660 0 : u = (y-c->y.ptr.p_double[l])*du;
43661 0 : iy = l;
43662 :
43663 : /*
43664 : * Bilinear interpolation
43665 : */
43666 0 : if( c->stype==-1 )
43667 : {
43668 0 : for(i=0; i<=c->d-1; i++)
43669 : {
43670 0 : y1 = c->f.ptr.p_double[c->d*(c->n*iy+ix)+i];
43671 0 : y2 = c->f.ptr.p_double[c->d*(c->n*iy+(ix+1))+i];
43672 0 : y3 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+(ix+1))+i];
43673 0 : y4 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+ix)+i];
43674 0 : f->ptr.p_double[i] = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
43675 : }
43676 0 : return;
43677 : }
43678 :
43679 : /*
43680 : * Bicubic interpolation:
43681 : * * calculate Hermite basis for dimensions X and Y (variables T and U),
43682 : * here HTij means basis function whose I-th derivative has value 1 at T=J.
43683 : * Same for HUij.
43684 : * * after initial calculation, apply scaling by DT/DU to the basis
43685 : * * calculate using stored table of second derivatives
43686 : */
43687 0 : ae_assert(c->stype==-3, "Spline2DCalc: integrity check failed", _state);
43688 0 : sfx = c->n*c->m*c->d;
43689 0 : sfy = 2*c->n*c->m*c->d;
43690 0 : sfxy = 3*c->n*c->m*c->d;
43691 0 : s1 = (c->n*iy+ix)*c->d;
43692 0 : s2 = (c->n*iy+(ix+1))*c->d;
43693 0 : s3 = (c->n*(iy+1)+ix)*c->d;
43694 0 : s4 = (c->n*(iy+1)+(ix+1))*c->d;
43695 0 : t2 = t*t;
43696 0 : t3 = t*t2;
43697 0 : u2 = u*u;
43698 0 : u3 = u*u2;
43699 0 : ht00 = 2*t3-3*t2+1;
43700 0 : ht10 = t3-2*t2+t;
43701 0 : ht01 = -2*t3+3*t2;
43702 0 : ht11 = t3-t2;
43703 0 : hu00 = 2*u3-3*u2+1;
43704 0 : hu10 = u3-2*u2+u;
43705 0 : hu01 = -2*u3+3*u2;
43706 0 : hu11 = u3-u2;
43707 0 : ht10 = ht10/dt;
43708 0 : ht11 = ht11/dt;
43709 0 : hu10 = hu10/du;
43710 0 : hu11 = hu11/du;
43711 0 : for(i=0; i<=c->d-1; i++)
43712 : {
43713 :
43714 : /*
43715 : * Calculate I-th component
43716 : */
43717 0 : f->ptr.p_double[i] = (double)(0);
43718 0 : f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[s1]*ht00*hu00+c->f.ptr.p_double[s2]*ht01*hu00+c->f.ptr.p_double[s3]*ht00*hu01+c->f.ptr.p_double[s4]*ht01*hu01;
43719 0 : f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[sfx+s1]*ht10*hu00+c->f.ptr.p_double[sfx+s2]*ht11*hu00+c->f.ptr.p_double[sfx+s3]*ht10*hu01+c->f.ptr.p_double[sfx+s4]*ht11*hu01;
43720 0 : f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[sfy+s1]*ht00*hu10+c->f.ptr.p_double[sfy+s2]*ht01*hu10+c->f.ptr.p_double[sfy+s3]*ht00*hu11+c->f.ptr.p_double[sfy+s4]*ht01*hu11;
43721 0 : f->ptr.p_double[i] = f->ptr.p_double[i]+c->f.ptr.p_double[sfxy+s1]*ht10*hu10+c->f.ptr.p_double[sfxy+s2]*ht11*hu10+c->f.ptr.p_double[sfxy+s3]*ht10*hu11+c->f.ptr.p_double[sfxy+s4]*ht11*hu11;
43722 :
43723 : /*
43724 : * Advance source indexes
43725 : */
43726 0 : s1 = s1+1;
43727 0 : s2 = s2+1;
43728 0 : s3 = s3+1;
43729 0 : s4 = s4+1;
43730 : }
43731 : }
43732 :
43733 :
43734 : /*************************************************************************
43735 : This subroutine calculates specific component of vector-valued bilinear or
43736 : bicubic spline at the given point (X,Y).
43737 :
43738 : INPUT PARAMETERS:
43739 : C - spline interpolant.
43740 : X, Y- point
43741 : I - component index, in [0,D). An exception is generated for out
43742 : of range values.
43743 :
43744 : RESULT:
43745 : value of I-th component
43746 :
43747 : -- ALGLIB PROJECT --
43748 : Copyright 01.02.2018 by Bochkanov Sergey
43749 : *************************************************************************/
43750 0 : double spline2dcalcvi(spline2dinterpolant* c,
43751 : double x,
43752 : double y,
43753 : ae_int_t i,
43754 : ae_state *_state)
43755 : {
43756 : ae_int_t ix;
43757 : ae_int_t iy;
43758 : ae_int_t l;
43759 : ae_int_t r;
43760 : ae_int_t h;
43761 : double t;
43762 : double dt;
43763 : double u;
43764 : double du;
43765 : double y1;
43766 : double y2;
43767 : double y3;
43768 : double y4;
43769 : ae_int_t s1;
43770 : ae_int_t s2;
43771 : ae_int_t s3;
43772 : ae_int_t s4;
43773 : ae_int_t sfx;
43774 : ae_int_t sfy;
43775 : ae_int_t sfxy;
43776 : double t2;
43777 : double t3;
43778 : double u2;
43779 : double u3;
43780 : double ht00;
43781 : double ht01;
43782 : double ht10;
43783 : double ht11;
43784 : double hu00;
43785 : double hu01;
43786 : double hu10;
43787 : double hu11;
43788 : double result;
43789 :
43790 :
43791 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcVi: incorrect C (incorrect parameter C.SType)", _state);
43792 0 : ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcVi: X or Y contains NaN or Infinite value", _state);
43793 0 : ae_assert(i>=0&&i<c->d, "Spline2DCalcVi: incorrect I (I<0 or I>=D)", _state);
43794 :
43795 : /*
43796 : * Determine evaluation interval
43797 : */
43798 0 : l = 0;
43799 0 : r = c->n-1;
43800 0 : while(l!=r-1)
43801 : {
43802 0 : h = (l+r)/2;
43803 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
43804 : {
43805 0 : r = h;
43806 : }
43807 : else
43808 : {
43809 0 : l = h;
43810 : }
43811 : }
43812 0 : dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
43813 0 : t = (x-c->x.ptr.p_double[l])*dt;
43814 0 : ix = l;
43815 0 : l = 0;
43816 0 : r = c->m-1;
43817 0 : while(l!=r-1)
43818 : {
43819 0 : h = (l+r)/2;
43820 0 : if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
43821 : {
43822 0 : r = h;
43823 : }
43824 : else
43825 : {
43826 0 : l = h;
43827 : }
43828 : }
43829 0 : du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
43830 0 : u = (y-c->y.ptr.p_double[l])*du;
43831 0 : iy = l;
43832 :
43833 : /*
43834 : * Bilinear interpolation
43835 : */
43836 0 : if( c->stype==-1 )
43837 : {
43838 0 : y1 = c->f.ptr.p_double[c->d*(c->n*iy+ix)+i];
43839 0 : y2 = c->f.ptr.p_double[c->d*(c->n*iy+(ix+1))+i];
43840 0 : y3 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+(ix+1))+i];
43841 0 : y4 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+ix)+i];
43842 0 : result = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
43843 0 : return result;
43844 : }
43845 :
43846 : /*
43847 : * Bicubic interpolation:
43848 : * * calculate Hermite basis for dimensions X and Y (variables T and U),
43849 : * here HTij means basis function whose I-th derivative has value 1 at T=J.
43850 : * Same for HUij.
43851 : * * after initial calculation, apply scaling by DT/DU to the basis
43852 : * * calculate using stored table of second derivatives
43853 : */
43854 0 : ae_assert(c->stype==-3, "Spline2DCalc: integrity check failed", _state);
43855 0 : sfx = c->n*c->m*c->d;
43856 0 : sfy = 2*c->n*c->m*c->d;
43857 0 : sfxy = 3*c->n*c->m*c->d;
43858 0 : s1 = (c->n*iy+ix)*c->d;
43859 0 : s2 = (c->n*iy+(ix+1))*c->d;
43860 0 : s3 = (c->n*(iy+1)+ix)*c->d;
43861 0 : s4 = (c->n*(iy+1)+(ix+1))*c->d;
43862 0 : t2 = t*t;
43863 0 : t3 = t*t2;
43864 0 : u2 = u*u;
43865 0 : u3 = u*u2;
43866 0 : ht00 = 2*t3-3*t2+1;
43867 0 : ht10 = t3-2*t2+t;
43868 0 : ht01 = -2*t3+3*t2;
43869 0 : ht11 = t3-t2;
43870 0 : hu00 = 2*u3-3*u2+1;
43871 0 : hu10 = u3-2*u2+u;
43872 0 : hu01 = -2*u3+3*u2;
43873 0 : hu11 = u3-u2;
43874 0 : ht10 = ht10/dt;
43875 0 : ht11 = ht11/dt;
43876 0 : hu10 = hu10/du;
43877 0 : hu11 = hu11/du;
43878 :
43879 : /*
43880 : * Advance source indexes to I-th position
43881 : */
43882 0 : s1 = s1+i;
43883 0 : s2 = s2+i;
43884 0 : s3 = s3+i;
43885 0 : s4 = s4+i;
43886 :
43887 : /*
43888 : * Calculate I-th component
43889 : */
43890 0 : result = (double)(0);
43891 0 : result = result+c->f.ptr.p_double[s1]*ht00*hu00+c->f.ptr.p_double[s2]*ht01*hu00+c->f.ptr.p_double[s3]*ht00*hu01+c->f.ptr.p_double[s4]*ht01*hu01;
43892 0 : result = result+c->f.ptr.p_double[sfx+s1]*ht10*hu00+c->f.ptr.p_double[sfx+s2]*ht11*hu00+c->f.ptr.p_double[sfx+s3]*ht10*hu01+c->f.ptr.p_double[sfx+s4]*ht11*hu01;
43893 0 : result = result+c->f.ptr.p_double[sfy+s1]*ht00*hu10+c->f.ptr.p_double[sfy+s2]*ht01*hu10+c->f.ptr.p_double[sfy+s3]*ht00*hu11+c->f.ptr.p_double[sfy+s4]*ht01*hu11;
43894 0 : result = result+c->f.ptr.p_double[sfxy+s1]*ht10*hu10+c->f.ptr.p_double[sfxy+s2]*ht11*hu10+c->f.ptr.p_double[sfxy+s3]*ht10*hu11+c->f.ptr.p_double[sfxy+s4]*ht11*hu11;
43895 0 : return result;
43896 : }
43897 :
43898 :
43899 : /*************************************************************************
43900 : This subroutine calculates bilinear or bicubic vector-valued spline at the
43901 : given point (X,Y).
43902 :
43903 : INPUT PARAMETERS:
43904 : C - spline interpolant.
43905 : X, Y- point
43906 :
43907 : OUTPUT PARAMETERS:
43908 : F - array[D] which stores function values. F is out-parameter and
43909 : it is reallocated after call to this function. In case you
43910 : want to reuse previously allocated F, you may use
43911 : Spline2DCalcVBuf(), which reallocates F only when it is too
43912 : small.
43913 :
43914 : -- ALGLIB PROJECT --
43915 : Copyright 16.04.2012 by Bochkanov Sergey
43916 : *************************************************************************/
43917 0 : void spline2dcalcv(spline2dinterpolant* c,
43918 : double x,
43919 : double y,
43920 : /* Real */ ae_vector* f,
43921 : ae_state *_state)
43922 : {
43923 :
43924 0 : ae_vector_clear(f);
43925 :
43926 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcV: incorrect C (incorrect parameter C.SType)", _state);
43927 0 : ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcV: either X=NaN/Infinite or Y=NaN/Infinite", _state);
43928 0 : spline2dcalcvbuf(c, x, y, f, _state);
43929 0 : }
43930 :
43931 :
43932 : /*************************************************************************
43933 : This subroutine calculates value of specific component of bilinear or
43934 : bicubic vector-valued spline and its derivatives.
43935 :
43936 : Input parameters:
43937 : C - spline interpolant.
43938 : X, Y- point
43939 : I - component index, in [0,D)
43940 :
43941 : Output parameters:
43942 : F - S(x,y)
43943 : FX - dS(x,y)/dX
43944 : FY - dS(x,y)/dY
43945 : FXY - d2S(x,y)/dXdY
43946 :
43947 : -- ALGLIB PROJECT --
43948 : Copyright 05.07.2007 by Bochkanov Sergey
43949 : *************************************************************************/
43950 0 : void spline2ddiffvi(spline2dinterpolant* c,
43951 : double x,
43952 : double y,
43953 : ae_int_t i,
43954 : double* f,
43955 : double* fx,
43956 : double* fy,
43957 : double* fxy,
43958 : ae_state *_state)
43959 : {
43960 : ae_int_t d;
43961 : double t;
43962 : double dt;
43963 : double u;
43964 : double du;
43965 : ae_int_t ix;
43966 : ae_int_t iy;
43967 : ae_int_t l;
43968 : ae_int_t r;
43969 : ae_int_t h;
43970 : ae_int_t s1;
43971 : ae_int_t s2;
43972 : ae_int_t s3;
43973 : ae_int_t s4;
43974 : ae_int_t sfx;
43975 : ae_int_t sfy;
43976 : ae_int_t sfxy;
43977 : double y1;
43978 : double y2;
43979 : double y3;
43980 : double y4;
43981 : double v0;
43982 : double v1;
43983 : double v2;
43984 : double v3;
43985 : double t2;
43986 : double t3;
43987 : double u2;
43988 : double u3;
43989 : double ht00;
43990 : double ht01;
43991 : double ht10;
43992 : double ht11;
43993 : double hu00;
43994 : double hu01;
43995 : double hu10;
43996 : double hu11;
43997 : double dht00;
43998 : double dht01;
43999 : double dht10;
44000 : double dht11;
44001 : double dhu00;
44002 : double dhu01;
44003 : double dhu10;
44004 : double dhu11;
44005 :
44006 0 : *f = 0;
44007 0 : *fx = 0;
44008 0 : *fy = 0;
44009 0 : *fxy = 0;
44010 :
44011 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline2DDiffVI: incorrect C (incorrect parameter C.SType)", _state);
44012 0 : ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DDiffVI: X or Y contains NaN or Infinite value", _state);
44013 0 : ae_assert(i>=0&&i<c->d, "Spline2DDiffVI: I<0 or I>=D", _state);
44014 :
44015 : /*
44016 : * Prepare F, dF/dX, dF/dY, d2F/dXdY
44017 : */
44018 0 : *f = (double)(0);
44019 0 : *fx = (double)(0);
44020 0 : *fy = (double)(0);
44021 0 : *fxy = (double)(0);
44022 0 : d = c->d;
44023 :
44024 : /*
44025 : * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
44026 : */
44027 0 : l = 0;
44028 0 : r = c->n-1;
44029 0 : while(l!=r-1)
44030 : {
44031 0 : h = (l+r)/2;
44032 0 : if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
44033 : {
44034 0 : r = h;
44035 : }
44036 : else
44037 : {
44038 0 : l = h;
44039 : }
44040 : }
44041 0 : t = (x-c->x.ptr.p_double[l])/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
44042 0 : dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
44043 0 : ix = l;
44044 :
44045 : /*
44046 : * Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included)
44047 : */
44048 0 : l = 0;
44049 0 : r = c->m-1;
44050 0 : while(l!=r-1)
44051 : {
44052 0 : h = (l+r)/2;
44053 0 : if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
44054 : {
44055 0 : r = h;
44056 : }
44057 : else
44058 : {
44059 0 : l = h;
44060 : }
44061 : }
44062 0 : u = (y-c->y.ptr.p_double[l])/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
44063 0 : du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
44064 0 : iy = l;
44065 :
44066 : /*
44067 : * Bilinear interpolation
44068 : */
44069 0 : if( c->stype==-1 )
44070 : {
44071 0 : y1 = c->f.ptr.p_double[d*(c->n*iy+ix)+i];
44072 0 : y2 = c->f.ptr.p_double[d*(c->n*iy+(ix+1))+i];
44073 0 : y3 = c->f.ptr.p_double[d*(c->n*(iy+1)+(ix+1))+i];
44074 0 : y4 = c->f.ptr.p_double[d*(c->n*(iy+1)+ix)+i];
44075 0 : *f = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
44076 0 : *fx = (-(1-u)*y1+(1-u)*y2+u*y3-u*y4)*dt;
44077 0 : *fy = (-(1-t)*y1-t*y2+t*y3+(1-t)*y4)*du;
44078 0 : *fxy = (y1-y2+y3-y4)*du*dt;
44079 0 : return;
44080 : }
44081 :
44082 : /*
44083 : * Bicubic interpolation
44084 : */
44085 0 : if( c->stype==-3 )
44086 : {
44087 0 : sfx = c->n*c->m*d;
44088 0 : sfy = 2*c->n*c->m*d;
44089 0 : sfxy = 3*c->n*c->m*d;
44090 0 : s1 = d*(c->n*iy+ix)+i;
44091 0 : s2 = d*(c->n*iy+(ix+1))+i;
44092 0 : s3 = d*(c->n*(iy+1)+ix)+i;
44093 0 : s4 = d*(c->n*(iy+1)+(ix+1))+i;
44094 0 : t2 = t*t;
44095 0 : t3 = t*t2;
44096 0 : u2 = u*u;
44097 0 : u3 = u*u2;
44098 0 : ht00 = 2*t3-3*t2+1;
44099 0 : ht10 = t3-2*t2+t;
44100 0 : ht01 = -2*t3+3*t2;
44101 0 : ht11 = t3-t2;
44102 0 : hu00 = 2*u3-3*u2+1;
44103 0 : hu10 = u3-2*u2+u;
44104 0 : hu01 = -2*u3+3*u2;
44105 0 : hu11 = u3-u2;
44106 0 : ht10 = ht10/dt;
44107 0 : ht11 = ht11/dt;
44108 0 : hu10 = hu10/du;
44109 0 : hu11 = hu11/du;
44110 0 : dht00 = 6*t2-6*t;
44111 0 : dht10 = 3*t2-4*t+1;
44112 0 : dht01 = -6*t2+6*t;
44113 0 : dht11 = 3*t2-2*t;
44114 0 : dhu00 = 6*u2-6*u;
44115 0 : dhu10 = 3*u2-4*u+1;
44116 0 : dhu01 = -6*u2+6*u;
44117 0 : dhu11 = 3*u2-2*u;
44118 0 : dht00 = dht00*dt;
44119 0 : dht01 = dht01*dt;
44120 0 : dhu00 = dhu00*du;
44121 0 : dhu01 = dhu01*du;
44122 0 : *f = (double)(0);
44123 0 : *fx = (double)(0);
44124 0 : *fy = (double)(0);
44125 0 : *fxy = (double)(0);
44126 0 : v0 = c->f.ptr.p_double[s1];
44127 0 : v1 = c->f.ptr.p_double[s2];
44128 0 : v2 = c->f.ptr.p_double[s3];
44129 0 : v3 = c->f.ptr.p_double[s4];
44130 0 : *f = *f+v0*ht00*hu00+v1*ht01*hu00+v2*ht00*hu01+v3*ht01*hu01;
44131 0 : *fx = *fx+v0*dht00*hu00+v1*dht01*hu00+v2*dht00*hu01+v3*dht01*hu01;
44132 0 : *fy = *fy+v0*ht00*dhu00+v1*ht01*dhu00+v2*ht00*dhu01+v3*ht01*dhu01;
44133 0 : *fxy = *fxy+v0*dht00*dhu00+v1*dht01*dhu00+v2*dht00*dhu01+v3*dht01*dhu01;
44134 0 : v0 = c->f.ptr.p_double[sfx+s1];
44135 0 : v1 = c->f.ptr.p_double[sfx+s2];
44136 0 : v2 = c->f.ptr.p_double[sfx+s3];
44137 0 : v3 = c->f.ptr.p_double[sfx+s4];
44138 0 : *f = *f+v0*ht10*hu00+v1*ht11*hu00+v2*ht10*hu01+v3*ht11*hu01;
44139 0 : *fx = *fx+v0*dht10*hu00+v1*dht11*hu00+v2*dht10*hu01+v3*dht11*hu01;
44140 0 : *fy = *fy+v0*ht10*dhu00+v1*ht11*dhu00+v2*ht10*dhu01+v3*ht11*dhu01;
44141 0 : *fxy = *fxy+v0*dht10*dhu00+v1*dht11*dhu00+v2*dht10*dhu01+v3*dht11*dhu01;
44142 0 : v0 = c->f.ptr.p_double[sfy+s1];
44143 0 : v1 = c->f.ptr.p_double[sfy+s2];
44144 0 : v2 = c->f.ptr.p_double[sfy+s3];
44145 0 : v3 = c->f.ptr.p_double[sfy+s4];
44146 0 : *f = *f+v0*ht00*hu10+v1*ht01*hu10+v2*ht00*hu11+v3*ht01*hu11;
44147 0 : *fx = *fx+v0*dht00*hu10+v1*dht01*hu10+v2*dht00*hu11+v3*dht01*hu11;
44148 0 : *fy = *fy+v0*ht00*dhu10+v1*ht01*dhu10+v2*ht00*dhu11+v3*ht01*dhu11;
44149 0 : *fxy = *fxy+v0*dht00*dhu10+v1*dht01*dhu10+v2*dht00*dhu11+v3*dht01*dhu11;
44150 0 : v0 = c->f.ptr.p_double[sfxy+s1];
44151 0 : v1 = c->f.ptr.p_double[sfxy+s2];
44152 0 : v2 = c->f.ptr.p_double[sfxy+s3];
44153 0 : v3 = c->f.ptr.p_double[sfxy+s4];
44154 0 : *f = *f+v0*ht10*hu10+v1*ht11*hu10+v2*ht10*hu11+v3*ht11*hu11;
44155 0 : *fx = *fx+v0*dht10*hu10+v1*dht11*hu10+v2*dht10*hu11+v3*dht11*hu11;
44156 0 : *fy = *fy+v0*ht10*dhu10+v1*ht11*dhu10+v2*ht10*dhu11+v3*ht11*dhu11;
44157 0 : *fxy = *fxy+v0*dht10*dhu10+v1*dht11*dhu10+v2*dht10*dhu11+v3*dht11*dhu11;
44158 0 : return;
44159 : }
44160 : }
44161 :
44162 :
44163 : /*************************************************************************
44164 : This subroutine performs linear transformation of the spline argument.
44165 :
44166 : Input parameters:
44167 : C - spline interpolant
44168 : AX, BX - transformation coefficients: x = A*t + B
44169 : AY, BY - transformation coefficients: y = A*u + B
44170 : Result:
44171 : C - transformed spline
44172 :
44173 : -- ALGLIB PROJECT --
44174 : Copyright 30.06.2007 by Bochkanov Sergey
44175 : *************************************************************************/
44176 0 : void spline2dlintransxy(spline2dinterpolant* c,
44177 : double ax,
44178 : double bx,
44179 : double ay,
44180 : double by,
44181 : ae_state *_state)
44182 : {
44183 : ae_frame _frame_block;
44184 : ae_vector x;
44185 : ae_vector y;
44186 : ae_vector f;
44187 : ae_vector v;
44188 : ae_int_t i;
44189 : ae_int_t j;
44190 : ae_int_t k;
44191 :
44192 0 : ae_frame_make(_state, &_frame_block);
44193 0 : memset(&x, 0, sizeof(x));
44194 0 : memset(&y, 0, sizeof(y));
44195 0 : memset(&f, 0, sizeof(f));
44196 0 : memset(&v, 0, sizeof(v));
44197 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
44198 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
44199 0 : ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
44200 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
44201 :
44202 0 : ae_assert(c->stype==-3||c->stype==-1, "Spline2DLinTransXY: incorrect C (incorrect parameter C.SType)", _state);
44203 0 : ae_assert(ae_isfinite(ax, _state), "Spline2DLinTransXY: AX is infinite or NaN", _state);
44204 0 : ae_assert(ae_isfinite(bx, _state), "Spline2DLinTransXY: BX is infinite or NaN", _state);
44205 0 : ae_assert(ae_isfinite(ay, _state), "Spline2DLinTransXY: AY is infinite or NaN", _state);
44206 0 : ae_assert(ae_isfinite(by, _state), "Spline2DLinTransXY: BY is infinite or NaN", _state);
44207 0 : ae_vector_set_length(&x, c->n, _state);
44208 0 : ae_vector_set_length(&y, c->m, _state);
44209 0 : ae_vector_set_length(&f, c->m*c->n*c->d, _state);
44210 0 : for(j=0; j<=c->n-1; j++)
44211 : {
44212 0 : x.ptr.p_double[j] = c->x.ptr.p_double[j];
44213 : }
44214 0 : for(i=0; i<=c->m-1; i++)
44215 : {
44216 0 : y.ptr.p_double[i] = c->y.ptr.p_double[i];
44217 : }
44218 0 : for(i=0; i<=c->m-1; i++)
44219 : {
44220 0 : for(j=0; j<=c->n-1; j++)
44221 : {
44222 0 : for(k=0; k<=c->d-1; k++)
44223 : {
44224 0 : f.ptr.p_double[c->d*(i*c->n+j)+k] = c->f.ptr.p_double[c->d*(i*c->n+j)+k];
44225 : }
44226 : }
44227 : }
44228 :
44229 : /*
44230 : * Handle different combinations of AX/AY
44231 : */
44232 0 : if( ae_fp_eq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)) )
44233 : {
44234 0 : for(i=0; i<=c->m-1; i++)
44235 : {
44236 0 : spline2dcalcvbuf(c, bx, y.ptr.p_double[i], &v, _state);
44237 0 : y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay;
44238 0 : for(j=0; j<=c->n-1; j++)
44239 : {
44240 0 : for(k=0; k<=c->d-1; k++)
44241 : {
44242 0 : f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k];
44243 : }
44244 : }
44245 : }
44246 : }
44247 0 : if( ae_fp_neq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)) )
44248 : {
44249 0 : for(j=0; j<=c->n-1; j++)
44250 : {
44251 0 : spline2dcalcvbuf(c, x.ptr.p_double[j], by, &v, _state);
44252 0 : x.ptr.p_double[j] = (x.ptr.p_double[j]-bx)/ax;
44253 0 : for(i=0; i<=c->m-1; i++)
44254 : {
44255 0 : for(k=0; k<=c->d-1; k++)
44256 : {
44257 0 : f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k];
44258 : }
44259 : }
44260 : }
44261 : }
44262 0 : if( ae_fp_neq(ax,(double)(0))&&ae_fp_neq(ay,(double)(0)) )
44263 : {
44264 0 : for(j=0; j<=c->n-1; j++)
44265 : {
44266 0 : x.ptr.p_double[j] = (x.ptr.p_double[j]-bx)/ax;
44267 : }
44268 0 : for(i=0; i<=c->m-1; i++)
44269 : {
44270 0 : y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay;
44271 : }
44272 : }
44273 0 : if( ae_fp_eq(ax,(double)(0))&&ae_fp_eq(ay,(double)(0)) )
44274 : {
44275 0 : spline2dcalcvbuf(c, bx, by, &v, _state);
44276 0 : for(i=0; i<=c->m-1; i++)
44277 : {
44278 0 : for(j=0; j<=c->n-1; j++)
44279 : {
44280 0 : for(k=0; k<=c->d-1; k++)
44281 : {
44282 0 : f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k];
44283 : }
44284 : }
44285 : }
44286 : }
44287 :
44288 : /*
44289 : * Rebuild spline
44290 : */
44291 0 : if( c->stype==-3 )
44292 : {
44293 0 : spline2dbuildbicubicv(&x, c->n, &y, c->m, &f, c->d, c, _state);
44294 : }
44295 0 : if( c->stype==-1 )
44296 : {
44297 0 : spline2dbuildbilinearv(&x, c->n, &y, c->m, &f, c->d, c, _state);
44298 : }
44299 0 : ae_frame_leave(_state);
44300 0 : }
44301 :
44302 :
44303 : /*************************************************************************
44304 : This subroutine performs linear transformation of the spline.
44305 :
44306 : Input parameters:
44307 : C - spline interpolant.
44308 : A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B
44309 :
44310 : Output parameters:
44311 : C - transformed spline
44312 :
44313 : -- ALGLIB PROJECT --
44314 : Copyright 30.06.2007 by Bochkanov Sergey
44315 : *************************************************************************/
44316 0 : void spline2dlintransf(spline2dinterpolant* c,
44317 : double a,
44318 : double b,
44319 : ae_state *_state)
44320 : {
44321 : ae_frame _frame_block;
44322 : ae_vector x;
44323 : ae_vector y;
44324 : ae_vector f;
44325 : ae_int_t i;
44326 : ae_int_t j;
44327 :
44328 0 : ae_frame_make(_state, &_frame_block);
44329 0 : memset(&x, 0, sizeof(x));
44330 0 : memset(&y, 0, sizeof(y));
44331 0 : memset(&f, 0, sizeof(f));
44332 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
44333 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
44334 0 : ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
44335 :
44336 0 : ae_assert(c->stype==-3||c->stype==-1, "Spline2DLinTransF: incorrect C (incorrect parameter C.SType)", _state);
44337 0 : ae_vector_set_length(&x, c->n, _state);
44338 0 : ae_vector_set_length(&y, c->m, _state);
44339 0 : ae_vector_set_length(&f, c->m*c->n*c->d, _state);
44340 0 : for(j=0; j<=c->n-1; j++)
44341 : {
44342 0 : x.ptr.p_double[j] = c->x.ptr.p_double[j];
44343 : }
44344 0 : for(i=0; i<=c->m-1; i++)
44345 : {
44346 0 : y.ptr.p_double[i] = c->y.ptr.p_double[i];
44347 : }
44348 0 : for(i=0; i<=c->m*c->n*c->d-1; i++)
44349 : {
44350 0 : f.ptr.p_double[i] = a*c->f.ptr.p_double[i]+b;
44351 : }
44352 0 : if( c->stype==-3 )
44353 : {
44354 0 : spline2dbuildbicubicv(&x, c->n, &y, c->m, &f, c->d, c, _state);
44355 : }
44356 0 : if( c->stype==-1 )
44357 : {
44358 0 : spline2dbuildbilinearv(&x, c->n, &y, c->m, &f, c->d, c, _state);
44359 : }
44360 0 : ae_frame_leave(_state);
44361 0 : }
44362 :
44363 :
44364 : /*************************************************************************
44365 : This subroutine makes the copy of the spline model.
44366 :
44367 : Input parameters:
44368 : C - spline interpolant
44369 :
44370 : Output parameters:
44371 : CC - spline copy
44372 :
44373 : -- ALGLIB PROJECT --
44374 : Copyright 29.06.2007 by Bochkanov Sergey
44375 : *************************************************************************/
44376 0 : void spline2dcopy(spline2dinterpolant* c,
44377 : spline2dinterpolant* cc,
44378 : ae_state *_state)
44379 : {
44380 : ae_int_t tblsize;
44381 :
44382 0 : _spline2dinterpolant_clear(cc);
44383 :
44384 0 : ae_assert(c->stype==-1||c->stype==-3, "Spline2DCopy: incorrect C (incorrect parameter C.SType)", _state);
44385 0 : cc->n = c->n;
44386 0 : cc->m = c->m;
44387 0 : cc->d = c->d;
44388 0 : cc->stype = c->stype;
44389 0 : tblsize = -1;
44390 0 : if( c->stype==-3 )
44391 : {
44392 0 : tblsize = 4*c->n*c->m*c->d;
44393 : }
44394 0 : if( c->stype==-1 )
44395 : {
44396 0 : tblsize = c->n*c->m*c->d;
44397 : }
44398 0 : ae_assert(tblsize>0, "Spline2DCopy: internal error", _state);
44399 0 : ae_vector_set_length(&cc->x, cc->n, _state);
44400 0 : ae_vector_set_length(&cc->y, cc->m, _state);
44401 0 : ae_vector_set_length(&cc->f, tblsize, _state);
44402 0 : ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1));
44403 0 : ae_v_move(&cc->y.ptr.p_double[0], 1, &c->y.ptr.p_double[0], 1, ae_v_len(0,cc->m-1));
44404 0 : ae_v_move(&cc->f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,tblsize-1));
44405 0 : }
44406 :
44407 :
44408 : /*************************************************************************
44409 : Bicubic spline resampling
44410 :
44411 : Input parameters:
44412 : A - function values at the old grid,
44413 : array[0..OldHeight-1, 0..OldWidth-1]
44414 : OldHeight - old grid height, OldHeight>1
44415 : OldWidth - old grid width, OldWidth>1
44416 : NewHeight - new grid height, NewHeight>1
44417 : NewWidth - new grid width, NewWidth>1
44418 :
44419 : Output parameters:
44420 : B - function values at the new grid,
44421 : array[0..NewHeight-1, 0..NewWidth-1]
44422 :
44423 : -- ALGLIB routine --
44424 : 15 May, 2007
44425 : Copyright by Bochkanov Sergey
44426 : *************************************************************************/
44427 0 : void spline2dresamplebicubic(/* Real */ ae_matrix* a,
44428 : ae_int_t oldheight,
44429 : ae_int_t oldwidth,
44430 : /* Real */ ae_matrix* b,
44431 : ae_int_t newheight,
44432 : ae_int_t newwidth,
44433 : ae_state *_state)
44434 : {
44435 : ae_frame _frame_block;
44436 : ae_matrix buf;
44437 : ae_vector x;
44438 : ae_vector y;
44439 : spline1dinterpolant c;
44440 : ae_int_t mw;
44441 : ae_int_t mh;
44442 : ae_int_t i;
44443 : ae_int_t j;
44444 :
44445 0 : ae_frame_make(_state, &_frame_block);
44446 0 : memset(&buf, 0, sizeof(buf));
44447 0 : memset(&x, 0, sizeof(x));
44448 0 : memset(&y, 0, sizeof(y));
44449 0 : memset(&c, 0, sizeof(c));
44450 0 : ae_matrix_clear(b);
44451 0 : ae_matrix_init(&buf, 0, 0, DT_REAL, _state, ae_true);
44452 0 : ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
44453 0 : ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
44454 0 : _spline1dinterpolant_init(&c, _state, ae_true);
44455 :
44456 0 : ae_assert(oldwidth>1&&oldheight>1, "Spline2DResampleBicubic: width/height less than 1", _state);
44457 0 : ae_assert(newwidth>1&&newheight>1, "Spline2DResampleBicubic: width/height less than 1", _state);
44458 :
44459 : /*
44460 : * Prepare
44461 : */
44462 0 : mw = ae_maxint(oldwidth, newwidth, _state);
44463 0 : mh = ae_maxint(oldheight, newheight, _state);
44464 0 : ae_matrix_set_length(b, newheight, newwidth, _state);
44465 0 : ae_matrix_set_length(&buf, oldheight, newwidth, _state);
44466 0 : ae_vector_set_length(&x, ae_maxint(mw, mh, _state), _state);
44467 0 : ae_vector_set_length(&y, ae_maxint(mw, mh, _state), _state);
44468 :
44469 : /*
44470 : * Horizontal interpolation
44471 : */
44472 0 : for(i=0; i<=oldheight-1; i++)
44473 : {
44474 :
44475 : /*
44476 : * Fill X, Y
44477 : */
44478 0 : for(j=0; j<=oldwidth-1; j++)
44479 : {
44480 0 : x.ptr.p_double[j] = (double)j/(double)(oldwidth-1);
44481 0 : y.ptr.p_double[j] = a->ptr.pp_double[i][j];
44482 : }
44483 :
44484 : /*
44485 : * Interpolate and place result into temporary matrix
44486 : */
44487 0 : spline1dbuildcubic(&x, &y, oldwidth, 0, 0.0, 0, 0.0, &c, _state);
44488 0 : for(j=0; j<=newwidth-1; j++)
44489 : {
44490 0 : buf.ptr.pp_double[i][j] = spline1dcalc(&c, (double)j/(double)(newwidth-1), _state);
44491 : }
44492 : }
44493 :
44494 : /*
44495 : * Vertical interpolation
44496 : */
44497 0 : for(j=0; j<=newwidth-1; j++)
44498 : {
44499 :
44500 : /*
44501 : * Fill X, Y
44502 : */
44503 0 : for(i=0; i<=oldheight-1; i++)
44504 : {
44505 0 : x.ptr.p_double[i] = (double)i/(double)(oldheight-1);
44506 0 : y.ptr.p_double[i] = buf.ptr.pp_double[i][j];
44507 : }
44508 :
44509 : /*
44510 : * Interpolate and place result into B
44511 : */
44512 0 : spline1dbuildcubic(&x, &y, oldheight, 0, 0.0, 0, 0.0, &c, _state);
44513 0 : for(i=0; i<=newheight-1; i++)
44514 : {
44515 0 : b->ptr.pp_double[i][j] = spline1dcalc(&c, (double)i/(double)(newheight-1), _state);
44516 : }
44517 : }
44518 0 : ae_frame_leave(_state);
44519 0 : }
44520 :
44521 :
44522 : /*************************************************************************
44523 : Bilinear spline resampling
44524 :
44525 : Input parameters:
44526 : A - function values at the old grid,
44527 : array[0..OldHeight-1, 0..OldWidth-1]
44528 : OldHeight - old grid height, OldHeight>1
44529 : OldWidth - old grid width, OldWidth>1
44530 : NewHeight - new grid height, NewHeight>1
44531 : NewWidth - new grid width, NewWidth>1
44532 :
44533 : Output parameters:
44534 : B - function values at the new grid,
44535 : array[0..NewHeight-1, 0..NewWidth-1]
44536 :
44537 : -- ALGLIB routine --
44538 : 09.07.2007
44539 : Copyright by Bochkanov Sergey
44540 : *************************************************************************/
44541 0 : void spline2dresamplebilinear(/* Real */ ae_matrix* a,
44542 : ae_int_t oldheight,
44543 : ae_int_t oldwidth,
44544 : /* Real */ ae_matrix* b,
44545 : ae_int_t newheight,
44546 : ae_int_t newwidth,
44547 : ae_state *_state)
44548 : {
44549 : ae_int_t l;
44550 : ae_int_t c;
44551 : double t;
44552 : double u;
44553 : ae_int_t i;
44554 : ae_int_t j;
44555 :
44556 0 : ae_matrix_clear(b);
44557 :
44558 0 : ae_assert(oldwidth>1&&oldheight>1, "Spline2DResampleBilinear: width/height less than 1", _state);
44559 0 : ae_assert(newwidth>1&&newheight>1, "Spline2DResampleBilinear: width/height less than 1", _state);
44560 0 : ae_matrix_set_length(b, newheight, newwidth, _state);
44561 0 : for(i=0; i<=newheight-1; i++)
44562 : {
44563 0 : for(j=0; j<=newwidth-1; j++)
44564 : {
44565 0 : l = i*(oldheight-1)/(newheight-1);
44566 0 : if( l==oldheight-1 )
44567 : {
44568 0 : l = oldheight-2;
44569 : }
44570 0 : u = (double)i/(double)(newheight-1)*(oldheight-1)-l;
44571 0 : c = j*(oldwidth-1)/(newwidth-1);
44572 0 : if( c==oldwidth-1 )
44573 : {
44574 0 : c = oldwidth-2;
44575 : }
44576 0 : t = (double)(j*(oldwidth-1))/(double)(newwidth-1)-c;
44577 0 : b->ptr.pp_double[i][j] = (1-t)*(1-u)*a->ptr.pp_double[l][c]+t*(1-u)*a->ptr.pp_double[l][c+1]+t*u*a->ptr.pp_double[l+1][c+1]+(1-t)*u*a->ptr.pp_double[l+1][c];
44578 : }
44579 : }
44580 0 : }
44581 :
44582 :
44583 : /*************************************************************************
44584 : This subroutine builds bilinear vector-valued spline.
44585 :
44586 : Input parameters:
44587 : X - spline abscissas, array[0..N-1]
44588 : Y - spline ordinates, array[0..M-1]
44589 : F - function values, array[0..M*N*D-1]:
44590 : * first D elements store D values at (X[0],Y[0])
44591 : * next D elements store D values at (X[1],Y[0])
44592 : * general form - D function values at (X[i],Y[j]) are stored
44593 : at F[D*(J*N+I)...D*(J*N+I)+D-1].
44594 : M,N - grid size, M>=2, N>=2
44595 : D - vector dimension, D>=1
44596 :
44597 : Output parameters:
44598 : C - spline interpolant
44599 :
44600 : -- ALGLIB PROJECT --
44601 : Copyright 16.04.2012 by Bochkanov Sergey
44602 : *************************************************************************/
44603 0 : void spline2dbuildbilinearv(/* Real */ ae_vector* x,
44604 : ae_int_t n,
44605 : /* Real */ ae_vector* y,
44606 : ae_int_t m,
44607 : /* Real */ ae_vector* f,
44608 : ae_int_t d,
44609 : spline2dinterpolant* c,
44610 : ae_state *_state)
44611 : {
44612 : double t;
44613 : ae_int_t i;
44614 : ae_int_t j;
44615 : ae_int_t k;
44616 : ae_int_t i0;
44617 :
44618 0 : _spline2dinterpolant_clear(c);
44619 :
44620 0 : ae_assert(n>=2, "Spline2DBuildBilinearV: N is less then 2", _state);
44621 0 : ae_assert(m>=2, "Spline2DBuildBilinearV: M is less then 2", _state);
44622 0 : ae_assert(d>=1, "Spline2DBuildBilinearV: invalid argument D (D<1)", _state);
44623 0 : ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBilinearV: length of X or Y is too short (Length(X/Y)<N/M)", _state);
44624 0 : ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBilinearV: X or Y contains NaN or Infinite value", _state);
44625 0 : k = n*m*d;
44626 0 : ae_assert(f->cnt>=k, "Spline2DBuildBilinearV: length of F is too short (Length(F)<N*M*D)", _state);
44627 0 : ae_assert(isfinitevector(f, k, _state), "Spline2DBuildBilinearV: F contains NaN or Infinite value", _state);
44628 :
44629 : /*
44630 : * Fill interpolant
44631 : */
44632 0 : c->n = n;
44633 0 : c->m = m;
44634 0 : c->d = d;
44635 0 : c->stype = -1;
44636 0 : ae_vector_set_length(&c->x, c->n, _state);
44637 0 : ae_vector_set_length(&c->y, c->m, _state);
44638 0 : ae_vector_set_length(&c->f, k, _state);
44639 0 : for(i=0; i<=c->n-1; i++)
44640 : {
44641 0 : c->x.ptr.p_double[i] = x->ptr.p_double[i];
44642 : }
44643 0 : for(i=0; i<=c->m-1; i++)
44644 : {
44645 0 : c->y.ptr.p_double[i] = y->ptr.p_double[i];
44646 : }
44647 0 : for(i=0; i<=k-1; i++)
44648 : {
44649 0 : c->f.ptr.p_double[i] = f->ptr.p_double[i];
44650 : }
44651 :
44652 : /*
44653 : * Sort points
44654 : */
44655 0 : for(j=0; j<=c->n-1; j++)
44656 : {
44657 0 : k = j;
44658 0 : for(i=j+1; i<=c->n-1; i++)
44659 : {
44660 0 : if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
44661 : {
44662 0 : k = i;
44663 : }
44664 : }
44665 0 : if( k!=j )
44666 : {
44667 0 : for(i=0; i<=c->m-1; i++)
44668 : {
44669 0 : for(i0=0; i0<=c->d-1; i0++)
44670 : {
44671 0 : t = c->f.ptr.p_double[c->d*(i*c->n+j)+i0];
44672 0 : c->f.ptr.p_double[c->d*(i*c->n+j)+i0] = c->f.ptr.p_double[c->d*(i*c->n+k)+i0];
44673 0 : c->f.ptr.p_double[c->d*(i*c->n+k)+i0] = t;
44674 : }
44675 : }
44676 0 : t = c->x.ptr.p_double[j];
44677 0 : c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
44678 0 : c->x.ptr.p_double[k] = t;
44679 : }
44680 : }
44681 0 : for(i=0; i<=c->m-1; i++)
44682 : {
44683 0 : k = i;
44684 0 : for(j=i+1; j<=c->m-1; j++)
44685 : {
44686 0 : if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
44687 : {
44688 0 : k = j;
44689 : }
44690 : }
44691 0 : if( k!=i )
44692 : {
44693 0 : for(j=0; j<=c->n-1; j++)
44694 : {
44695 0 : for(i0=0; i0<=c->d-1; i0++)
44696 : {
44697 0 : t = c->f.ptr.p_double[c->d*(i*c->n+j)+i0];
44698 0 : c->f.ptr.p_double[c->d*(i*c->n+j)+i0] = c->f.ptr.p_double[c->d*(k*c->n+j)+i0];
44699 0 : c->f.ptr.p_double[c->d*(k*c->n+j)+i0] = t;
44700 : }
44701 : }
44702 0 : t = c->y.ptr.p_double[i];
44703 0 : c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
44704 0 : c->y.ptr.p_double[k] = t;
44705 : }
44706 : }
44707 0 : }
44708 :
44709 :
44710 : /*************************************************************************
44711 : This subroutine builds bicubic vector-valued spline.
44712 :
44713 : Input parameters:
44714 : X - spline abscissas, array[0..N-1]
44715 : Y - spline ordinates, array[0..M-1]
44716 : F - function values, array[0..M*N*D-1]:
44717 : * first D elements store D values at (X[0],Y[0])
44718 : * next D elements store D values at (X[1],Y[0])
44719 : * general form - D function values at (X[i],Y[j]) are stored
44720 : at F[D*(J*N+I)...D*(J*N+I)+D-1].
44721 : M,N - grid size, M>=2, N>=2
44722 : D - vector dimension, D>=1
44723 :
44724 : Output parameters:
44725 : C - spline interpolant
44726 :
44727 : -- ALGLIB PROJECT --
44728 : Copyright 16.04.2012 by Bochkanov Sergey
44729 : *************************************************************************/
44730 0 : void spline2dbuildbicubicv(/* Real */ ae_vector* x,
44731 : ae_int_t n,
44732 : /* Real */ ae_vector* y,
44733 : ae_int_t m,
44734 : /* Real */ ae_vector* f,
44735 : ae_int_t d,
44736 : spline2dinterpolant* c,
44737 : ae_state *_state)
44738 : {
44739 : ae_frame _frame_block;
44740 : ae_vector _f;
44741 : ae_matrix tf;
44742 : ae_matrix dx;
44743 : ae_matrix dy;
44744 : ae_matrix dxy;
44745 : double t;
44746 : ae_int_t i;
44747 : ae_int_t j;
44748 : ae_int_t k;
44749 : ae_int_t di;
44750 :
44751 0 : ae_frame_make(_state, &_frame_block);
44752 0 : memset(&_f, 0, sizeof(_f));
44753 0 : memset(&tf, 0, sizeof(tf));
44754 0 : memset(&dx, 0, sizeof(dx));
44755 0 : memset(&dy, 0, sizeof(dy));
44756 0 : memset(&dxy, 0, sizeof(dxy));
44757 0 : ae_vector_init_copy(&_f, f, _state, ae_true);
44758 0 : f = &_f;
44759 0 : _spline2dinterpolant_clear(c);
44760 0 : ae_matrix_init(&tf, 0, 0, DT_REAL, _state, ae_true);
44761 0 : ae_matrix_init(&dx, 0, 0, DT_REAL, _state, ae_true);
44762 0 : ae_matrix_init(&dy, 0, 0, DT_REAL, _state, ae_true);
44763 0 : ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true);
44764 :
44765 0 : ae_assert(n>=2, "Spline2DBuildBicubicV: N is less than 2", _state);
44766 0 : ae_assert(m>=2, "Spline2DBuildBicubicV: M is less than 2", _state);
44767 0 : ae_assert(d>=1, "Spline2DBuildBicubicV: invalid argument D (D<1)", _state);
44768 0 : ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBicubicV: length of X or Y is too short (Length(X/Y)<N/M)", _state);
44769 0 : ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBicubicV: X or Y contains NaN or Infinite value", _state);
44770 0 : k = n*m*d;
44771 0 : ae_assert(f->cnt>=k, "Spline2DBuildBicubicV: length of F is too short (Length(F)<N*M*D)", _state);
44772 0 : ae_assert(isfinitevector(f, k, _state), "Spline2DBuildBicubicV: F contains NaN or Infinite value", _state);
44773 :
44774 : /*
44775 : * Fill interpolant:
44776 : * F[0]...F[N*M*D-1]:
44777 : * f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on...
44778 : * F[N*M*D]...F[2*N*M*D-1]:
44779 : * df(i,j)/dx table.
44780 : * F[2*N*M*D]...F[3*N*M*D-1]:
44781 : * df(i,j)/dy table.
44782 : * F[3*N*M*D]...F[4*N*M*D-1]:
44783 : * d2f(i,j)/dxdy table.
44784 : */
44785 0 : c->d = d;
44786 0 : c->n = n;
44787 0 : c->m = m;
44788 0 : c->stype = -3;
44789 0 : k = 4*k;
44790 0 : ae_vector_set_length(&c->x, c->n, _state);
44791 0 : ae_vector_set_length(&c->y, c->m, _state);
44792 0 : ae_vector_set_length(&c->f, k, _state);
44793 0 : ae_matrix_set_length(&tf, c->m, c->n, _state);
44794 0 : for(i=0; i<=c->n-1; i++)
44795 : {
44796 0 : c->x.ptr.p_double[i] = x->ptr.p_double[i];
44797 : }
44798 0 : for(i=0; i<=c->m-1; i++)
44799 : {
44800 0 : c->y.ptr.p_double[i] = y->ptr.p_double[i];
44801 : }
44802 :
44803 : /*
44804 : * Sort points
44805 : */
44806 0 : for(j=0; j<=c->n-1; j++)
44807 : {
44808 0 : k = j;
44809 0 : for(i=j+1; i<=c->n-1; i++)
44810 : {
44811 0 : if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
44812 : {
44813 0 : k = i;
44814 : }
44815 : }
44816 0 : if( k!=j )
44817 : {
44818 0 : for(i=0; i<=c->m-1; i++)
44819 : {
44820 0 : for(di=0; di<=c->d-1; di++)
44821 : {
44822 0 : t = f->ptr.p_double[c->d*(i*c->n+j)+di];
44823 0 : f->ptr.p_double[c->d*(i*c->n+j)+di] = f->ptr.p_double[c->d*(i*c->n+k)+di];
44824 0 : f->ptr.p_double[c->d*(i*c->n+k)+di] = t;
44825 : }
44826 : }
44827 0 : t = c->x.ptr.p_double[j];
44828 0 : c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
44829 0 : c->x.ptr.p_double[k] = t;
44830 : }
44831 : }
44832 0 : for(i=0; i<=c->m-1; i++)
44833 : {
44834 0 : k = i;
44835 0 : for(j=i+1; j<=c->m-1; j++)
44836 : {
44837 0 : if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
44838 : {
44839 0 : k = j;
44840 : }
44841 : }
44842 0 : if( k!=i )
44843 : {
44844 0 : for(j=0; j<=c->n-1; j++)
44845 : {
44846 0 : for(di=0; di<=c->d-1; di++)
44847 : {
44848 0 : t = f->ptr.p_double[c->d*(i*c->n+j)+di];
44849 0 : f->ptr.p_double[c->d*(i*c->n+j)+di] = f->ptr.p_double[c->d*(k*c->n+j)+di];
44850 0 : f->ptr.p_double[c->d*(k*c->n+j)+di] = t;
44851 : }
44852 : }
44853 0 : t = c->y.ptr.p_double[i];
44854 0 : c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
44855 0 : c->y.ptr.p_double[k] = t;
44856 : }
44857 : }
44858 0 : for(di=0; di<=c->d-1; di++)
44859 : {
44860 0 : for(i=0; i<=c->m-1; i++)
44861 : {
44862 0 : for(j=0; j<=c->n-1; j++)
44863 : {
44864 0 : tf.ptr.pp_double[i][j] = f->ptr.p_double[c->d*(i*c->n+j)+di];
44865 : }
44866 : }
44867 0 : spline2d_bicubiccalcderivatives(&tf, &c->x, &c->y, c->m, c->n, &dx, &dy, &dxy, _state);
44868 0 : for(i=0; i<=c->m-1; i++)
44869 : {
44870 0 : for(j=0; j<=c->n-1; j++)
44871 : {
44872 0 : k = c->d*(i*c->n+j)+di;
44873 0 : c->f.ptr.p_double[k] = tf.ptr.pp_double[i][j];
44874 0 : c->f.ptr.p_double[c->n*c->m*c->d+k] = dx.ptr.pp_double[i][j];
44875 0 : c->f.ptr.p_double[2*c->n*c->m*c->d+k] = dy.ptr.pp_double[i][j];
44876 0 : c->f.ptr.p_double[3*c->n*c->m*c->d+k] = dxy.ptr.pp_double[i][j];
44877 : }
44878 : }
44879 : }
44880 0 : ae_frame_leave(_state);
44881 0 : }
44882 :
44883 :
44884 : /*************************************************************************
44885 : This subroutine unpacks two-dimensional spline into the coefficients table
44886 :
44887 : Input parameters:
44888 : C - spline interpolant.
44889 :
44890 : Result:
44891 : M, N- grid size (x-axis and y-axis)
44892 : D - number of components
44893 : Tbl - coefficients table, unpacked format,
44894 : D - components: [0..(N-1)*(M-1)*D-1, 0..19].
44895 : For T=0..D-1 (component index), I = 0...N-2 (x index),
44896 : J=0..M-2 (y index):
44897 : K := T + I*D + J*D*(N-1)
44898 :
44899 : K-th row stores decomposition for T-th component of the
44900 : vector-valued function
44901 :
44902 : Tbl[K,0] = X[i]
44903 : Tbl[K,1] = X[i+1]
44904 : Tbl[K,2] = Y[j]
44905 : Tbl[K,3] = Y[j+1]
44906 : Tbl[K,4] = C00
44907 : Tbl[K,5] = C01
44908 : Tbl[K,6] = C02
44909 : Tbl[K,7] = C03
44910 : Tbl[K,8] = C10
44911 : Tbl[K,9] = C11
44912 : ...
44913 : Tbl[K,19] = C33
44914 : On each grid square spline is equals to:
44915 : S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3)
44916 : t = x-x[j]
44917 : u = y-y[i]
44918 :
44919 : -- ALGLIB PROJECT --
44920 : Copyright 16.04.2012 by Bochkanov Sergey
44921 : *************************************************************************/
44922 0 : void spline2dunpackv(spline2dinterpolant* c,
44923 : ae_int_t* m,
44924 : ae_int_t* n,
44925 : ae_int_t* d,
44926 : /* Real */ ae_matrix* tbl,
44927 : ae_state *_state)
44928 : {
44929 : ae_int_t k;
44930 : ae_int_t p;
44931 : ae_int_t ci;
44932 : ae_int_t cj;
44933 : ae_int_t s1;
44934 : ae_int_t s2;
44935 : ae_int_t s3;
44936 : ae_int_t s4;
44937 : ae_int_t sfx;
44938 : ae_int_t sfy;
44939 : ae_int_t sfxy;
44940 : double y1;
44941 : double y2;
44942 : double y3;
44943 : double y4;
44944 : double dt;
44945 : double du;
44946 : ae_int_t i;
44947 : ae_int_t j;
44948 : ae_int_t k0;
44949 :
44950 0 : *m = 0;
44951 0 : *n = 0;
44952 0 : *d = 0;
44953 0 : ae_matrix_clear(tbl);
44954 :
44955 0 : ae_assert(c->stype==-3||c->stype==-1, "Spline2DUnpackV: incorrect C (incorrect parameter C.SType)", _state);
44956 0 : *n = c->n;
44957 0 : *m = c->m;
44958 0 : *d = c->d;
44959 0 : ae_matrix_set_length(tbl, (*n-1)*(*m-1)*(*d), 20, _state);
44960 0 : sfx = *n*(*m)*(*d);
44961 0 : sfy = 2*(*n)*(*m)*(*d);
44962 0 : sfxy = 3*(*n)*(*m)*(*d);
44963 0 : for(i=0; i<=*m-2; i++)
44964 : {
44965 0 : for(j=0; j<=*n-2; j++)
44966 : {
44967 0 : for(k=0; k<=*d-1; k++)
44968 : {
44969 0 : p = *d*(i*(*n-1)+j)+k;
44970 0 : tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[j];
44971 0 : tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[j+1];
44972 0 : tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[i];
44973 0 : tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[i+1];
44974 0 : dt = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]);
44975 0 : du = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]);
44976 :
44977 : /*
44978 : * Bilinear interpolation
44979 : */
44980 0 : if( c->stype==-1 )
44981 : {
44982 0 : for(k0=4; k0<=19; k0++)
44983 : {
44984 0 : tbl->ptr.pp_double[p][k0] = (double)(0);
44985 : }
44986 0 : y1 = c->f.ptr.p_double[*d*(*n*i+j)+k];
44987 0 : y2 = c->f.ptr.p_double[*d*(*n*i+(j+1))+k];
44988 0 : y3 = c->f.ptr.p_double[*d*(*n*(i+1)+(j+1))+k];
44989 0 : y4 = c->f.ptr.p_double[*d*(*n*(i+1)+j)+k];
44990 0 : tbl->ptr.pp_double[p][4] = y1;
44991 0 : tbl->ptr.pp_double[p][4+1*4+0] = y2-y1;
44992 0 : tbl->ptr.pp_double[p][4+0*4+1] = y4-y1;
44993 0 : tbl->ptr.pp_double[p][4+1*4+1] = y3-y2-y4+y1;
44994 : }
44995 :
44996 : /*
44997 : * Bicubic interpolation
44998 : */
44999 0 : if( c->stype==-3 )
45000 : {
45001 0 : s1 = *d*(*n*i+j)+k;
45002 0 : s2 = *d*(*n*i+(j+1))+k;
45003 0 : s3 = *d*(*n*(i+1)+(j+1))+k;
45004 0 : s4 = *d*(*n*(i+1)+j)+k;
45005 0 : tbl->ptr.pp_double[p][4+0*4+0] = c->f.ptr.p_double[s1];
45006 0 : tbl->ptr.pp_double[p][4+0*4+1] = c->f.ptr.p_double[sfy+s1]/du;
45007 0 : tbl->ptr.pp_double[p][4+0*4+2] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s4]-2*c->f.ptr.p_double[sfy+s1]/du-c->f.ptr.p_double[sfy+s4]/du;
45008 0 : tbl->ptr.pp_double[p][4+0*4+3] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s4]+c->f.ptr.p_double[sfy+s1]/du+c->f.ptr.p_double[sfy+s4]/du;
45009 0 : tbl->ptr.pp_double[p][4+1*4+0] = c->f.ptr.p_double[sfx+s1]/dt;
45010 0 : tbl->ptr.pp_double[p][4+1*4+1] = c->f.ptr.p_double[sfxy+s1]/(dt*du);
45011 0 : tbl->ptr.pp_double[p][4+1*4+2] = -3*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du);
45012 0 : tbl->ptr.pp_double[p][4+1*4+3] = 2*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du);
45013 0 : tbl->ptr.pp_double[p][4+2*4+0] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s2]-2*c->f.ptr.p_double[sfx+s1]/dt-c->f.ptr.p_double[sfx+s2]/dt;
45014 0 : tbl->ptr.pp_double[p][4+2*4+1] = -3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du);
45015 0 : tbl->ptr.pp_double[p][4+2*4+2] = 9*c->f.ptr.p_double[s1]-9*c->f.ptr.p_double[s2]+9*c->f.ptr.p_double[s3]-9*c->f.ptr.p_double[s4]+6*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s2]/dt-3*c->f.ptr.p_double[sfx+s3]/dt-6*c->f.ptr.p_double[sfx+s4]/dt+6*c->f.ptr.p_double[sfy+s1]/du-6*c->f.ptr.p_double[sfy+s2]/du-3*c->f.ptr.p_double[sfy+s3]/du+3*c->f.ptr.p_double[sfy+s4]/du+4*c->f.ptr.p_double[sfxy+s1]/(dt*du)+2*c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+2*c->f.ptr.p_double[sfxy+s4]/(dt*du);
45016 0 : tbl->ptr.pp_double[p][4+2*4+3] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-4*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s2]/dt+2*c->f.ptr.p_double[sfx+s3]/dt+4*c->f.ptr.p_double[sfx+s4]/dt-3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du+3*c->f.ptr.p_double[sfy+s3]/du-3*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-2*c->f.ptr.p_double[sfxy+s4]/(dt*du);
45017 0 : tbl->ptr.pp_double[p][4+3*4+0] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s2]+c->f.ptr.p_double[sfx+s1]/dt+c->f.ptr.p_double[sfx+s2]/dt;
45018 0 : tbl->ptr.pp_double[p][4+3*4+1] = 2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du);
45019 0 : tbl->ptr.pp_double[p][4+3*4+2] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-3*c->f.ptr.p_double[sfx+s1]/dt-3*c->f.ptr.p_double[sfx+s2]/dt+3*c->f.ptr.p_double[sfx+s3]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-4*c->f.ptr.p_double[sfy+s1]/du+4*c->f.ptr.p_double[sfy+s2]/du+2*c->f.ptr.p_double[sfy+s3]/du-2*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-2*c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du);
45020 0 : tbl->ptr.pp_double[p][4+3*4+3] = 4*c->f.ptr.p_double[s1]-4*c->f.ptr.p_double[s2]+4*c->f.ptr.p_double[s3]-4*c->f.ptr.p_double[s4]+2*c->f.ptr.p_double[sfx+s1]/dt+2*c->f.ptr.p_double[sfx+s2]/dt-2*c->f.ptr.p_double[sfx+s3]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfy+s3]/du+2*c->f.ptr.p_double[sfy+s4]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du);
45021 : }
45022 :
45023 : /*
45024 : * Rescale Cij
45025 : */
45026 0 : for(ci=0; ci<=3; ci++)
45027 : {
45028 0 : for(cj=0; cj<=3; cj++)
45029 : {
45030 0 : tbl->ptr.pp_double[p][4+ci*4+cj] = tbl->ptr.pp_double[p][4+ci*4+cj]*ae_pow(dt, (double)(ci), _state)*ae_pow(du, (double)(cj), _state);
45031 : }
45032 : }
45033 : }
45034 : }
45035 : }
45036 0 : }
45037 :
45038 :
45039 : /*************************************************************************
45040 : This subroutine was deprecated in ALGLIB 3.6.0
45041 :
45042 : We recommend you to switch to Spline2DBuildBilinearV(), which is more
45043 : flexible and accepts its arguments in more convenient order.
45044 :
45045 : -- ALGLIB PROJECT --
45046 : Copyright 05.07.2007 by Bochkanov Sergey
45047 : *************************************************************************/
45048 0 : void spline2dbuildbilinear(/* Real */ ae_vector* x,
45049 : /* Real */ ae_vector* y,
45050 : /* Real */ ae_matrix* f,
45051 : ae_int_t m,
45052 : ae_int_t n,
45053 : spline2dinterpolant* c,
45054 : ae_state *_state)
45055 : {
45056 : double t;
45057 : ae_int_t i;
45058 : ae_int_t j;
45059 : ae_int_t k;
45060 :
45061 0 : _spline2dinterpolant_clear(c);
45062 :
45063 0 : ae_assert(n>=2, "Spline2DBuildBilinear: N<2", _state);
45064 0 : ae_assert(m>=2, "Spline2DBuildBilinear: M<2", _state);
45065 0 : ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBilinear: length of X or Y is too short (Length(X/Y)<N/M)", _state);
45066 0 : ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBilinear: X or Y contains NaN or Infinite value", _state);
45067 0 : ae_assert(f->rows>=m&&f->cols>=n, "Spline2DBuildBilinear: size of F is too small (rows(F)<M or cols(F)<N)", _state);
45068 0 : ae_assert(apservisfinitematrix(f, m, n, _state), "Spline2DBuildBilinear: F contains NaN or Infinite value", _state);
45069 :
45070 : /*
45071 : * Fill interpolant
45072 : */
45073 0 : c->n = n;
45074 0 : c->m = m;
45075 0 : c->d = 1;
45076 0 : c->stype = -1;
45077 0 : ae_vector_set_length(&c->x, c->n, _state);
45078 0 : ae_vector_set_length(&c->y, c->m, _state);
45079 0 : ae_vector_set_length(&c->f, c->n*c->m, _state);
45080 0 : for(i=0; i<=c->n-1; i++)
45081 : {
45082 0 : c->x.ptr.p_double[i] = x->ptr.p_double[i];
45083 : }
45084 0 : for(i=0; i<=c->m-1; i++)
45085 : {
45086 0 : c->y.ptr.p_double[i] = y->ptr.p_double[i];
45087 : }
45088 0 : for(i=0; i<=c->m-1; i++)
45089 : {
45090 0 : for(j=0; j<=c->n-1; j++)
45091 : {
45092 0 : c->f.ptr.p_double[i*c->n+j] = f->ptr.pp_double[i][j];
45093 : }
45094 : }
45095 :
45096 : /*
45097 : * Sort points
45098 : */
45099 0 : for(j=0; j<=c->n-1; j++)
45100 : {
45101 0 : k = j;
45102 0 : for(i=j+1; i<=c->n-1; i++)
45103 : {
45104 0 : if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
45105 : {
45106 0 : k = i;
45107 : }
45108 : }
45109 0 : if( k!=j )
45110 : {
45111 0 : for(i=0; i<=c->m-1; i++)
45112 : {
45113 0 : t = c->f.ptr.p_double[i*c->n+j];
45114 0 : c->f.ptr.p_double[i*c->n+j] = c->f.ptr.p_double[i*c->n+k];
45115 0 : c->f.ptr.p_double[i*c->n+k] = t;
45116 : }
45117 0 : t = c->x.ptr.p_double[j];
45118 0 : c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
45119 0 : c->x.ptr.p_double[k] = t;
45120 : }
45121 : }
45122 0 : for(i=0; i<=c->m-1; i++)
45123 : {
45124 0 : k = i;
45125 0 : for(j=i+1; j<=c->m-1; j++)
45126 : {
45127 0 : if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
45128 : {
45129 0 : k = j;
45130 : }
45131 : }
45132 0 : if( k!=i )
45133 : {
45134 0 : for(j=0; j<=c->n-1; j++)
45135 : {
45136 0 : t = c->f.ptr.p_double[i*c->n+j];
45137 0 : c->f.ptr.p_double[i*c->n+j] = c->f.ptr.p_double[k*c->n+j];
45138 0 : c->f.ptr.p_double[k*c->n+j] = t;
45139 : }
45140 0 : t = c->y.ptr.p_double[i];
45141 0 : c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
45142 0 : c->y.ptr.p_double[k] = t;
45143 : }
45144 : }
45145 0 : }
45146 :
45147 :
45148 : /*************************************************************************
45149 : This subroutine was deprecated in ALGLIB 3.6.0
45150 :
45151 : We recommend you to switch to Spline2DBuildBicubicV(), which is more
45152 : flexible and accepts its arguments in more convenient order.
45153 :
45154 : -- ALGLIB PROJECT --
45155 : Copyright 05.07.2007 by Bochkanov Sergey
45156 : *************************************************************************/
45157 0 : void spline2dbuildbicubic(/* Real */ ae_vector* x,
45158 : /* Real */ ae_vector* y,
45159 : /* Real */ ae_matrix* f,
45160 : ae_int_t m,
45161 : ae_int_t n,
45162 : spline2dinterpolant* c,
45163 : ae_state *_state)
45164 : {
45165 : ae_frame _frame_block;
45166 : ae_matrix _f;
45167 : ae_int_t sfx;
45168 : ae_int_t sfy;
45169 : ae_int_t sfxy;
45170 : ae_matrix dx;
45171 : ae_matrix dy;
45172 : ae_matrix dxy;
45173 : double t;
45174 : ae_int_t i;
45175 : ae_int_t j;
45176 : ae_int_t k;
45177 :
45178 0 : ae_frame_make(_state, &_frame_block);
45179 0 : memset(&_f, 0, sizeof(_f));
45180 0 : memset(&dx, 0, sizeof(dx));
45181 0 : memset(&dy, 0, sizeof(dy));
45182 0 : memset(&dxy, 0, sizeof(dxy));
45183 0 : ae_matrix_init_copy(&_f, f, _state, ae_true);
45184 0 : f = &_f;
45185 0 : _spline2dinterpolant_clear(c);
45186 0 : ae_matrix_init(&dx, 0, 0, DT_REAL, _state, ae_true);
45187 0 : ae_matrix_init(&dy, 0, 0, DT_REAL, _state, ae_true);
45188 0 : ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true);
45189 :
45190 0 : ae_assert(n>=2, "Spline2DBuildBicubicSpline: N<2", _state);
45191 0 : ae_assert(m>=2, "Spline2DBuildBicubicSpline: M<2", _state);
45192 0 : ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBicubic: length of X or Y is too short (Length(X/Y)<N/M)", _state);
45193 0 : ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBicubic: X or Y contains NaN or Infinite value", _state);
45194 0 : ae_assert(f->rows>=m&&f->cols>=n, "Spline2DBuildBicubic: size of F is too small (rows(F)<M or cols(F)<N)", _state);
45195 0 : ae_assert(apservisfinitematrix(f, m, n, _state), "Spline2DBuildBicubic: F contains NaN or Infinite value", _state);
45196 :
45197 : /*
45198 : * Fill interpolant:
45199 : * F[0]...F[N*M-1]:
45200 : * f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on...
45201 : * F[N*M]...F[2*N*M-1]:
45202 : * df(i,j)/dx table.
45203 : * F[2*N*M]...F[3*N*M-1]:
45204 : * df(i,j)/dy table.
45205 : * F[3*N*M]...F[4*N*M-1]:
45206 : * d2f(i,j)/dxdy table.
45207 : */
45208 0 : c->d = 1;
45209 0 : c->n = n;
45210 0 : c->m = m;
45211 0 : c->stype = -3;
45212 0 : sfx = c->n*c->m;
45213 0 : sfy = 2*c->n*c->m;
45214 0 : sfxy = 3*c->n*c->m;
45215 0 : ae_vector_set_length(&c->x, c->n, _state);
45216 0 : ae_vector_set_length(&c->y, c->m, _state);
45217 0 : ae_vector_set_length(&c->f, 4*c->n*c->m, _state);
45218 0 : for(i=0; i<=c->n-1; i++)
45219 : {
45220 0 : c->x.ptr.p_double[i] = x->ptr.p_double[i];
45221 : }
45222 0 : for(i=0; i<=c->m-1; i++)
45223 : {
45224 0 : c->y.ptr.p_double[i] = y->ptr.p_double[i];
45225 : }
45226 :
45227 : /*
45228 : * Sort points
45229 : */
45230 0 : for(j=0; j<=c->n-1; j++)
45231 : {
45232 0 : k = j;
45233 0 : for(i=j+1; i<=c->n-1; i++)
45234 : {
45235 0 : if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
45236 : {
45237 0 : k = i;
45238 : }
45239 : }
45240 0 : if( k!=j )
45241 : {
45242 0 : for(i=0; i<=c->m-1; i++)
45243 : {
45244 0 : t = f->ptr.pp_double[i][j];
45245 0 : f->ptr.pp_double[i][j] = f->ptr.pp_double[i][k];
45246 0 : f->ptr.pp_double[i][k] = t;
45247 : }
45248 0 : t = c->x.ptr.p_double[j];
45249 0 : c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
45250 0 : c->x.ptr.p_double[k] = t;
45251 : }
45252 : }
45253 0 : for(i=0; i<=c->m-1; i++)
45254 : {
45255 0 : k = i;
45256 0 : for(j=i+1; j<=c->m-1; j++)
45257 : {
45258 0 : if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
45259 : {
45260 0 : k = j;
45261 : }
45262 : }
45263 0 : if( k!=i )
45264 : {
45265 0 : for(j=0; j<=c->n-1; j++)
45266 : {
45267 0 : t = f->ptr.pp_double[i][j];
45268 0 : f->ptr.pp_double[i][j] = f->ptr.pp_double[k][j];
45269 0 : f->ptr.pp_double[k][j] = t;
45270 : }
45271 0 : t = c->y.ptr.p_double[i];
45272 0 : c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
45273 0 : c->y.ptr.p_double[k] = t;
45274 : }
45275 : }
45276 0 : spline2d_bicubiccalcderivatives(f, &c->x, &c->y, c->m, c->n, &dx, &dy, &dxy, _state);
45277 0 : for(i=0; i<=c->m-1; i++)
45278 : {
45279 0 : for(j=0; j<=c->n-1; j++)
45280 : {
45281 0 : k = i*c->n+j;
45282 0 : c->f.ptr.p_double[k] = f->ptr.pp_double[i][j];
45283 0 : c->f.ptr.p_double[sfx+k] = dx.ptr.pp_double[i][j];
45284 0 : c->f.ptr.p_double[sfy+k] = dy.ptr.pp_double[i][j];
45285 0 : c->f.ptr.p_double[sfxy+k] = dxy.ptr.pp_double[i][j];
45286 : }
45287 : }
45288 0 : ae_frame_leave(_state);
45289 0 : }
45290 :
45291 :
45292 : /*************************************************************************
45293 : This subroutine was deprecated in ALGLIB 3.6.0
45294 :
45295 : We recommend you to switch to Spline2DUnpackV(), which is more flexible
45296 : and accepts its arguments in more convenient order.
45297 :
45298 : -- ALGLIB PROJECT --
45299 : Copyright 29.06.2007 by Bochkanov Sergey
45300 : *************************************************************************/
45301 0 : void spline2dunpack(spline2dinterpolant* c,
45302 : ae_int_t* m,
45303 : ae_int_t* n,
45304 : /* Real */ ae_matrix* tbl,
45305 : ae_state *_state)
45306 : {
45307 : ae_int_t k;
45308 : ae_int_t p;
45309 : ae_int_t ci;
45310 : ae_int_t cj;
45311 : ae_int_t s1;
45312 : ae_int_t s2;
45313 : ae_int_t s3;
45314 : ae_int_t s4;
45315 : ae_int_t sfx;
45316 : ae_int_t sfy;
45317 : ae_int_t sfxy;
45318 : double y1;
45319 : double y2;
45320 : double y3;
45321 : double y4;
45322 : double dt;
45323 : double du;
45324 : ae_int_t i;
45325 : ae_int_t j;
45326 :
45327 0 : *m = 0;
45328 0 : *n = 0;
45329 0 : ae_matrix_clear(tbl);
45330 :
45331 0 : ae_assert(c->stype==-3||c->stype==-1, "Spline2DUnpack: incorrect C (incorrect parameter C.SType)", _state);
45332 0 : if( c->d!=1 )
45333 : {
45334 0 : *n = 0;
45335 0 : *m = 0;
45336 0 : return;
45337 : }
45338 0 : *n = c->n;
45339 0 : *m = c->m;
45340 0 : ae_matrix_set_length(tbl, (*n-1)*(*m-1), 20, _state);
45341 0 : sfx = *n*(*m);
45342 0 : sfy = 2*(*n)*(*m);
45343 0 : sfxy = 3*(*n)*(*m);
45344 :
45345 : /*
45346 : * Fill
45347 : */
45348 0 : for(i=0; i<=*m-2; i++)
45349 : {
45350 0 : for(j=0; j<=*n-2; j++)
45351 : {
45352 0 : p = i*(*n-1)+j;
45353 0 : tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[j];
45354 0 : tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[j+1];
45355 0 : tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[i];
45356 0 : tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[i+1];
45357 0 : dt = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]);
45358 0 : du = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]);
45359 :
45360 : /*
45361 : * Bilinear interpolation
45362 : */
45363 0 : if( c->stype==-1 )
45364 : {
45365 0 : for(k=4; k<=19; k++)
45366 : {
45367 0 : tbl->ptr.pp_double[p][k] = (double)(0);
45368 : }
45369 0 : y1 = c->f.ptr.p_double[*n*i+j];
45370 0 : y2 = c->f.ptr.p_double[*n*i+(j+1)];
45371 0 : y3 = c->f.ptr.p_double[*n*(i+1)+(j+1)];
45372 0 : y4 = c->f.ptr.p_double[*n*(i+1)+j];
45373 0 : tbl->ptr.pp_double[p][4] = y1;
45374 0 : tbl->ptr.pp_double[p][4+1*4+0] = y2-y1;
45375 0 : tbl->ptr.pp_double[p][4+0*4+1] = y4-y1;
45376 0 : tbl->ptr.pp_double[p][4+1*4+1] = y3-y2-y4+y1;
45377 : }
45378 :
45379 : /*
45380 : * Bicubic interpolation
45381 : */
45382 0 : if( c->stype==-3 )
45383 : {
45384 0 : s1 = *n*i+j;
45385 0 : s2 = *n*i+(j+1);
45386 0 : s3 = *n*(i+1)+(j+1);
45387 0 : s4 = *n*(i+1)+j;
45388 0 : tbl->ptr.pp_double[p][4+0*4+0] = c->f.ptr.p_double[s1];
45389 0 : tbl->ptr.pp_double[p][4+0*4+1] = c->f.ptr.p_double[sfy+s1]/du;
45390 0 : tbl->ptr.pp_double[p][4+0*4+2] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s4]-2*c->f.ptr.p_double[sfy+s1]/du-c->f.ptr.p_double[sfy+s4]/du;
45391 0 : tbl->ptr.pp_double[p][4+0*4+3] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s4]+c->f.ptr.p_double[sfy+s1]/du+c->f.ptr.p_double[sfy+s4]/du;
45392 0 : tbl->ptr.pp_double[p][4+1*4+0] = c->f.ptr.p_double[sfx+s1]/dt;
45393 0 : tbl->ptr.pp_double[p][4+1*4+1] = c->f.ptr.p_double[sfxy+s1]/(dt*du);
45394 0 : tbl->ptr.pp_double[p][4+1*4+2] = -3*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du);
45395 0 : tbl->ptr.pp_double[p][4+1*4+3] = 2*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du);
45396 0 : tbl->ptr.pp_double[p][4+2*4+0] = -3*c->f.ptr.p_double[s1]+3*c->f.ptr.p_double[s2]-2*c->f.ptr.p_double[sfx+s1]/dt-c->f.ptr.p_double[sfx+s2]/dt;
45397 0 : tbl->ptr.pp_double[p][4+2*4+1] = -3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du);
45398 0 : tbl->ptr.pp_double[p][4+2*4+2] = 9*c->f.ptr.p_double[s1]-9*c->f.ptr.p_double[s2]+9*c->f.ptr.p_double[s3]-9*c->f.ptr.p_double[s4]+6*c->f.ptr.p_double[sfx+s1]/dt+3*c->f.ptr.p_double[sfx+s2]/dt-3*c->f.ptr.p_double[sfx+s3]/dt-6*c->f.ptr.p_double[sfx+s4]/dt+6*c->f.ptr.p_double[sfy+s1]/du-6*c->f.ptr.p_double[sfy+s2]/du-3*c->f.ptr.p_double[sfy+s3]/du+3*c->f.ptr.p_double[sfy+s4]/du+4*c->f.ptr.p_double[sfxy+s1]/(dt*du)+2*c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+2*c->f.ptr.p_double[sfxy+s4]/(dt*du);
45399 0 : tbl->ptr.pp_double[p][4+2*4+3] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-4*c->f.ptr.p_double[sfx+s1]/dt-2*c->f.ptr.p_double[sfx+s2]/dt+2*c->f.ptr.p_double[sfx+s3]/dt+4*c->f.ptr.p_double[sfx+s4]/dt-3*c->f.ptr.p_double[sfy+s1]/du+3*c->f.ptr.p_double[sfy+s2]/du+3*c->f.ptr.p_double[sfy+s3]/du-3*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-2*c->f.ptr.p_double[sfxy+s4]/(dt*du);
45400 0 : tbl->ptr.pp_double[p][4+3*4+0] = 2*c->f.ptr.p_double[s1]-2*c->f.ptr.p_double[s2]+c->f.ptr.p_double[sfx+s1]/dt+c->f.ptr.p_double[sfx+s2]/dt;
45401 0 : tbl->ptr.pp_double[p][4+3*4+1] = 2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du);
45402 0 : tbl->ptr.pp_double[p][4+3*4+2] = -6*c->f.ptr.p_double[s1]+6*c->f.ptr.p_double[s2]-6*c->f.ptr.p_double[s3]+6*c->f.ptr.p_double[s4]-3*c->f.ptr.p_double[sfx+s1]/dt-3*c->f.ptr.p_double[sfx+s2]/dt+3*c->f.ptr.p_double[sfx+s3]/dt+3*c->f.ptr.p_double[sfx+s4]/dt-4*c->f.ptr.p_double[sfy+s1]/du+4*c->f.ptr.p_double[sfy+s2]/du+2*c->f.ptr.p_double[sfy+s3]/du-2*c->f.ptr.p_double[sfy+s4]/du-2*c->f.ptr.p_double[sfxy+s1]/(dt*du)-2*c->f.ptr.p_double[sfxy+s2]/(dt*du)-c->f.ptr.p_double[sfxy+s3]/(dt*du)-c->f.ptr.p_double[sfxy+s4]/(dt*du);
45403 0 : tbl->ptr.pp_double[p][4+3*4+3] = 4*c->f.ptr.p_double[s1]-4*c->f.ptr.p_double[s2]+4*c->f.ptr.p_double[s3]-4*c->f.ptr.p_double[s4]+2*c->f.ptr.p_double[sfx+s1]/dt+2*c->f.ptr.p_double[sfx+s2]/dt-2*c->f.ptr.p_double[sfx+s3]/dt-2*c->f.ptr.p_double[sfx+s4]/dt+2*c->f.ptr.p_double[sfy+s1]/du-2*c->f.ptr.p_double[sfy+s2]/du-2*c->f.ptr.p_double[sfy+s3]/du+2*c->f.ptr.p_double[sfy+s4]/du+c->f.ptr.p_double[sfxy+s1]/(dt*du)+c->f.ptr.p_double[sfxy+s2]/(dt*du)+c->f.ptr.p_double[sfxy+s3]/(dt*du)+c->f.ptr.p_double[sfxy+s4]/(dt*du);
45404 : }
45405 :
45406 : /*
45407 : * Rescale Cij
45408 : */
45409 0 : for(ci=0; ci<=3; ci++)
45410 : {
45411 0 : for(cj=0; cj<=3; cj++)
45412 : {
45413 0 : tbl->ptr.pp_double[p][4+ci*4+cj] = tbl->ptr.pp_double[p][4+ci*4+cj]*ae_pow(dt, (double)(ci), _state)*ae_pow(du, (double)(cj), _state);
45414 : }
45415 : }
45416 : }
45417 : }
45418 : }
45419 :
45420 :
45421 : /*************************************************************************
45422 : This subroutine creates least squares solver used to fit 2D splines to
45423 : irregularly sampled (scattered) data.
45424 :
45425 : Solver object is used to perform spline fits as follows:
45426 : * solver object is created with spline2dbuildercreate() function
45427 : * dataset is added with spline2dbuildersetpoints() function
45428 : * fit area is chosen:
45429 : * spline2dbuildersetarea() - for user-defined area
45430 : * spline2dbuildersetareaauto() - for automatically chosen area
45431 : * number of grid nodes is chosen with spline2dbuildersetgrid()
45432 : * prior term is chosen with one of the following functions:
45433 : * spline2dbuildersetlinterm() to set linear prior
45434 : * spline2dbuildersetconstterm() to set constant prior
45435 : * spline2dbuildersetzeroterm() to set zero prior
45436 : * spline2dbuildersetuserterm() to set user-defined constant prior
45437 : * solver algorithm is chosen with either:
45438 : * spline2dbuildersetalgoblocklls() - BlockLLS algorithm, medium-scale problems
45439 : * spline2dbuildersetalgofastddm() - FastDDM algorithm, large-scale problems
45440 : * finally, fitting itself is performed with spline2dfit() function.
45441 :
45442 : Most of the steps above can be omitted, solver is configured with good
45443 : defaults. The minimum is to call:
45444 : * spline2dbuildercreate() to create solver object
45445 : * spline2dbuildersetpoints() to specify dataset
45446 : * spline2dbuildersetgrid() to tell how many nodes you need
45447 : * spline2dfit() to perform fit
45448 :
45449 : ! COMMERCIAL EDITION OF ALGLIB:
45450 : !
45451 : ! Commercial Edition of ALGLIB includes following important improvements
45452 : ! of this function:
45453 : ! * high-performance native backend with same C# interface (C# version)
45454 : ! * multithreading support (C++ and C# versions)
45455 : ! * hardware vendor (Intel) implementations of linear algebra primitives
45456 : ! (C++ and C# versions, x86/x64 platform)
45457 : !
45458 : ! We recommend you to read 'Working with commercial version' section of
45459 : ! ALGLIB Reference Manual in order to find out how to use performance-
45460 : ! related features provided by commercial edition of ALGLIB.
45461 :
45462 : INPUT PARAMETERS:
45463 : D - positive number, number of Y-components: D=1 for simple scalar
45464 : fit, D>1 for vector-valued spline fitting.
45465 :
45466 : OUTPUT PARAMETERS:
45467 : S - solver object
45468 :
45469 : -- ALGLIB PROJECT --
45470 : Copyright 29.01.2018 by Bochkanov Sergey
45471 : *************************************************************************/
45472 0 : void spline2dbuildercreate(ae_int_t d,
45473 : spline2dbuilder* state,
45474 : ae_state *_state)
45475 : {
45476 :
45477 0 : _spline2dbuilder_clear(state);
45478 :
45479 0 : ae_assert(d>=1, "Spline2DBuilderCreate: D<=0", _state);
45480 :
45481 : /*
45482 : * NOTES:
45483 : *
45484 : * 1. Prior term is set to linear one (good default option)
45485 : * 2. Solver is set to BlockLLS - good enough for small-scale problems.
45486 : * 3. Refinement rounds: 5; enough to get good convergence.
45487 : */
45488 0 : state->priorterm = 1;
45489 0 : state->priortermval = (double)(0);
45490 0 : state->areatype = 0;
45491 0 : state->gridtype = 0;
45492 0 : state->smoothing = 0.0;
45493 0 : state->nlayers = 0;
45494 0 : state->solvertype = 1;
45495 0 : state->npoints = 0;
45496 0 : state->d = d;
45497 0 : state->sx = 1.0;
45498 0 : state->sy = 1.0;
45499 0 : state->lsqrcnt = 5;
45500 :
45501 : /*
45502 : * Algorithm settings
45503 : */
45504 0 : state->adddegreeoffreedom = ae_true;
45505 0 : state->maxcoresize = 16;
45506 0 : state->interfacesize = 5;
45507 0 : }
45508 :
45509 :
45510 : /*************************************************************************
45511 : This function sets constant prior term (model is a sum of bicubic spline
45512 : and global prior, which can be linear, constant, user-defined constant or
45513 : zero).
45514 :
45515 : Constant prior term is determined by least squares fitting.
45516 :
45517 : INPUT PARAMETERS:
45518 : S - spline builder
45519 : V - value for user-defined prior
45520 :
45521 : -- ALGLIB --
45522 : Copyright 01.02.2018 by Bochkanov Sergey
45523 : *************************************************************************/
45524 0 : void spline2dbuildersetuserterm(spline2dbuilder* state,
45525 : double v,
45526 : ae_state *_state)
45527 : {
45528 :
45529 :
45530 0 : ae_assert(ae_isfinite(v, _state), "Spline2DBuilderSetUserTerm: infinite/NAN value passed", _state);
45531 0 : state->priorterm = 0;
45532 0 : state->priortermval = v;
45533 0 : }
45534 :
45535 :
45536 : /*************************************************************************
45537 : This function sets linear prior term (model is a sum of bicubic spline and
45538 : global prior, which can be linear, constant, user-defined constant or
45539 : zero).
45540 :
45541 : Linear prior term is determined by least squares fitting.
45542 :
45543 : INPUT PARAMETERS:
45544 : S - spline builder
45545 :
45546 : -- ALGLIB --
45547 : Copyright 01.02.2018 by Bochkanov Sergey
45548 : *************************************************************************/
45549 0 : void spline2dbuildersetlinterm(spline2dbuilder* state, ae_state *_state)
45550 : {
45551 :
45552 :
45553 0 : state->priorterm = 1;
45554 0 : }
45555 :
45556 :
45557 : /*************************************************************************
45558 : This function sets constant prior term (model is a sum of bicubic spline
45559 : and global prior, which can be linear, constant, user-defined constant or
45560 : zero).
45561 :
45562 : Constant prior term is determined by least squares fitting.
45563 :
45564 : INPUT PARAMETERS:
45565 : S - spline builder
45566 :
45567 : -- ALGLIB --
45568 : Copyright 01.02.2018 by Bochkanov Sergey
45569 : *************************************************************************/
45570 0 : void spline2dbuildersetconstterm(spline2dbuilder* state, ae_state *_state)
45571 : {
45572 :
45573 :
45574 0 : state->priorterm = 2;
45575 0 : }
45576 :
45577 :
45578 : /*************************************************************************
45579 : This function sets zero prior term (model is a sum of bicubic spline and
45580 : global prior, which can be linear, constant, user-defined constant or
45581 : zero).
45582 :
45583 : INPUT PARAMETERS:
45584 : S - spline builder
45585 :
45586 : -- ALGLIB --
45587 : Copyright 01.02.2018 by Bochkanov Sergey
45588 : *************************************************************************/
45589 0 : void spline2dbuildersetzeroterm(spline2dbuilder* state, ae_state *_state)
45590 : {
45591 :
45592 :
45593 0 : state->priorterm = 3;
45594 0 : }
45595 :
45596 :
45597 : /*************************************************************************
45598 : This function adds dataset to the builder object.
45599 :
45600 : This function overrides results of the previous calls, i.e. multiple calls
45601 : of this function will result in only the last set being added.
45602 :
45603 : INPUT PARAMETERS:
45604 : S - spline 2D builder object
45605 : XY - points, array[N,2+D]. One row corresponds to one point
45606 : in the dataset. First 2 elements are coordinates, next
45607 : D elements are function values. Array may be larger than
45608 : specified, in this case only leading [N,NX+NY] elements
45609 : will be used.
45610 : N - number of points in the dataset
45611 :
45612 : -- ALGLIB --
45613 : Copyright 05.02.2018 by Bochkanov Sergey
45614 : *************************************************************************/
45615 0 : void spline2dbuildersetpoints(spline2dbuilder* state,
45616 : /* Real */ ae_matrix* xy,
45617 : ae_int_t n,
45618 : ae_state *_state)
45619 : {
45620 : ae_int_t i;
45621 : ae_int_t j;
45622 : ae_int_t ew;
45623 :
45624 :
45625 0 : ae_assert(n>0, "Spline2DBuilderSetPoints: N<0", _state);
45626 0 : ae_assert(xy->rows>=n, "Spline2DBuilderSetPoints: Rows(XY)<N", _state);
45627 0 : ae_assert(xy->cols>=2+state->d, "Spline2DBuilderSetPoints: Cols(XY)<NX+NY", _state);
45628 0 : ae_assert(apservisfinitematrix(xy, n, 2+state->d, _state), "Spline2DBuilderSetPoints: XY contains infinite or NaN values!", _state);
45629 0 : state->npoints = n;
45630 0 : ew = 2+state->d;
45631 0 : rvectorsetlengthatleast(&state->xy, n*ew, _state);
45632 0 : for(i=0; i<=n-1; i++)
45633 : {
45634 0 : for(j=0; j<=ew-1; j++)
45635 : {
45636 0 : state->xy.ptr.p_double[i*ew+j] = xy->ptr.pp_double[i][j];
45637 : }
45638 : }
45639 0 : }
45640 :
45641 :
45642 : /*************************************************************************
45643 : This function sets area where 2D spline interpolant is built. "Auto" means
45644 : that area extent is determined automatically from dataset extent.
45645 :
45646 : INPUT PARAMETERS:
45647 : S - spline 2D builder object
45648 :
45649 : -- ALGLIB --
45650 : Copyright 05.02.2018 by Bochkanov Sergey
45651 : *************************************************************************/
45652 0 : void spline2dbuildersetareaauto(spline2dbuilder* state, ae_state *_state)
45653 : {
45654 :
45655 :
45656 0 : state->areatype = 0;
45657 0 : }
45658 :
45659 :
45660 : /*************************************************************************
45661 : This function sets area where 2D spline interpolant is built to
45662 : user-defined one: [XA,XB]*[YA,YB]
45663 :
45664 : INPUT PARAMETERS:
45665 : S - spline 2D builder object
45666 : XA,XB - spatial extent in the first (X) dimension, XA<XB
45667 : YA,YB - spatial extent in the second (Y) dimension, YA<YB
45668 :
45669 : -- ALGLIB --
45670 : Copyright 05.02.2018 by Bochkanov Sergey
45671 : *************************************************************************/
45672 0 : void spline2dbuildersetarea(spline2dbuilder* state,
45673 : double xa,
45674 : double xb,
45675 : double ya,
45676 : double yb,
45677 : ae_state *_state)
45678 : {
45679 :
45680 :
45681 0 : ae_assert(ae_isfinite(xa, _state), "Spline2DBuilderSetArea: XA is not finite", _state);
45682 0 : ae_assert(ae_isfinite(xb, _state), "Spline2DBuilderSetArea: XB is not finite", _state);
45683 0 : ae_assert(ae_isfinite(ya, _state), "Spline2DBuilderSetArea: YA is not finite", _state);
45684 0 : ae_assert(ae_isfinite(yb, _state), "Spline2DBuilderSetArea: YB is not finite", _state);
45685 0 : ae_assert(ae_fp_less(xa,xb), "Spline2DBuilderSetArea: XA>=XB", _state);
45686 0 : ae_assert(ae_fp_less(ya,yb), "Spline2DBuilderSetArea: YA>=YB", _state);
45687 0 : state->areatype = 1;
45688 0 : state->xa = xa;
45689 0 : state->xb = xb;
45690 0 : state->ya = ya;
45691 0 : state->yb = yb;
45692 0 : }
45693 :
45694 :
45695 : /*************************************************************************
45696 : This function sets nodes count for 2D spline interpolant. Fitting is
45697 : performed on area defined with one of the "setarea" functions; this one
45698 : sets number of nodes placed upon the fitting area.
45699 :
45700 : INPUT PARAMETERS:
45701 : S - spline 2D builder object
45702 : KX - nodes count for the first (X) dimension; fitting interval
45703 : [XA,XB] is separated into KX-1 subintervals, with KX nodes
45704 : created at the boundaries.
45705 : KY - nodes count for the first (Y) dimension; fitting interval
45706 : [YA,YB] is separated into KY-1 subintervals, with KY nodes
45707 : created at the boundaries.
45708 :
45709 : NOTE: at least 4 nodes is created in each dimension, so KX and KY are
45710 : silently increased if needed.
45711 :
45712 : -- ALGLIB --
45713 : Copyright 05.02.2018 by Bochkanov Sergey
45714 : *************************************************************************/
45715 0 : void spline2dbuildersetgrid(spline2dbuilder* state,
45716 : ae_int_t kx,
45717 : ae_int_t ky,
45718 : ae_state *_state)
45719 : {
45720 :
45721 :
45722 0 : ae_assert(kx>0, "Spline2DBuilderSetGridSizePrecisely: KX<=0", _state);
45723 0 : ae_assert(ky>0, "Spline2DBuilderSetGridSizePrecisely: KY<=0", _state);
45724 0 : state->gridtype = 1;
45725 0 : state->kx = ae_maxint(kx, 4, _state);
45726 0 : state->ky = ae_maxint(ky, 4, _state);
45727 0 : }
45728 :
45729 :
45730 : /*************************************************************************
45731 : This function allows you to choose least squares solver used to perform
45732 : fitting. This function sets solver algorithm to "FastDDM", which performs
45733 : fast parallel fitting by splitting problem into smaller chunks and merging
45734 : results together.
45735 :
45736 : This solver is optimized for large-scale problems, starting from 256x256
45737 : grids, and up to 10000x10000 grids. Of course, it will work for smaller
45738 : grids too.
45739 :
45740 : More detailed description of the algorithm is given below:
45741 : * algorithm generates hierarchy of nested grids, ranging from ~16x16
45742 : (topmost "layer" of the model) to ~KX*KY one (final layer). Upper layers
45743 : model global behavior of the function, lower layers are used to model
45744 : fine details. Moving from layer to layer doubles grid density.
45745 : * fitting is started from topmost layer, subsequent layers are fitted
45746 : using residuals from previous ones.
45747 : * user may choose to skip generation of upper layers and generate only a
45748 : few bottom ones, which will result in much better performance and
45749 : parallelization efficiency, at the cost of algorithm inability to "patch"
45750 : large holes in the dataset.
45751 : * every layer is regularized using progressively increasing regularization
45752 : coefficient; thus, increasing LambdaV penalizes fine details first,
45753 : leaving lower frequencies almost intact for a while.
45754 : * after fitting is done, all layers are merged together into one bicubic
45755 : spline
45756 :
45757 : IMPORTANT: regularization coefficient used by this solver is different
45758 : from the one used by BlockLLS. Latter utilizes nonlinearity
45759 : penalty, which is global in nature (large regularization
45760 : results in global linear trend being extracted); this solver
45761 : uses another, localized form of penalty, which is suitable for
45762 : parallel processing.
45763 :
45764 : Notes on memory and performance:
45765 : * memory requirements: most memory is consumed during modeling of the
45766 : higher layers; ~[512*NPoints] bytes is required for a model with full
45767 : hierarchy of grids being generated. However, if you skip a few topmost
45768 : layers, you will get nearly constant (wrt. points count and grid size)
45769 : memory consumption.
45770 : * serial running time: O(K*K)+O(NPoints) for a KxK grid
45771 : * parallelism potential: good. You may get nearly linear speed-up when
45772 : performing fitting with just a few layers. Adding more layers results in
45773 : model becoming more global, which somewhat reduces efficiency of the
45774 : parallel code.
45775 :
45776 : ! COMMERCIAL EDITION OF ALGLIB:
45777 : !
45778 : ! Commercial Edition of ALGLIB includes following important improvements
45779 : ! of this function:
45780 : ! * high-performance native backend with same C# interface (C# version)
45781 : ! * multithreading support (C++ and C# versions)
45782 : ! * hardware vendor (Intel) implementations of linear algebra primitives
45783 : ! (C++ and C# versions, x86/x64 platform)
45784 : !
45785 : ! We recommend you to read 'Working with commercial version' section of
45786 : ! ALGLIB Reference Manual in order to find out how to use performance-
45787 : ! related features provided by commercial edition of ALGLIB.
45788 :
45789 : INPUT PARAMETERS:
45790 : S - spline 2D builder object
45791 : NLayers - number of layers in the model:
45792 : * NLayers>=1 means that up to chosen number of bottom
45793 : layers is fitted
45794 : * NLayers=0 means that maximum number of layers is chosen
45795 : (according to current grid size)
45796 : * NLayers<=-1 means that up to |NLayers| topmost layers is
45797 : skipped
45798 : Recommendations:
45799 : * good "default" value is 2 layers
45800 : * you may need more layers, if your dataset is very
45801 : irregular and you want to "patch" large holes. For a
45802 : grid step H (equal to AreaWidth/GridSize) you may expect
45803 : that last layer reproduces variations at distance H (and
45804 : can patch holes that wide); that higher layers operate
45805 : at distances 2*H, 4*H, 8*H and so on.
45806 : * good value for "bullletproof" mode is NLayers=0, which
45807 : results in complete hierarchy of layers being generated.
45808 : LambdaV - regularization coefficient, chosen in such a way that it
45809 : penalizes bottom layers (fine details) first.
45810 : LambdaV>=0, zero value means that no penalty is applied.
45811 :
45812 : -- ALGLIB --
45813 : Copyright 05.02.2018 by Bochkanov Sergey
45814 : *************************************************************************/
45815 0 : void spline2dbuildersetalgofastddm(spline2dbuilder* state,
45816 : ae_int_t nlayers,
45817 : double lambdav,
45818 : ae_state *_state)
45819 : {
45820 :
45821 :
45822 0 : ae_assert(ae_isfinite(lambdav, _state), "Spline2DBuilderSetAlgoFastDDM: LambdaV is not finite value", _state);
45823 0 : ae_assert(ae_fp_greater_eq(lambdav,(double)(0)), "Spline2DBuilderSetAlgoFastDDM: LambdaV<0", _state);
45824 0 : state->solvertype = 3;
45825 0 : state->nlayers = nlayers;
45826 0 : state->smoothing = lambdav;
45827 0 : }
45828 :
45829 :
45830 : /*************************************************************************
45831 : This function allows you to choose least squares solver used to perform
45832 : fitting. This function sets solver algorithm to "BlockLLS", which performs
45833 : least squares fitting with fast sparse direct solver, with optional
45834 : nonsmoothness penalty being applied.
45835 :
45836 : Nonlinearity penalty has the following form:
45837 :
45838 : [ ]
45839 : P() ~ Lambda* integral[ (d2S/dx2)^2 + 2*(d2S/dxdy)^2 + (d2S/dy2)^2 ]dxdy
45840 : [ ]
45841 :
45842 : here integral is calculated over entire grid, and "~" means "proportional"
45843 : because integral is normalized after calcilation. Extremely large values
45844 : of Lambda result in linear fit being performed.
45845 :
45846 : NOTE: this algorithm is the most robust and controllable one, but it is
45847 : limited by 512x512 grids and (say) up to 1.000.000 points. However,
45848 : ALGLIB has one more spline solver: FastDDM algorithm, which is
45849 : intended for really large-scale problems (in 10M-100M range). FastDDM
45850 : algorithm also has better parallelism properties.
45851 :
45852 : More information on BlockLLS solver:
45853 : * memory requirements: ~[32*K^3+256*NPoints] bytes for KxK grid with
45854 : NPoints-sized dataset
45855 : * serial running time: O(K^4+NPoints)
45856 : * parallelism potential: limited. You may get some sublinear gain when
45857 : working with large grids (K's in 256..512 range)
45858 :
45859 : ! COMMERCIAL EDITION OF ALGLIB:
45860 : !
45861 : ! Commercial Edition of ALGLIB includes following important improvements
45862 : ! of this function:
45863 : ! * high-performance native backend with same C# interface (C# version)
45864 : ! * multithreading support (C++ and C# versions)
45865 : ! * hardware vendor (Intel) implementations of linear algebra primitives
45866 : ! (C++ and C# versions, x86/x64 platform)
45867 : !
45868 : ! We recommend you to read 'Working with commercial version' section of
45869 : ! ALGLIB Reference Manual in order to find out how to use performance-
45870 : ! related features provided by commercial edition of ALGLIB.
45871 :
45872 : INPUT PARAMETERS:
45873 : S - spline 2D builder object
45874 : LambdaNS- non-negative value:
45875 : * positive value means that some smoothing is applied
45876 : * zero value means that no smoothing is applied, and
45877 : corresponding entries of design matrix are numerically
45878 : zero and dropped from consideration.
45879 :
45880 : -- ALGLIB --
45881 : Copyright 05.02.2018 by Bochkanov Sergey
45882 : *************************************************************************/
45883 0 : void spline2dbuildersetalgoblocklls(spline2dbuilder* state,
45884 : double lambdans,
45885 : ae_state *_state)
45886 : {
45887 :
45888 :
45889 0 : ae_assert(ae_isfinite(lambdans, _state), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS is not finite value", _state);
45890 0 : ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS<0", _state);
45891 0 : state->solvertype = 1;
45892 0 : state->smoothing = lambdans;
45893 0 : }
45894 :
45895 :
45896 : /*************************************************************************
45897 : This function allows you to choose least squares solver used to perform
45898 : fitting. This function sets solver algorithm to "NaiveLLS".
45899 :
45900 : IMPORTANT: NaiveLLS is NOT intended to be used in real life code! This
45901 : algorithm solves problem by generated dense (K^2)x(K^2+NPoints)
45902 : matrix and solves linear least squares problem with dense
45903 : solver.
45904 :
45905 : It is here just to test BlockLLS against reference solver
45906 : (and maybe for someone trying to compare well optimized solver
45907 : against straightforward approach to the LLS problem).
45908 :
45909 : More information on naive LLS solver:
45910 : * memory requirements: ~[8*K^4+256*NPoints] bytes for KxK grid.
45911 : * serial running time: O(K^6+NPoints) for KxK grid
45912 : * when compared with BlockLLS, NaiveLLS has ~K larger memory demand and
45913 : ~K^2 larger running time.
45914 :
45915 : INPUT PARAMETERS:
45916 : S - spline 2D builder object
45917 : LambdaNS- nonsmoothness penalty
45918 :
45919 : -- ALGLIB --
45920 : Copyright 05.02.2018 by Bochkanov Sergey
45921 : *************************************************************************/
45922 0 : void spline2dbuildersetalgonaivells(spline2dbuilder* state,
45923 : double lambdans,
45924 : ae_state *_state)
45925 : {
45926 :
45927 :
45928 0 : ae_assert(ae_isfinite(lambdans, _state), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS is not finite value", _state);
45929 0 : ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "Spline2DBuilderSetAlgoBlockLLS: LambdaNS<0", _state);
45930 0 : state->solvertype = 2;
45931 0 : state->smoothing = lambdans;
45932 0 : }
45933 :
45934 :
45935 : /*************************************************************************
45936 : This function fits bicubic spline to current dataset, using current area/
45937 : grid and current LLS solver.
45938 :
45939 : ! COMMERCIAL EDITION OF ALGLIB:
45940 : !
45941 : ! Commercial Edition of ALGLIB includes following important improvements
45942 : ! of this function:
45943 : ! * high-performance native backend with same C# interface (C# version)
45944 : ! * multithreading support (C++ and C# versions)
45945 : ! * hardware vendor (Intel) implementations of linear algebra primitives
45946 : ! (C++ and C# versions, x86/x64 platform)
45947 : !
45948 : ! We recommend you to read 'Working with commercial version' section of
45949 : ! ALGLIB Reference Manual in order to find out how to use performance-
45950 : ! related features provided by commercial edition of ALGLIB.
45951 :
45952 : INPUT PARAMETERS:
45953 : State - spline 2D builder object
45954 :
45955 : OUTPUT PARAMETERS:
45956 : S - 2D spline, fit result
45957 : Rep - fitting report, which provides some additional info about
45958 : errors, R2 coefficient and so on.
45959 :
45960 : -- ALGLIB --
45961 : Copyright 05.02.2018 by Bochkanov Sergey
45962 : *************************************************************************/
45963 0 : void spline2dfit(spline2dbuilder* state,
45964 : spline2dinterpolant* s,
45965 : spline2dfitreport* rep,
45966 : ae_state *_state)
45967 : {
45968 : ae_frame _frame_block;
45969 : double xa;
45970 : double xb;
45971 : double ya;
45972 : double yb;
45973 : double xaraw;
45974 : double xbraw;
45975 : double yaraw;
45976 : double ybraw;
45977 : ae_int_t kx;
45978 : ae_int_t ky;
45979 : double hx;
45980 : double hy;
45981 : double invhx;
45982 : double invhy;
45983 : ae_int_t gridexpansion;
45984 : ae_int_t nzwidth;
45985 : ae_int_t bfrad;
45986 : ae_int_t npoints;
45987 : ae_int_t d;
45988 : ae_int_t ew;
45989 : ae_int_t i;
45990 : ae_int_t j;
45991 : ae_int_t k;
45992 : double v;
45993 : ae_int_t k0;
45994 : ae_int_t k1;
45995 : double vx;
45996 : double vy;
45997 : ae_int_t arows;
45998 : ae_int_t acopied;
45999 : ae_int_t basecasex;
46000 : ae_int_t basecasey;
46001 : double eps;
46002 : ae_vector xywork;
46003 : ae_matrix vterm;
46004 : ae_vector tmpx;
46005 : ae_vector tmpy;
46006 : ae_vector tmp0;
46007 : ae_vector tmp1;
46008 : ae_vector meany;
46009 : ae_vector xyindex;
46010 : ae_vector tmpi;
46011 : spline1dinterpolant basis1;
46012 : sparsematrix av;
46013 : sparsematrix ah;
46014 : spline2dxdesignmatrix xdesignmatrix;
46015 : ae_vector z;
46016 : spline2dblockllsbuf blockllsbuf;
46017 : ae_int_t sfx;
46018 : ae_int_t sfy;
46019 : ae_int_t sfxy;
46020 : double tss;
46021 : ae_int_t dstidx;
46022 :
46023 0 : ae_frame_make(_state, &_frame_block);
46024 0 : memset(&xywork, 0, sizeof(xywork));
46025 0 : memset(&vterm, 0, sizeof(vterm));
46026 0 : memset(&tmpx, 0, sizeof(tmpx));
46027 0 : memset(&tmpy, 0, sizeof(tmpy));
46028 0 : memset(&tmp0, 0, sizeof(tmp0));
46029 0 : memset(&tmp1, 0, sizeof(tmp1));
46030 0 : memset(&meany, 0, sizeof(meany));
46031 0 : memset(&xyindex, 0, sizeof(xyindex));
46032 0 : memset(&tmpi, 0, sizeof(tmpi));
46033 0 : memset(&basis1, 0, sizeof(basis1));
46034 0 : memset(&av, 0, sizeof(av));
46035 0 : memset(&ah, 0, sizeof(ah));
46036 0 : memset(&xdesignmatrix, 0, sizeof(xdesignmatrix));
46037 0 : memset(&z, 0, sizeof(z));
46038 0 : memset(&blockllsbuf, 0, sizeof(blockllsbuf));
46039 0 : _spline2dinterpolant_clear(s);
46040 0 : _spline2dfitreport_clear(rep);
46041 0 : ae_vector_init(&xywork, 0, DT_REAL, _state, ae_true);
46042 0 : ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true);
46043 0 : ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true);
46044 0 : ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
46045 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
46046 0 : ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
46047 0 : ae_vector_init(&meany, 0, DT_REAL, _state, ae_true);
46048 0 : ae_vector_init(&xyindex, 0, DT_INT, _state, ae_true);
46049 0 : ae_vector_init(&tmpi, 0, DT_INT, _state, ae_true);
46050 0 : _spline1dinterpolant_init(&basis1, _state, ae_true);
46051 0 : _sparsematrix_init(&av, _state, ae_true);
46052 0 : _sparsematrix_init(&ah, _state, ae_true);
46053 0 : _spline2dxdesignmatrix_init(&xdesignmatrix, _state, ae_true);
46054 0 : ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
46055 0 : _spline2dblockllsbuf_init(&blockllsbuf, _state, ae_true);
46056 :
46057 0 : nzwidth = 4;
46058 0 : bfrad = 2;
46059 0 : npoints = state->npoints;
46060 0 : d = state->d;
46061 0 : ew = 2+d;
46062 :
46063 : /*
46064 : * Integrity checks
46065 : */
46066 0 : ae_assert(ae_fp_eq(state->sx,(double)(1)), "Spline2DFit: integrity error", _state);
46067 0 : ae_assert(ae_fp_eq(state->sy,(double)(1)), "Spline2DFit: integrity error", _state);
46068 :
46069 : /*
46070 : * Determine actual area size and grid step
46071 : *
46072 : * NOTE: initialize vars by zeros in order to avoid spurious
46073 : * compiler warnings.
46074 : */
46075 0 : xa = (double)(0);
46076 0 : xb = (double)(0);
46077 0 : ya = (double)(0);
46078 0 : yb = (double)(0);
46079 0 : if( state->areatype==0 )
46080 : {
46081 0 : if( npoints>0 )
46082 : {
46083 0 : xa = state->xy.ptr.p_double[0];
46084 0 : xb = state->xy.ptr.p_double[0];
46085 0 : ya = state->xy.ptr.p_double[1];
46086 0 : yb = state->xy.ptr.p_double[1];
46087 0 : for(i=1; i<=npoints-1; i++)
46088 : {
46089 0 : xa = ae_minreal(xa, state->xy.ptr.p_double[i*ew+0], _state);
46090 0 : xb = ae_maxreal(xb, state->xy.ptr.p_double[i*ew+0], _state);
46091 0 : ya = ae_minreal(ya, state->xy.ptr.p_double[i*ew+1], _state);
46092 0 : yb = ae_maxreal(yb, state->xy.ptr.p_double[i*ew+1], _state);
46093 : }
46094 : }
46095 : else
46096 : {
46097 0 : xa = (double)(-1);
46098 0 : xb = (double)(1);
46099 0 : ya = (double)(-1);
46100 0 : yb = (double)(1);
46101 : }
46102 : }
46103 : else
46104 : {
46105 0 : if( state->areatype==1 )
46106 : {
46107 0 : xa = state->xa;
46108 0 : xb = state->xb;
46109 0 : ya = state->ya;
46110 0 : yb = state->yb;
46111 : }
46112 : else
46113 : {
46114 0 : ae_assert(ae_false, "Assertion failed", _state);
46115 : }
46116 : }
46117 0 : if( ae_fp_eq(xa,xb) )
46118 : {
46119 0 : v = xa;
46120 0 : if( ae_fp_greater_eq(v,(double)(0)) )
46121 : {
46122 0 : xa = v/2-1;
46123 0 : xb = v*2+1;
46124 : }
46125 : else
46126 : {
46127 0 : xa = v*2-1;
46128 0 : xb = v/2+1;
46129 : }
46130 : }
46131 0 : if( ae_fp_eq(ya,yb) )
46132 : {
46133 0 : v = ya;
46134 0 : if( ae_fp_greater_eq(v,(double)(0)) )
46135 : {
46136 0 : ya = v/2-1;
46137 0 : yb = v*2+1;
46138 : }
46139 : else
46140 : {
46141 0 : ya = v*2-1;
46142 0 : yb = v/2+1;
46143 : }
46144 : }
46145 0 : ae_assert(ae_fp_less(xa,xb), "Spline2DFit: integrity error", _state);
46146 0 : ae_assert(ae_fp_less(ya,yb), "Spline2DFit: integrity error", _state);
46147 0 : kx = 0;
46148 0 : ky = 0;
46149 0 : if( state->gridtype==0 )
46150 : {
46151 0 : kx = 4;
46152 0 : ky = 4;
46153 : }
46154 : else
46155 : {
46156 0 : if( state->gridtype==1 )
46157 : {
46158 0 : kx = state->kx;
46159 0 : ky = state->ky;
46160 : }
46161 : else
46162 : {
46163 0 : ae_assert(ae_false, "Assertion failed", _state);
46164 : }
46165 : }
46166 0 : ae_assert(kx>0, "Spline2DFit: integrity error", _state);
46167 0 : ae_assert(ky>0, "Spline2DFit: integrity error", _state);
46168 0 : basecasex = -1;
46169 0 : basecasey = -1;
46170 0 : if( state->solvertype==3 )
46171 : {
46172 :
46173 : /*
46174 : * Large-scale solver with special requirements to grid size.
46175 : */
46176 0 : kx = ae_maxint(kx, nzwidth, _state);
46177 0 : ky = ae_maxint(ky, nzwidth, _state);
46178 0 : k = 1;
46179 0 : while(imin2(kx, ky, _state)>state->maxcoresize+1)
46180 : {
46181 0 : kx = idivup(kx-1, 2, _state)+1;
46182 0 : ky = idivup(ky-1, 2, _state)+1;
46183 0 : k = k+1;
46184 : }
46185 0 : basecasex = kx-1;
46186 0 : k0 = 1;
46187 0 : while(kx>state->maxcoresize+1)
46188 : {
46189 0 : basecasex = idivup(kx-1, 2, _state);
46190 0 : kx = basecasex+1;
46191 0 : k0 = k0+1;
46192 : }
46193 0 : while(k0>1)
46194 : {
46195 0 : kx = (kx-1)*2+1;
46196 0 : k0 = k0-1;
46197 : }
46198 0 : basecasey = ky-1;
46199 0 : k1 = 1;
46200 0 : while(ky>state->maxcoresize+1)
46201 : {
46202 0 : basecasey = idivup(ky-1, 2, _state);
46203 0 : ky = basecasey+1;
46204 0 : k1 = k1+1;
46205 : }
46206 0 : while(k1>1)
46207 : {
46208 0 : ky = (ky-1)*2+1;
46209 0 : k1 = k1-1;
46210 : }
46211 0 : while(k>1)
46212 : {
46213 0 : kx = (kx-1)*2+1;
46214 0 : ky = (ky-1)*2+1;
46215 0 : k = k-1;
46216 : }
46217 :
46218 : /*
46219 : * Grid is NOT expanded. We have very strict requirements on
46220 : * grid size, and we do not want to overcomplicate it by
46221 : * playing with grid size in order to add one more degree of
46222 : * freedom. It is not relevant for such large tasks.
46223 : */
46224 0 : gridexpansion = 0;
46225 : }
46226 : else
46227 : {
46228 :
46229 : /*
46230 : * Medium-scale solvers which are tolerant to grid size.
46231 : */
46232 0 : kx = ae_maxint(kx, nzwidth, _state);
46233 0 : ky = ae_maxint(ky, nzwidth, _state);
46234 :
46235 : /*
46236 : * Grid is expanded by 1 in order to add one more effective degree
46237 : * of freedom to the spline. Having additional nodes outside of the
46238 : * area allows us to emulate changes in the derivative at the bound
46239 : * without having specialized "boundary" version of the basis function.
46240 : */
46241 0 : if( state->adddegreeoffreedom )
46242 : {
46243 0 : gridexpansion = 1;
46244 : }
46245 : else
46246 : {
46247 0 : gridexpansion = 0;
46248 : }
46249 : }
46250 0 : hx = coalesce(xb-xa, 1.0, _state)/(kx-1);
46251 0 : hy = coalesce(yb-ya, 1.0, _state)/(ky-1);
46252 0 : invhx = 1/hx;
46253 0 : invhy = 1/hy;
46254 :
46255 : /*
46256 : * We determined "raw" grid size. Now perform a grid correction according
46257 : * to current grid expansion size.
46258 : */
46259 0 : xaraw = xa;
46260 0 : yaraw = ya;
46261 0 : xbraw = xb;
46262 0 : ybraw = yb;
46263 0 : xa = xa-hx*gridexpansion;
46264 0 : ya = ya-hy*gridexpansion;
46265 0 : xb = xb+hx*gridexpansion;
46266 0 : yb = yb+hy*gridexpansion;
46267 0 : kx = kx+2*gridexpansion;
46268 0 : ky = ky+2*gridexpansion;
46269 :
46270 : /*
46271 : * Create output spline using transformed (unit-scale)
46272 : * coordinates, fill by zero values
46273 : */
46274 0 : s->d = d;
46275 0 : s->n = kx;
46276 0 : s->m = ky;
46277 0 : s->stype = -3;
46278 0 : sfx = s->n*s->m*d;
46279 0 : sfy = 2*s->n*s->m*d;
46280 0 : sfxy = 3*s->n*s->m*d;
46281 0 : ae_vector_set_length(&s->x, s->n, _state);
46282 0 : ae_vector_set_length(&s->y, s->m, _state);
46283 0 : ae_vector_set_length(&s->f, 4*s->n*s->m*d, _state);
46284 0 : for(i=0; i<=s->n-1; i++)
46285 : {
46286 0 : s->x.ptr.p_double[i] = (double)(i);
46287 : }
46288 0 : for(i=0; i<=s->m-1; i++)
46289 : {
46290 0 : s->y.ptr.p_double[i] = (double)(i);
46291 : }
46292 0 : for(i=0; i<=4*s->n*s->m*d-1; i++)
46293 : {
46294 0 : s->f.ptr.p_double[i] = 0.0;
46295 : }
46296 :
46297 : /*
46298 : * Create local copy of dataset (only points in the grid are copied;
46299 : * we allow small step out of the grid, by Eps*H, in order to deal
46300 : * with numerical rounding errors).
46301 : *
46302 : * An additional copy of Y-values is created at columns beyond 2+J;
46303 : * it is preserved during all transformations. This copy is used
46304 : * to calculate error-related metrics.
46305 : *
46306 : * Calculate mean(Y), TSS
46307 : */
46308 0 : ae_vector_set_length(&meany, d, _state);
46309 0 : for(j=0; j<=d-1; j++)
46310 : {
46311 0 : meany.ptr.p_double[j] = (double)(0);
46312 : }
46313 0 : rvectorsetlengthatleast(&xywork, npoints*ew, _state);
46314 0 : acopied = 0;
46315 0 : eps = 1.0E-6;
46316 0 : for(i=0; i<=npoints-1; i++)
46317 : {
46318 0 : vx = state->xy.ptr.p_double[i*ew+0];
46319 0 : vy = state->xy.ptr.p_double[i*ew+1];
46320 0 : if( ((ae_fp_less_eq(xaraw-eps*hx,vx)&&ae_fp_less_eq(vx,xbraw+eps*hx))&&ae_fp_less_eq(yaraw-eps*hy,vy))&&ae_fp_less_eq(vy,ybraw+eps*hy) )
46321 : {
46322 0 : xywork.ptr.p_double[acopied*ew+0] = (vx-xa)*invhx;
46323 0 : xywork.ptr.p_double[acopied*ew+1] = (vy-ya)*invhy;
46324 0 : for(j=0; j<=d-1; j++)
46325 : {
46326 0 : v = state->xy.ptr.p_double[i*ew+2+j];
46327 0 : xywork.ptr.p_double[acopied*ew+2+j] = v;
46328 0 : meany.ptr.p_double[j] = meany.ptr.p_double[j]+v;
46329 : }
46330 0 : acopied = acopied+1;
46331 : }
46332 : }
46333 0 : npoints = acopied;
46334 0 : for(j=0; j<=d-1; j++)
46335 : {
46336 0 : meany.ptr.p_double[j] = meany.ptr.p_double[j]/coalesce((double)(npoints), (double)(1), _state);
46337 : }
46338 0 : tss = 0.0;
46339 0 : for(i=0; i<=npoints-1; i++)
46340 : {
46341 0 : for(j=0; j<=d-1; j++)
46342 : {
46343 0 : tss = tss+ae_sqr(xywork.ptr.p_double[i*ew+2+j]-meany.ptr.p_double[j], _state);
46344 : }
46345 : }
46346 0 : tss = coalesce(tss, 1.0, _state);
46347 :
46348 : /*
46349 : * Handle prior term.
46350 : * Modify output spline.
46351 : * Quick exit if dataset is empty.
46352 : */
46353 0 : buildpriorterm1(&xywork, npoints, 2, d, state->priorterm, state->priortermval, &vterm, _state);
46354 0 : if( npoints==0 )
46355 : {
46356 :
46357 : /*
46358 : * Quick exit
46359 : */
46360 0 : for(k=0; k<=s->n*s->m-1; k++)
46361 : {
46362 0 : k0 = k%s->n;
46363 0 : k1 = k/s->n;
46364 0 : for(j=0; j<=d-1; j++)
46365 : {
46366 0 : dstidx = d*(k1*s->n+k0)+j;
46367 0 : s->f.ptr.p_double[dstidx] = s->f.ptr.p_double[dstidx]+vterm.ptr.pp_double[j][0]*s->x.ptr.p_double[k0]+vterm.ptr.pp_double[j][1]*s->y.ptr.p_double[k1]+vterm.ptr.pp_double[j][2];
46368 0 : s->f.ptr.p_double[sfx+dstidx] = s->f.ptr.p_double[sfx+dstidx]+vterm.ptr.pp_double[j][0];
46369 0 : s->f.ptr.p_double[sfy+dstidx] = s->f.ptr.p_double[sfy+dstidx]+vterm.ptr.pp_double[j][1];
46370 : }
46371 : }
46372 0 : for(i=0; i<=s->n-1; i++)
46373 : {
46374 0 : s->x.ptr.p_double[i] = s->x.ptr.p_double[i]*hx+xa;
46375 : }
46376 0 : for(i=0; i<=s->m-1; i++)
46377 : {
46378 0 : s->y.ptr.p_double[i] = s->y.ptr.p_double[i]*hy+ya;
46379 : }
46380 0 : for(i=0; i<=s->n*s->m*d-1; i++)
46381 : {
46382 0 : s->f.ptr.p_double[sfx+i] = s->f.ptr.p_double[sfx+i]*invhx;
46383 0 : s->f.ptr.p_double[sfy+i] = s->f.ptr.p_double[sfy+i]*invhy;
46384 0 : s->f.ptr.p_double[sfxy+i] = s->f.ptr.p_double[sfxy+i]*invhx*invhy;
46385 : }
46386 0 : rep->rmserror = (double)(0);
46387 0 : rep->avgerror = (double)(0);
46388 0 : rep->maxerror = (double)(0);
46389 0 : rep->r2 = 1.0;
46390 0 : ae_frame_leave(_state);
46391 0 : return;
46392 : }
46393 :
46394 : /*
46395 : * Build 1D compact basis function
46396 : * Generate design matrix
46397 : */
46398 0 : ae_vector_set_length(&tmpx, 7, _state);
46399 0 : ae_vector_set_length(&tmpy, 7, _state);
46400 0 : tmpx.ptr.p_double[0] = (double)(-3);
46401 0 : tmpx.ptr.p_double[1] = (double)(-2);
46402 0 : tmpx.ptr.p_double[2] = (double)(-1);
46403 0 : tmpx.ptr.p_double[3] = (double)(0);
46404 0 : tmpx.ptr.p_double[4] = (double)(1);
46405 0 : tmpx.ptr.p_double[5] = (double)(2);
46406 0 : tmpx.ptr.p_double[6] = (double)(3);
46407 0 : tmpy.ptr.p_double[0] = (double)(0);
46408 0 : tmpy.ptr.p_double[1] = (double)(0);
46409 0 : tmpy.ptr.p_double[2] = (double)1/(double)12;
46410 0 : tmpy.ptr.p_double[3] = (double)2/(double)6;
46411 0 : tmpy.ptr.p_double[4] = (double)1/(double)12;
46412 0 : tmpy.ptr.p_double[5] = (double)(0);
46413 0 : tmpy.ptr.p_double[6] = (double)(0);
46414 0 : spline1dbuildcubic(&tmpx, &tmpy, tmpx.cnt, 2, 0.0, 2, 0.0, &basis1, _state);
46415 :
46416 : /*
46417 : * Solve.
46418 : * Update spline.
46419 : */
46420 0 : if( state->solvertype==1 )
46421 : {
46422 :
46423 : /*
46424 : * BlockLLS
46425 : */
46426 0 : spline2d_reorderdatasetandbuildindex(&xywork, npoints, d, &tmp0, 0, kx, ky, &xyindex, &tmpi, _state);
46427 0 : spline2d_xdesigngenerate(&xywork, &xyindex, 0, kx, kx, 0, ky, ky, d, spline2d_lambdaregblocklls, state->smoothing, &basis1, &xdesignmatrix, _state);
46428 0 : spline2d_blockllsfit(&xdesignmatrix, state->lsqrcnt, &z, rep, tss, &blockllsbuf, _state);
46429 0 : spline2d_updatesplinetable(&z, kx, ky, d, &basis1, bfrad, &s->f, s->m, s->n, 1, _state);
46430 : }
46431 : else
46432 : {
46433 0 : if( state->solvertype==2 )
46434 : {
46435 :
46436 : /*
46437 : * NaiveLLS, reference implementation
46438 : */
46439 0 : spline2d_generatedesignmatrix(&xywork, npoints, d, kx, ky, state->smoothing, spline2d_lambdaregblocklls, &basis1, &av, &ah, &arows, _state);
46440 0 : spline2d_naivellsfit(&av, &ah, arows, &xywork, kx, ky, npoints, d, state->lsqrcnt, &z, rep, tss, _state);
46441 0 : spline2d_updatesplinetable(&z, kx, ky, d, &basis1, bfrad, &s->f, s->m, s->n, 1, _state);
46442 : }
46443 : else
46444 : {
46445 0 : if( state->solvertype==3 )
46446 : {
46447 :
46448 : /*
46449 : * FastDDM method
46450 : */
46451 0 : ae_assert(basecasex>0, "Spline2DFit: integrity error", _state);
46452 0 : ae_assert(basecasey>0, "Spline2DFit: integrity error", _state);
46453 0 : spline2d_fastddmfit(&xywork, npoints, d, kx, ky, basecasex, basecasey, state->maxcoresize, state->interfacesize, state->nlayers, state->smoothing, state->lsqrcnt, &basis1, s, rep, tss, _state);
46454 : }
46455 : else
46456 : {
46457 0 : ae_assert(ae_false, "Spline2DFit: integrity error", _state);
46458 : }
46459 : }
46460 : }
46461 :
46462 : /*
46463 : * Append prior term.
46464 : * Transform spline to original coordinates
46465 : */
46466 0 : for(k=0; k<=s->n*s->m-1; k++)
46467 : {
46468 0 : k0 = k%s->n;
46469 0 : k1 = k/s->n;
46470 0 : for(j=0; j<=d-1; j++)
46471 : {
46472 0 : dstidx = d*(k1*s->n+k0)+j;
46473 0 : s->f.ptr.p_double[dstidx] = s->f.ptr.p_double[dstidx]+vterm.ptr.pp_double[j][0]*s->x.ptr.p_double[k0]+vterm.ptr.pp_double[j][1]*s->y.ptr.p_double[k1]+vterm.ptr.pp_double[j][2];
46474 0 : s->f.ptr.p_double[sfx+dstidx] = s->f.ptr.p_double[sfx+dstidx]+vterm.ptr.pp_double[j][0];
46475 0 : s->f.ptr.p_double[sfy+dstidx] = s->f.ptr.p_double[sfy+dstidx]+vterm.ptr.pp_double[j][1];
46476 : }
46477 : }
46478 0 : for(i=0; i<=s->n-1; i++)
46479 : {
46480 0 : s->x.ptr.p_double[i] = s->x.ptr.p_double[i]*hx+xa;
46481 : }
46482 0 : for(i=0; i<=s->m-1; i++)
46483 : {
46484 0 : s->y.ptr.p_double[i] = s->y.ptr.p_double[i]*hy+ya;
46485 : }
46486 0 : for(i=0; i<=s->n*s->m*d-1; i++)
46487 : {
46488 0 : s->f.ptr.p_double[sfx+i] = s->f.ptr.p_double[sfx+i]*invhx;
46489 0 : s->f.ptr.p_double[sfy+i] = s->f.ptr.p_double[sfy+i]*invhy;
46490 0 : s->f.ptr.p_double[sfxy+i] = s->f.ptr.p_double[sfxy+i]*invhx*invhy;
46491 : }
46492 0 : ae_frame_leave(_state);
46493 : }
46494 :
46495 :
46496 : /*************************************************************************
46497 : Serializer: allocation
46498 :
46499 : -- ALGLIB --
46500 : Copyright 28.02.2018 by Bochkanov Sergey
46501 : *************************************************************************/
46502 0 : void spline2dalloc(ae_serializer* s,
46503 : spline2dinterpolant* spline,
46504 : ae_state *_state)
46505 : {
46506 :
46507 :
46508 :
46509 : /*
46510 : * Header
46511 : */
46512 0 : ae_serializer_alloc_entry(s);
46513 :
46514 : /*
46515 : * Data
46516 : */
46517 0 : ae_serializer_alloc_entry(s);
46518 0 : ae_serializer_alloc_entry(s);
46519 0 : ae_serializer_alloc_entry(s);
46520 0 : ae_serializer_alloc_entry(s);
46521 0 : allocrealarray(s, &spline->x, -1, _state);
46522 0 : allocrealarray(s, &spline->y, -1, _state);
46523 0 : allocrealarray(s, &spline->f, -1, _state);
46524 0 : }
46525 :
46526 :
46527 : /*************************************************************************
46528 : Serializer: serialization
46529 :
46530 : -- ALGLIB --
46531 : Copyright 28.02.2018 by Bochkanov Sergey
46532 : *************************************************************************/
46533 0 : void spline2dserialize(ae_serializer* s,
46534 : spline2dinterpolant* spline,
46535 : ae_state *_state)
46536 : {
46537 :
46538 :
46539 :
46540 : /*
46541 : * Header
46542 : */
46543 0 : ae_serializer_serialize_int(s, getspline2dserializationcode(_state), _state);
46544 :
46545 : /*
46546 : * Data
46547 : */
46548 0 : ae_serializer_serialize_int(s, spline->stype, _state);
46549 0 : ae_serializer_serialize_int(s, spline->n, _state);
46550 0 : ae_serializer_serialize_int(s, spline->m, _state);
46551 0 : ae_serializer_serialize_int(s, spline->d, _state);
46552 0 : serializerealarray(s, &spline->x, -1, _state);
46553 0 : serializerealarray(s, &spline->y, -1, _state);
46554 0 : serializerealarray(s, &spline->f, -1, _state);
46555 0 : }
46556 :
46557 :
46558 : /*************************************************************************
46559 : Serializer: unserialization
46560 :
46561 : -- ALGLIB --
46562 : Copyright 28.02.2018 by Bochkanov Sergey
46563 : *************************************************************************/
46564 0 : void spline2dunserialize(ae_serializer* s,
46565 : spline2dinterpolant* spline,
46566 : ae_state *_state)
46567 : {
46568 : ae_int_t scode;
46569 :
46570 0 : _spline2dinterpolant_clear(spline);
46571 :
46572 :
46573 : /*
46574 : * Header
46575 : */
46576 0 : ae_serializer_unserialize_int(s, &scode, _state);
46577 0 : ae_assert(scode==getspline2dserializationcode(_state), "Spline2DUnserialize: stream header corrupted", _state);
46578 :
46579 : /*
46580 : * Data
46581 : */
46582 0 : ae_serializer_unserialize_int(s, &spline->stype, _state);
46583 0 : ae_serializer_unserialize_int(s, &spline->n, _state);
46584 0 : ae_serializer_unserialize_int(s, &spline->m, _state);
46585 0 : ae_serializer_unserialize_int(s, &spline->d, _state);
46586 0 : unserializerealarray(s, &spline->x, _state);
46587 0 : unserializerealarray(s, &spline->y, _state);
46588 0 : unserializerealarray(s, &spline->f, _state);
46589 0 : }
46590 :
46591 :
46592 : /*************************************************************************
46593 : Internal subroutine.
46594 : Calculation of the first derivatives and the cross-derivative.
46595 : *************************************************************************/
46596 0 : static void spline2d_bicubiccalcderivatives(/* Real */ ae_matrix* a,
46597 : /* Real */ ae_vector* x,
46598 : /* Real */ ae_vector* y,
46599 : ae_int_t m,
46600 : ae_int_t n,
46601 : /* Real */ ae_matrix* dx,
46602 : /* Real */ ae_matrix* dy,
46603 : /* Real */ ae_matrix* dxy,
46604 : ae_state *_state)
46605 : {
46606 : ae_frame _frame_block;
46607 : ae_int_t i;
46608 : ae_int_t j;
46609 : ae_vector xt;
46610 : ae_vector ft;
46611 : double s;
46612 : double ds;
46613 : double d2s;
46614 : spline1dinterpolant c;
46615 :
46616 0 : ae_frame_make(_state, &_frame_block);
46617 0 : memset(&xt, 0, sizeof(xt));
46618 0 : memset(&ft, 0, sizeof(ft));
46619 0 : memset(&c, 0, sizeof(c));
46620 0 : ae_matrix_clear(dx);
46621 0 : ae_matrix_clear(dy);
46622 0 : ae_matrix_clear(dxy);
46623 0 : ae_vector_init(&xt, 0, DT_REAL, _state, ae_true);
46624 0 : ae_vector_init(&ft, 0, DT_REAL, _state, ae_true);
46625 0 : _spline1dinterpolant_init(&c, _state, ae_true);
46626 :
46627 0 : ae_matrix_set_length(dx, m, n, _state);
46628 0 : ae_matrix_set_length(dy, m, n, _state);
46629 0 : ae_matrix_set_length(dxy, m, n, _state);
46630 :
46631 : /*
46632 : * dF/dX
46633 : */
46634 0 : ae_vector_set_length(&xt, n, _state);
46635 0 : ae_vector_set_length(&ft, n, _state);
46636 0 : for(i=0; i<=m-1; i++)
46637 : {
46638 0 : for(j=0; j<=n-1; j++)
46639 : {
46640 0 : xt.ptr.p_double[j] = x->ptr.p_double[j];
46641 0 : ft.ptr.p_double[j] = a->ptr.pp_double[i][j];
46642 : }
46643 0 : spline1dbuildcubic(&xt, &ft, n, 0, 0.0, 0, 0.0, &c, _state);
46644 0 : for(j=0; j<=n-1; j++)
46645 : {
46646 0 : spline1ddiff(&c, x->ptr.p_double[j], &s, &ds, &d2s, _state);
46647 0 : dx->ptr.pp_double[i][j] = ds;
46648 : }
46649 : }
46650 :
46651 : /*
46652 : * dF/dY
46653 : */
46654 0 : ae_vector_set_length(&xt, m, _state);
46655 0 : ae_vector_set_length(&ft, m, _state);
46656 0 : for(j=0; j<=n-1; j++)
46657 : {
46658 0 : for(i=0; i<=m-1; i++)
46659 : {
46660 0 : xt.ptr.p_double[i] = y->ptr.p_double[i];
46661 0 : ft.ptr.p_double[i] = a->ptr.pp_double[i][j];
46662 : }
46663 0 : spline1dbuildcubic(&xt, &ft, m, 0, 0.0, 0, 0.0, &c, _state);
46664 0 : for(i=0; i<=m-1; i++)
46665 : {
46666 0 : spline1ddiff(&c, y->ptr.p_double[i], &s, &ds, &d2s, _state);
46667 0 : dy->ptr.pp_double[i][j] = ds;
46668 : }
46669 : }
46670 :
46671 : /*
46672 : * d2F/dXdY
46673 : */
46674 0 : ae_vector_set_length(&xt, n, _state);
46675 0 : ae_vector_set_length(&ft, n, _state);
46676 0 : for(i=0; i<=m-1; i++)
46677 : {
46678 0 : for(j=0; j<=n-1; j++)
46679 : {
46680 0 : xt.ptr.p_double[j] = x->ptr.p_double[j];
46681 0 : ft.ptr.p_double[j] = dy->ptr.pp_double[i][j];
46682 : }
46683 0 : spline1dbuildcubic(&xt, &ft, n, 0, 0.0, 0, 0.0, &c, _state);
46684 0 : for(j=0; j<=n-1; j++)
46685 : {
46686 0 : spline1ddiff(&c, x->ptr.p_double[j], &s, &ds, &d2s, _state);
46687 0 : dxy->ptr.pp_double[i][j] = ds;
46688 : }
46689 : }
46690 0 : ae_frame_leave(_state);
46691 0 : }
46692 :
46693 :
46694 : /*************************************************************************
46695 : This function generates design matrix for the problem (in fact, two design
46696 : matrices are generated: "vertical" one and transposed (horizontal) one.
46697 :
46698 : INPUT PARAMETERS:
46699 : XY - array[NPoints*(2+D)]; dataset after scaling in such
46700 : way that grid step is equal to 1.0 in both dimensions.
46701 : NPoints - dataset size, NPoints>=1
46702 : KX, KY - grid size, KX,KY>=4
46703 : Smoothing - nonlinearity penalty coefficient, >=0
46704 : LambdaReg - regularization coefficient, >=0
46705 : Basis1 - basis spline, expected to be non-zero only at [-2,+2]
46706 : AV, AH - possibly preallocated buffers
46707 :
46708 : OUTPUT PARAMETERS:
46709 : AV - sparse matrix[ARows,KX*KY]; design matrix
46710 : AH - transpose of AV
46711 : ARows - number of rows in design matrix
46712 :
46713 : -- ALGLIB --
46714 : Copyright 05.02.2018 by Bochkanov Sergey
46715 : *************************************************************************/
46716 0 : static void spline2d_generatedesignmatrix(/* Real */ ae_vector* xy,
46717 : ae_int_t npoints,
46718 : ae_int_t d,
46719 : ae_int_t kx,
46720 : ae_int_t ky,
46721 : double smoothing,
46722 : double lambdareg,
46723 : spline1dinterpolant* basis1,
46724 : sparsematrix* av,
46725 : sparsematrix* ah,
46726 : ae_int_t* arows,
46727 : ae_state *_state)
46728 : {
46729 : ae_frame _frame_block;
46730 : ae_int_t nzwidth;
46731 : ae_int_t nzshift;
46732 : ae_int_t ew;
46733 : ae_int_t i;
46734 : ae_int_t j0;
46735 : ae_int_t j1;
46736 : ae_int_t k0;
46737 : ae_int_t k1;
46738 : ae_int_t dstidx;
46739 : double v;
46740 : double v0;
46741 : double v1;
46742 : double v2;
46743 : double w0;
46744 : double w1;
46745 : double w2;
46746 : ae_vector crx;
46747 : ae_vector cry;
46748 : ae_vector nrs;
46749 : ae_matrix d2x;
46750 : ae_matrix d2y;
46751 : ae_matrix dxy;
46752 :
46753 0 : ae_frame_make(_state, &_frame_block);
46754 0 : memset(&crx, 0, sizeof(crx));
46755 0 : memset(&cry, 0, sizeof(cry));
46756 0 : memset(&nrs, 0, sizeof(nrs));
46757 0 : memset(&d2x, 0, sizeof(d2x));
46758 0 : memset(&d2y, 0, sizeof(d2y));
46759 0 : memset(&dxy, 0, sizeof(dxy));
46760 0 : *arows = 0;
46761 0 : ae_vector_init(&crx, 0, DT_INT, _state, ae_true);
46762 0 : ae_vector_init(&cry, 0, DT_INT, _state, ae_true);
46763 0 : ae_vector_init(&nrs, 0, DT_INT, _state, ae_true);
46764 0 : ae_matrix_init(&d2x, 0, 0, DT_REAL, _state, ae_true);
46765 0 : ae_matrix_init(&d2y, 0, 0, DT_REAL, _state, ae_true);
46766 0 : ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true);
46767 :
46768 0 : nzwidth = 4;
46769 0 : nzshift = 1;
46770 0 : ae_assert(npoints>0, "Spline2DFit: integrity check failed", _state);
46771 0 : ae_assert(kx>=nzwidth, "Spline2DFit: integrity check failed", _state);
46772 0 : ae_assert(ky>=nzwidth, "Spline2DFit: integrity check failed", _state);
46773 0 : ew = 2+d;
46774 :
46775 : /*
46776 : * Determine canonical rectangle for every point. Every point of the dataset is
46777 : * influenced by at most NZWidth*NZWidth basis functions, which form NZWidth*NZWidth
46778 : * canonical rectangle.
46779 : *
46780 : * Thus, we have (KX-NZWidth+1)*(KY-NZWidth+1) overlapping canonical rectangles.
46781 : * Assigning every point to its rectangle simplifies creation of sparse basis
46782 : * matrix at the next steps.
46783 : */
46784 0 : ae_vector_set_length(&crx, npoints, _state);
46785 0 : ae_vector_set_length(&cry, npoints, _state);
46786 0 : for(i=0; i<=npoints-1; i++)
46787 : {
46788 0 : crx.ptr.p_int[i] = iboundval(ae_ifloor(xy->ptr.p_double[i*ew+0], _state)-nzshift, 0, kx-nzwidth, _state);
46789 0 : cry.ptr.p_int[i] = iboundval(ae_ifloor(xy->ptr.p_double[i*ew+1], _state)-nzshift, 0, ky-nzwidth, _state);
46790 : }
46791 :
46792 : /*
46793 : * Create vertical and horizontal design matrices
46794 : */
46795 0 : *arows = npoints+kx*ky;
46796 0 : if( ae_fp_neq(smoothing,0.0) )
46797 : {
46798 0 : ae_assert(ae_fp_greater(smoothing,0.0), "Spline2DFit: integrity check failed", _state);
46799 0 : *arows = *arows+3*(kx-2)*(ky-2);
46800 : }
46801 0 : ae_vector_set_length(&nrs, *arows, _state);
46802 0 : dstidx = 0;
46803 0 : for(i=0; i<=npoints-1; i++)
46804 : {
46805 0 : nrs.ptr.p_int[dstidx+i] = nzwidth*nzwidth;
46806 : }
46807 0 : dstidx = dstidx+npoints;
46808 0 : for(i=0; i<=kx*ky-1; i++)
46809 : {
46810 0 : nrs.ptr.p_int[dstidx+i] = 1;
46811 : }
46812 0 : dstidx = dstidx+kx*ky;
46813 0 : if( ae_fp_neq(smoothing,0.0) )
46814 : {
46815 0 : for(i=0; i<=3*(kx-2)*(ky-2)-1; i++)
46816 : {
46817 0 : nrs.ptr.p_int[dstidx+i] = 3*3;
46818 : }
46819 0 : dstidx = dstidx+3*(kx-2)*(ky-2);
46820 : }
46821 0 : ae_assert(dstidx==(*arows), "Spline2DFit: integrity check failed", _state);
46822 0 : sparsecreatecrs(*arows, kx*ky, &nrs, av, _state);
46823 0 : dstidx = 0;
46824 0 : for(i=0; i<=npoints-1; i++)
46825 : {
46826 0 : for(j1=0; j1<=nzwidth-1; j1++)
46827 : {
46828 0 : for(j0=0; j0<=nzwidth-1; j0++)
46829 : {
46830 0 : v0 = spline1dcalc(basis1, xy->ptr.p_double[i*ew+0]-(crx.ptr.p_int[i]+j0), _state);
46831 0 : v1 = spline1dcalc(basis1, xy->ptr.p_double[i*ew+1]-(cry.ptr.p_int[i]+j1), _state);
46832 0 : sparseset(av, dstidx+i, (cry.ptr.p_int[i]+j1)*kx+(crx.ptr.p_int[i]+j0), v0*v1, _state);
46833 : }
46834 : }
46835 : }
46836 0 : dstidx = dstidx+npoints;
46837 0 : for(i=0; i<=kx*ky-1; i++)
46838 : {
46839 0 : sparseset(av, dstidx+i, i, lambdareg, _state);
46840 : }
46841 0 : dstidx = dstidx+kx*ky;
46842 0 : if( ae_fp_neq(smoothing,0.0) )
46843 : {
46844 :
46845 : /*
46846 : * Smoothing is applied. Because all grid nodes are same,
46847 : * we apply same smoothing kernel, which is calculated only
46848 : * once at the beginning of design matrix generation.
46849 : */
46850 0 : ae_matrix_set_length(&d2x, 3, 3, _state);
46851 0 : ae_matrix_set_length(&d2y, 3, 3, _state);
46852 0 : ae_matrix_set_length(&dxy, 3, 3, _state);
46853 0 : for(j1=0; j1<=2; j1++)
46854 : {
46855 0 : for(j0=0; j0<=2; j0++)
46856 : {
46857 0 : d2x.ptr.pp_double[j0][j1] = 0.0;
46858 0 : d2y.ptr.pp_double[j0][j1] = 0.0;
46859 0 : dxy.ptr.pp_double[j0][j1] = 0.0;
46860 : }
46861 : }
46862 0 : for(k1=0; k1<=2; k1++)
46863 : {
46864 0 : for(k0=0; k0<=2; k0++)
46865 : {
46866 0 : spline1ddiff(basis1, (double)(-(k0-1)), &v0, &v1, &v2, _state);
46867 0 : spline1ddiff(basis1, (double)(-(k1-1)), &w0, &w1, &w2, _state);
46868 0 : d2x.ptr.pp_double[k0][k1] = d2x.ptr.pp_double[k0][k1]+v2*w0;
46869 0 : d2y.ptr.pp_double[k0][k1] = d2y.ptr.pp_double[k0][k1]+w2*v0;
46870 0 : dxy.ptr.pp_double[k0][k1] = dxy.ptr.pp_double[k0][k1]+v1*w1;
46871 : }
46872 : }
46873 :
46874 : /*
46875 : * Now, kernel is ready - apply it to all inner nodes of the grid.
46876 : */
46877 0 : for(j1=1; j1<=ky-2; j1++)
46878 : {
46879 0 : for(j0=1; j0<=kx-2; j0++)
46880 : {
46881 :
46882 : /*
46883 : * d2F/dx2 term
46884 : */
46885 0 : v = smoothing;
46886 0 : for(k1=-1; k1<=1; k1++)
46887 : {
46888 0 : for(k0=-1; k0<=1; k0++)
46889 : {
46890 0 : sparseset(av, dstidx, (j1+k1)*kx+(j0+k0), v*d2x.ptr.pp_double[1+k0][1+k1], _state);
46891 : }
46892 : }
46893 0 : dstidx = dstidx+1;
46894 :
46895 : /*
46896 : * d2F/dy2 term
46897 : */
46898 0 : v = smoothing;
46899 0 : for(k1=-1; k1<=1; k1++)
46900 : {
46901 0 : for(k0=-1; k0<=1; k0++)
46902 : {
46903 0 : sparseset(av, dstidx, (j1+k1)*kx+(j0+k0), v*d2y.ptr.pp_double[1+k0][1+k1], _state);
46904 : }
46905 : }
46906 0 : dstidx = dstidx+1;
46907 :
46908 : /*
46909 : * 2*d2F/dxdy term
46910 : */
46911 0 : v = ae_sqrt((double)(2), _state)*smoothing;
46912 0 : for(k1=-1; k1<=1; k1++)
46913 : {
46914 0 : for(k0=-1; k0<=1; k0++)
46915 : {
46916 0 : sparseset(av, dstidx, (j1+k1)*kx+(j0+k0), v*dxy.ptr.pp_double[1+k0][1+k1], _state);
46917 : }
46918 : }
46919 0 : dstidx = dstidx+1;
46920 : }
46921 : }
46922 : }
46923 0 : ae_assert(dstidx==(*arows), "Spline2DFit: integrity check failed", _state);
46924 0 : sparsecopy(av, ah, _state);
46925 0 : sparsetransposecrs(ah, _state);
46926 0 : ae_frame_leave(_state);
46927 0 : }
46928 :
46929 :
46930 : /*************************************************************************
46931 : This function updates table of spline values/derivatives using coefficients
46932 : for a layer of basis functions.
46933 :
46934 : -- ALGLIB --
46935 : Copyright 05.02.2018 by Bochkanov Sergey
46936 : *************************************************************************/
46937 0 : static void spline2d_updatesplinetable(/* Real */ ae_vector* z,
46938 : ae_int_t kx,
46939 : ae_int_t ky,
46940 : ae_int_t d,
46941 : spline1dinterpolant* basis1,
46942 : ae_int_t bfrad,
46943 : /* Real */ ae_vector* ftbl,
46944 : ae_int_t m,
46945 : ae_int_t n,
46946 : ae_int_t scalexy,
46947 : ae_state *_state)
46948 : {
46949 : ae_int_t k;
46950 : ae_int_t k0;
46951 : ae_int_t k1;
46952 : ae_int_t j;
46953 : ae_int_t j0;
46954 : ae_int_t j1;
46955 : ae_int_t j0a;
46956 : ae_int_t j0b;
46957 : ae_int_t j1a;
46958 : ae_int_t j1b;
46959 : double v;
46960 : double v0;
46961 : double v1;
46962 : double v01;
46963 : double v11;
46964 : double rdummy;
46965 : ae_int_t dstidx;
46966 : ae_int_t sfx;
46967 : ae_int_t sfy;
46968 : ae_int_t sfxy;
46969 : double invscalexy;
46970 :
46971 :
46972 0 : ae_assert(n==(kx-1)*scalexy+1, "Spline2DFit.UpdateSplineTable: integrity check failed", _state);
46973 0 : ae_assert(m==(ky-1)*scalexy+1, "Spline2DFit.UpdateSplineTable: integrity check failed", _state);
46974 0 : invscalexy = (double)1/(double)scalexy;
46975 0 : sfx = n*m*d;
46976 0 : sfy = 2*n*m*d;
46977 0 : sfxy = 3*n*m*d;
46978 0 : for(k=0; k<=kx*ky-1; k++)
46979 : {
46980 0 : k0 = k%kx;
46981 0 : k1 = k/kx;
46982 0 : j0a = iboundval(k0*scalexy-(bfrad*scalexy-1), 0, n-1, _state);
46983 0 : j0b = iboundval(k0*scalexy+(bfrad*scalexy-1), 0, n-1, _state);
46984 0 : j1a = iboundval(k1*scalexy-(bfrad*scalexy-1), 0, m-1, _state);
46985 0 : j1b = iboundval(k1*scalexy+(bfrad*scalexy-1), 0, m-1, _state);
46986 0 : for(j1=j1a; j1<=j1b; j1++)
46987 : {
46988 0 : spline1ddiff(basis1, (j1-k1*scalexy)*invscalexy, &v1, &v11, &rdummy, _state);
46989 0 : v11 = v11*invscalexy;
46990 0 : for(j0=j0a; j0<=j0b; j0++)
46991 : {
46992 0 : spline1ddiff(basis1, (j0-k0*scalexy)*invscalexy, &v0, &v01, &rdummy, _state);
46993 0 : v01 = v01*invscalexy;
46994 0 : for(j=0; j<=d-1; j++)
46995 : {
46996 0 : dstidx = d*(j1*n+j0)+j;
46997 0 : v = z->ptr.p_double[j*kx*ky+k];
46998 0 : ftbl->ptr.p_double[dstidx] = ftbl->ptr.p_double[dstidx]+v0*v1*v;
46999 0 : ftbl->ptr.p_double[sfx+dstidx] = ftbl->ptr.p_double[sfx+dstidx]+v01*v1*v;
47000 0 : ftbl->ptr.p_double[sfy+dstidx] = ftbl->ptr.p_double[sfy+dstidx]+v0*v11*v;
47001 0 : ftbl->ptr.p_double[sfxy+dstidx] = ftbl->ptr.p_double[sfxy+dstidx]+v01*v11*v;
47002 : }
47003 : }
47004 : }
47005 : }
47006 0 : }
47007 :
47008 :
47009 : /*************************************************************************
47010 : This function performs fitting with FastDDM solver.
47011 : Internal function, never use it directly.
47012 :
47013 : INPUT PARAMETERS:
47014 : XY - array[NPoints*(2+D)], dataset; destroyed in process
47015 : KX, KY - grid size
47016 : TileSize - tile size
47017 : InterfaceSize- interface size
47018 : NPoints - points count
47019 : D - number of components in vector-valued spline, D>=1
47020 : LSQRCnt - number of iterations, non-zero:
47021 : * LSQRCnt>0 means that specified amount of preconditioned
47022 : LSQR iterations will be performed to solve problem;
47023 : usually we need 2..5 its. Recommended option - best
47024 : convergence and stability/quality.
47025 : * LSQRCnt<0 means that instead of LSQR we use iterative
47026 : refinement on normal equations. Again, 2..5 its is enough.
47027 : Basis1 - basis spline, expected to be non-zero only at [-2,+2]
47028 : Z - possibly preallocated buffer for solution
47029 : Residuals - possibly preallocated buffer for residuals at dataset points
47030 : Rep - report structure; fields which are not set by this function
47031 : are left intact
47032 : TSS - total sum of squares; used to calculate R2
47033 :
47034 :
47035 : OUTPUT PARAMETERS:
47036 : XY - destroyed in process
47037 : Z - array[KX*KY*D], filled by solution; KX*KY coefficients
47038 : corresponding to each of D dimensions are stored contiguously.
47039 : Rep - following fields are set:
47040 : * Rep.RMSError
47041 : * Rep.AvgError
47042 : * Rep.MaxError
47043 : * Rep.R2
47044 :
47045 : -- ALGLIB --
47046 : Copyright 05.02.2018 by Bochkanov Sergey
47047 : *************************************************************************/
47048 0 : static void spline2d_fastddmfit(/* Real */ ae_vector* xy,
47049 : ae_int_t npoints,
47050 : ae_int_t d,
47051 : ae_int_t kx,
47052 : ae_int_t ky,
47053 : ae_int_t basecasex,
47054 : ae_int_t basecasey,
47055 : ae_int_t maxcoresize,
47056 : ae_int_t interfacesize,
47057 : ae_int_t nlayers,
47058 : double smoothing,
47059 : ae_int_t lsqrcnt,
47060 : spline1dinterpolant* basis1,
47061 : spline2dinterpolant* spline,
47062 : spline2dfitreport* rep,
47063 : double tss,
47064 : ae_state *_state)
47065 : {
47066 : ae_frame _frame_block;
47067 : ae_int_t i;
47068 : ae_int_t j;
47069 : ae_int_t nzwidth;
47070 : ae_int_t xew;
47071 : ae_int_t ntotallayers;
47072 : ae_int_t scaleidx;
47073 : ae_int_t scalexy;
47074 : double invscalexy;
47075 : ae_int_t kxcur;
47076 : ae_int_t kycur;
47077 : ae_int_t tilescount0;
47078 : ae_int_t tilescount1;
47079 : double v;
47080 : double rss;
47081 : ae_vector yraw;
47082 : ae_vector xyindex;
47083 : ae_vector tmp0;
47084 : ae_vector bufi;
47085 : spline2dfastddmbuf seed;
47086 : ae_shared_pool pool;
47087 : spline2dxdesignmatrix xdesignmatrix;
47088 : spline2dblockllsbuf blockllsbuf;
47089 : spline2dfitreport dummyrep;
47090 :
47091 0 : ae_frame_make(_state, &_frame_block);
47092 0 : memset(&yraw, 0, sizeof(yraw));
47093 0 : memset(&xyindex, 0, sizeof(xyindex));
47094 0 : memset(&tmp0, 0, sizeof(tmp0));
47095 0 : memset(&bufi, 0, sizeof(bufi));
47096 0 : memset(&seed, 0, sizeof(seed));
47097 0 : memset(&pool, 0, sizeof(pool));
47098 0 : memset(&xdesignmatrix, 0, sizeof(xdesignmatrix));
47099 0 : memset(&blockllsbuf, 0, sizeof(blockllsbuf));
47100 0 : memset(&dummyrep, 0, sizeof(dummyrep));
47101 0 : ae_vector_init(&yraw, 0, DT_REAL, _state, ae_true);
47102 0 : ae_vector_init(&xyindex, 0, DT_INT, _state, ae_true);
47103 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
47104 0 : ae_vector_init(&bufi, 0, DT_INT, _state, ae_true);
47105 0 : _spline2dfastddmbuf_init(&seed, _state, ae_true);
47106 0 : ae_shared_pool_init(&pool, _state, ae_true);
47107 0 : _spline2dxdesignmatrix_init(&xdesignmatrix, _state, ae_true);
47108 0 : _spline2dblockllsbuf_init(&blockllsbuf, _state, ae_true);
47109 0 : _spline2dfitreport_init(&dummyrep, _state, ae_true);
47110 :
47111 :
47112 : /*
47113 : * Dataset metrics and integrity checks
47114 : */
47115 0 : nzwidth = 4;
47116 0 : xew = 2+d;
47117 0 : ae_assert(maxcoresize>=2, "Spline2DFit: integrity check failed", _state);
47118 0 : ae_assert(interfacesize>=1, "Spline2DFit: integrity check failed", _state);
47119 0 : ae_assert(kx>=nzwidth, "Spline2DFit: integrity check failed", _state);
47120 0 : ae_assert(ky>=nzwidth, "Spline2DFit: integrity check failed", _state);
47121 :
47122 : /*
47123 : * Verify consistency of the grid size (KX,KY) with basecase sizes.
47124 : * Determine full number of layers.
47125 : */
47126 0 : ae_assert(basecasex<=maxcoresize, "Spline2DFit: integrity error", _state);
47127 0 : ae_assert(basecasey<=maxcoresize, "Spline2DFit: integrity error", _state);
47128 0 : ntotallayers = 1;
47129 0 : scalexy = 1;
47130 0 : kxcur = kx;
47131 0 : kycur = ky;
47132 0 : while(kxcur>basecasex+1&&kycur>basecasey+1)
47133 : {
47134 0 : ae_assert(kxcur%2==1, "Spline2DFit: integrity error", _state);
47135 0 : ae_assert(kycur%2==1, "Spline2DFit: integrity error", _state);
47136 0 : kxcur = (kxcur-1)/2+1;
47137 0 : kycur = (kycur-1)/2+1;
47138 0 : scalexy = scalexy*2;
47139 0 : inc(&ntotallayers, _state);
47140 : }
47141 0 : invscalexy = (double)1/(double)scalexy;
47142 0 : ae_assert((kxcur<=maxcoresize+1&&kxcur==basecasex+1)||kxcur%basecasex==1, "Spline2DFit: integrity error", _state);
47143 0 : ae_assert((kycur<=maxcoresize+1&&kycur==basecasey+1)||kycur%basecasey==1, "Spline2DFit: integrity error", _state);
47144 0 : ae_assert(kxcur==basecasex+1||kycur==basecasey+1, "Spline2DFit: integrity error", _state);
47145 :
47146 : /*
47147 : * Initial scaling of dataset.
47148 : * Store original target values to YRaw.
47149 : */
47150 0 : rvectorsetlengthatleast(&yraw, npoints*d, _state);
47151 0 : for(i=0; i<=npoints-1; i++)
47152 : {
47153 0 : xy->ptr.p_double[xew*i+0] = xy->ptr.p_double[xew*i+0]*invscalexy;
47154 0 : xy->ptr.p_double[xew*i+1] = xy->ptr.p_double[xew*i+1]*invscalexy;
47155 0 : for(j=0; j<=d-1; j++)
47156 : {
47157 0 : yraw.ptr.p_double[i*d+j] = xy->ptr.p_double[xew*i+2+j];
47158 : }
47159 : }
47160 0 : kxcur = (kx-1)/scalexy+1;
47161 0 : kycur = (ky-1)/scalexy+1;
47162 :
47163 : /*
47164 : * Build initial dataset index; area is divided into (KXCur-1)*(KYCur-1)
47165 : * cells, with contiguous storage of points in the same cell.
47166 : * Iterate over different scales
47167 : */
47168 0 : ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _spline2dfastddmbuf_init, _spline2dfastddmbuf_init_copy, _spline2dfastddmbuf_destroy, _state);
47169 0 : spline2d_reorderdatasetandbuildindex(xy, npoints, d, &yraw, d, kxcur, kycur, &xyindex, &bufi, _state);
47170 0 : for(scaleidx=ntotallayers-1; scaleidx>=0; scaleidx--)
47171 : {
47172 0 : if( (nlayers>0&&scaleidx<nlayers)||(nlayers<=0&&scaleidx<imax2(ntotallayers+nlayers, 1, _state)) )
47173 : {
47174 :
47175 : /*
47176 : * Fit current layer
47177 : */
47178 0 : ae_assert(kxcur%basecasex==1, "Spline2DFit: integrity error", _state);
47179 0 : ae_assert(kycur%basecasey==1, "Spline2DFit: integrity error", _state);
47180 0 : tilescount0 = kxcur/basecasex;
47181 0 : tilescount1 = kycur/basecasey;
47182 0 : spline2d_fastddmfitlayer(xy, d, scalexy, &xyindex, basecasex, 0, tilescount0, tilescount0, basecasey, 0, tilescount1, tilescount1, maxcoresize, interfacesize, lsqrcnt, spline2d_lambdaregfastddm+smoothing*ae_pow(spline2d_lambdadecay, (double)(scaleidx), _state), basis1, &pool, spline, _state);
47183 :
47184 : /*
47185 : * Compute residuals and update XY
47186 : */
47187 0 : spline2d_computeresidualsfromscratch(xy, &yraw, npoints, d, scalexy, spline, _state);
47188 : }
47189 :
47190 : /*
47191 : * Move to the next level
47192 : */
47193 0 : if( scaleidx!=0 )
47194 : {
47195 :
47196 : /*
47197 : * Transform dataset (multply everything by 2.0) and refine grid.
47198 : */
47199 0 : kxcur = 2*kxcur-1;
47200 0 : kycur = 2*kycur-1;
47201 0 : scalexy = scalexy/2;
47202 0 : invscalexy = (double)1/(double)scalexy;
47203 0 : spline2d_rescaledatasetandrefineindex(xy, npoints, d, &yraw, d, kxcur, kycur, &xyindex, &bufi, _state);
47204 :
47205 : /*
47206 : * Clear temporaries from previous round.
47207 : *
47208 : * We have to do it because upper layer of the multilevel spline
47209 : * needs more memory then subsequent layers, and we want to free
47210 : * this memory as soon as possible.
47211 : */
47212 0 : ae_shared_pool_clear_recycled(&pool, _state);
47213 : }
47214 : }
47215 :
47216 : /*
47217 : * Post-check
47218 : */
47219 0 : ae_assert(kxcur==kx, "Spline2DFit: integrity check failed", _state);
47220 0 : ae_assert(kycur==ky, "Spline2DFit: integrity check failed", _state);
47221 0 : ae_assert(scalexy==1, "Spline2DFit: integrity check failed", _state);
47222 :
47223 : /*
47224 : * Report
47225 : */
47226 0 : rep->rmserror = (double)(0);
47227 0 : rep->avgerror = (double)(0);
47228 0 : rep->maxerror = (double)(0);
47229 0 : rss = 0.0;
47230 0 : for(i=0; i<=npoints-1; i++)
47231 : {
47232 0 : for(j=0; j<=d-1; j++)
47233 : {
47234 0 : v = xy->ptr.p_double[i*xew+2+j];
47235 0 : rss = rss+v*v;
47236 0 : rep->rmserror = rep->rmserror+ae_sqr(v, _state);
47237 0 : rep->avgerror = rep->avgerror+ae_fabs(v, _state);
47238 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state);
47239 : }
47240 : }
47241 0 : rep->rmserror = ae_sqrt(rep->rmserror/coalesce((double)(npoints*d), 1.0, _state), _state);
47242 0 : rep->avgerror = rep->avgerror/coalesce((double)(npoints*d), 1.0, _state);
47243 0 : rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state);
47244 0 : ae_frame_leave(_state);
47245 0 : }
47246 :
47247 :
47248 : /*************************************************************************
47249 : Recursive fitting function for FastDDM algorithm.
47250 :
47251 : Works with KX*KY grid, with KX=BasecaseX*TilesCountX+1 and KY=BasecaseY*TilesCountY+1,
47252 : which is partitioned into TilesCountX*TilesCountY tiles, each having size
47253 : BasecaseX*BasecaseY.
47254 :
47255 : This function processes tiles in range [TileX0,TileX1)x[TileY0,TileY1) and
47256 : recursively divides this range until we move down to single tile, which
47257 : is processed with BlockLLS solver.
47258 :
47259 : -- ALGLIB --
47260 : Copyright 05.02.2018 by Bochkanov Sergey
47261 : *************************************************************************/
47262 0 : static void spline2d_fastddmfitlayer(/* Real */ ae_vector* xy,
47263 : ae_int_t d,
47264 : ae_int_t scalexy,
47265 : /* Integer */ ae_vector* xyindex,
47266 : ae_int_t basecasex,
47267 : ae_int_t tilex0,
47268 : ae_int_t tilex1,
47269 : ae_int_t tilescountx,
47270 : ae_int_t basecasey,
47271 : ae_int_t tiley0,
47272 : ae_int_t tiley1,
47273 : ae_int_t tilescounty,
47274 : ae_int_t maxcoresize,
47275 : ae_int_t interfacesize,
47276 : ae_int_t lsqrcnt,
47277 : double lambdareg,
47278 : spline1dinterpolant* basis1,
47279 : ae_shared_pool* pool,
47280 : spline2dinterpolant* spline,
47281 : ae_state *_state)
47282 : {
47283 : ae_frame _frame_block;
47284 : ae_int_t kx;
47285 : ae_int_t ky;
47286 : ae_int_t i;
47287 : ae_int_t j;
47288 : ae_int_t j0;
47289 : ae_int_t j1;
47290 : ae_int_t bfrad;
47291 : ae_int_t xa;
47292 : ae_int_t xb;
47293 : ae_int_t ya;
47294 : ae_int_t yb;
47295 : ae_int_t tile0;
47296 : ae_int_t tile1;
47297 : ae_int_t tilesize0;
47298 : ae_int_t tilesize1;
47299 : ae_int_t sfx;
47300 : ae_int_t sfy;
47301 : ae_int_t sfxy;
47302 : double dummytss;
47303 : double invscalexy;
47304 : ae_int_t cnt0;
47305 : ae_int_t cnt1;
47306 : ae_int_t offs;
47307 : double vs;
47308 : double vsx;
47309 : double vsy;
47310 : double vsxy;
47311 : spline2dfastddmbuf *buf;
47312 : ae_smart_ptr _buf;
47313 :
47314 0 : ae_frame_make(_state, &_frame_block);
47315 0 : memset(&_buf, 0, sizeof(_buf));
47316 0 : ae_smart_ptr_init(&_buf, (void**)&buf, _state, ae_true);
47317 :
47318 :
47319 : /*
47320 : * Dataset metrics and fast integrity checks;
47321 : * no code with side effects is allowed before parallel split.
47322 : */
47323 0 : bfrad = 2;
47324 0 : invscalexy = (double)1/(double)scalexy;
47325 0 : kx = basecasex*tilescountx+1;
47326 0 : ky = basecasey*tilescounty+1;
47327 :
47328 : /*
47329 : * Parallelism; because this function is intended for
47330 : * large-scale problems, we always try to:
47331 : * * invoke parallel execution mode
47332 : * * activate spawn support
47333 : */
47334 0 : if( _trypexec_spline2d_fastddmfitlayer(xy,d,scalexy,xyindex,basecasex,tilex0,tilex1,tilescountx,basecasey,tiley0,tiley1,tilescounty,maxcoresize,interfacesize,lsqrcnt,lambdareg,basis1,pool,spline, _state) )
47335 : {
47336 0 : ae_frame_leave(_state);
47337 0 : return;
47338 : }
47339 0 : if( imax2(tiley1-tiley0, tilex1-tilex0, _state)>=2 )
47340 : {
47341 0 : if( tiley1-tiley0>tilex1-tilex0 )
47342 : {
47343 :
47344 : /*
47345 : * Split problem in Y dimension
47346 : *
47347 : * NOTE: recursive calls to FastDDMFitLayer() compute
47348 : * residuals in the inner cells defined by XYIndex[],
47349 : * but we still have to compute residuals for cells
47350 : * BETWEEN two recursive subdivisions of the task.
47351 : */
47352 0 : tiledsplit(tiley1-tiley0, 1, &j0, &j1, _state);
47353 0 : spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0, tilex1, tilescountx, basecasey, tiley0, tiley0+j0, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state);
47354 0 : spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0, tilex1, tilescountx, basecasey, tiley0+j0, tiley1, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state);
47355 : }
47356 : else
47357 : {
47358 :
47359 : /*
47360 : * Split problem in X dimension
47361 : *
47362 : * NOTE: recursive calls to FastDDMFitLayer() compute
47363 : * residuals in the inner cells defined by XYIndex[],
47364 : * but we still have to compute residuals for cells
47365 : * BETWEEN two recursive subdivisions of the task.
47366 : */
47367 0 : tiledsplit(tilex1-tilex0, 1, &j0, &j1, _state);
47368 0 : spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0, tilex0+j0, tilescountx, basecasey, tiley0, tiley1, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state);
47369 0 : spline2d_fastddmfitlayer(xy, d, scalexy, xyindex, basecasex, tilex0+j0, tilex1, tilescountx, basecasey, tiley0, tiley1, tilescounty, maxcoresize, interfacesize, lsqrcnt, lambdareg, basis1, pool, spline, _state);
47370 : }
47371 0 : ae_frame_leave(_state);
47372 0 : return;
47373 : }
47374 0 : ae_assert(tiley0==tiley1-1, "Spline2DFit.FastDDMFitLayer: integrity check failed", _state);
47375 0 : ae_assert(tilex0==tilex1-1, "Spline2DFit.FastDDMFitLayer: integrity check failed", _state);
47376 0 : tile1 = tiley0;
47377 0 : tile0 = tilex0;
47378 :
47379 : /*
47380 : * Retrieve temporaries
47381 : */
47382 0 : ae_shared_pool_retrieve(pool, &_buf, _state);
47383 :
47384 : /*
47385 : * Analyze dataset
47386 : */
47387 0 : xa = iboundval(tile0*basecasex-interfacesize, 0, kx, _state);
47388 0 : xb = iboundval((tile0+1)*basecasex+interfacesize, 0, kx, _state);
47389 0 : ya = iboundval(tile1*basecasey-interfacesize, 0, ky, _state);
47390 0 : yb = iboundval((tile1+1)*basecasey+interfacesize, 0, ky, _state);
47391 0 : tilesize0 = xb-xa;
47392 0 : tilesize1 = yb-ya;
47393 :
47394 : /*
47395 : * Solve current chunk with BlockLLS
47396 : */
47397 0 : dummytss = 1.0;
47398 0 : spline2d_xdesigngenerate(xy, xyindex, xa, xb, kx, ya, yb, ky, d, lambdareg, 0.0, basis1, &buf->xdesignmatrix, _state);
47399 0 : spline2d_blockllsfit(&buf->xdesignmatrix, lsqrcnt, &buf->tmpz, &buf->dummyrep, dummytss, &buf->blockllsbuf, _state);
47400 0 : buf->localmodel.d = d;
47401 0 : buf->localmodel.m = tilesize1;
47402 0 : buf->localmodel.n = tilesize0;
47403 0 : buf->localmodel.stype = -3;
47404 0 : rvectorsetlengthatleast(&buf->localmodel.x, tilesize0, _state);
47405 0 : rvectorsetlengthatleast(&buf->localmodel.y, tilesize1, _state);
47406 0 : rvectorsetlengthatleast(&buf->localmodel.f, tilesize0*tilesize1*d*4, _state);
47407 0 : for(i=0; i<=tilesize0-1; i++)
47408 : {
47409 0 : buf->localmodel.x.ptr.p_double[i] = (double)(xa+i);
47410 : }
47411 0 : for(i=0; i<=tilesize1-1; i++)
47412 : {
47413 0 : buf->localmodel.y.ptr.p_double[i] = (double)(ya+i);
47414 : }
47415 0 : for(i=0; i<=tilesize0*tilesize1*d*4-1; i++)
47416 : {
47417 0 : buf->localmodel.f.ptr.p_double[i] = 0.0;
47418 : }
47419 0 : spline2d_updatesplinetable(&buf->tmpz, tilesize0, tilesize1, d, basis1, bfrad, &buf->localmodel.f, tilesize1, tilesize0, 1, _state);
47420 :
47421 : /*
47422 : * Transform local spline to original coordinates
47423 : */
47424 0 : sfx = buf->localmodel.n*buf->localmodel.m*d;
47425 0 : sfy = 2*buf->localmodel.n*buf->localmodel.m*d;
47426 0 : sfxy = 3*buf->localmodel.n*buf->localmodel.m*d;
47427 0 : for(i=0; i<=tilesize0-1; i++)
47428 : {
47429 0 : buf->localmodel.x.ptr.p_double[i] = buf->localmodel.x.ptr.p_double[i]*scalexy;
47430 : }
47431 0 : for(i=0; i<=tilesize1-1; i++)
47432 : {
47433 0 : buf->localmodel.y.ptr.p_double[i] = buf->localmodel.y.ptr.p_double[i]*scalexy;
47434 : }
47435 0 : for(i=0; i<=tilesize0*tilesize1*d-1; i++)
47436 : {
47437 0 : buf->localmodel.f.ptr.p_double[sfx+i] = buf->localmodel.f.ptr.p_double[sfx+i]*invscalexy;
47438 0 : buf->localmodel.f.ptr.p_double[sfy+i] = buf->localmodel.f.ptr.p_double[sfy+i]*invscalexy;
47439 0 : buf->localmodel.f.ptr.p_double[sfxy+i] = buf->localmodel.f.ptr.p_double[sfxy+i]*(invscalexy*invscalexy);
47440 : }
47441 :
47442 : /*
47443 : * Output results; for inner and topmost/leftmost tiles we output only BasecaseX*BasecaseY
47444 : * inner elements; for rightmost/bottom ones we also output one column/row of the interface
47445 : * part.
47446 : *
47447 : * Such complexity is explained by the fact that area size (by design) is not evenly divisible
47448 : * by the tile size; it is divisible with remainder=1, and we expect that interface size is
47449 : * at least 1, so we can fill the missing rightmost/bottom elements of Z by the interface
47450 : * values.
47451 : */
47452 0 : ae_assert(interfacesize>=1, "Spline2DFit: integrity check failed", _state);
47453 0 : sfx = spline->n*spline->m*d;
47454 0 : sfy = 2*spline->n*spline->m*d;
47455 0 : sfxy = 3*spline->n*spline->m*d;
47456 0 : cnt0 = basecasex*scalexy;
47457 0 : cnt1 = basecasey*scalexy;
47458 0 : if( tile0==tilescountx-1 )
47459 : {
47460 0 : inc(&cnt0, _state);
47461 : }
47462 0 : if( tile1==tilescounty-1 )
47463 : {
47464 0 : inc(&cnt1, _state);
47465 : }
47466 0 : offs = d*(spline->n*tile1*basecasey*scalexy+tile0*basecasex*scalexy);
47467 0 : for(j1=0; j1<=cnt1-1; j1++)
47468 : {
47469 0 : for(j0=0; j0<=cnt0-1; j0++)
47470 : {
47471 0 : for(j=0; j<=d-1; j++)
47472 : {
47473 0 : spline2ddiffvi(&buf->localmodel, (double)(tile0*basecasex*scalexy+j0), (double)(tile1*basecasey*scalexy+j1), j, &vs, &vsx, &vsy, &vsxy, _state);
47474 0 : spline->f.ptr.p_double[offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[offs+d*(spline->n*j1+j0)+j]+vs;
47475 0 : spline->f.ptr.p_double[sfx+offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[sfx+offs+d*(spline->n*j1+j0)+j]+vsx;
47476 0 : spline->f.ptr.p_double[sfy+offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[sfy+offs+d*(spline->n*j1+j0)+j]+vsy;
47477 0 : spline->f.ptr.p_double[sfxy+offs+d*(spline->n*j1+j0)+j] = spline->f.ptr.p_double[sfxy+offs+d*(spline->n*j1+j0)+j]+vsxy;
47478 : }
47479 : }
47480 : }
47481 :
47482 : /*
47483 : * Recycle temporaries
47484 : */
47485 0 : ae_shared_pool_recycle(pool, &_buf, _state);
47486 0 : ae_frame_leave(_state);
47487 : }
47488 :
47489 :
47490 : /*************************************************************************
47491 : Serial stub for GPL edition.
47492 : *************************************************************************/
47493 0 : ae_bool _trypexec_spline2d_fastddmfitlayer(/* Real */ ae_vector* xy,
47494 : ae_int_t d,
47495 : ae_int_t scalexy,
47496 : /* Integer */ ae_vector* xyindex,
47497 : ae_int_t basecasex,
47498 : ae_int_t tilex0,
47499 : ae_int_t tilex1,
47500 : ae_int_t tilescountx,
47501 : ae_int_t basecasey,
47502 : ae_int_t tiley0,
47503 : ae_int_t tiley1,
47504 : ae_int_t tilescounty,
47505 : ae_int_t maxcoresize,
47506 : ae_int_t interfacesize,
47507 : ae_int_t lsqrcnt,
47508 : double lambdareg,
47509 : spline1dinterpolant* basis1,
47510 : ae_shared_pool* pool,
47511 : spline2dinterpolant* spline,
47512 : ae_state *_state)
47513 : {
47514 0 : return ae_false;
47515 : }
47516 :
47517 :
47518 : /*************************************************************************
47519 : This function performs fitting with BlockLLS solver. Internal function,
47520 : never use it directly.
47521 :
47522 : IMPORTANT: performance and memory requirements of this function are
47523 : asymmetric w.r.t. KX and KY: it has
47524 : * O(KY*KX^2) memory requirements
47525 : * O(KY*KX^3) running time
47526 : Thus, if you have large KY and small KX, simple transposition
47527 : of your dataset may give you great speedup.
47528 :
47529 : INPUT PARAMETERS:
47530 : AV - sparse matrix, [ARows,KX*KY] in size. "Vertical" version
47531 : of design matrix, rows [0,NPoints) contain values of basis
47532 : functions at dataset points. Other rows are used for
47533 : nonlinearity penalty and other stuff like that.
47534 : AH - transpose(AV), "horizontal" version of AV
47535 : ARows - rows count
47536 : XY - array[NPoints*(2+D)], dataset
47537 : KX, KY - grid size
47538 : NPoints - points count
47539 : D - number of components in vector-valued spline, D>=1
47540 : LSQRCnt - number of iterations, non-zero:
47541 : * LSQRCnt>0 means that specified amount of preconditioned
47542 : LSQR iterations will be performed to solve problem;
47543 : usually we need 2..5 its. Recommended option - best
47544 : convergence and stability/quality.
47545 : * LSQRCnt<0 means that instead of LSQR we use iterative
47546 : refinement on normal equations. Again, 2..5 its is enough.
47547 : Z - possibly preallocated buffer for solution
47548 : Rep - report structure; fields which are not set by this function
47549 : are left intact
47550 : TSS - total sum of squares; used to calculate R2
47551 :
47552 :
47553 : OUTPUT PARAMETERS:
47554 : XY - destroyed in process
47555 : Z - array[KX*KY*D], filled by solution; KX*KY coefficients
47556 : corresponding to each of D dimensions are stored contiguously.
47557 : Rep - following fields are set:
47558 : * Rep.RMSError
47559 : * Rep.AvgError
47560 : * Rep.MaxError
47561 : * Rep.R2
47562 :
47563 : -- ALGLIB --
47564 : Copyright 05.02.2018 by Bochkanov Sergey
47565 : *************************************************************************/
47566 0 : static void spline2d_blockllsfit(spline2dxdesignmatrix* xdesign,
47567 : ae_int_t lsqrcnt,
47568 : /* Real */ ae_vector* z,
47569 : spline2dfitreport* rep,
47570 : double tss,
47571 : spline2dblockllsbuf* buf,
47572 : ae_state *_state)
47573 : {
47574 : ae_frame _frame_block;
47575 : ae_int_t blockbandwidth;
47576 : ae_int_t d;
47577 : ae_int_t i;
47578 : ae_int_t j;
47579 : double lambdachol;
47580 : sreal mxata;
47581 : double v;
47582 : ae_int_t celloffset;
47583 : ae_int_t i0;
47584 : ae_int_t i1;
47585 : double rss;
47586 : ae_int_t arows;
47587 : ae_int_t bw2;
47588 : ae_int_t kx;
47589 : ae_int_t ky;
47590 :
47591 0 : ae_frame_make(_state, &_frame_block);
47592 0 : memset(&mxata, 0, sizeof(mxata));
47593 0 : _sreal_init(&mxata, _state, ae_true);
47594 :
47595 0 : ae_assert(xdesign->blockwidth==4, "Spline2DFit: integrity check failed", _state);
47596 0 : blockbandwidth = 3;
47597 0 : d = xdesign->d;
47598 0 : arows = xdesign->nrows;
47599 0 : kx = xdesign->kx;
47600 0 : ky = xdesign->ky;
47601 0 : bw2 = xdesign->blockwidth*xdesign->blockwidth;
47602 :
47603 : /*
47604 : * Initial values for Z/Residuals
47605 : */
47606 0 : rvectorsetlengthatleast(z, kx*ky*d, _state);
47607 0 : for(i=0; i<=kx*ky*d-1; i++)
47608 : {
47609 0 : z->ptr.p_double[i] = (double)(0);
47610 : }
47611 :
47612 : /*
47613 : * Create and factorize design matrix. Add regularizer if
47614 : * factorization failed (happens sometimes with zero
47615 : * smoothing and sparsely populated datasets).
47616 : *
47617 : * The algorithm below is refactoring of NaiveLLS algorithm,
47618 : * which uses sparsity properties and compressed block storage.
47619 : *
47620 : * Problem sparsity pattern results in block-band-diagonal
47621 : * matrix (block matrix with limited bandwidth, equal to 3
47622 : * for bicubic splines). Thus, we have KY*KY blocks, each
47623 : * of them is KX*KX in size. Design matrix is stored in
47624 : * large NROWS*KX matrix, with NROWS=(BlockBandwidth+1)*KY*KX.
47625 : *
47626 : * We use adaptation of block skyline storage format, with
47627 : * TOWERSIZE*KX skyline bands (towers) stored sequentially;
47628 : * here TOWERSIZE=(BlockBandwidth+1)*KX. So, we have KY
47629 : * "towers", stored one below other, in BlockATA matrix.
47630 : * Every "tower" is a sequence of BlockBandwidth+1 cells,
47631 : * each of them being KX*KX in size.
47632 : */
47633 0 : lambdachol = spline2d_cholreg;
47634 0 : rmatrixsetlengthatleast(&buf->blockata, (blockbandwidth+1)*ky*kx, kx, _state);
47635 : for(;;)
47636 : {
47637 :
47638 : /*
47639 : * Parallel generation of squared design matrix.
47640 : */
47641 0 : spline2d_xdesignblockata(xdesign, &buf->blockata, &mxata.val, _state);
47642 :
47643 : /*
47644 : * Regularization
47645 : */
47646 0 : v = coalesce(mxata.val, 1.0, _state)*lambdachol;
47647 0 : for(i1=0; i1<=ky-1; i1++)
47648 : {
47649 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i1, _state);
47650 0 : for(i0=0; i0<=kx-1; i0++)
47651 : {
47652 0 : buf->blockata.ptr.pp_double[celloffset+i0][i0] = buf->blockata.ptr.pp_double[celloffset+i0][i0]+v;
47653 : }
47654 : }
47655 :
47656 : /*
47657 : * Try Cholesky factorization.
47658 : */
47659 0 : if( !spline2d_blockllscholesky(&buf->blockata, kx, ky, &buf->trsmbuf2, &buf->cholbuf2, &buf->cholbuf1, _state) )
47660 : {
47661 :
47662 : /*
47663 : * Factorization failed, increase regularizer and repeat
47664 : */
47665 0 : lambdachol = coalesce(10*lambdachol, 1.0E-12, _state);
47666 0 : continue;
47667 : }
47668 0 : break;
47669 : }
47670 :
47671 : /*
47672 : * Solve
47673 : */
47674 0 : rss = 0.0;
47675 0 : rep->rmserror = (double)(0);
47676 0 : rep->avgerror = (double)(0);
47677 0 : rep->maxerror = (double)(0);
47678 0 : ae_assert(lsqrcnt>0, "Spline2DFit: integrity failure", _state);
47679 0 : rvectorsetlengthatleast(&buf->tmp0, arows, _state);
47680 0 : rvectorsetlengthatleast(&buf->tmp1, kx*ky, _state);
47681 0 : linlsqrcreatebuf(arows, kx*ky, &buf->solver, _state);
47682 0 : for(j=0; j<=d-1; j++)
47683 : {
47684 :
47685 : /*
47686 : * Preconditioned LSQR:
47687 : *
47688 : * use Cholesky factor U of squared design matrix A'*A to
47689 : * transform min|A*x-b| to min|[A*inv(U)]*y-b| with y=U*x.
47690 : *
47691 : * Preconditioned problem is solved with LSQR solver, which
47692 : * gives superior results than normal equations.
47693 : */
47694 0 : for(i=0; i<=arows-1; i++)
47695 : {
47696 0 : if( i<xdesign->npoints )
47697 : {
47698 0 : buf->tmp0.ptr.p_double[i] = xdesign->vals.ptr.pp_double[i][bw2+j];
47699 : }
47700 : else
47701 : {
47702 0 : buf->tmp0.ptr.p_double[i] = 0.0;
47703 : }
47704 : }
47705 0 : linlsqrrestart(&buf->solver, _state);
47706 0 : linlsqrsetb(&buf->solver, &buf->tmp0, _state);
47707 0 : linlsqrsetcond(&buf->solver, 1.0E-14, 1.0E-14, lsqrcnt, _state);
47708 0 : while(linlsqriteration(&buf->solver, _state))
47709 : {
47710 0 : if( buf->solver.needmv )
47711 : {
47712 :
47713 : /*
47714 : * Use Cholesky factorization of the system matrix
47715 : * as preconditioner: solve TRSV(U,Solver.X)
47716 : */
47717 0 : for(i=0; i<=kx*ky-1; i++)
47718 : {
47719 0 : buf->tmp1.ptr.p_double[i] = buf->solver.x.ptr.p_double[i];
47720 : }
47721 0 : spline2d_blockllstrsv(&buf->blockata, kx, ky, ae_false, &buf->tmp1, _state);
47722 :
47723 : /*
47724 : * After preconditioning is done, multiply by A
47725 : */
47726 0 : spline2d_xdesignmv(xdesign, &buf->tmp1, &buf->solver.mv, _state);
47727 : }
47728 0 : if( buf->solver.needmtv )
47729 : {
47730 :
47731 : /*
47732 : * Multiply by design matrix A
47733 : */
47734 0 : spline2d_xdesignmtv(xdesign, &buf->solver.x, &buf->solver.mtv, _state);
47735 :
47736 : /*
47737 : * Multiply by preconditioner: solve TRSV(U',A*Solver.X)
47738 : */
47739 0 : spline2d_blockllstrsv(&buf->blockata, kx, ky, ae_true, &buf->solver.mtv, _state);
47740 : }
47741 : }
47742 :
47743 : /*
47744 : * Get results and post-multiply by preconditioner to get
47745 : * original variables.
47746 : */
47747 0 : linlsqrresults(&buf->solver, &buf->tmp1, &buf->solverrep, _state);
47748 0 : spline2d_blockllstrsv(&buf->blockata, kx, ky, ae_false, &buf->tmp1, _state);
47749 0 : for(i=0; i<=kx*ky-1; i++)
47750 : {
47751 0 : z->ptr.p_double[kx*ky*j+i] = buf->tmp1.ptr.p_double[i];
47752 : }
47753 :
47754 : /*
47755 : * Calculate model values
47756 : */
47757 0 : spline2d_xdesignmv(xdesign, &buf->tmp1, &buf->tmp0, _state);
47758 0 : for(i=0; i<=xdesign->npoints-1; i++)
47759 : {
47760 0 : v = xdesign->vals.ptr.pp_double[i][bw2+j]-buf->tmp0.ptr.p_double[i];
47761 0 : rss = rss+v*v;
47762 0 : rep->rmserror = rep->rmserror+ae_sqr(v, _state);
47763 0 : rep->avgerror = rep->avgerror+ae_fabs(v, _state);
47764 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state);
47765 : }
47766 : }
47767 0 : rep->rmserror = ae_sqrt(rep->rmserror/coalesce((double)(xdesign->npoints*d), 1.0, _state), _state);
47768 0 : rep->avgerror = rep->avgerror/coalesce((double)(xdesign->npoints*d), 1.0, _state);
47769 0 : rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state);
47770 0 : ae_frame_leave(_state);
47771 0 : }
47772 :
47773 :
47774 : /*************************************************************************
47775 : This function performs fitting with NaiveLLS solver. Internal function,
47776 : never use it directly.
47777 :
47778 : INPUT PARAMETERS:
47779 : AV - sparse matrix, [ARows,KX*KY] in size. "Vertical" version
47780 : of design matrix, rows [0,NPoints] contain values of basis
47781 : functions at dataset points. Other rows are used for
47782 : nonlinearity penalty and other stuff like that.
47783 : AH - transpose(AV), "horizontal" version of AV
47784 : ARows - rows count
47785 : XY - array[NPoints*(2+D)], dataset
47786 : KX, KY - grid size
47787 : NPoints - points count
47788 : D - number of components in vector-valued spline, D>=1
47789 : LSQRCnt - number of iterations, non-zero:
47790 : * LSQRCnt>0 means that specified amount of preconditioned
47791 : LSQR iterations will be performed to solve problem;
47792 : usually we need 2..5 its. Recommended option - best
47793 : convergence and stability/quality.
47794 : * LSQRCnt<0 means that instead of LSQR we use iterative
47795 : refinement on normal equations. Again, 2..5 its is enough.
47796 : Z - possibly preallocated buffer for solution
47797 : Rep - report structure; fields which are not set by this function
47798 : are left intact
47799 : TSS - total sum of squares; used to calculate R2
47800 :
47801 :
47802 : OUTPUT PARAMETERS:
47803 : XY - destroyed in process
47804 : Z - array[KX*KY*D], filled by solution; KX*KY coefficients
47805 : corresponding to each of D dimensions are stored contiguously.
47806 : Rep - following fields are set:
47807 : * Rep.RMSError
47808 : * Rep.AvgError
47809 : * Rep.MaxError
47810 : * Rep.R2
47811 :
47812 : -- ALGLIB --
47813 : Copyright 05.02.2018 by Bochkanov Sergey
47814 : *************************************************************************/
47815 0 : static void spline2d_naivellsfit(sparsematrix* av,
47816 : sparsematrix* ah,
47817 : ae_int_t arows,
47818 : /* Real */ ae_vector* xy,
47819 : ae_int_t kx,
47820 : ae_int_t ky,
47821 : ae_int_t npoints,
47822 : ae_int_t d,
47823 : ae_int_t lsqrcnt,
47824 : /* Real */ ae_vector* z,
47825 : spline2dfitreport* rep,
47826 : double tss,
47827 : ae_state *_state)
47828 : {
47829 : ae_frame _frame_block;
47830 : ae_int_t ew;
47831 : ae_int_t i;
47832 : ae_int_t j;
47833 : ae_int_t i0;
47834 : ae_int_t i1;
47835 : ae_int_t j0;
47836 : ae_int_t j1;
47837 : double v;
47838 : ae_int_t blockbandwidth;
47839 : double lambdareg;
47840 : ae_int_t srci;
47841 : ae_int_t srcj;
47842 : ae_int_t idxi;
47843 : ae_int_t idxj;
47844 : ae_int_t endi;
47845 : ae_int_t endj;
47846 : ae_int_t rfsidx;
47847 : ae_matrix ata;
47848 : ae_vector tmp0;
47849 : ae_vector tmp1;
47850 : double mxata;
47851 : linlsqrstate solver;
47852 : linlsqrreport solverrep;
47853 : double rss;
47854 :
47855 0 : ae_frame_make(_state, &_frame_block);
47856 0 : memset(&ata, 0, sizeof(ata));
47857 0 : memset(&tmp0, 0, sizeof(tmp0));
47858 0 : memset(&tmp1, 0, sizeof(tmp1));
47859 0 : memset(&solver, 0, sizeof(solver));
47860 0 : memset(&solverrep, 0, sizeof(solverrep));
47861 0 : ae_matrix_init(&ata, 0, 0, DT_REAL, _state, ae_true);
47862 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
47863 0 : ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
47864 0 : _linlsqrstate_init(&solver, _state, ae_true);
47865 0 : _linlsqrreport_init(&solverrep, _state, ae_true);
47866 :
47867 0 : blockbandwidth = 3;
47868 0 : ew = 2+d;
47869 :
47870 : /*
47871 : * Initial values for Z/Residuals
47872 : */
47873 0 : rvectorsetlengthatleast(z, kx*ky*d, _state);
47874 0 : for(i=0; i<=kx*ky*d-1; i++)
47875 : {
47876 0 : z->ptr.p_double[i] = (double)(0);
47877 : }
47878 :
47879 : /*
47880 : * Create and factorize design matrix.
47881 : *
47882 : * Add regularizer if factorization failed (happens sometimes
47883 : * with zero smoothing and sparsely populated datasets).
47884 : */
47885 0 : lambdareg = spline2d_cholreg;
47886 0 : rmatrixsetlengthatleast(&ata, kx*ky, kx*ky, _state);
47887 : for(;;)
47888 : {
47889 0 : mxata = 0.0;
47890 0 : for(i=0; i<=kx*ky-1; i++)
47891 : {
47892 0 : for(j=i; j<=kx*ky-1; j++)
47893 : {
47894 :
47895 : /*
47896 : * Initialize by zero
47897 : */
47898 0 : ata.ptr.pp_double[i][j] = (double)(0);
47899 :
47900 : /*
47901 : * Determine grid nodes corresponding to I and J;
47902 : * skip if too far away
47903 : */
47904 0 : i0 = i%kx;
47905 0 : i1 = i/kx;
47906 0 : j0 = j%kx;
47907 0 : j1 = j/kx;
47908 0 : if( ae_iabs(i0-j0, _state)>blockbandwidth||ae_iabs(i1-j1, _state)>blockbandwidth )
47909 : {
47910 0 : continue;
47911 : }
47912 :
47913 : /*
47914 : * Nodes are close enough, calculate product of columns I and J of A.
47915 : */
47916 0 : v = (double)(0);
47917 0 : srci = ah->ridx.ptr.p_int[i];
47918 0 : srcj = ah->ridx.ptr.p_int[j];
47919 0 : endi = ah->ridx.ptr.p_int[i+1];
47920 0 : endj = ah->ridx.ptr.p_int[j+1];
47921 : for(;;)
47922 : {
47923 0 : if( srci>=endi||srcj>=endj )
47924 : {
47925 : break;
47926 : }
47927 0 : idxi = ah->idx.ptr.p_int[srci];
47928 0 : idxj = ah->idx.ptr.p_int[srcj];
47929 0 : if( idxi==idxj )
47930 : {
47931 0 : v = v+ah->vals.ptr.p_double[srci]*ah->vals.ptr.p_double[srcj];
47932 0 : srci = srci+1;
47933 0 : srcj = srcj+1;
47934 0 : continue;
47935 : }
47936 0 : if( idxi<idxj )
47937 : {
47938 0 : srci = srci+1;
47939 : }
47940 : else
47941 : {
47942 0 : srcj = srcj+1;
47943 : }
47944 : }
47945 0 : ata.ptr.pp_double[i][j] = v;
47946 0 : mxata = ae_maxreal(mxata, ae_fabs(v, _state), _state);
47947 : }
47948 : }
47949 0 : v = coalesce(mxata, 1.0, _state)*lambdareg;
47950 0 : for(i=0; i<=kx*ky-1; i++)
47951 : {
47952 0 : ata.ptr.pp_double[i][i] = ata.ptr.pp_double[i][i]+v;
47953 : }
47954 0 : if( spdmatrixcholesky(&ata, kx*ky, ae_true, _state) )
47955 : {
47956 :
47957 : /*
47958 : * Success!
47959 : */
47960 0 : break;
47961 : }
47962 :
47963 : /*
47964 : * Factorization failed, increase regularizer and repeat
47965 : */
47966 0 : lambdareg = coalesce(10*lambdareg, 1.0E-12, _state);
47967 : }
47968 :
47969 : /*
47970 : * Solve
47971 : *
47972 : * NOTE: we expect that Z is zero-filled, and we treat it
47973 : * like initial approximation to solution.
47974 : */
47975 0 : rvectorsetlengthatleast(&tmp0, arows, _state);
47976 0 : rvectorsetlengthatleast(&tmp1, kx*ky, _state);
47977 0 : if( lsqrcnt>0 )
47978 : {
47979 0 : linlsqrcreate(arows, kx*ky, &solver, _state);
47980 : }
47981 0 : for(j=0; j<=d-1; j++)
47982 : {
47983 0 : ae_assert(lsqrcnt!=0, "Spline2DFit: integrity failure", _state);
47984 0 : if( lsqrcnt>0 )
47985 : {
47986 :
47987 : /*
47988 : * Preconditioned LSQR:
47989 : *
47990 : * use Cholesky factor U of squared design matrix A'*A to
47991 : * transform min|A*x-b| to min|[A*inv(U)]*y-b| with y=U*x.
47992 : *
47993 : * Preconditioned problem is solved with LSQR solver, which
47994 : * gives superior results than normal equations.
47995 : */
47996 0 : linlsqrcreate(arows, kx*ky, &solver, _state);
47997 0 : for(i=0; i<=arows-1; i++)
47998 : {
47999 0 : if( i<npoints )
48000 : {
48001 0 : tmp0.ptr.p_double[i] = xy->ptr.p_double[i*ew+2+j];
48002 : }
48003 : else
48004 : {
48005 0 : tmp0.ptr.p_double[i] = 0.0;
48006 : }
48007 : }
48008 0 : linlsqrsetb(&solver, &tmp0, _state);
48009 0 : linlsqrsetcond(&solver, 1.0E-14, 1.0E-14, lsqrcnt, _state);
48010 0 : while(linlsqriteration(&solver, _state))
48011 : {
48012 0 : if( solver.needmv )
48013 : {
48014 :
48015 : /*
48016 : * Use Cholesky factorization of the system matrix
48017 : * as preconditioner: solve TRSV(U,Solver.X)
48018 : */
48019 0 : for(i=0; i<=kx*ky-1; i++)
48020 : {
48021 0 : tmp1.ptr.p_double[i] = solver.x.ptr.p_double[i];
48022 : }
48023 0 : rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 0, &tmp1, 0, _state);
48024 :
48025 : /*
48026 : * After preconditioning is done, multiply by A
48027 : */
48028 0 : sparsemv(av, &tmp1, &solver.mv, _state);
48029 : }
48030 0 : if( solver.needmtv )
48031 : {
48032 :
48033 : /*
48034 : * Multiply by design matrix A
48035 : */
48036 0 : sparsemv(ah, &solver.x, &solver.mtv, _state);
48037 :
48038 : /*
48039 : * Multiply by preconditioner: solve TRSV(U',A*Solver.X)
48040 : */
48041 0 : rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 1, &solver.mtv, 0, _state);
48042 : }
48043 : }
48044 0 : linlsqrresults(&solver, &tmp1, &solverrep, _state);
48045 0 : rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 0, &tmp1, 0, _state);
48046 0 : for(i=0; i<=kx*ky-1; i++)
48047 : {
48048 0 : z->ptr.p_double[kx*ky*j+i] = tmp1.ptr.p_double[i];
48049 : }
48050 :
48051 : /*
48052 : * Calculate model values
48053 : */
48054 0 : sparsemv(av, &tmp1, &tmp0, _state);
48055 0 : for(i=0; i<=npoints-1; i++)
48056 : {
48057 0 : xy->ptr.p_double[i*ew+2+j] = xy->ptr.p_double[i*ew+2+j]-tmp0.ptr.p_double[i];
48058 : }
48059 : }
48060 : else
48061 : {
48062 :
48063 : /*
48064 : * Iterative refinement, inferior to LSQR
48065 : *
48066 : * For each dimension D:
48067 : * * fetch current estimate for solution from Z to Tmp1
48068 : * * calculate residual r for current estimate, store in Tmp0
48069 : * * calculate product of residual and design matrix A'*r, store it in Tmp1
48070 : * * Cholesky solver
48071 : * * update current estimate
48072 : */
48073 0 : for(rfsidx=1; rfsidx<=-lsqrcnt; rfsidx++)
48074 : {
48075 0 : for(i=0; i<=kx*ky-1; i++)
48076 : {
48077 0 : tmp1.ptr.p_double[i] = z->ptr.p_double[kx*ky*j+i];
48078 : }
48079 0 : sparsemv(av, &tmp1, &tmp0, _state);
48080 0 : for(i=0; i<=arows-1; i++)
48081 : {
48082 0 : if( i<npoints )
48083 : {
48084 0 : v = xy->ptr.p_double[i*ew+2+j];
48085 : }
48086 : else
48087 : {
48088 0 : v = (double)(0);
48089 : }
48090 0 : tmp0.ptr.p_double[i] = v-tmp0.ptr.p_double[i];
48091 : }
48092 0 : sparsemv(ah, &tmp0, &tmp1, _state);
48093 0 : rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 1, &tmp1, 0, _state);
48094 0 : rmatrixtrsv(kx*ky, &ata, 0, 0, ae_true, ae_false, 0, &tmp1, 0, _state);
48095 0 : for(i=0; i<=kx*ky-1; i++)
48096 : {
48097 0 : z->ptr.p_double[kx*ky*j+i] = z->ptr.p_double[kx*ky*j+i]+tmp1.ptr.p_double[i];
48098 : }
48099 : }
48100 :
48101 : /*
48102 : * Calculate model values
48103 : */
48104 0 : for(i=0; i<=kx*ky-1; i++)
48105 : {
48106 0 : tmp1.ptr.p_double[i] = z->ptr.p_double[kx*ky*j+i];
48107 : }
48108 0 : sparsemv(av, &tmp1, &tmp0, _state);
48109 0 : for(i=0; i<=npoints-1; i++)
48110 : {
48111 0 : xy->ptr.p_double[i*ew+2+j] = xy->ptr.p_double[i*ew+2+j]-tmp0.ptr.p_double[i];
48112 : }
48113 : }
48114 : }
48115 :
48116 : /*
48117 : * Generate report
48118 : */
48119 0 : rep->rmserror = (double)(0);
48120 0 : rep->avgerror = (double)(0);
48121 0 : rep->maxerror = (double)(0);
48122 0 : rss = 0.0;
48123 0 : for(i=0; i<=npoints-1; i++)
48124 : {
48125 0 : for(j=0; j<=d-1; j++)
48126 : {
48127 0 : v = xy->ptr.p_double[i*ew+2+j];
48128 0 : rss = rss+v*v;
48129 0 : rep->rmserror = rep->rmserror+ae_sqr(v, _state);
48130 0 : rep->avgerror = rep->avgerror+ae_fabs(v, _state);
48131 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v, _state), _state);
48132 : }
48133 : }
48134 0 : rep->rmserror = ae_sqrt(rep->rmserror/coalesce((double)(npoints*d), 1.0, _state), _state);
48135 0 : rep->avgerror = rep->avgerror/coalesce((double)(npoints*d), 1.0, _state);
48136 0 : rep->r2 = 1.0-rss/coalesce(tss, 1.0, _state);
48137 0 : ae_frame_leave(_state);
48138 0 : }
48139 :
48140 :
48141 : /*************************************************************************
48142 : This is convenience function for band block storage format; it returns
48143 : offset of KX*KX-sized block (I,J) in a compressed 2D array.
48144 :
48145 : For specific offset=OFFSET,
48146 : block (I,J) will be stored in entries BlockMatrix[OFFSET:OFFSET+KX-1,0:KX-1]
48147 :
48148 : -- ALGLIB --
48149 : Copyright 05.02.2018 by Bochkanov Sergey
48150 : *************************************************************************/
48151 0 : static ae_int_t spline2d_getcelloffset(ae_int_t kx,
48152 : ae_int_t ky,
48153 : ae_int_t blockbandwidth,
48154 : ae_int_t i,
48155 : ae_int_t j,
48156 : ae_state *_state)
48157 : {
48158 : ae_int_t result;
48159 :
48160 :
48161 0 : ae_assert(i>=0&&i<ky, "Spline2DFit: GetCellOffset() integrity error", _state);
48162 0 : ae_assert(j>=0&&j<ky, "Spline2DFit: GetCellOffset() integrity error", _state);
48163 0 : ae_assert(j>=i&&j<=i+blockbandwidth, "Spline2DFit: GetCellOffset() integrity error", _state);
48164 0 : result = j*(blockbandwidth+1)*kx;
48165 0 : result = result+(blockbandwidth-(j-i))*kx;
48166 0 : return result;
48167 : }
48168 :
48169 :
48170 : /*************************************************************************
48171 : This is convenience function for band block storage format; it copies
48172 : cell (I,J) from compressed format to uncompressed general matrix, at desired
48173 : position.
48174 :
48175 : -- ALGLIB --
48176 : Copyright 05.02.2018 by Bochkanov Sergey
48177 : *************************************************************************/
48178 0 : static void spline2d_copycellto(ae_int_t kx,
48179 : ae_int_t ky,
48180 : ae_int_t blockbandwidth,
48181 : /* Real */ ae_matrix* blockata,
48182 : ae_int_t i,
48183 : ae_int_t j,
48184 : /* Real */ ae_matrix* dst,
48185 : ae_int_t dst0,
48186 : ae_int_t dst1,
48187 : ae_state *_state)
48188 : {
48189 : ae_int_t celloffset;
48190 : ae_int_t idx0;
48191 : ae_int_t idx1;
48192 :
48193 :
48194 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i, j, _state);
48195 0 : for(idx0=0; idx0<=kx-1; idx0++)
48196 : {
48197 0 : for(idx1=0; idx1<=kx-1; idx1++)
48198 : {
48199 0 : dst->ptr.pp_double[dst0+idx0][dst1+idx1] = blockata->ptr.pp_double[celloffset+idx0][idx1];
48200 : }
48201 : }
48202 0 : }
48203 :
48204 :
48205 : /*************************************************************************
48206 : This is convenience function for band block storage format; it
48207 : truncates all elements of cell (I,J) which are less than Eps in magnitude.
48208 :
48209 : -- ALGLIB --
48210 : Copyright 05.02.2018 by Bochkanov Sergey
48211 : *************************************************************************/
48212 0 : static void spline2d_flushtozerocell(ae_int_t kx,
48213 : ae_int_t ky,
48214 : ae_int_t blockbandwidth,
48215 : /* Real */ ae_matrix* blockata,
48216 : ae_int_t i,
48217 : ae_int_t j,
48218 : double eps,
48219 : ae_state *_state)
48220 : {
48221 : ae_int_t celloffset;
48222 : ae_int_t idx0;
48223 : ae_int_t idx1;
48224 : double eps2;
48225 : double v;
48226 :
48227 :
48228 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i, j, _state);
48229 0 : eps2 = eps*eps;
48230 0 : for(idx0=0; idx0<=kx-1; idx0++)
48231 : {
48232 0 : for(idx1=0; idx1<=kx-1; idx1++)
48233 : {
48234 0 : v = blockata->ptr.pp_double[celloffset+idx0][idx1];
48235 0 : if( v*v<eps2 )
48236 : {
48237 0 : blockata->ptr.pp_double[celloffset+idx0][idx1] = (double)(0);
48238 : }
48239 : }
48240 : }
48241 0 : }
48242 :
48243 :
48244 : /*************************************************************************
48245 : This function generates squared design matrix stored in block band format.
48246 :
48247 : We use adaptation of block skyline storage format, with
48248 : TOWERSIZE*KX skyline bands (towers) stored sequentially;
48249 : here TOWERSIZE=(BlockBandwidth+1)*KX. So, we have KY
48250 : "towers", stored one below other, in BlockATA matrix.
48251 : Every "tower" is a sequence of BlockBandwidth+1 cells,
48252 : each of them being KX*KX in size.
48253 :
48254 : INPUT PARAMETERS:
48255 : AH - sparse matrix, [KX*KY,ARows] in size. "Horizontal" version
48256 : of design matrix, cols [0,NPoints] contain values of basis
48257 : functions at dataset points. Other cols are used for
48258 : nonlinearity penalty and other stuff like that.
48259 : KY0, KY1- subset of output matrix bands to process; on entry it MUST
48260 : be set to 0 and KY respectively.
48261 : KX, KY - grid size
48262 : BlockATA- array[KY*(BlockBandwidth+1)*KX,KX], preallocated storage
48263 : for output matrix in compressed block band format
48264 : MXATA - on entry MUST be zero
48265 :
48266 : OUTPUT PARAMETERS:
48267 : BlockATA- AH*AH', stored in compressed block band format
48268 :
48269 : -- ALGLIB --
48270 : Copyright 05.02.2018 by Bochkanov Sergey
48271 : *************************************************************************/
48272 0 : static void spline2d_blockllsgenerateata(sparsematrix* ah,
48273 : ae_int_t ky0,
48274 : ae_int_t ky1,
48275 : ae_int_t kx,
48276 : ae_int_t ky,
48277 : /* Real */ ae_matrix* blockata,
48278 : sreal* mxata,
48279 : ae_state *_state)
48280 : {
48281 : ae_frame _frame_block;
48282 : ae_int_t blockbandwidth;
48283 : double avgrowlen;
48284 : double cellcost;
48285 : double totalcost;
48286 : sreal tmpmxata;
48287 : ae_int_t i;
48288 : ae_int_t j;
48289 : ae_int_t i0;
48290 : ae_int_t i1;
48291 : ae_int_t j0;
48292 : ae_int_t j1;
48293 : ae_int_t celloffset;
48294 : double v;
48295 : ae_int_t srci;
48296 : ae_int_t srcj;
48297 : ae_int_t idxi;
48298 : ae_int_t idxj;
48299 : ae_int_t endi;
48300 : ae_int_t endj;
48301 :
48302 0 : ae_frame_make(_state, &_frame_block);
48303 0 : memset(&tmpmxata, 0, sizeof(tmpmxata));
48304 0 : _sreal_init(&tmpmxata, _state, ae_true);
48305 :
48306 0 : ae_assert(ae_fp_greater_eq(mxata->val,(double)(0)), "BlockLLSGenerateATA: integrity check failed", _state);
48307 0 : blockbandwidth = 3;
48308 :
48309 : /*
48310 : * Determine problem cost, perform recursive subdivision
48311 : * (with optional parallelization)
48312 : */
48313 0 : avgrowlen = (double)ah->ridx.ptr.p_int[kx*ky]/(double)(kx*ky);
48314 0 : cellcost = rmul3((double)(kx), (double)(1+2*blockbandwidth), avgrowlen, _state);
48315 0 : totalcost = rmul3((double)(ky1-ky0), (double)(1+2*blockbandwidth), cellcost, _state);
48316 0 : if( ky1-ky0>=2&&ae_fp_greater(totalcost,smpactivationlevel(_state)) )
48317 : {
48318 0 : if( _trypexec_spline2d_blockllsgenerateata(ah,ky0,ky1,kx,ky,blockata,mxata, _state) )
48319 : {
48320 0 : ae_frame_leave(_state);
48321 0 : return;
48322 : }
48323 : }
48324 0 : if( ky1-ky0>=2 )
48325 : {
48326 :
48327 : /*
48328 : * Split X: X*A = (X1 X2)^T*A
48329 : */
48330 0 : j = (ky1-ky0)/2;
48331 0 : spline2d_blockllsgenerateata(ah, ky0, ky0+j, kx, ky, blockata, &tmpmxata, _state);
48332 0 : spline2d_blockllsgenerateata(ah, ky0+j, ky1, kx, ky, blockata, mxata, _state);
48333 0 : mxata->val = ae_maxreal(mxata->val, tmpmxata.val, _state);
48334 0 : ae_frame_leave(_state);
48335 0 : return;
48336 : }
48337 :
48338 : /*
48339 : * Splitting in Y-dimension is done, fill I1-th "tower"
48340 : */
48341 0 : ae_assert(ky1==ky0+1, "BlockLLSGenerateATA: integrity check failed", _state);
48342 0 : i1 = ky0;
48343 0 : for(j1=i1; j1<=ae_minint(ky-1, i1+blockbandwidth, _state); j1++)
48344 : {
48345 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, j1, _state);
48346 :
48347 : /*
48348 : * Clear cell (I1,J1)
48349 : */
48350 0 : for(i0=0; i0<=kx-1; i0++)
48351 : {
48352 0 : for(j0=0; j0<=kx-1; j0++)
48353 : {
48354 0 : blockata->ptr.pp_double[celloffset+i0][j0] = 0.0;
48355 : }
48356 : }
48357 :
48358 : /*
48359 : * Initialize cell internals
48360 : */
48361 0 : for(i0=0; i0<=kx-1; i0++)
48362 : {
48363 0 : for(j0=0; j0<=kx-1; j0++)
48364 : {
48365 0 : if( ae_iabs(i0-j0, _state)<=blockbandwidth )
48366 : {
48367 :
48368 : /*
48369 : * Nodes are close enough, calculate product of columns I and J of A.
48370 : */
48371 0 : v = (double)(0);
48372 0 : i = i1*kx+i0;
48373 0 : j = j1*kx+j0;
48374 0 : srci = ah->ridx.ptr.p_int[i];
48375 0 : srcj = ah->ridx.ptr.p_int[j];
48376 0 : endi = ah->ridx.ptr.p_int[i+1];
48377 0 : endj = ah->ridx.ptr.p_int[j+1];
48378 : for(;;)
48379 : {
48380 0 : if( srci>=endi||srcj>=endj )
48381 : {
48382 : break;
48383 : }
48384 0 : idxi = ah->idx.ptr.p_int[srci];
48385 0 : idxj = ah->idx.ptr.p_int[srcj];
48386 0 : if( idxi==idxj )
48387 : {
48388 0 : v = v+ah->vals.ptr.p_double[srci]*ah->vals.ptr.p_double[srcj];
48389 0 : srci = srci+1;
48390 0 : srcj = srcj+1;
48391 0 : continue;
48392 : }
48393 0 : if( idxi<idxj )
48394 : {
48395 0 : srci = srci+1;
48396 : }
48397 : else
48398 : {
48399 0 : srcj = srcj+1;
48400 : }
48401 : }
48402 0 : blockata->ptr.pp_double[celloffset+i0][j0] = v;
48403 0 : mxata->val = ae_maxreal(mxata->val, ae_fabs(v, _state), _state);
48404 : }
48405 : }
48406 : }
48407 : }
48408 0 : ae_frame_leave(_state);
48409 : }
48410 :
48411 :
48412 : /*************************************************************************
48413 : Serial stub for GPL edition.
48414 : *************************************************************************/
48415 0 : ae_bool _trypexec_spline2d_blockllsgenerateata(sparsematrix* ah,
48416 : ae_int_t ky0,
48417 : ae_int_t ky1,
48418 : ae_int_t kx,
48419 : ae_int_t ky,
48420 : /* Real */ ae_matrix* blockata,
48421 : sreal* mxata,
48422 : ae_state *_state)
48423 : {
48424 0 : return ae_false;
48425 : }
48426 :
48427 :
48428 : /*************************************************************************
48429 : This function performs Cholesky decomposition of squared design matrix
48430 : stored in block band format.
48431 :
48432 : INPUT PARAMETERS:
48433 : BlockATA - array[KY*(BlockBandwidth+1)*KX,KX], matrix in compressed
48434 : block band format
48435 : KX, KY - grid size
48436 : TrsmBuf2,
48437 : CholBuf2,
48438 : CholBuf1 - buffers; reused by this function on subsequent calls,
48439 : automatically preallocated on the first call
48440 :
48441 : OUTPUT PARAMETERS:
48442 : BlockATA- Cholesky factor, in compressed block band format
48443 :
48444 : Result:
48445 : True on success, False on Cholesky failure
48446 :
48447 : -- ALGLIB --
48448 : Copyright 05.02.2018 by Bochkanov Sergey
48449 : *************************************************************************/
48450 0 : static ae_bool spline2d_blockllscholesky(/* Real */ ae_matrix* blockata,
48451 : ae_int_t kx,
48452 : ae_int_t ky,
48453 : /* Real */ ae_matrix* trsmbuf2,
48454 : /* Real */ ae_matrix* cholbuf2,
48455 : /* Real */ ae_vector* cholbuf1,
48456 : ae_state *_state)
48457 : {
48458 : ae_int_t blockbandwidth;
48459 : ae_int_t blockidx;
48460 : ae_int_t i;
48461 : ae_int_t j;
48462 : ae_int_t celloffset;
48463 : ae_int_t celloffset1;
48464 : ae_bool result;
48465 :
48466 :
48467 0 : blockbandwidth = 3;
48468 0 : rmatrixsetlengthatleast(trsmbuf2, (blockbandwidth+1)*kx, (blockbandwidth+1)*kx, _state);
48469 0 : rmatrixsetlengthatleast(cholbuf2, kx, kx, _state);
48470 0 : rvectorsetlengthatleast(cholbuf1, kx, _state);
48471 0 : result = ae_true;
48472 0 : for(blockidx=0; blockidx<=ky-1; blockidx++)
48473 : {
48474 :
48475 : /*
48476 : * TRSM for TRAIL*TRAIL block matrix before current cell;
48477 : * here TRAIL=MinInt(BlockIdx,BlockBandwidth).
48478 : */
48479 0 : for(i=0; i<=ae_minint(blockidx, blockbandwidth, _state)-1; i++)
48480 : {
48481 0 : for(j=i; j<=ae_minint(blockidx, blockbandwidth, _state)-1; j++)
48482 : {
48483 0 : spline2d_copycellto(kx, ky, blockbandwidth, blockata, ae_maxint(blockidx-blockbandwidth, 0, _state)+i, ae_maxint(blockidx-blockbandwidth, 0, _state)+j, trsmbuf2, i*kx, j*kx, _state);
48484 : }
48485 : }
48486 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, ae_maxint(blockidx-blockbandwidth, 0, _state), blockidx, _state);
48487 0 : rmatrixlefttrsm(ae_minint(blockidx, blockbandwidth, _state)*kx, kx, trsmbuf2, 0, 0, ae_true, ae_false, 1, blockata, celloffset, 0, _state);
48488 :
48489 : /*
48490 : * SYRK for diagonal cell: MaxInt(BlockIdx-BlockBandwidth,0)
48491 : * cells above diagonal one are used for update.
48492 : */
48493 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, ae_maxint(blockidx-blockbandwidth, 0, _state), blockidx, _state);
48494 0 : celloffset1 = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state);
48495 0 : rmatrixsyrk(kx, ae_minint(blockidx, blockbandwidth, _state)*kx, -1.0, blockata, celloffset, 0, 1, 1.0, blockata, celloffset1, 0, ae_true, _state);
48496 :
48497 : /*
48498 : * Factorize diagonal cell
48499 : */
48500 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state);
48501 0 : rmatrixcopy(kx, kx, blockata, celloffset, 0, cholbuf2, 0, 0, _state);
48502 0 : if( !spdmatrixcholeskyrec(cholbuf2, 0, kx, ae_true, cholbuf1, _state) )
48503 : {
48504 0 : result = ae_false;
48505 0 : return result;
48506 : }
48507 0 : rmatrixcopy(kx, kx, cholbuf2, 0, 0, blockata, celloffset, 0, _state);
48508 :
48509 : /*
48510 : * PERFORMANCE TWEAK: drop nearly-denormals from last "tower".
48511 : *
48512 : * Sparse matrices like these may produce denormal numbers on
48513 : * sparse datasets, with significant (10x!) performance penalty
48514 : * on Intel chips. In order to avoid it, we manually truncate
48515 : * small enough numbers.
48516 : *
48517 : * We use 1.0E-50 as clipping level (not really denormal, but
48518 : * such small numbers are not actually important anyway).
48519 : */
48520 0 : for(i=ae_maxint(blockidx-blockbandwidth, 0, _state); i<=blockidx; i++)
48521 : {
48522 0 : spline2d_flushtozerocell(kx, ky, blockbandwidth, blockata, i, blockidx, 1.0E-50, _state);
48523 : }
48524 : }
48525 0 : return result;
48526 : }
48527 :
48528 :
48529 : /*************************************************************************
48530 : This function performs TRSV on upper triangular Cholesky factor U, solving
48531 : either U*x=b or U'*x=b.
48532 :
48533 : INPUT PARAMETERS:
48534 : BlockATA - array[KY*(BlockBandwidth+1)*KX,KX], matrix U
48535 : in compressed block band format
48536 : KX, KY - grid size
48537 : TransU - whether to transpose U or not
48538 : B - array[KX*KY], on entry - stores right part B
48539 :
48540 : OUTPUT PARAMETERS:
48541 : B - replaced by X
48542 :
48543 : -- ALGLIB --
48544 : Copyright 05.02.2018 by Bochkanov Sergey
48545 : *************************************************************************/
48546 0 : static void spline2d_blockllstrsv(/* Real */ ae_matrix* blockata,
48547 : ae_int_t kx,
48548 : ae_int_t ky,
48549 : ae_bool transu,
48550 : /* Real */ ae_vector* b,
48551 : ae_state *_state)
48552 : {
48553 : ae_int_t blockbandwidth;
48554 : ae_int_t blockidx;
48555 : ae_int_t blockidx1;
48556 : ae_int_t celloffset;
48557 :
48558 :
48559 0 : blockbandwidth = 3;
48560 0 : if( !transu )
48561 : {
48562 :
48563 : /*
48564 : * Solve U*x=b
48565 : */
48566 0 : for(blockidx=ky-1; blockidx>=0; blockidx--)
48567 : {
48568 0 : for(blockidx1=1; blockidx1<=ae_minint(ky-(blockidx+1), blockbandwidth, _state); blockidx1++)
48569 : {
48570 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx+blockidx1, _state);
48571 0 : rmatrixgemv(kx, kx, -1.0, blockata, celloffset, 0, 0, b, (blockidx+blockidx1)*kx, 1.0, b, blockidx*kx, _state);
48572 : }
48573 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state);
48574 0 : rmatrixtrsv(kx, blockata, celloffset, 0, ae_true, ae_false, 0, b, blockidx*kx, _state);
48575 : }
48576 : }
48577 : else
48578 : {
48579 :
48580 : /*
48581 : * Solve U'*x=b
48582 : */
48583 0 : for(blockidx=0; blockidx<=ky-1; blockidx++)
48584 : {
48585 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx, _state);
48586 0 : rmatrixtrsv(kx, blockata, celloffset, 0, ae_true, ae_false, 1, b, blockidx*kx, _state);
48587 0 : for(blockidx1=1; blockidx1<=ae_minint(ky-(blockidx+1), blockbandwidth, _state); blockidx1++)
48588 : {
48589 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, blockidx, blockidx+blockidx1, _state);
48590 0 : rmatrixgemv(kx, kx, -1.0, blockata, celloffset, 0, 1, b, blockidx*kx, 1.0, b, (blockidx+blockidx1)*kx, _state);
48591 : }
48592 : }
48593 : }
48594 0 : }
48595 :
48596 :
48597 : /*************************************************************************
48598 : This function computes residuals for dataset XY[], using array of original
48599 : values YRaw[], and loads residuals to XY.
48600 :
48601 : Processing is performed in parallel manner.
48602 :
48603 : -- ALGLIB --
48604 : Copyright 05.02.2018 by Bochkanov Sergey
48605 : *************************************************************************/
48606 0 : static void spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy,
48607 : /* Real */ ae_vector* yraw,
48608 : ae_int_t npoints,
48609 : ae_int_t d,
48610 : ae_int_t scalexy,
48611 : spline2dinterpolant* spline,
48612 : ae_state *_state)
48613 : {
48614 : ae_frame _frame_block;
48615 : srealarray seed;
48616 : ae_shared_pool pool;
48617 : ae_int_t chunksize;
48618 : double pointcost;
48619 :
48620 0 : ae_frame_make(_state, &_frame_block);
48621 0 : memset(&seed, 0, sizeof(seed));
48622 0 : memset(&pool, 0, sizeof(pool));
48623 0 : _srealarray_init(&seed, _state, ae_true);
48624 0 : ae_shared_pool_init(&pool, _state, ae_true);
48625 :
48626 :
48627 : /*
48628 : * Setting up
48629 : */
48630 0 : chunksize = 1000;
48631 0 : pointcost = 100.0;
48632 0 : if( ae_fp_greater(npoints*pointcost,smpactivationlevel(_state)) )
48633 : {
48634 0 : if( _trypexec_spline2d_computeresidualsfromscratch(xy,yraw,npoints,d,scalexy,spline, _state) )
48635 : {
48636 0 : ae_frame_leave(_state);
48637 0 : return;
48638 : }
48639 : }
48640 0 : ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _srealarray_init, _srealarray_init_copy, _srealarray_destroy, _state);
48641 :
48642 : /*
48643 : * Call compute workhorse
48644 : */
48645 0 : spline2d_computeresidualsfromscratchrec(xy, yraw, 0, npoints, chunksize, d, scalexy, spline, &pool, _state);
48646 0 : ae_frame_leave(_state);
48647 : }
48648 :
48649 :
48650 : /*************************************************************************
48651 : Serial stub for GPL edition.
48652 : *************************************************************************/
48653 0 : ae_bool _trypexec_spline2d_computeresidualsfromscratch(/* Real */ ae_vector* xy,
48654 : /* Real */ ae_vector* yraw,
48655 : ae_int_t npoints,
48656 : ae_int_t d,
48657 : ae_int_t scalexy,
48658 : spline2dinterpolant* spline,
48659 : ae_state *_state)
48660 : {
48661 0 : return ae_false;
48662 : }
48663 :
48664 :
48665 : /*************************************************************************
48666 : Recursive workhorse for ComputeResidualsFromScratch.
48667 :
48668 : -- ALGLIB --
48669 : Copyright 05.02.2018 by Bochkanov Sergey
48670 : *************************************************************************/
48671 0 : static void spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy,
48672 : /* Real */ ae_vector* yraw,
48673 : ae_int_t pt0,
48674 : ae_int_t pt1,
48675 : ae_int_t chunksize,
48676 : ae_int_t d,
48677 : ae_int_t scalexy,
48678 : spline2dinterpolant* spline,
48679 : ae_shared_pool* pool,
48680 : ae_state *_state)
48681 : {
48682 : ae_frame _frame_block;
48683 : ae_int_t i;
48684 : ae_int_t j;
48685 : srealarray *pbuf;
48686 : ae_smart_ptr _pbuf;
48687 : ae_int_t xew;
48688 :
48689 0 : ae_frame_make(_state, &_frame_block);
48690 0 : memset(&_pbuf, 0, sizeof(_pbuf));
48691 0 : ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true);
48692 :
48693 0 : xew = 2+d;
48694 :
48695 : /*
48696 : * Parallelism
48697 : */
48698 0 : if( pt1-pt0>chunksize )
48699 : {
48700 0 : tiledsplit(pt1-pt0, chunksize, &i, &j, _state);
48701 0 : spline2d_computeresidualsfromscratchrec(xy, yraw, pt0, pt0+i, chunksize, d, scalexy, spline, pool, _state);
48702 0 : spline2d_computeresidualsfromscratchrec(xy, yraw, pt0+i, pt1, chunksize, d, scalexy, spline, pool, _state);
48703 0 : ae_frame_leave(_state);
48704 0 : return;
48705 : }
48706 :
48707 : /*
48708 : * Serial execution
48709 : */
48710 0 : ae_shared_pool_retrieve(pool, &_pbuf, _state);
48711 0 : for(i=pt0; i<=pt1-1; i++)
48712 : {
48713 0 : spline2dcalcvbuf(spline, xy->ptr.p_double[i*xew+0]*scalexy, xy->ptr.p_double[i*xew+1]*scalexy, &pbuf->val, _state);
48714 0 : for(j=0; j<=d-1; j++)
48715 : {
48716 0 : xy->ptr.p_double[i*xew+2+j] = yraw->ptr.p_double[i*d+j]-pbuf->val.ptr.p_double[j];
48717 : }
48718 : }
48719 0 : ae_shared_pool_recycle(pool, &_pbuf, _state);
48720 0 : ae_frame_leave(_state);
48721 : }
48722 :
48723 :
48724 : /*************************************************************************
48725 : Serial stub for GPL edition.
48726 : *************************************************************************/
48727 0 : ae_bool _trypexec_spline2d_computeresidualsfromscratchrec(/* Real */ ae_vector* xy,
48728 : /* Real */ ae_vector* yraw,
48729 : ae_int_t pt0,
48730 : ae_int_t pt1,
48731 : ae_int_t chunksize,
48732 : ae_int_t d,
48733 : ae_int_t scalexy,
48734 : spline2dinterpolant* spline,
48735 : ae_shared_pool* pool,
48736 : ae_state *_state)
48737 : {
48738 0 : return ae_false;
48739 : }
48740 :
48741 :
48742 : /*************************************************************************
48743 : This function reorders dataset and builds index:
48744 : * it is assumed that all points have X in [0,KX-1], Y in [0,KY-1]
48745 : * area is divided into (KX-1)*(KY-1) cells
48746 : * all points are reordered in such way that points in same cell are stored
48747 : contiguously
48748 : * dataset index, array[(KX-1)*(KY-1)+1], is generated. Points of cell I
48749 : now have indexes XYIndex[I]..XYIndex[I+1]-1;
48750 :
48751 : INPUT PARAMETERS:
48752 : XY - array[NPoints*(2+D)], dataset
48753 : KX, KY, D - grid size and dimensionality of the outputs
48754 : Shadow - shadow array[NPoints*NS], which is sorted together
48755 : with XY; if NS=0, it is not referenced at all.
48756 : NS - entry width of shadow array
48757 : BufI - possibly preallocated temporary buffer; resized if
48758 : needed.
48759 :
48760 : OUTPUT PARAMETERS:
48761 : XY - reordered
48762 : XYIndex - array[(KX-1)*(KY-1)+1], dataset index
48763 :
48764 : -- ALGLIB --
48765 : Copyright 05.02.2018 by Bochkanov Sergey
48766 : *************************************************************************/
48767 0 : static void spline2d_reorderdatasetandbuildindex(/* Real */ ae_vector* xy,
48768 : ae_int_t npoints,
48769 : ae_int_t d,
48770 : /* Real */ ae_vector* shadow,
48771 : ae_int_t ns,
48772 : ae_int_t kx,
48773 : ae_int_t ky,
48774 : /* Integer */ ae_vector* xyindex,
48775 : /* Integer */ ae_vector* bufi,
48776 : ae_state *_state)
48777 : {
48778 : ae_int_t i;
48779 : ae_int_t i0;
48780 : ae_int_t i1;
48781 : ae_int_t entrywidth;
48782 :
48783 :
48784 :
48785 : /*
48786 : * Set up
48787 : */
48788 0 : ae_assert(kx>=2, "Spline2DFit.ReorderDatasetAndBuildIndex: integrity check failed", _state);
48789 0 : ae_assert(ky>=2, "Spline2DFit.ReorderDatasetAndBuildIndex: integrity check failed", _state);
48790 0 : entrywidth = 2+d;
48791 0 : ivectorsetlengthatleast(xyindex, (kx-1)*(ky-1)+1, _state);
48792 0 : ivectorsetlengthatleast(bufi, npoints, _state);
48793 0 : for(i=0; i<=npoints-1; i++)
48794 : {
48795 0 : i0 = iboundval(ae_ifloor(xy->ptr.p_double[i*entrywidth+0], _state), 0, kx-2, _state);
48796 0 : i1 = iboundval(ae_ifloor(xy->ptr.p_double[i*entrywidth+1], _state), 0, ky-2, _state);
48797 0 : bufi->ptr.p_int[i] = i1*(kx-1)+i0;
48798 : }
48799 :
48800 : /*
48801 : * Reorder
48802 : */
48803 0 : spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, bufi, 0, npoints, xyindex, 0, (kx-1)*(ky-1), ae_true, _state);
48804 0 : xyindex->ptr.p_int[(kx-1)*(ky-1)] = npoints;
48805 0 : }
48806 :
48807 :
48808 : /*************************************************************************
48809 : This function multiplies all points in dataset by 2.0 and rebuilds index,
48810 : given previous index built for KX_prev=(KX-1)/2 and KY_prev=(KY-1)/2
48811 :
48812 : INPUT PARAMETERS:
48813 : XY - array[NPoints*(2+D)], dataset BEFORE scaling
48814 : NPoints, D - dataset size and dimensionality of the outputs
48815 : Shadow - shadow array[NPoints*NS], which is sorted together
48816 : with XY; if NS=0, it is not referenced at all.
48817 : NS - entry width of shadow array
48818 : KX, KY - new grid dimensionality
48819 : XYIndex - index built for previous values of KX and KY
48820 : BufI - possibly preallocated temporary buffer; resized if
48821 : needed.
48822 :
48823 : OUTPUT PARAMETERS:
48824 : XY - reordered and multiplied by 2.0
48825 : XYIndex - array[(KX-1)*(KY-1)+1], dataset index
48826 :
48827 : -- ALGLIB --
48828 : Copyright 05.02.2018 by Bochkanov Sergey
48829 : *************************************************************************/
48830 0 : static void spline2d_rescaledatasetandrefineindex(/* Real */ ae_vector* xy,
48831 : ae_int_t npoints,
48832 : ae_int_t d,
48833 : /* Real */ ae_vector* shadow,
48834 : ae_int_t ns,
48835 : ae_int_t kx,
48836 : ae_int_t ky,
48837 : /* Integer */ ae_vector* xyindex,
48838 : /* Integer */ ae_vector* bufi,
48839 : ae_state *_state)
48840 : {
48841 : ae_frame _frame_block;
48842 : ae_vector xyindexprev;
48843 :
48844 0 : ae_frame_make(_state, &_frame_block);
48845 0 : memset(&xyindexprev, 0, sizeof(xyindexprev));
48846 0 : ae_vector_init(&xyindexprev, 0, DT_INT, _state, ae_true);
48847 :
48848 :
48849 : /*
48850 : * Set up
48851 : */
48852 0 : ae_assert(kx>=2, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state);
48853 0 : ae_assert(ky>=2, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state);
48854 0 : ae_assert((kx-1)%2==0, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state);
48855 0 : ae_assert((ky-1)%2==0, "Spline2DFit.RescaleDataset2AndRefineIndex: integrity check failed", _state);
48856 0 : ae_swap_vectors(xyindex, &xyindexprev);
48857 0 : ivectorsetlengthatleast(xyindex, (kx-1)*(ky-1)+1, _state);
48858 0 : ivectorsetlengthatleast(bufi, npoints, _state);
48859 :
48860 : /*
48861 : * Refine
48862 : */
48863 0 : spline2d_expandindexrows(xy, d, shadow, ns, bufi, 0, npoints, &xyindexprev, 0, (ky+1)/2-1, xyindex, kx, ky, ae_true, _state);
48864 0 : xyindex->ptr.p_int[(kx-1)*(ky-1)] = npoints;
48865 :
48866 : /*
48867 : * Integrity check
48868 : */
48869 0 : ae_frame_leave(_state);
48870 0 : }
48871 :
48872 :
48873 : /*************************************************************************
48874 : Recurrent divide-and-conquer indexing function
48875 :
48876 : -- ALGLIB --
48877 : Copyright 05.02.2018 by Bochkanov Sergey
48878 : *************************************************************************/
48879 0 : static void spline2d_expandindexrows(/* Real */ ae_vector* xy,
48880 : ae_int_t d,
48881 : /* Real */ ae_vector* shadow,
48882 : ae_int_t ns,
48883 : /* Integer */ ae_vector* cidx,
48884 : ae_int_t pt0,
48885 : ae_int_t pt1,
48886 : /* Integer */ ae_vector* xyindexprev,
48887 : ae_int_t row0,
48888 : ae_int_t row1,
48889 : /* Integer */ ae_vector* xyindexnew,
48890 : ae_int_t kxnew,
48891 : ae_int_t kynew,
48892 : ae_bool rootcall,
48893 : ae_state *_state)
48894 : {
48895 : ae_int_t i;
48896 : ae_int_t entrywidth;
48897 : ae_int_t kxprev;
48898 : double v;
48899 : ae_int_t i0;
48900 : ae_int_t i1;
48901 : double efficiency;
48902 : double cost;
48903 : ae_int_t rowmid;
48904 :
48905 :
48906 0 : kxprev = (kxnew+1)/2;
48907 0 : entrywidth = 2+d;
48908 0 : efficiency = 0.1;
48909 0 : cost = d*(pt1-pt0+1)*(ae_log((double)(kxnew), _state)/ae_log((double)(2), _state))/efficiency;
48910 0 : ae_assert(xyindexprev->ptr.p_int[row0*(kxprev-1)+0]==pt0, "Spline2DFit.ExpandIndexRows: integrity check failed", _state);
48911 0 : ae_assert(xyindexprev->ptr.p_int[row1*(kxprev-1)+0]==pt1, "Spline2DFit.ExpandIndexRows: integrity check failed", _state);
48912 :
48913 : /*
48914 : * Parallelism
48915 : */
48916 0 : if( ((rootcall&&pt1-pt0>10000)&&row1-row0>=2)&&ae_fp_greater(cost,smpactivationlevel(_state)) )
48917 : {
48918 0 : if( _trypexec_spline2d_expandindexrows(xy,d,shadow,ns,cidx,pt0,pt1,xyindexprev,row0,row1,xyindexnew,kxnew,kynew,rootcall, _state) )
48919 : {
48920 0 : return;
48921 : }
48922 : }
48923 :
48924 : /*
48925 : * Partition
48926 : */
48927 0 : if( row1-row0>=2 )
48928 : {
48929 0 : tiledsplit(row1-row0, 1, &i0, &i1, _state);
48930 0 : rowmid = row0+i0;
48931 0 : spline2d_expandindexrows(xy, d, shadow, ns, cidx, pt0, xyindexprev->ptr.p_int[rowmid*(kxprev-1)+0], xyindexprev, row0, rowmid, xyindexnew, kxnew, kynew, ae_false, _state);
48932 0 : spline2d_expandindexrows(xy, d, shadow, ns, cidx, xyindexprev->ptr.p_int[rowmid*(kxprev-1)+0], pt1, xyindexprev, rowmid, row1, xyindexnew, kxnew, kynew, ae_false, _state);
48933 0 : return;
48934 : }
48935 :
48936 : /*
48937 : * Serial execution
48938 : */
48939 0 : for(i=pt0; i<=pt1-1; i++)
48940 : {
48941 0 : v = 2*xy->ptr.p_double[i*entrywidth+0];
48942 0 : xy->ptr.p_double[i*entrywidth+0] = v;
48943 0 : i0 = iboundval(ae_ifloor(v, _state), 0, kxnew-2, _state);
48944 0 : v = 2*xy->ptr.p_double[i*entrywidth+1];
48945 0 : xy->ptr.p_double[i*entrywidth+1] = v;
48946 0 : i1 = iboundval(ae_ifloor(v, _state), 0, kynew-2, _state);
48947 0 : cidx->ptr.p_int[i] = i1*(kxnew-1)+i0;
48948 : }
48949 0 : spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, cidx, pt0, pt1, xyindexnew, 2*row0*(kxnew-1)+0, 2*row1*(kxnew-1)+0, ae_false, _state);
48950 : }
48951 :
48952 :
48953 : /*************************************************************************
48954 : Serial stub for GPL edition.
48955 : *************************************************************************/
48956 0 : ae_bool _trypexec_spline2d_expandindexrows(/* Real */ ae_vector* xy,
48957 : ae_int_t d,
48958 : /* Real */ ae_vector* shadow,
48959 : ae_int_t ns,
48960 : /* Integer */ ae_vector* cidx,
48961 : ae_int_t pt0,
48962 : ae_int_t pt1,
48963 : /* Integer */ ae_vector* xyindexprev,
48964 : ae_int_t row0,
48965 : ae_int_t row1,
48966 : /* Integer */ ae_vector* xyindexnew,
48967 : ae_int_t kxnew,
48968 : ae_int_t kynew,
48969 : ae_bool rootcall,
48970 : ae_state *_state)
48971 : {
48972 0 : return ae_false;
48973 : }
48974 :
48975 :
48976 : /*************************************************************************
48977 : Recurrent divide-and-conquer indexing function
48978 :
48979 : -- ALGLIB --
48980 : Copyright 05.02.2018 by Bochkanov Sergey
48981 : *************************************************************************/
48982 0 : static void spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy,
48983 : ae_int_t d,
48984 : /* Real */ ae_vector* shadow,
48985 : ae_int_t ns,
48986 : /* Integer */ ae_vector* cidx,
48987 : ae_int_t pt0,
48988 : ae_int_t pt1,
48989 : /* Integer */ ae_vector* xyindex,
48990 : ae_int_t idx0,
48991 : ae_int_t idx1,
48992 : ae_bool rootcall,
48993 : ae_state *_state)
48994 : {
48995 : ae_int_t entrywidth;
48996 : ae_int_t idxmid;
48997 : ae_int_t wrk0;
48998 : ae_int_t wrk1;
48999 : double efficiency;
49000 : double cost;
49001 :
49002 :
49003 :
49004 : /*
49005 : * Efficiency - performance of the code when compared with that
49006 : * of linear algebra code.
49007 : */
49008 0 : entrywidth = 2+d;
49009 0 : efficiency = 0.1;
49010 0 : cost = d*(pt1-pt0+1)*ae_log((double)(idx1-idx0+1), _state)/ae_log((double)(2), _state)/efficiency;
49011 :
49012 : /*
49013 : * Parallelism
49014 : */
49015 0 : if( ((rootcall&&pt1-pt0>10000)&&idx1-idx0>=2)&&ae_fp_greater(cost,smpactivationlevel(_state)) )
49016 : {
49017 0 : if( _trypexec_spline2d_reorderdatasetandbuildindexrec(xy,d,shadow,ns,cidx,pt0,pt1,xyindex,idx0,idx1,rootcall, _state) )
49018 : {
49019 0 : return;
49020 : }
49021 : }
49022 :
49023 : /*
49024 : * Store left bound to XYIndex
49025 : */
49026 0 : xyindex->ptr.p_int[idx0] = pt0;
49027 :
49028 : /*
49029 : * Quick exit strategies
49030 : */
49031 0 : if( idx1<=idx0+1 )
49032 : {
49033 0 : return;
49034 : }
49035 0 : if( pt0==pt1 )
49036 : {
49037 0 : for(idxmid=idx0+1; idxmid<=idx1-1; idxmid++)
49038 : {
49039 0 : xyindex->ptr.p_int[idxmid] = pt1;
49040 : }
49041 0 : return;
49042 : }
49043 :
49044 : /*
49045 : * Select middle element
49046 : */
49047 0 : idxmid = idx0+(idx1-idx0)/2;
49048 0 : ae_assert(idx0<idxmid&&idxmid<idx1, "Spline2D: integrity check failed", _state);
49049 0 : wrk0 = pt0;
49050 0 : wrk1 = pt1-1;
49051 : for(;;)
49052 : {
49053 0 : while(wrk0<pt1&&cidx->ptr.p_int[wrk0]<idxmid)
49054 : {
49055 0 : wrk0 = wrk0+1;
49056 : }
49057 0 : while(wrk1>=pt0&&cidx->ptr.p_int[wrk1]>=idxmid)
49058 : {
49059 0 : wrk1 = wrk1-1;
49060 : }
49061 0 : if( wrk1<=wrk0 )
49062 : {
49063 0 : break;
49064 : }
49065 0 : swapentries(xy, wrk0, wrk1, entrywidth, _state);
49066 0 : if( ns>0 )
49067 : {
49068 0 : swapentries(shadow, wrk0, wrk1, ns, _state);
49069 : }
49070 0 : swapelementsi(cidx, wrk0, wrk1, _state);
49071 : }
49072 0 : spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, cidx, pt0, wrk0, xyindex, idx0, idxmid, ae_false, _state);
49073 0 : spline2d_reorderdatasetandbuildindexrec(xy, d, shadow, ns, cidx, wrk0, pt1, xyindex, idxmid, idx1, ae_false, _state);
49074 : }
49075 :
49076 :
49077 : /*************************************************************************
49078 : Serial stub for GPL edition.
49079 : *************************************************************************/
49080 0 : ae_bool _trypexec_spline2d_reorderdatasetandbuildindexrec(/* Real */ ae_vector* xy,
49081 : ae_int_t d,
49082 : /* Real */ ae_vector* shadow,
49083 : ae_int_t ns,
49084 : /* Integer */ ae_vector* cidx,
49085 : ae_int_t pt0,
49086 : ae_int_t pt1,
49087 : /* Integer */ ae_vector* xyindex,
49088 : ae_int_t idx0,
49089 : ae_int_t idx1,
49090 : ae_bool rootcall,
49091 : ae_state *_state)
49092 : {
49093 0 : return ae_false;
49094 : }
49095 :
49096 :
49097 : /*************************************************************************
49098 : This function performs fitting with BlockLLS solver. Internal function,
49099 : never use it directly.
49100 :
49101 : INPUT PARAMETERS:
49102 : XY - dataset, array[NPoints,2+D]
49103 : XYIndex - dataset index, see ReorderDatasetAndBuildIndex() for more info
49104 : KX0, KX1- X-indices of basis functions to select and fit;
49105 : range [KX0,KX1) is processed
49106 : KXTotal - total number of indexes in the entire grid
49107 : KY0, KY1- Y-indices of basis functions to select and fit;
49108 : range [KY0,KY1) is processed
49109 : KYTotal - total number of indexes in the entire grid
49110 : D - number of components in vector-valued spline, D>=1
49111 : LambdaReg- regularization coefficient
49112 : LambdaNS- nonlinearity penalty, exactly zero value is specially handled
49113 : (entire set of rows is not added to the matrix)
49114 : Basis1 - single-dimensional B-spline
49115 :
49116 :
49117 : OUTPUT PARAMETERS:
49118 : A - design matrix
49119 :
49120 : -- ALGLIB --
49121 : Copyright 05.02.2018 by Bochkanov Sergey
49122 : *************************************************************************/
49123 0 : static void spline2d_xdesigngenerate(/* Real */ ae_vector* xy,
49124 : /* Integer */ ae_vector* xyindex,
49125 : ae_int_t kx0,
49126 : ae_int_t kx1,
49127 : ae_int_t kxtotal,
49128 : ae_int_t ky0,
49129 : ae_int_t ky1,
49130 : ae_int_t kytotal,
49131 : ae_int_t d,
49132 : double lambdareg,
49133 : double lambdans,
49134 : spline1dinterpolant* basis1,
49135 : spline2dxdesignmatrix* a,
49136 : ae_state *_state)
49137 : {
49138 : ae_frame _frame_block;
49139 : ae_int_t entrywidth;
49140 : ae_int_t i;
49141 : ae_int_t j;
49142 : ae_int_t j0;
49143 : ae_int_t j1;
49144 : ae_int_t k0;
49145 : ae_int_t k1;
49146 : ae_int_t kx;
49147 : ae_int_t ky;
49148 : ae_int_t rowsdone;
49149 : ae_int_t batchesdone;
49150 : ae_int_t pt0;
49151 : ae_int_t pt1;
49152 : ae_int_t base0;
49153 : ae_int_t base1;
49154 : ae_int_t baseidx;
49155 : ae_int_t nzshift;
49156 : ae_int_t nzwidth;
49157 : ae_matrix d2x;
49158 : ae_matrix d2y;
49159 : ae_matrix dxy;
49160 : double v;
49161 : double v0;
49162 : double v1;
49163 : double v2;
49164 : double w0;
49165 : double w1;
49166 : double w2;
49167 :
49168 0 : ae_frame_make(_state, &_frame_block);
49169 0 : memset(&d2x, 0, sizeof(d2x));
49170 0 : memset(&d2y, 0, sizeof(d2y));
49171 0 : memset(&dxy, 0, sizeof(dxy));
49172 0 : ae_matrix_init(&d2x, 0, 0, DT_REAL, _state, ae_true);
49173 0 : ae_matrix_init(&d2y, 0, 0, DT_REAL, _state, ae_true);
49174 0 : ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true);
49175 :
49176 0 : nzshift = 1;
49177 0 : nzwidth = 4;
49178 0 : entrywidth = 2+d;
49179 0 : kx = kx1-kx0;
49180 0 : ky = ky1-ky0;
49181 0 : a->lambdareg = lambdareg;
49182 0 : a->blockwidth = 4;
49183 0 : a->kx = kx;
49184 0 : a->ky = ky;
49185 0 : a->d = d;
49186 0 : a->npoints = 0;
49187 0 : a->ndenserows = 0;
49188 0 : a->ndensebatches = 0;
49189 0 : a->maxbatch = 0;
49190 0 : for(j1=ky0; j1<=ky1-2; j1++)
49191 : {
49192 0 : for(j0=kx0; j0<=kx1-2; j0++)
49193 : {
49194 0 : i = xyindex->ptr.p_int[j1*(kxtotal-1)+j0+1]-xyindex->ptr.p_int[j1*(kxtotal-1)+j0];
49195 0 : a->npoints = a->npoints+i;
49196 0 : a->ndenserows = a->ndenserows+i;
49197 0 : a->ndensebatches = a->ndensebatches+1;
49198 0 : a->maxbatch = ae_maxint(a->maxbatch, i, _state);
49199 : }
49200 : }
49201 0 : if( ae_fp_neq(lambdans,(double)(0)) )
49202 : {
49203 0 : ae_assert(ae_fp_greater_eq(lambdans,(double)(0)), "Spline2DFit: integrity check failed", _state);
49204 0 : a->ndenserows = a->ndenserows+3*(kx-2)*(ky-2);
49205 0 : a->ndensebatches = a->ndensebatches+(kx-2)*(ky-2);
49206 0 : a->maxbatch = ae_maxint(a->maxbatch, 3, _state);
49207 : }
49208 0 : a->nrows = a->ndenserows+kx*ky;
49209 0 : rmatrixsetlengthatleast(&a->vals, a->ndenserows, a->blockwidth*a->blockwidth+d, _state);
49210 0 : ivectorsetlengthatleast(&a->batches, a->ndensebatches+1, _state);
49211 0 : ivectorsetlengthatleast(&a->batchbases, a->ndensebatches, _state);
49212 :
49213 : /*
49214 : * Setup output counters
49215 : */
49216 0 : batchesdone = 0;
49217 0 : rowsdone = 0;
49218 :
49219 : /*
49220 : * Generate rows corresponding to dataset points
49221 : */
49222 0 : ae_assert(kx>=nzwidth, "Spline2DFit: integrity check failed", _state);
49223 0 : ae_assert(ky>=nzwidth, "Spline2DFit: integrity check failed", _state);
49224 0 : rvectorsetlengthatleast(&a->tmp0, nzwidth, _state);
49225 0 : rvectorsetlengthatleast(&a->tmp1, nzwidth, _state);
49226 0 : a->batches.ptr.p_int[batchesdone] = 0;
49227 0 : for(j1=ky0; j1<=ky1-2; j1++)
49228 : {
49229 0 : for(j0=kx0; j0<=kx1-2; j0++)
49230 : {
49231 0 : pt0 = xyindex->ptr.p_int[j1*(kxtotal-1)+j0];
49232 0 : pt1 = xyindex->ptr.p_int[j1*(kxtotal-1)+j0+1];
49233 0 : base0 = iboundval(j0-kx0-nzshift, 0, kx-nzwidth, _state);
49234 0 : base1 = iboundval(j1-ky0-nzshift, 0, ky-nzwidth, _state);
49235 0 : baseidx = base1*kx+base0;
49236 0 : a->batchbases.ptr.p_int[batchesdone] = baseidx;
49237 0 : for(i=pt0; i<=pt1-1; i++)
49238 : {
49239 0 : for(k0=0; k0<=nzwidth-1; k0++)
49240 : {
49241 0 : a->tmp0.ptr.p_double[k0] = spline1dcalc(basis1, xy->ptr.p_double[i*entrywidth+0]-(base0+kx0+k0), _state);
49242 : }
49243 0 : for(k1=0; k1<=nzwidth-1; k1++)
49244 : {
49245 0 : a->tmp1.ptr.p_double[k1] = spline1dcalc(basis1, xy->ptr.p_double[i*entrywidth+1]-(base1+ky0+k1), _state);
49246 : }
49247 0 : for(k1=0; k1<=nzwidth-1; k1++)
49248 : {
49249 0 : for(k0=0; k0<=nzwidth-1; k0++)
49250 : {
49251 0 : a->vals.ptr.pp_double[rowsdone][k1*nzwidth+k0] = a->tmp0.ptr.p_double[k0]*a->tmp1.ptr.p_double[k1];
49252 : }
49253 : }
49254 0 : for(j=0; j<=d-1; j++)
49255 : {
49256 0 : a->vals.ptr.pp_double[rowsdone][nzwidth*nzwidth+j] = xy->ptr.p_double[i*entrywidth+2+j];
49257 : }
49258 0 : rowsdone = rowsdone+1;
49259 : }
49260 0 : batchesdone = batchesdone+1;
49261 0 : a->batches.ptr.p_int[batchesdone] = rowsdone;
49262 : }
49263 : }
49264 :
49265 : /*
49266 : * Generate rows corresponding to nonlinearity penalty
49267 : */
49268 0 : if( ae_fp_greater(lambdans,(double)(0)) )
49269 : {
49270 :
49271 : /*
49272 : * Smoothing is applied. Because all grid nodes are same,
49273 : * we apply same smoothing kernel, which is calculated only
49274 : * once at the beginning of design matrix generation.
49275 : */
49276 0 : ae_matrix_set_length(&d2x, 3, 3, _state);
49277 0 : ae_matrix_set_length(&d2y, 3, 3, _state);
49278 0 : ae_matrix_set_length(&dxy, 3, 3, _state);
49279 0 : for(j1=0; j1<=2; j1++)
49280 : {
49281 0 : for(j0=0; j0<=2; j0++)
49282 : {
49283 0 : d2x.ptr.pp_double[j0][j1] = 0.0;
49284 0 : d2y.ptr.pp_double[j0][j1] = 0.0;
49285 0 : dxy.ptr.pp_double[j0][j1] = 0.0;
49286 : }
49287 : }
49288 0 : for(k1=0; k1<=2; k1++)
49289 : {
49290 0 : for(k0=0; k0<=2; k0++)
49291 : {
49292 0 : spline1ddiff(basis1, (double)(-(k0-1)), &v0, &v1, &v2, _state);
49293 0 : spline1ddiff(basis1, (double)(-(k1-1)), &w0, &w1, &w2, _state);
49294 0 : d2x.ptr.pp_double[k0][k1] = d2x.ptr.pp_double[k0][k1]+v2*w0;
49295 0 : d2y.ptr.pp_double[k0][k1] = d2y.ptr.pp_double[k0][k1]+w2*v0;
49296 0 : dxy.ptr.pp_double[k0][k1] = dxy.ptr.pp_double[k0][k1]+v1*w1;
49297 : }
49298 : }
49299 :
49300 : /*
49301 : * Now, kernel is ready - apply it to all inner nodes of the grid.
49302 : */
49303 0 : for(j1=1; j1<=ky-2; j1++)
49304 : {
49305 0 : for(j0=1; j0<=kx-2; j0++)
49306 : {
49307 0 : base0 = imax2(j0-2, 0, _state);
49308 0 : base1 = imax2(j1-2, 0, _state);
49309 0 : baseidx = base1*kx+base0;
49310 0 : a->batchbases.ptr.p_int[batchesdone] = baseidx;
49311 :
49312 : /*
49313 : * d2F/dx2 term
49314 : */
49315 0 : v = lambdans;
49316 0 : for(j=0; j<=nzwidth*nzwidth+d-1; j++)
49317 : {
49318 0 : a->vals.ptr.pp_double[rowsdone][j] = (double)(0);
49319 : }
49320 0 : for(k1=j1-1; k1<=j1+1; k1++)
49321 : {
49322 0 : for(k0=j0-1; k0<=j0+1; k0++)
49323 : {
49324 0 : a->vals.ptr.pp_double[rowsdone][nzwidth*(k1-base1)+(k0-base0)] = v*d2x.ptr.pp_double[1+(k0-j0)][1+(k1-j1)];
49325 : }
49326 : }
49327 0 : rowsdone = rowsdone+1;
49328 :
49329 : /*
49330 : * d2F/dy2 term
49331 : */
49332 0 : v = lambdans;
49333 0 : for(j=0; j<=nzwidth*nzwidth+d-1; j++)
49334 : {
49335 0 : a->vals.ptr.pp_double[rowsdone][j] = (double)(0);
49336 : }
49337 0 : for(k1=j1-1; k1<=j1+1; k1++)
49338 : {
49339 0 : for(k0=j0-1; k0<=j0+1; k0++)
49340 : {
49341 0 : a->vals.ptr.pp_double[rowsdone][nzwidth*(k1-base1)+(k0-base0)] = v*d2y.ptr.pp_double[1+(k0-j0)][1+(k1-j1)];
49342 : }
49343 : }
49344 0 : rowsdone = rowsdone+1;
49345 :
49346 : /*
49347 : * 2*d2F/dxdy term
49348 : */
49349 0 : v = ae_sqrt((double)(2), _state)*lambdans;
49350 0 : for(j=0; j<=nzwidth*nzwidth+d-1; j++)
49351 : {
49352 0 : a->vals.ptr.pp_double[rowsdone][j] = (double)(0);
49353 : }
49354 0 : for(k1=j1-1; k1<=j1+1; k1++)
49355 : {
49356 0 : for(k0=j0-1; k0<=j0+1; k0++)
49357 : {
49358 0 : a->vals.ptr.pp_double[rowsdone][nzwidth*(k1-base1)+(k0-base0)] = v*dxy.ptr.pp_double[1+(k0-j0)][1+(k1-j1)];
49359 : }
49360 : }
49361 0 : rowsdone = rowsdone+1;
49362 0 : batchesdone = batchesdone+1;
49363 0 : a->batches.ptr.p_int[batchesdone] = rowsdone;
49364 : }
49365 : }
49366 : }
49367 :
49368 : /*
49369 : * Integrity post-check
49370 : */
49371 0 : ae_assert(batchesdone==a->ndensebatches, "Spline2DFit: integrity check failed", _state);
49372 0 : ae_assert(rowsdone==a->ndenserows, "Spline2DFit: integrity check failed", _state);
49373 0 : ae_frame_leave(_state);
49374 0 : }
49375 :
49376 :
49377 : /*************************************************************************
49378 : This function performs matrix-vector product of design matrix and dense
49379 : vector.
49380 :
49381 : INPUT PARAMETERS:
49382 : A - design matrix, (a.nrows) X (a.kx*a.ky);
49383 : some fields of A are used for temporaries,
49384 : so it is non-constant.
49385 : X - array[A.KX*A.KY]
49386 :
49387 :
49388 : OUTPUT PARAMETERS:
49389 : Y - product, array[A.NRows], automatically allocated
49390 :
49391 : -- ALGLIB --
49392 : Copyright 05.02.2018 by Bochkanov Sergey
49393 : *************************************************************************/
49394 0 : static void spline2d_xdesignmv(spline2dxdesignmatrix* a,
49395 : /* Real */ ae_vector* x,
49396 : /* Real */ ae_vector* y,
49397 : ae_state *_state)
49398 : {
49399 : ae_int_t bidx;
49400 : ae_int_t i;
49401 : ae_int_t cnt;
49402 : double v;
49403 : ae_int_t baseidx;
49404 : ae_int_t outidx;
49405 : ae_int_t batchsize;
49406 : ae_int_t kx;
49407 : ae_int_t k0;
49408 : ae_int_t k1;
49409 : ae_int_t nzwidth;
49410 :
49411 :
49412 0 : nzwidth = 4;
49413 0 : ae_assert(a->blockwidth==nzwidth, "Spline2DFit: integrity check failed", _state);
49414 0 : ae_assert(x->cnt>=a->kx*a->ky, "Spline2DFit: integrity check failed", _state);
49415 :
49416 : /*
49417 : * Prepare
49418 : */
49419 0 : rvectorsetlengthatleast(y, a->nrows, _state);
49420 0 : rvectorsetlengthatleast(&a->tmp0, nzwidth*nzwidth, _state);
49421 0 : rvectorsetlengthatleast(&a->tmp1, a->maxbatch, _state);
49422 0 : kx = a->kx;
49423 0 : outidx = 0;
49424 :
49425 : /*
49426 : * Process dense part
49427 : */
49428 0 : for(bidx=0; bidx<=a->ndensebatches-1; bidx++)
49429 : {
49430 0 : if( a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]>0 )
49431 : {
49432 0 : batchsize = a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx];
49433 0 : baseidx = a->batchbases.ptr.p_int[bidx];
49434 0 : for(k1=0; k1<=nzwidth-1; k1++)
49435 : {
49436 0 : for(k0=0; k0<=nzwidth-1; k0++)
49437 : {
49438 0 : a->tmp0.ptr.p_double[k1*nzwidth+k0] = x->ptr.p_double[baseidx+k1*kx+k0];
49439 : }
49440 : }
49441 0 : rmatrixgemv(batchsize, nzwidth*nzwidth, 1.0, &a->vals, a->batches.ptr.p_int[bidx], 0, 0, &a->tmp0, 0, 0.0, &a->tmp1, 0, _state);
49442 0 : for(i=0; i<=batchsize-1; i++)
49443 : {
49444 0 : y->ptr.p_double[outidx+i] = a->tmp1.ptr.p_double[i];
49445 : }
49446 0 : outidx = outidx+batchsize;
49447 : }
49448 : }
49449 0 : ae_assert(outidx==a->ndenserows, "Spline2DFit: integrity check failed", _state);
49450 :
49451 : /*
49452 : * Process regularizer
49453 : */
49454 0 : v = a->lambdareg;
49455 0 : cnt = a->kx*a->ky;
49456 0 : for(i=0; i<=cnt-1; i++)
49457 : {
49458 0 : y->ptr.p_double[outidx+i] = v*x->ptr.p_double[i];
49459 : }
49460 0 : outidx = outidx+cnt;
49461 :
49462 : /*
49463 : * Post-check
49464 : */
49465 0 : ae_assert(outidx==a->nrows, "Spline2DFit: integrity check failed", _state);
49466 0 : }
49467 :
49468 :
49469 : /*************************************************************************
49470 : This function performs matrix-vector product of transposed design matrix and dense
49471 : vector.
49472 :
49473 : INPUT PARAMETERS:
49474 : A - design matrix, (a.nrows) X (a.kx*a.ky);
49475 : some fields of A are used for temporaries,
49476 : so it is non-constant.
49477 : X - array[A.NRows]
49478 :
49479 :
49480 : OUTPUT PARAMETERS:
49481 : Y - product, array[A.KX*A.KY], automatically allocated
49482 :
49483 : -- ALGLIB --
49484 : Copyright 05.02.2018 by Bochkanov Sergey
49485 : *************************************************************************/
49486 0 : static void spline2d_xdesignmtv(spline2dxdesignmatrix* a,
49487 : /* Real */ ae_vector* x,
49488 : /* Real */ ae_vector* y,
49489 : ae_state *_state)
49490 : {
49491 : ae_int_t bidx;
49492 : ae_int_t i;
49493 : ae_int_t cnt;
49494 : double v;
49495 : ae_int_t baseidx;
49496 : ae_int_t inidx;
49497 : ae_int_t batchsize;
49498 : ae_int_t kx;
49499 : ae_int_t k0;
49500 : ae_int_t k1;
49501 : ae_int_t nzwidth;
49502 :
49503 :
49504 0 : nzwidth = 4;
49505 0 : ae_assert(a->blockwidth==nzwidth, "Spline2DFit: integrity check failed", _state);
49506 0 : ae_assert(x->cnt>=a->nrows, "Spline2DFit: integrity check failed", _state);
49507 :
49508 : /*
49509 : * Prepare
49510 : */
49511 0 : rvectorsetlengthatleast(y, a->kx*a->ky, _state);
49512 0 : rvectorsetlengthatleast(&a->tmp0, nzwidth*nzwidth, _state);
49513 0 : rvectorsetlengthatleast(&a->tmp1, a->maxbatch, _state);
49514 0 : kx = a->kx;
49515 0 : inidx = 0;
49516 0 : cnt = a->kx*a->ky;
49517 0 : for(i=0; i<=cnt-1; i++)
49518 : {
49519 0 : y->ptr.p_double[i] = (double)(0);
49520 : }
49521 :
49522 : /*
49523 : * Process dense part
49524 : */
49525 0 : for(bidx=0; bidx<=a->ndensebatches-1; bidx++)
49526 : {
49527 0 : if( a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]>0 )
49528 : {
49529 0 : batchsize = a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx];
49530 0 : baseidx = a->batchbases.ptr.p_int[bidx];
49531 0 : for(i=0; i<=batchsize-1; i++)
49532 : {
49533 0 : a->tmp1.ptr.p_double[i] = x->ptr.p_double[inidx+i];
49534 : }
49535 0 : rmatrixgemv(nzwidth*nzwidth, batchsize, 1.0, &a->vals, a->batches.ptr.p_int[bidx], 0, 1, &a->tmp1, 0, 0.0, &a->tmp0, 0, _state);
49536 0 : for(k1=0; k1<=nzwidth-1; k1++)
49537 : {
49538 0 : for(k0=0; k0<=nzwidth-1; k0++)
49539 : {
49540 0 : y->ptr.p_double[baseidx+k1*kx+k0] = y->ptr.p_double[baseidx+k1*kx+k0]+a->tmp0.ptr.p_double[k1*nzwidth+k0];
49541 : }
49542 : }
49543 0 : inidx = inidx+batchsize;
49544 : }
49545 : }
49546 0 : ae_assert(inidx==a->ndenserows, "Spline2DFit: integrity check failed", _state);
49547 :
49548 : /*
49549 : * Process regularizer
49550 : */
49551 0 : v = a->lambdareg;
49552 0 : cnt = a->kx*a->ky;
49553 0 : for(i=0; i<=cnt-1; i++)
49554 : {
49555 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+v*x->ptr.p_double[inidx+i];
49556 : }
49557 0 : inidx = inidx+cnt;
49558 :
49559 : /*
49560 : * Post-check
49561 : */
49562 0 : ae_assert(inidx==a->nrows, "Spline2DFit: integrity check failed", _state);
49563 0 : }
49564 :
49565 :
49566 : /*************************************************************************
49567 : This function generates squared design matrix stored in block band format.
49568 :
49569 : We use an adaptation of block skyline storage format, with
49570 : TOWERSIZE*KX skyline bands (towers) stored sequentially; here
49571 : TOWERSIZE=(BlockBandwidth+1)*KX. So, we have KY "towers", stored one below
49572 : other, in BlockATA matrix. Every "tower" is a sequence of BlockBandwidth+1
49573 : cells, each of them being KX*KX in size.
49574 :
49575 : INPUT PARAMETERS:
49576 : A - design matrix; some of its fields are used for temporaries
49577 : BlockATA- array[KY*(BlockBandwidth+1)*KX,KX], preallocated storage
49578 : for output matrix in compressed block band format
49579 :
49580 : OUTPUT PARAMETERS:
49581 : BlockATA- AH*AH', stored in compressed block band format
49582 : MXATA - max(|AH*AH'|), elementwise
49583 :
49584 : -- ALGLIB --
49585 : Copyright 05.02.2018 by Bochkanov Sergey
49586 : *************************************************************************/
49587 0 : static void spline2d_xdesignblockata(spline2dxdesignmatrix* a,
49588 : /* Real */ ae_matrix* blockata,
49589 : double* mxata,
49590 : ae_state *_state)
49591 : {
49592 : ae_int_t blockbandwidth;
49593 : ae_int_t nzwidth;
49594 : ae_int_t kx;
49595 : ae_int_t ky;
49596 : ae_int_t i0;
49597 : ae_int_t i1;
49598 : ae_int_t j0;
49599 : ae_int_t j1;
49600 : ae_int_t celloffset;
49601 : ae_int_t bidx;
49602 : ae_int_t baseidx;
49603 : ae_int_t batchsize;
49604 : ae_int_t offs0;
49605 : ae_int_t offs1;
49606 : double v;
49607 :
49608 :
49609 0 : blockbandwidth = 3;
49610 0 : nzwidth = 4;
49611 0 : kx = a->kx;
49612 0 : ky = a->ky;
49613 0 : ae_assert(a->blockwidth==nzwidth, "Spline2DFit: integrity check failed", _state);
49614 0 : rmatrixsetlengthatleast(&a->tmp2, nzwidth*nzwidth, nzwidth*nzwidth, _state);
49615 :
49616 : /*
49617 : * Initial zero-fill:
49618 : * * zero-fill ALL elements of BlockATA
49619 : * * zero-fill ALL elements of Tmp2
49620 : *
49621 : * Filling ALL elements, including unused ones, is essential for the
49622 : * purposes of calculating max(BlockATA).
49623 : */
49624 0 : for(i1=0; i1<=ky-1; i1++)
49625 : {
49626 0 : for(i0=i1; i0<=ae_minint(ky-1, i1+blockbandwidth, _state); i0++)
49627 : {
49628 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i0, _state);
49629 0 : for(j1=0; j1<=kx-1; j1++)
49630 : {
49631 0 : for(j0=0; j0<=kx-1; j0++)
49632 : {
49633 0 : blockata->ptr.pp_double[celloffset+j1][j0] = 0.0;
49634 : }
49635 : }
49636 : }
49637 : }
49638 0 : for(j1=0; j1<=nzwidth*nzwidth-1; j1++)
49639 : {
49640 0 : for(j0=0; j0<=nzwidth*nzwidth-1; j0++)
49641 : {
49642 0 : a->tmp2.ptr.pp_double[j1][j0] = 0.0;
49643 : }
49644 : }
49645 :
49646 : /*
49647 : * Process dense part of A
49648 : */
49649 0 : for(bidx=0; bidx<=a->ndensebatches-1; bidx++)
49650 : {
49651 0 : if( a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx]>0 )
49652 : {
49653 :
49654 : /*
49655 : * Generate 16x16 U = BATCH'*BATCH and add it to ATA.
49656 : *
49657 : * NOTE: it is essential that lower triangle of Tmp2 is
49658 : * filled by zeros.
49659 : */
49660 0 : batchsize = a->batches.ptr.p_int[bidx+1]-a->batches.ptr.p_int[bidx];
49661 0 : rmatrixsyrk(nzwidth*nzwidth, batchsize, 1.0, &a->vals, a->batches.ptr.p_int[bidx], 0, 2, 0.0, &a->tmp2, 0, 0, ae_true, _state);
49662 0 : baseidx = a->batchbases.ptr.p_int[bidx];
49663 0 : for(i1=0; i1<=nzwidth-1; i1++)
49664 : {
49665 0 : for(j1=i1; j1<=nzwidth-1; j1++)
49666 : {
49667 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, baseidx/kx+i1, baseidx/kx+j1, _state);
49668 0 : offs0 = baseidx%kx;
49669 0 : offs1 = baseidx%kx;
49670 0 : for(i0=0; i0<=nzwidth-1; i0++)
49671 : {
49672 0 : for(j0=0; j0<=nzwidth-1; j0++)
49673 : {
49674 0 : v = a->tmp2.ptr.pp_double[i1*nzwidth+i0][j1*nzwidth+j0];
49675 0 : blockata->ptr.pp_double[celloffset+offs1+i0][offs0+j0] = blockata->ptr.pp_double[celloffset+offs1+i0][offs0+j0]+v;
49676 : }
49677 : }
49678 : }
49679 : }
49680 : }
49681 : }
49682 :
49683 : /*
49684 : * Process regularizer term
49685 : */
49686 0 : for(i1=0; i1<=ky-1; i1++)
49687 : {
49688 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i1, _state);
49689 0 : for(j1=0; j1<=kx-1; j1++)
49690 : {
49691 0 : blockata->ptr.pp_double[celloffset+j1][j1] = blockata->ptr.pp_double[celloffset+j1][j1]+ae_sqr(a->lambdareg, _state);
49692 : }
49693 : }
49694 :
49695 : /*
49696 : * Calculate max(ATA)
49697 : *
49698 : * NOTE: here we rely on zero initialization of unused parts of
49699 : * BlockATA and Tmp2.
49700 : */
49701 0 : *mxata = 0.0;
49702 0 : for(i1=0; i1<=ky-1; i1++)
49703 : {
49704 0 : for(i0=i1; i0<=ae_minint(ky-1, i1+blockbandwidth, _state); i0++)
49705 : {
49706 0 : celloffset = spline2d_getcelloffset(kx, ky, blockbandwidth, i1, i0, _state);
49707 0 : for(j1=0; j1<=kx-1; j1++)
49708 : {
49709 0 : for(j0=0; j0<=kx-1; j0++)
49710 : {
49711 0 : *mxata = ae_maxreal(*mxata, ae_fabs(blockata->ptr.pp_double[celloffset+j1][j0], _state), _state);
49712 : }
49713 : }
49714 : }
49715 : }
49716 0 : }
49717 :
49718 :
49719 0 : void _spline2dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
49720 : {
49721 0 : spline2dinterpolant *p = (spline2dinterpolant*)_p;
49722 0 : ae_touch_ptr((void*)p);
49723 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
49724 0 : ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic);
49725 0 : ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic);
49726 0 : }
49727 :
49728 :
49729 0 : void _spline2dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
49730 : {
49731 0 : spline2dinterpolant *dst = (spline2dinterpolant*)_dst;
49732 0 : spline2dinterpolant *src = (spline2dinterpolant*)_src;
49733 0 : dst->stype = src->stype;
49734 0 : dst->n = src->n;
49735 0 : dst->m = src->m;
49736 0 : dst->d = src->d;
49737 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
49738 0 : ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic);
49739 0 : ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic);
49740 0 : }
49741 :
49742 :
49743 0 : void _spline2dinterpolant_clear(void* _p)
49744 : {
49745 0 : spline2dinterpolant *p = (spline2dinterpolant*)_p;
49746 0 : ae_touch_ptr((void*)p);
49747 0 : ae_vector_clear(&p->x);
49748 0 : ae_vector_clear(&p->y);
49749 0 : ae_vector_clear(&p->f);
49750 0 : }
49751 :
49752 :
49753 0 : void _spline2dinterpolant_destroy(void* _p)
49754 : {
49755 0 : spline2dinterpolant *p = (spline2dinterpolant*)_p;
49756 0 : ae_touch_ptr((void*)p);
49757 0 : ae_vector_destroy(&p->x);
49758 0 : ae_vector_destroy(&p->y);
49759 0 : ae_vector_destroy(&p->f);
49760 0 : }
49761 :
49762 :
49763 0 : void _spline2dbuilder_init(void* _p, ae_state *_state, ae_bool make_automatic)
49764 : {
49765 0 : spline2dbuilder *p = (spline2dbuilder*)_p;
49766 0 : ae_touch_ptr((void*)p);
49767 0 : ae_vector_init(&p->xy, 0, DT_REAL, _state, make_automatic);
49768 0 : }
49769 :
49770 :
49771 0 : void _spline2dbuilder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
49772 : {
49773 0 : spline2dbuilder *dst = (spline2dbuilder*)_dst;
49774 0 : spline2dbuilder *src = (spline2dbuilder*)_src;
49775 0 : dst->priorterm = src->priorterm;
49776 0 : dst->priortermval = src->priortermval;
49777 0 : dst->areatype = src->areatype;
49778 0 : dst->xa = src->xa;
49779 0 : dst->xb = src->xb;
49780 0 : dst->ya = src->ya;
49781 0 : dst->yb = src->yb;
49782 0 : dst->gridtype = src->gridtype;
49783 0 : dst->kx = src->kx;
49784 0 : dst->ky = src->ky;
49785 0 : dst->smoothing = src->smoothing;
49786 0 : dst->nlayers = src->nlayers;
49787 0 : dst->solvertype = src->solvertype;
49788 0 : dst->lambdabase = src->lambdabase;
49789 0 : ae_vector_init_copy(&dst->xy, &src->xy, _state, make_automatic);
49790 0 : dst->npoints = src->npoints;
49791 0 : dst->d = src->d;
49792 0 : dst->sx = src->sx;
49793 0 : dst->sy = src->sy;
49794 0 : dst->adddegreeoffreedom = src->adddegreeoffreedom;
49795 0 : dst->interfacesize = src->interfacesize;
49796 0 : dst->lsqrcnt = src->lsqrcnt;
49797 0 : dst->maxcoresize = src->maxcoresize;
49798 0 : }
49799 :
49800 :
49801 0 : void _spline2dbuilder_clear(void* _p)
49802 : {
49803 0 : spline2dbuilder *p = (spline2dbuilder*)_p;
49804 0 : ae_touch_ptr((void*)p);
49805 0 : ae_vector_clear(&p->xy);
49806 0 : }
49807 :
49808 :
49809 0 : void _spline2dbuilder_destroy(void* _p)
49810 : {
49811 0 : spline2dbuilder *p = (spline2dbuilder*)_p;
49812 0 : ae_touch_ptr((void*)p);
49813 0 : ae_vector_destroy(&p->xy);
49814 0 : }
49815 :
49816 :
49817 0 : void _spline2dfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
49818 : {
49819 0 : spline2dfitreport *p = (spline2dfitreport*)_p;
49820 0 : ae_touch_ptr((void*)p);
49821 0 : }
49822 :
49823 :
49824 0 : void _spline2dfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
49825 : {
49826 0 : spline2dfitreport *dst = (spline2dfitreport*)_dst;
49827 0 : spline2dfitreport *src = (spline2dfitreport*)_src;
49828 0 : dst->rmserror = src->rmserror;
49829 0 : dst->avgerror = src->avgerror;
49830 0 : dst->maxerror = src->maxerror;
49831 0 : dst->r2 = src->r2;
49832 0 : }
49833 :
49834 :
49835 0 : void _spline2dfitreport_clear(void* _p)
49836 : {
49837 0 : spline2dfitreport *p = (spline2dfitreport*)_p;
49838 0 : ae_touch_ptr((void*)p);
49839 0 : }
49840 :
49841 :
49842 0 : void _spline2dfitreport_destroy(void* _p)
49843 : {
49844 0 : spline2dfitreport *p = (spline2dfitreport*)_p;
49845 0 : ae_touch_ptr((void*)p);
49846 0 : }
49847 :
49848 :
49849 0 : void _spline2dxdesignmatrix_init(void* _p, ae_state *_state, ae_bool make_automatic)
49850 : {
49851 0 : spline2dxdesignmatrix *p = (spline2dxdesignmatrix*)_p;
49852 0 : ae_touch_ptr((void*)p);
49853 0 : ae_matrix_init(&p->vals, 0, 0, DT_REAL, _state, make_automatic);
49854 0 : ae_vector_init(&p->batches, 0, DT_INT, _state, make_automatic);
49855 0 : ae_vector_init(&p->batchbases, 0, DT_INT, _state, make_automatic);
49856 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
49857 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
49858 0 : ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic);
49859 0 : }
49860 :
49861 :
49862 0 : void _spline2dxdesignmatrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
49863 : {
49864 0 : spline2dxdesignmatrix *dst = (spline2dxdesignmatrix*)_dst;
49865 0 : spline2dxdesignmatrix *src = (spline2dxdesignmatrix*)_src;
49866 0 : dst->blockwidth = src->blockwidth;
49867 0 : dst->kx = src->kx;
49868 0 : dst->ky = src->ky;
49869 0 : dst->npoints = src->npoints;
49870 0 : dst->nrows = src->nrows;
49871 0 : dst->ndenserows = src->ndenserows;
49872 0 : dst->ndensebatches = src->ndensebatches;
49873 0 : dst->d = src->d;
49874 0 : dst->maxbatch = src->maxbatch;
49875 0 : ae_matrix_init_copy(&dst->vals, &src->vals, _state, make_automatic);
49876 0 : ae_vector_init_copy(&dst->batches, &src->batches, _state, make_automatic);
49877 0 : ae_vector_init_copy(&dst->batchbases, &src->batchbases, _state, make_automatic);
49878 0 : dst->lambdareg = src->lambdareg;
49879 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
49880 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
49881 0 : ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
49882 0 : }
49883 :
49884 :
49885 0 : void _spline2dxdesignmatrix_clear(void* _p)
49886 : {
49887 0 : spline2dxdesignmatrix *p = (spline2dxdesignmatrix*)_p;
49888 0 : ae_touch_ptr((void*)p);
49889 0 : ae_matrix_clear(&p->vals);
49890 0 : ae_vector_clear(&p->batches);
49891 0 : ae_vector_clear(&p->batchbases);
49892 0 : ae_vector_clear(&p->tmp0);
49893 0 : ae_vector_clear(&p->tmp1);
49894 0 : ae_matrix_clear(&p->tmp2);
49895 0 : }
49896 :
49897 :
49898 0 : void _spline2dxdesignmatrix_destroy(void* _p)
49899 : {
49900 0 : spline2dxdesignmatrix *p = (spline2dxdesignmatrix*)_p;
49901 0 : ae_touch_ptr((void*)p);
49902 0 : ae_matrix_destroy(&p->vals);
49903 0 : ae_vector_destroy(&p->batches);
49904 0 : ae_vector_destroy(&p->batchbases);
49905 0 : ae_vector_destroy(&p->tmp0);
49906 0 : ae_vector_destroy(&p->tmp1);
49907 0 : ae_matrix_destroy(&p->tmp2);
49908 0 : }
49909 :
49910 :
49911 0 : void _spline2dblockllsbuf_init(void* _p, ae_state *_state, ae_bool make_automatic)
49912 : {
49913 0 : spline2dblockllsbuf *p = (spline2dblockllsbuf*)_p;
49914 0 : ae_touch_ptr((void*)p);
49915 0 : _linlsqrstate_init(&p->solver, _state, make_automatic);
49916 0 : _linlsqrreport_init(&p->solverrep, _state, make_automatic);
49917 0 : ae_matrix_init(&p->blockata, 0, 0, DT_REAL, _state, make_automatic);
49918 0 : ae_matrix_init(&p->trsmbuf2, 0, 0, DT_REAL, _state, make_automatic);
49919 0 : ae_matrix_init(&p->cholbuf2, 0, 0, DT_REAL, _state, make_automatic);
49920 0 : ae_vector_init(&p->cholbuf1, 0, DT_REAL, _state, make_automatic);
49921 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
49922 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
49923 0 : }
49924 :
49925 :
49926 0 : void _spline2dblockllsbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
49927 : {
49928 0 : spline2dblockllsbuf *dst = (spline2dblockllsbuf*)_dst;
49929 0 : spline2dblockllsbuf *src = (spline2dblockllsbuf*)_src;
49930 0 : _linlsqrstate_init_copy(&dst->solver, &src->solver, _state, make_automatic);
49931 0 : _linlsqrreport_init_copy(&dst->solverrep, &src->solverrep, _state, make_automatic);
49932 0 : ae_matrix_init_copy(&dst->blockata, &src->blockata, _state, make_automatic);
49933 0 : ae_matrix_init_copy(&dst->trsmbuf2, &src->trsmbuf2, _state, make_automatic);
49934 0 : ae_matrix_init_copy(&dst->cholbuf2, &src->cholbuf2, _state, make_automatic);
49935 0 : ae_vector_init_copy(&dst->cholbuf1, &src->cholbuf1, _state, make_automatic);
49936 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
49937 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
49938 0 : }
49939 :
49940 :
49941 0 : void _spline2dblockllsbuf_clear(void* _p)
49942 : {
49943 0 : spline2dblockllsbuf *p = (spline2dblockllsbuf*)_p;
49944 0 : ae_touch_ptr((void*)p);
49945 0 : _linlsqrstate_clear(&p->solver);
49946 0 : _linlsqrreport_clear(&p->solverrep);
49947 0 : ae_matrix_clear(&p->blockata);
49948 0 : ae_matrix_clear(&p->trsmbuf2);
49949 0 : ae_matrix_clear(&p->cholbuf2);
49950 0 : ae_vector_clear(&p->cholbuf1);
49951 0 : ae_vector_clear(&p->tmp0);
49952 0 : ae_vector_clear(&p->tmp1);
49953 0 : }
49954 :
49955 :
49956 0 : void _spline2dblockllsbuf_destroy(void* _p)
49957 : {
49958 0 : spline2dblockllsbuf *p = (spline2dblockllsbuf*)_p;
49959 0 : ae_touch_ptr((void*)p);
49960 0 : _linlsqrstate_destroy(&p->solver);
49961 0 : _linlsqrreport_destroy(&p->solverrep);
49962 0 : ae_matrix_destroy(&p->blockata);
49963 0 : ae_matrix_destroy(&p->trsmbuf2);
49964 0 : ae_matrix_destroy(&p->cholbuf2);
49965 0 : ae_vector_destroy(&p->cholbuf1);
49966 0 : ae_vector_destroy(&p->tmp0);
49967 0 : ae_vector_destroy(&p->tmp1);
49968 0 : }
49969 :
49970 :
49971 0 : void _spline2dfastddmbuf_init(void* _p, ae_state *_state, ae_bool make_automatic)
49972 : {
49973 0 : spline2dfastddmbuf *p = (spline2dfastddmbuf*)_p;
49974 0 : ae_touch_ptr((void*)p);
49975 0 : _spline2dxdesignmatrix_init(&p->xdesignmatrix, _state, make_automatic);
49976 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
49977 0 : ae_vector_init(&p->tmpz, 0, DT_REAL, _state, make_automatic);
49978 0 : _spline2dfitreport_init(&p->dummyrep, _state, make_automatic);
49979 0 : _spline2dinterpolant_init(&p->localmodel, _state, make_automatic);
49980 0 : _spline2dblockllsbuf_init(&p->blockllsbuf, _state, make_automatic);
49981 0 : }
49982 :
49983 :
49984 0 : void _spline2dfastddmbuf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
49985 : {
49986 0 : spline2dfastddmbuf *dst = (spline2dfastddmbuf*)_dst;
49987 0 : spline2dfastddmbuf *src = (spline2dfastddmbuf*)_src;
49988 0 : _spline2dxdesignmatrix_init_copy(&dst->xdesignmatrix, &src->xdesignmatrix, _state, make_automatic);
49989 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
49990 0 : ae_vector_init_copy(&dst->tmpz, &src->tmpz, _state, make_automatic);
49991 0 : _spline2dfitreport_init_copy(&dst->dummyrep, &src->dummyrep, _state, make_automatic);
49992 0 : _spline2dinterpolant_init_copy(&dst->localmodel, &src->localmodel, _state, make_automatic);
49993 0 : _spline2dblockllsbuf_init_copy(&dst->blockllsbuf, &src->blockllsbuf, _state, make_automatic);
49994 0 : }
49995 :
49996 :
49997 0 : void _spline2dfastddmbuf_clear(void* _p)
49998 : {
49999 0 : spline2dfastddmbuf *p = (spline2dfastddmbuf*)_p;
50000 0 : ae_touch_ptr((void*)p);
50001 0 : _spline2dxdesignmatrix_clear(&p->xdesignmatrix);
50002 0 : ae_vector_clear(&p->tmp0);
50003 0 : ae_vector_clear(&p->tmpz);
50004 0 : _spline2dfitreport_clear(&p->dummyrep);
50005 0 : _spline2dinterpolant_clear(&p->localmodel);
50006 0 : _spline2dblockllsbuf_clear(&p->blockllsbuf);
50007 0 : }
50008 :
50009 :
50010 0 : void _spline2dfastddmbuf_destroy(void* _p)
50011 : {
50012 0 : spline2dfastddmbuf *p = (spline2dfastddmbuf*)_p;
50013 0 : ae_touch_ptr((void*)p);
50014 0 : _spline2dxdesignmatrix_destroy(&p->xdesignmatrix);
50015 0 : ae_vector_destroy(&p->tmp0);
50016 0 : ae_vector_destroy(&p->tmpz);
50017 0 : _spline2dfitreport_destroy(&p->dummyrep);
50018 0 : _spline2dinterpolant_destroy(&p->localmodel);
50019 0 : _spline2dblockllsbuf_destroy(&p->blockllsbuf);
50020 0 : }
50021 :
50022 :
50023 : #endif
50024 : #if defined(AE_COMPILE_RBFV1) || !defined(AE_PARTIAL_BUILD)
50025 :
50026 :
50027 : /*************************************************************************
50028 : This function creates RBF model for a scalar (NY=1) or vector (NY>1)
50029 : function in a NX-dimensional space (NX=2 or NX=3).
50030 :
50031 : INPUT PARAMETERS:
50032 : NX - dimension of the space, NX=2 or NX=3
50033 : NY - function dimension, NY>=1
50034 :
50035 : OUTPUT PARAMETERS:
50036 : S - RBF model (initially equals to zero)
50037 :
50038 : -- ALGLIB --
50039 : Copyright 13.12.2011 by Bochkanov Sergey
50040 : *************************************************************************/
50041 0 : void rbfv1create(ae_int_t nx,
50042 : ae_int_t ny,
50043 : rbfv1model* s,
50044 : ae_state *_state)
50045 : {
50046 : ae_int_t i;
50047 : ae_int_t j;
50048 :
50049 0 : _rbfv1model_clear(s);
50050 :
50051 0 : ae_assert(nx==2||nx==3, "RBFCreate: NX<>2 and NX<>3", _state);
50052 0 : ae_assert(ny>=1, "RBFCreate: NY<1", _state);
50053 0 : s->nx = nx;
50054 0 : s->ny = ny;
50055 0 : s->nl = 0;
50056 0 : s->nc = 0;
50057 0 : ae_matrix_set_length(&s->v, ny, rbfv1_mxnx+1, _state);
50058 0 : for(i=0; i<=ny-1; i++)
50059 : {
50060 0 : for(j=0; j<=rbfv1_mxnx; j++)
50061 : {
50062 0 : s->v.ptr.pp_double[i][j] = (double)(0);
50063 : }
50064 : }
50065 0 : s->rmax = (double)(0);
50066 0 : }
50067 :
50068 :
50069 : /*************************************************************************
50070 : This function creates buffer structure which can be used to perform
50071 : parallel RBF model evaluations (with one RBF model instance being
50072 : used from multiple threads, as long as different threads use different
50073 : instances of buffer).
50074 :
50075 : This buffer object can be used with rbftscalcbuf() function (here "ts"
50076 : stands for "thread-safe", "buf" is a suffix which denotes function which
50077 : reuses previously allocated output space).
50078 :
50079 : How to use it:
50080 : * create RBF model structure with rbfcreate()
50081 : * load data, tune parameters
50082 : * call rbfbuildmodel()
50083 : * call rbfcreatecalcbuffer(), once per thread working with RBF model (you
50084 : should call this function only AFTER call to rbfbuildmodel(), see below
50085 : for more information)
50086 : * call rbftscalcbuf() from different threads, with each thread working
50087 : with its own copy of buffer object.
50088 :
50089 : INPUT PARAMETERS
50090 : S - RBF model
50091 :
50092 : OUTPUT PARAMETERS
50093 : Buf - external buffer.
50094 :
50095 :
50096 : IMPORTANT: buffer object should be used only with RBF model object which
50097 : was used to initialize buffer. Any attempt to use buffer with
50098 : different object is dangerous - you may get memory violation
50099 : error because sizes of internal arrays do not fit to dimensions
50100 : of RBF structure.
50101 :
50102 : IMPORTANT: you should call this function only for model which was built
50103 : with rbfbuildmodel() function, after successful invocation of
50104 : rbfbuildmodel(). Sizes of some internal structures are
50105 : determined only after model is built, so buffer object created
50106 : before model construction stage will be useless (and any
50107 : attempt to use it will result in exception).
50108 :
50109 : -- ALGLIB --
50110 : Copyright 02.04.2016 by Sergey Bochkanov
50111 : *************************************************************************/
50112 0 : void rbfv1createcalcbuffer(rbfv1model* s,
50113 : rbfv1calcbuffer* buf,
50114 : ae_state *_state)
50115 : {
50116 :
50117 0 : _rbfv1calcbuffer_clear(buf);
50118 :
50119 0 : kdtreecreaterequestbuffer(&s->tree, &buf->requestbuffer, _state);
50120 0 : }
50121 :
50122 :
50123 : /*************************************************************************
50124 : This function builds RBF model and returns report (contains some
50125 : information which can be used for evaluation of the algorithm properties).
50126 :
50127 : Call to this function modifies RBF model by calculating its centers/radii/
50128 : weights and saving them into RBFModel structure. Initially RBFModel
50129 : contain zero coefficients, but after call to this function we will have
50130 : coefficients which were calculated in order to fit our dataset.
50131 :
50132 : After you called this function you can call RBFCalc(), RBFGridCalc() and
50133 : other model calculation functions.
50134 :
50135 : INPUT PARAMETERS:
50136 : S - RBF model, initialized by RBFCreate() call
50137 : Rep - report:
50138 : * Rep.TerminationType:
50139 : * -5 - non-distinct basis function centers were detected,
50140 : interpolation aborted
50141 : * -4 - nonconvergence of the internal SVD solver
50142 : * 1 - successful termination
50143 : Fields are used for debugging purposes:
50144 : * Rep.IterationsCount - iterations count of the LSQR solver
50145 : * Rep.NMV - number of matrix-vector products
50146 : * Rep.ARows - rows count for the system matrix
50147 : * Rep.ACols - columns count for the system matrix
50148 : * Rep.ANNZ - number of significantly non-zero elements
50149 : (elements above some algorithm-determined threshold)
50150 :
50151 : NOTE: failure to build model will leave current state of the structure
50152 : unchanged.
50153 :
50154 : -- ALGLIB --
50155 : Copyright 13.12.2011 by Bochkanov Sergey
50156 : *************************************************************************/
50157 0 : void rbfv1buildmodel(/* Real */ ae_matrix* x,
50158 : /* Real */ ae_matrix* y,
50159 : ae_int_t n,
50160 : ae_int_t aterm,
50161 : ae_int_t algorithmtype,
50162 : ae_int_t nlayers,
50163 : double radvalue,
50164 : double radzvalue,
50165 : double lambdav,
50166 : double epsort,
50167 : double epserr,
50168 : ae_int_t maxits,
50169 : rbfv1model* s,
50170 : rbfv1report* rep,
50171 : ae_state *_state)
50172 : {
50173 : ae_frame _frame_block;
50174 : kdtree tree;
50175 : kdtree ctree;
50176 : ae_vector dist;
50177 : ae_vector xcx;
50178 : ae_matrix a;
50179 : ae_matrix v;
50180 : ae_matrix omega;
50181 : ae_matrix residualy;
50182 : ae_vector radius;
50183 : ae_matrix xc;
50184 : ae_int_t nc;
50185 : double rmax;
50186 : ae_vector tags;
50187 : ae_vector ctags;
50188 : ae_int_t i;
50189 : ae_int_t j;
50190 : ae_int_t k;
50191 : ae_int_t snnz;
50192 : ae_vector tmp0;
50193 : ae_vector tmp1;
50194 : ae_int_t layerscnt;
50195 : ae_bool modelstatus;
50196 :
50197 0 : ae_frame_make(_state, &_frame_block);
50198 0 : memset(&tree, 0, sizeof(tree));
50199 0 : memset(&ctree, 0, sizeof(ctree));
50200 0 : memset(&dist, 0, sizeof(dist));
50201 0 : memset(&xcx, 0, sizeof(xcx));
50202 0 : memset(&a, 0, sizeof(a));
50203 0 : memset(&v, 0, sizeof(v));
50204 0 : memset(&omega, 0, sizeof(omega));
50205 0 : memset(&residualy, 0, sizeof(residualy));
50206 0 : memset(&radius, 0, sizeof(radius));
50207 0 : memset(&xc, 0, sizeof(xc));
50208 0 : memset(&tags, 0, sizeof(tags));
50209 0 : memset(&ctags, 0, sizeof(ctags));
50210 0 : memset(&tmp0, 0, sizeof(tmp0));
50211 0 : memset(&tmp1, 0, sizeof(tmp1));
50212 0 : _rbfv1report_clear(rep);
50213 0 : _kdtree_init(&tree, _state, ae_true);
50214 0 : _kdtree_init(&ctree, _state, ae_true);
50215 0 : ae_vector_init(&dist, 0, DT_REAL, _state, ae_true);
50216 0 : ae_vector_init(&xcx, 0, DT_REAL, _state, ae_true);
50217 0 : ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
50218 0 : ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
50219 0 : ae_matrix_init(&omega, 0, 0, DT_REAL, _state, ae_true);
50220 0 : ae_matrix_init(&residualy, 0, 0, DT_REAL, _state, ae_true);
50221 0 : ae_vector_init(&radius, 0, DT_REAL, _state, ae_true);
50222 0 : ae_matrix_init(&xc, 0, 0, DT_REAL, _state, ae_true);
50223 0 : ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
50224 0 : ae_vector_init(&ctags, 0, DT_INT, _state, ae_true);
50225 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
50226 0 : ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
50227 :
50228 0 : ae_assert(s->nx==2||s->nx==3, "RBFBuildModel: S.NX<>2 or S.NX<>3!", _state);
50229 :
50230 : /*
50231 : * Quick exit when we have no points
50232 : */
50233 0 : if( n==0 )
50234 : {
50235 0 : rep->terminationtype = 1;
50236 0 : rep->iterationscount = 0;
50237 0 : rep->nmv = 0;
50238 0 : rep->arows = 0;
50239 0 : rep->acols = 0;
50240 0 : kdtreebuildtagged(&s->xc, &tags, 0, rbfv1_mxnx, 0, 2, &s->tree, _state);
50241 0 : ae_matrix_set_length(&s->xc, 0, 0, _state);
50242 0 : ae_matrix_set_length(&s->wr, 0, 0, _state);
50243 0 : s->nc = 0;
50244 0 : s->rmax = (double)(0);
50245 0 : ae_matrix_set_length(&s->v, s->ny, rbfv1_mxnx+1, _state);
50246 0 : for(i=0; i<=s->ny-1; i++)
50247 : {
50248 0 : for(j=0; j<=rbfv1_mxnx; j++)
50249 : {
50250 0 : s->v.ptr.pp_double[i][j] = (double)(0);
50251 : }
50252 : }
50253 0 : ae_frame_leave(_state);
50254 0 : return;
50255 : }
50256 :
50257 : /*
50258 : * General case, N>0
50259 : */
50260 0 : rep->annz = 0;
50261 0 : rep->iterationscount = 0;
50262 0 : rep->nmv = 0;
50263 0 : ae_vector_set_length(&xcx, rbfv1_mxnx, _state);
50264 :
50265 : /*
50266 : * First model in a sequence - linear model.
50267 : * Residuals from linear regression are stored in the ResidualY variable
50268 : * (used later to build RBF models).
50269 : */
50270 0 : ae_matrix_set_length(&residualy, n, s->ny, _state);
50271 0 : for(i=0; i<=n-1; i++)
50272 : {
50273 0 : for(j=0; j<=s->ny-1; j++)
50274 : {
50275 0 : residualy.ptr.pp_double[i][j] = y->ptr.pp_double[i][j];
50276 : }
50277 : }
50278 0 : if( !rbfv1_rbfv1buildlinearmodel(x, &residualy, n, s->ny, aterm, &v, _state) )
50279 : {
50280 0 : rep->terminationtype = -5;
50281 0 : ae_frame_leave(_state);
50282 0 : return;
50283 : }
50284 :
50285 : /*
50286 : * Handle special case: multilayer model with NLayers=0.
50287 : * Quick exit.
50288 : */
50289 0 : if( algorithmtype==2&&nlayers==0 )
50290 : {
50291 0 : rep->terminationtype = 1;
50292 0 : rep->iterationscount = 0;
50293 0 : rep->nmv = 0;
50294 0 : rep->arows = 0;
50295 0 : rep->acols = 0;
50296 0 : kdtreebuildtagged(&s->xc, &tags, 0, rbfv1_mxnx, 0, 2, &s->tree, _state);
50297 0 : ae_matrix_set_length(&s->xc, 0, 0, _state);
50298 0 : ae_matrix_set_length(&s->wr, 0, 0, _state);
50299 0 : s->nc = 0;
50300 0 : s->rmax = (double)(0);
50301 0 : ae_matrix_set_length(&s->v, s->ny, rbfv1_mxnx+1, _state);
50302 0 : for(i=0; i<=s->ny-1; i++)
50303 : {
50304 0 : for(j=0; j<=rbfv1_mxnx; j++)
50305 : {
50306 0 : s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j];
50307 : }
50308 : }
50309 0 : ae_frame_leave(_state);
50310 0 : return;
50311 : }
50312 :
50313 : /*
50314 : * Second model in a sequence - RBF term.
50315 : *
50316 : * NOTE: assignments below are not necessary, but without them
50317 : * MSVC complains about unitialized variables.
50318 : */
50319 0 : nc = 0;
50320 0 : rmax = (double)(0);
50321 0 : layerscnt = 0;
50322 0 : modelstatus = ae_false;
50323 0 : if( algorithmtype==1 )
50324 : {
50325 :
50326 : /*
50327 : * Add RBF model.
50328 : * This model uses local KD-trees to speed-up nearest neighbor searches.
50329 : */
50330 0 : nc = n;
50331 0 : ae_matrix_set_length(&xc, nc, rbfv1_mxnx, _state);
50332 0 : for(i=0; i<=nc-1; i++)
50333 : {
50334 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
50335 : {
50336 0 : xc.ptr.pp_double[i][j] = x->ptr.pp_double[i][j];
50337 : }
50338 : }
50339 0 : rmax = (double)(0);
50340 0 : ae_vector_set_length(&radius, nc, _state);
50341 0 : ae_vector_set_length(&ctags, nc, _state);
50342 0 : for(i=0; i<=nc-1; i++)
50343 : {
50344 0 : ctags.ptr.p_int[i] = i;
50345 : }
50346 0 : kdtreebuildtagged(&xc, &ctags, nc, rbfv1_mxnx, 0, 2, &ctree, _state);
50347 0 : if( nc==0 )
50348 : {
50349 0 : rmax = (double)(1);
50350 : }
50351 : else
50352 : {
50353 0 : if( nc==1 )
50354 : {
50355 0 : radius.ptr.p_double[0] = radvalue;
50356 0 : rmax = radius.ptr.p_double[0];
50357 : }
50358 : else
50359 : {
50360 :
50361 : /*
50362 : * NC>1, calculate radii using distances to nearest neigbors
50363 : */
50364 0 : for(i=0; i<=nc-1; i++)
50365 : {
50366 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
50367 : {
50368 0 : xcx.ptr.p_double[j] = xc.ptr.pp_double[i][j];
50369 : }
50370 0 : if( kdtreequeryknn(&ctree, &xcx, 1, ae_false, _state)>0 )
50371 : {
50372 0 : kdtreequeryresultsdistances(&ctree, &dist, _state);
50373 0 : radius.ptr.p_double[i] = radvalue*dist.ptr.p_double[0];
50374 : }
50375 : else
50376 : {
50377 :
50378 : /*
50379 : * No neighbors found (it will happen when we have only one center).
50380 : * Initialize radius with default value.
50381 : */
50382 0 : radius.ptr.p_double[i] = 1.0;
50383 : }
50384 : }
50385 :
50386 : /*
50387 : * Apply filtering
50388 : */
50389 0 : rvectorsetlengthatleast(&tmp0, nc, _state);
50390 0 : for(i=0; i<=nc-1; i++)
50391 : {
50392 0 : tmp0.ptr.p_double[i] = radius.ptr.p_double[i];
50393 : }
50394 0 : tagsortfast(&tmp0, &tmp1, nc, _state);
50395 0 : for(i=0; i<=nc-1; i++)
50396 : {
50397 0 : radius.ptr.p_double[i] = ae_minreal(radius.ptr.p_double[i], radzvalue*tmp0.ptr.p_double[nc/2], _state);
50398 : }
50399 :
50400 : /*
50401 : * Calculate RMax, check that all radii are non-zero
50402 : */
50403 0 : for(i=0; i<=nc-1; i++)
50404 : {
50405 0 : rmax = ae_maxreal(rmax, radius.ptr.p_double[i], _state);
50406 : }
50407 0 : for(i=0; i<=nc-1; i++)
50408 : {
50409 0 : if( ae_fp_eq(radius.ptr.p_double[i],(double)(0)) )
50410 : {
50411 0 : rep->terminationtype = -5;
50412 0 : ae_frame_leave(_state);
50413 0 : return;
50414 : }
50415 : }
50416 : }
50417 : }
50418 0 : ivectorsetlengthatleast(&tags, n, _state);
50419 0 : for(i=0; i<=n-1; i++)
50420 : {
50421 0 : tags.ptr.p_int[i] = i;
50422 : }
50423 0 : kdtreebuildtagged(x, &tags, n, rbfv1_mxnx, 0, 2, &tree, _state);
50424 0 : rbfv1_buildrbfmodellsqr(x, &residualy, &xc, &radius, n, nc, s->ny, &tree, &ctree, epsort, epserr, maxits, &rep->annz, &snnz, &omega, &rep->terminationtype, &rep->iterationscount, &rep->nmv, _state);
50425 0 : layerscnt = 1;
50426 0 : modelstatus = ae_true;
50427 : }
50428 0 : if( algorithmtype==2 )
50429 : {
50430 0 : rmax = radvalue;
50431 0 : rbfv1_buildrbfmlayersmodellsqr(x, &residualy, &xc, radvalue, &radius, n, &nc, s->ny, nlayers, &ctree, 1.0E-6, 1.0E-6, 50, lambdav, &rep->annz, &omega, &rep->terminationtype, &rep->iterationscount, &rep->nmv, _state);
50432 0 : layerscnt = nlayers;
50433 0 : modelstatus = ae_true;
50434 : }
50435 0 : ae_assert(modelstatus, "RBFBuildModel: integrity error", _state);
50436 0 : if( rep->terminationtype<=0 )
50437 : {
50438 0 : ae_frame_leave(_state);
50439 0 : return;
50440 : }
50441 :
50442 : /*
50443 : * Model is built
50444 : */
50445 0 : s->nc = nc/layerscnt;
50446 0 : s->rmax = rmax;
50447 0 : s->nl = layerscnt;
50448 0 : ae_matrix_set_length(&s->xc, s->nc, rbfv1_mxnx, _state);
50449 0 : ae_matrix_set_length(&s->wr, s->nc, 1+s->nl*s->ny, _state);
50450 0 : ae_matrix_set_length(&s->v, s->ny, rbfv1_mxnx+1, _state);
50451 0 : for(i=0; i<=s->nc-1; i++)
50452 : {
50453 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
50454 : {
50455 0 : s->xc.ptr.pp_double[i][j] = xc.ptr.pp_double[i][j];
50456 : }
50457 : }
50458 0 : ivectorsetlengthatleast(&tags, s->nc, _state);
50459 0 : for(i=0; i<=s->nc-1; i++)
50460 : {
50461 0 : tags.ptr.p_int[i] = i;
50462 : }
50463 0 : kdtreebuildtagged(&s->xc, &tags, s->nc, rbfv1_mxnx, 0, 2, &s->tree, _state);
50464 0 : for(i=0; i<=s->nc-1; i++)
50465 : {
50466 0 : s->wr.ptr.pp_double[i][0] = radius.ptr.p_double[i];
50467 0 : for(k=0; k<=layerscnt-1; k++)
50468 : {
50469 0 : for(j=0; j<=s->ny-1; j++)
50470 : {
50471 0 : s->wr.ptr.pp_double[i][1+k*s->ny+j] = omega.ptr.pp_double[k*s->nc+i][j];
50472 : }
50473 : }
50474 : }
50475 0 : for(i=0; i<=s->ny-1; i++)
50476 : {
50477 0 : for(j=0; j<=rbfv1_mxnx; j++)
50478 : {
50479 0 : s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j];
50480 : }
50481 : }
50482 0 : rep->terminationtype = 1;
50483 0 : rep->arows = n;
50484 0 : rep->acols = s->nc;
50485 0 : ae_frame_leave(_state);
50486 : }
50487 :
50488 :
50489 : /*************************************************************************
50490 : Serializer: allocation
50491 :
50492 : -- ALGLIB --
50493 : Copyright 02.02.2012 by Bochkanov Sergey
50494 : *************************************************************************/
50495 0 : void rbfv1alloc(ae_serializer* s, rbfv1model* model, ae_state *_state)
50496 : {
50497 :
50498 :
50499 :
50500 : /*
50501 : * Data
50502 : */
50503 0 : ae_serializer_alloc_entry(s);
50504 0 : ae_serializer_alloc_entry(s);
50505 0 : ae_serializer_alloc_entry(s);
50506 0 : ae_serializer_alloc_entry(s);
50507 0 : kdtreealloc(s, &model->tree, _state);
50508 0 : allocrealmatrix(s, &model->xc, -1, -1, _state);
50509 0 : allocrealmatrix(s, &model->wr, -1, -1, _state);
50510 0 : ae_serializer_alloc_entry(s);
50511 0 : allocrealmatrix(s, &model->v, -1, -1, _state);
50512 0 : }
50513 :
50514 :
50515 : /*************************************************************************
50516 : Serializer: serialization
50517 :
50518 : -- ALGLIB --
50519 : Copyright 02.02.2012 by Bochkanov Sergey
50520 : *************************************************************************/
50521 0 : void rbfv1serialize(ae_serializer* s, rbfv1model* model, ae_state *_state)
50522 : {
50523 :
50524 :
50525 :
50526 : /*
50527 : * Data
50528 : */
50529 0 : ae_serializer_serialize_int(s, model->nx, _state);
50530 0 : ae_serializer_serialize_int(s, model->ny, _state);
50531 0 : ae_serializer_serialize_int(s, model->nc, _state);
50532 0 : ae_serializer_serialize_int(s, model->nl, _state);
50533 0 : kdtreeserialize(s, &model->tree, _state);
50534 0 : serializerealmatrix(s, &model->xc, -1, -1, _state);
50535 0 : serializerealmatrix(s, &model->wr, -1, -1, _state);
50536 0 : ae_serializer_serialize_double(s, model->rmax, _state);
50537 0 : serializerealmatrix(s, &model->v, -1, -1, _state);
50538 0 : }
50539 :
50540 :
50541 : /*************************************************************************
50542 : Serializer: unserialization
50543 :
50544 : -- ALGLIB --
50545 : Copyright 02.02.2012 by Bochkanov Sergey
50546 : *************************************************************************/
50547 0 : void rbfv1unserialize(ae_serializer* s,
50548 : rbfv1model* model,
50549 : ae_state *_state)
50550 : {
50551 : ae_int_t nx;
50552 : ae_int_t ny;
50553 :
50554 0 : _rbfv1model_clear(model);
50555 :
50556 :
50557 : /*
50558 : * Unserialize primary model parameters, initialize model.
50559 : *
50560 : * It is necessary to call RBFCreate() because some internal fields
50561 : * which are NOT unserialized will need initialization.
50562 : */
50563 0 : ae_serializer_unserialize_int(s, &nx, _state);
50564 0 : ae_serializer_unserialize_int(s, &ny, _state);
50565 0 : rbfv1create(nx, ny, model, _state);
50566 0 : ae_serializer_unserialize_int(s, &model->nc, _state);
50567 0 : ae_serializer_unserialize_int(s, &model->nl, _state);
50568 0 : kdtreeunserialize(s, &model->tree, _state);
50569 0 : unserializerealmatrix(s, &model->xc, _state);
50570 0 : unserializerealmatrix(s, &model->wr, _state);
50571 0 : ae_serializer_unserialize_double(s, &model->rmax, _state);
50572 0 : unserializerealmatrix(s, &model->v, _state);
50573 0 : }
50574 :
50575 :
50576 : /*************************************************************************
50577 : This function calculates values of the RBF model in the given point.
50578 :
50579 : This function should be used when we have NY=1 (scalar function) and NX=2
50580 : (2-dimensional space). If you have 3-dimensional space, use RBFCalc3(). If
50581 : you have general situation (NX-dimensional space, NY-dimensional function)
50582 : you should use general, less efficient implementation RBFCalc().
50583 :
50584 : If you want to calculate function values many times, consider using
50585 : RBFGridCalc2(), which is far more efficient than many subsequent calls to
50586 : RBFCalc2().
50587 :
50588 : This function returns 0.0 when:
50589 : * model is not initialized
50590 : * NX<>2
50591 : *NY<>1
50592 :
50593 : INPUT PARAMETERS:
50594 : S - RBF model
50595 : X0 - first coordinate, finite number
50596 : X1 - second coordinate, finite number
50597 :
50598 : RESULT:
50599 : value of the model or 0.0 (as defined above)
50600 :
50601 : -- ALGLIB --
50602 : Copyright 13.12.2011 by Bochkanov Sergey
50603 : *************************************************************************/
50604 0 : double rbfv1calc2(rbfv1model* s, double x0, double x1, ae_state *_state)
50605 : {
50606 : ae_int_t i;
50607 : ae_int_t j;
50608 : ae_int_t lx;
50609 : ae_int_t tg;
50610 : double d2;
50611 : double t;
50612 : double bfcur;
50613 : double rcur;
50614 : double result;
50615 :
50616 :
50617 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc2: invalid value for X0 (X0 is Inf)!", _state);
50618 0 : ae_assert(ae_isfinite(x1, _state), "RBFCalc2: invalid value for X1 (X1 is Inf)!", _state);
50619 0 : if( s->ny!=1||s->nx!=2 )
50620 : {
50621 0 : result = (double)(0);
50622 0 : return result;
50623 : }
50624 0 : result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][rbfv1_mxnx];
50625 0 : if( s->nc==0 )
50626 : {
50627 0 : return result;
50628 : }
50629 0 : rvectorsetlengthatleast(&s->calcbufxcx, rbfv1_mxnx, _state);
50630 0 : for(i=0; i<=rbfv1_mxnx-1; i++)
50631 : {
50632 0 : s->calcbufxcx.ptr.p_double[i] = 0.0;
50633 : }
50634 0 : s->calcbufxcx.ptr.p_double[0] = x0;
50635 0 : s->calcbufxcx.ptr.p_double[1] = x1;
50636 0 : lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state);
50637 0 : kdtreequeryresultsx(&s->tree, &s->calcbufx, _state);
50638 0 : kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state);
50639 0 : for(i=0; i<=lx-1; i++)
50640 : {
50641 0 : tg = s->calcbuftags.ptr.p_int[i];
50642 0 : d2 = ae_sqr(x0-s->calcbufx.ptr.pp_double[i][0], _state)+ae_sqr(x1-s->calcbufx.ptr.pp_double[i][1], _state);
50643 0 : rcur = s->wr.ptr.pp_double[tg][0];
50644 0 : bfcur = ae_exp(-d2/(rcur*rcur), _state);
50645 0 : for(j=0; j<=s->nl-1; j++)
50646 : {
50647 0 : result = result+bfcur*s->wr.ptr.pp_double[tg][1+j];
50648 0 : rcur = 0.5*rcur;
50649 0 : t = bfcur*bfcur;
50650 0 : bfcur = t*t;
50651 : }
50652 : }
50653 0 : return result;
50654 : }
50655 :
50656 :
50657 : /*************************************************************************
50658 : This function calculates values of the RBF model in the given point.
50659 :
50660 : This function should be used when we have NY=1 (scalar function) and NX=3
50661 : (3-dimensional space). If you have 2-dimensional space, use RBFCalc2(). If
50662 : you have general situation (NX-dimensional space, NY-dimensional function)
50663 : you should use general, less efficient implementation RBFCalc().
50664 :
50665 : This function returns 0.0 when:
50666 : * model is not initialized
50667 : * NX<>3
50668 : *NY<>1
50669 :
50670 : INPUT PARAMETERS:
50671 : S - RBF model
50672 : X0 - first coordinate, finite number
50673 : X1 - second coordinate, finite number
50674 : X2 - third coordinate, finite number
50675 :
50676 : RESULT:
50677 : value of the model or 0.0 (as defined above)
50678 :
50679 : -- ALGLIB --
50680 : Copyright 13.12.2011 by Bochkanov Sergey
50681 : *************************************************************************/
50682 0 : double rbfv1calc3(rbfv1model* s,
50683 : double x0,
50684 : double x1,
50685 : double x2,
50686 : ae_state *_state)
50687 : {
50688 : ae_int_t i;
50689 : ae_int_t j;
50690 : ae_int_t lx;
50691 : ae_int_t tg;
50692 : double t;
50693 : double rcur;
50694 : double bf;
50695 : double result;
50696 :
50697 :
50698 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc3: invalid value for X0 (X0 is Inf or NaN)!", _state);
50699 0 : ae_assert(ae_isfinite(x1, _state), "RBFCalc3: invalid value for X1 (X1 is Inf or NaN)!", _state);
50700 0 : ae_assert(ae_isfinite(x2, _state), "RBFCalc3: invalid value for X2 (X2 is Inf or NaN)!", _state);
50701 0 : if( s->ny!=1||s->nx!=3 )
50702 : {
50703 0 : result = (double)(0);
50704 0 : return result;
50705 : }
50706 0 : result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][2]*x2+s->v.ptr.pp_double[0][rbfv1_mxnx];
50707 0 : if( s->nc==0 )
50708 : {
50709 0 : return result;
50710 : }
50711 :
50712 : /*
50713 : * calculating value for F(X)
50714 : */
50715 0 : rvectorsetlengthatleast(&s->calcbufxcx, rbfv1_mxnx, _state);
50716 0 : for(i=0; i<=rbfv1_mxnx-1; i++)
50717 : {
50718 0 : s->calcbufxcx.ptr.p_double[i] = 0.0;
50719 : }
50720 0 : s->calcbufxcx.ptr.p_double[0] = x0;
50721 0 : s->calcbufxcx.ptr.p_double[1] = x1;
50722 0 : s->calcbufxcx.ptr.p_double[2] = x2;
50723 0 : lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state);
50724 0 : kdtreequeryresultsx(&s->tree, &s->calcbufx, _state);
50725 0 : kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state);
50726 0 : for(i=0; i<=lx-1; i++)
50727 : {
50728 0 : tg = s->calcbuftags.ptr.p_int[i];
50729 0 : rcur = s->wr.ptr.pp_double[tg][0];
50730 0 : bf = ae_exp(-(ae_sqr(x0-s->calcbufx.ptr.pp_double[i][0], _state)+ae_sqr(x1-s->calcbufx.ptr.pp_double[i][1], _state)+ae_sqr(x2-s->calcbufx.ptr.pp_double[i][2], _state))/ae_sqr(rcur, _state), _state);
50731 0 : for(j=0; j<=s->nl-1; j++)
50732 : {
50733 0 : result = result+bf*s->wr.ptr.pp_double[tg][1+j];
50734 0 : t = bf*bf;
50735 0 : bf = t*t;
50736 : }
50737 : }
50738 0 : return result;
50739 : }
50740 :
50741 :
50742 : /*************************************************************************
50743 : This function calculates values of the RBF model at the given point.
50744 :
50745 : Same as RBFCalc(), but does not reallocate Y when in is large enough to
50746 : store function values.
50747 :
50748 : INPUT PARAMETERS:
50749 : S - RBF model
50750 : X - coordinates, array[NX].
50751 : X may have more than NX elements, in this case only
50752 : leading NX will be used.
50753 : Y - possibly preallocated array
50754 :
50755 : OUTPUT PARAMETERS:
50756 : Y - function value, array[NY]. Y is not reallocated when it
50757 : is larger than NY.
50758 :
50759 : -- ALGLIB --
50760 : Copyright 13.12.2011 by Bochkanov Sergey
50761 : *************************************************************************/
50762 0 : void rbfv1calcbuf(rbfv1model* s,
50763 : /* Real */ ae_vector* x,
50764 : /* Real */ ae_vector* y,
50765 : ae_state *_state)
50766 : {
50767 : ae_int_t i;
50768 : ae_int_t j;
50769 : ae_int_t k;
50770 : ae_int_t lx;
50771 : ae_int_t tg;
50772 : double t;
50773 : double rcur;
50774 : double bf;
50775 :
50776 :
50777 0 : ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)<NX", _state);
50778 0 : ae_assert(isfinitevector(x, s->nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state);
50779 0 : if( y->cnt<s->ny )
50780 : {
50781 0 : ae_vector_set_length(y, s->ny, _state);
50782 : }
50783 0 : for(i=0; i<=s->ny-1; i++)
50784 : {
50785 0 : y->ptr.p_double[i] = s->v.ptr.pp_double[i][rbfv1_mxnx];
50786 0 : for(j=0; j<=s->nx-1; j++)
50787 : {
50788 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+s->v.ptr.pp_double[i][j]*x->ptr.p_double[j];
50789 : }
50790 : }
50791 0 : if( s->nc==0 )
50792 : {
50793 0 : return;
50794 : }
50795 0 : rvectorsetlengthatleast(&s->calcbufxcx, rbfv1_mxnx, _state);
50796 0 : for(i=0; i<=rbfv1_mxnx-1; i++)
50797 : {
50798 0 : s->calcbufxcx.ptr.p_double[i] = 0.0;
50799 : }
50800 0 : for(i=0; i<=s->nx-1; i++)
50801 : {
50802 0 : s->calcbufxcx.ptr.p_double[i] = x->ptr.p_double[i];
50803 : }
50804 0 : lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state);
50805 0 : kdtreequeryresultsx(&s->tree, &s->calcbufx, _state);
50806 0 : kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state);
50807 0 : for(i=0; i<=s->ny-1; i++)
50808 : {
50809 0 : for(j=0; j<=lx-1; j++)
50810 : {
50811 0 : tg = s->calcbuftags.ptr.p_int[j];
50812 0 : rcur = s->wr.ptr.pp_double[tg][0];
50813 0 : bf = ae_exp(-(ae_sqr(s->calcbufxcx.ptr.p_double[0]-s->calcbufx.ptr.pp_double[j][0], _state)+ae_sqr(s->calcbufxcx.ptr.p_double[1]-s->calcbufx.ptr.pp_double[j][1], _state)+ae_sqr(s->calcbufxcx.ptr.p_double[2]-s->calcbufx.ptr.pp_double[j][2], _state))/ae_sqr(rcur, _state), _state);
50814 0 : for(k=0; k<=s->nl-1; k++)
50815 : {
50816 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+bf*s->wr.ptr.pp_double[tg][1+k*s->ny+i];
50817 0 : t = bf*bf;
50818 0 : bf = t*t;
50819 : }
50820 : }
50821 : }
50822 : }
50823 :
50824 :
50825 : /*************************************************************************
50826 : This function calculates values of the RBF model at the given point, using
50827 : external buffer object (internal temporaries of RBF model are not
50828 : modified).
50829 :
50830 : This function allows to use same RBF model object in different threads,
50831 : assuming that different threads use different instances of buffer
50832 : structure.
50833 :
50834 : INPUT PARAMETERS:
50835 : S - RBF model, may be shared between different threads
50836 : Buf - buffer object created for this particular instance of RBF
50837 : model with rbfcreatecalcbuffer().
50838 : X - coordinates, array[NX].
50839 : X may have more than NX elements, in this case only
50840 : leading NX will be used.
50841 : Y - possibly preallocated array
50842 :
50843 : OUTPUT PARAMETERS:
50844 : Y - function value, array[NY]. Y is not reallocated when it
50845 : is larger than NY.
50846 :
50847 : -- ALGLIB --
50848 : Copyright 13.12.2011 by Bochkanov Sergey
50849 : *************************************************************************/
50850 0 : void rbfv1tscalcbuf(rbfv1model* s,
50851 : rbfv1calcbuffer* buf,
50852 : /* Real */ ae_vector* x,
50853 : /* Real */ ae_vector* y,
50854 : ae_state *_state)
50855 : {
50856 : ae_int_t i;
50857 : ae_int_t j;
50858 : ae_int_t k;
50859 : ae_int_t lx;
50860 : ae_int_t tg;
50861 : double t;
50862 : double rcur;
50863 : double bf;
50864 :
50865 :
50866 0 : ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)<NX", _state);
50867 0 : ae_assert(isfinitevector(x, s->nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state);
50868 0 : if( y->cnt<s->ny )
50869 : {
50870 0 : ae_vector_set_length(y, s->ny, _state);
50871 : }
50872 0 : for(i=0; i<=s->ny-1; i++)
50873 : {
50874 0 : y->ptr.p_double[i] = s->v.ptr.pp_double[i][rbfv1_mxnx];
50875 0 : for(j=0; j<=s->nx-1; j++)
50876 : {
50877 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+s->v.ptr.pp_double[i][j]*x->ptr.p_double[j];
50878 : }
50879 : }
50880 0 : if( s->nc==0 )
50881 : {
50882 0 : return;
50883 : }
50884 0 : rvectorsetlengthatleast(&buf->calcbufxcx, rbfv1_mxnx, _state);
50885 0 : for(i=0; i<=rbfv1_mxnx-1; i++)
50886 : {
50887 0 : buf->calcbufxcx.ptr.p_double[i] = 0.0;
50888 : }
50889 0 : for(i=0; i<=s->nx-1; i++)
50890 : {
50891 0 : buf->calcbufxcx.ptr.p_double[i] = x->ptr.p_double[i];
50892 : }
50893 0 : lx = kdtreetsqueryrnn(&s->tree, &buf->requestbuffer, &buf->calcbufxcx, s->rmax*rbfv1_rbffarradius, ae_true, _state);
50894 0 : kdtreetsqueryresultsx(&s->tree, &buf->requestbuffer, &buf->calcbufx, _state);
50895 0 : kdtreetsqueryresultstags(&s->tree, &buf->requestbuffer, &buf->calcbuftags, _state);
50896 0 : for(i=0; i<=s->ny-1; i++)
50897 : {
50898 0 : for(j=0; j<=lx-1; j++)
50899 : {
50900 0 : tg = buf->calcbuftags.ptr.p_int[j];
50901 0 : rcur = s->wr.ptr.pp_double[tg][0];
50902 0 : bf = ae_exp(-(ae_sqr(buf->calcbufxcx.ptr.p_double[0]-buf->calcbufx.ptr.pp_double[j][0], _state)+ae_sqr(buf->calcbufxcx.ptr.p_double[1]-buf->calcbufx.ptr.pp_double[j][1], _state)+ae_sqr(buf->calcbufxcx.ptr.p_double[2]-buf->calcbufx.ptr.pp_double[j][2], _state))/ae_sqr(rcur, _state), _state);
50903 0 : for(k=0; k<=s->nl-1; k++)
50904 : {
50905 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+bf*s->wr.ptr.pp_double[tg][1+k*s->ny+i];
50906 0 : t = bf*bf;
50907 0 : bf = t*t;
50908 : }
50909 : }
50910 : }
50911 : }
50912 :
50913 :
50914 : /*************************************************************************
50915 : This function calculates values of the RBF model at the regular grid.
50916 :
50917 : Grid have N0*N1 points, with Point[I,J] = (X0[I], X1[J])
50918 :
50919 : This function returns 0.0 when:
50920 : * model is not initialized
50921 : * NX<>2
50922 : *NY<>1
50923 :
50924 : INPUT PARAMETERS:
50925 : S - RBF model
50926 : X0 - array of grid nodes, first coordinates, array[N0]
50927 : N0 - grid size (number of nodes) in the first dimension
50928 : X1 - array of grid nodes, second coordinates, array[N1]
50929 : N1 - grid size (number of nodes) in the second dimension
50930 :
50931 : OUTPUT PARAMETERS:
50932 : Y - function values, array[N0,N1]. Y is out-variable and
50933 : is reallocated by this function.
50934 :
50935 : NOTE: as a special exception, this function supports unordered arrays X0
50936 : and X1. However, future versions may be more efficient for X0/X1
50937 : ordered by ascending.
50938 :
50939 : -- ALGLIB --
50940 : Copyright 13.12.2011 by Bochkanov Sergey
50941 : *************************************************************************/
50942 0 : void rbfv1gridcalc2(rbfv1model* s,
50943 : /* Real */ ae_vector* x0,
50944 : ae_int_t n0,
50945 : /* Real */ ae_vector* x1,
50946 : ae_int_t n1,
50947 : /* Real */ ae_matrix* y,
50948 : ae_state *_state)
50949 : {
50950 : ae_frame _frame_block;
50951 : ae_vector cpx0;
50952 : ae_vector cpx1;
50953 : ae_vector p01;
50954 : ae_vector p11;
50955 : ae_vector p2;
50956 : double rlimit;
50957 : double xcnorm2;
50958 : ae_int_t hp01;
50959 : double hcpx0;
50960 : double xc0;
50961 : double xc1;
50962 : double omega;
50963 : double radius;
50964 : ae_int_t i;
50965 : ae_int_t j;
50966 : ae_int_t k;
50967 : ae_int_t d;
50968 : ae_int_t i00;
50969 : ae_int_t i01;
50970 : ae_int_t i10;
50971 : ae_int_t i11;
50972 :
50973 0 : ae_frame_make(_state, &_frame_block);
50974 0 : memset(&cpx0, 0, sizeof(cpx0));
50975 0 : memset(&cpx1, 0, sizeof(cpx1));
50976 0 : memset(&p01, 0, sizeof(p01));
50977 0 : memset(&p11, 0, sizeof(p11));
50978 0 : memset(&p2, 0, sizeof(p2));
50979 0 : ae_matrix_clear(y);
50980 0 : ae_vector_init(&cpx0, 0, DT_REAL, _state, ae_true);
50981 0 : ae_vector_init(&cpx1, 0, DT_REAL, _state, ae_true);
50982 0 : ae_vector_init(&p01, 0, DT_INT, _state, ae_true);
50983 0 : ae_vector_init(&p11, 0, DT_INT, _state, ae_true);
50984 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
50985 :
50986 0 : ae_assert(n0>0, "RBFGridCalc2: invalid value for N0 (N0<=0)!", _state);
50987 0 : ae_assert(n1>0, "RBFGridCalc2: invalid value for N1 (N1<=0)!", _state);
50988 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc2: Length(X0)<N0", _state);
50989 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc2: Length(X1)<N1", _state);
50990 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc2: X0 contains infinite or NaN values!", _state);
50991 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc2: X1 contains infinite or NaN values!", _state);
50992 0 : ae_matrix_set_length(y, n0, n1, _state);
50993 0 : for(i=0; i<=n0-1; i++)
50994 : {
50995 0 : for(j=0; j<=n1-1; j++)
50996 : {
50997 0 : y->ptr.pp_double[i][j] = (double)(0);
50998 : }
50999 : }
51000 0 : if( (s->ny!=1||s->nx!=2)||s->nc==0 )
51001 : {
51002 0 : ae_frame_leave(_state);
51003 0 : return;
51004 : }
51005 :
51006 : /*
51007 : *create and sort arrays
51008 : */
51009 0 : ae_vector_set_length(&cpx0, n0, _state);
51010 0 : for(i=0; i<=n0-1; i++)
51011 : {
51012 0 : cpx0.ptr.p_double[i] = x0->ptr.p_double[i];
51013 : }
51014 0 : tagsort(&cpx0, n0, &p01, &p2, _state);
51015 0 : ae_vector_set_length(&cpx1, n1, _state);
51016 0 : for(i=0; i<=n1-1; i++)
51017 : {
51018 0 : cpx1.ptr.p_double[i] = x1->ptr.p_double[i];
51019 : }
51020 0 : tagsort(&cpx1, n1, &p11, &p2, _state);
51021 :
51022 : /*
51023 : *calculate function's value
51024 : */
51025 0 : for(i=0; i<=s->nc-1; i++)
51026 : {
51027 0 : radius = s->wr.ptr.pp_double[i][0];
51028 0 : for(d=0; d<=s->nl-1; d++)
51029 : {
51030 0 : omega = s->wr.ptr.pp_double[i][1+d];
51031 0 : rlimit = radius*rbfv1_rbffarradius;
51032 :
51033 : /*
51034 : *search lower and upper indexes
51035 : */
51036 0 : i00 = lowerbound(&cpx0, n0, s->xc.ptr.pp_double[i][0]-rlimit, _state);
51037 0 : i01 = upperbound(&cpx0, n0, s->xc.ptr.pp_double[i][0]+rlimit, _state);
51038 0 : i10 = lowerbound(&cpx1, n1, s->xc.ptr.pp_double[i][1]-rlimit, _state);
51039 0 : i11 = upperbound(&cpx1, n1, s->xc.ptr.pp_double[i][1]+rlimit, _state);
51040 0 : xc0 = s->xc.ptr.pp_double[i][0];
51041 0 : xc1 = s->xc.ptr.pp_double[i][1];
51042 0 : for(j=i00; j<=i01-1; j++)
51043 : {
51044 0 : hcpx0 = cpx0.ptr.p_double[j];
51045 0 : hp01 = p01.ptr.p_int[j];
51046 0 : for(k=i10; k<=i11-1; k++)
51047 : {
51048 0 : xcnorm2 = ae_sqr(hcpx0-xc0, _state)+ae_sqr(cpx1.ptr.p_double[k]-xc1, _state);
51049 0 : if( ae_fp_less_eq(xcnorm2,rlimit*rlimit) )
51050 : {
51051 0 : y->ptr.pp_double[hp01][p11.ptr.p_int[k]] = y->ptr.pp_double[hp01][p11.ptr.p_int[k]]+ae_exp(-xcnorm2/ae_sqr(radius, _state), _state)*omega;
51052 : }
51053 : }
51054 : }
51055 0 : radius = 0.5*radius;
51056 : }
51057 : }
51058 :
51059 : /*
51060 : *add linear term
51061 : */
51062 0 : for(i=0; i<=n0-1; i++)
51063 : {
51064 0 : for(j=0; j<=n1-1; j++)
51065 : {
51066 0 : y->ptr.pp_double[i][j] = y->ptr.pp_double[i][j]+s->v.ptr.pp_double[0][0]*x0->ptr.p_double[i]+s->v.ptr.pp_double[0][1]*x1->ptr.p_double[j]+s->v.ptr.pp_double[0][rbfv1_mxnx];
51067 : }
51068 : }
51069 0 : ae_frame_leave(_state);
51070 : }
51071 :
51072 :
51073 0 : void rbfv1gridcalc3vrec(rbfv1model* s,
51074 : /* Real */ ae_vector* x0,
51075 : ae_int_t n0,
51076 : /* Real */ ae_vector* x1,
51077 : ae_int_t n1,
51078 : /* Real */ ae_vector* x2,
51079 : ae_int_t n2,
51080 : /* Integer */ ae_vector* blocks0,
51081 : ae_int_t block0a,
51082 : ae_int_t block0b,
51083 : /* Integer */ ae_vector* blocks1,
51084 : ae_int_t block1a,
51085 : ae_int_t block1b,
51086 : /* Integer */ ae_vector* blocks2,
51087 : ae_int_t block2a,
51088 : ae_int_t block2b,
51089 : /* Boolean */ ae_vector* flagy,
51090 : ae_bool sparsey,
51091 : double searchradius,
51092 : double avgfuncpernode,
51093 : ae_shared_pool* bufpool,
51094 : /* Real */ ae_vector* y,
51095 : ae_state *_state)
51096 : {
51097 : ae_frame _frame_block;
51098 : ae_int_t i;
51099 : ae_int_t j;
51100 : ae_int_t k;
51101 : ae_int_t t;
51102 : ae_int_t l;
51103 : ae_int_t i0;
51104 : ae_int_t i1;
51105 : ae_int_t i2;
51106 : ae_int_t ic;
51107 : gridcalc3v1buf *pbuf;
51108 : ae_smart_ptr _pbuf;
51109 : ae_int_t flag12dim1;
51110 : ae_int_t flag12dim2;
51111 : double problemcost;
51112 : ae_int_t maxbs;
51113 : ae_int_t nx;
51114 : ae_int_t ny;
51115 : double v;
51116 : ae_int_t kc;
51117 : ae_int_t tg;
51118 : double rcur;
51119 : double rcur2;
51120 : double basisfuncval;
51121 : ae_int_t dstoffs;
51122 : ae_int_t srcoffs;
51123 : ae_int_t ubnd;
51124 : double w0;
51125 : double w1;
51126 : double w2;
51127 : ae_bool allnodes;
51128 : ae_bool somenodes;
51129 :
51130 0 : ae_frame_make(_state, &_frame_block);
51131 0 : memset(&_pbuf, 0, sizeof(_pbuf));
51132 0 : ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true);
51133 :
51134 0 : nx = s->nx;
51135 0 : ny = s->ny;
51136 :
51137 : /*
51138 : * Try to split large problem
51139 : */
51140 0 : problemcost = (s->nl+1)*s->ny*2*(avgfuncpernode+1);
51141 0 : problemcost = problemcost*(blocks0->ptr.p_int[block0b]-blocks0->ptr.p_int[block0a]);
51142 0 : problemcost = problemcost*(blocks1->ptr.p_int[block1b]-blocks1->ptr.p_int[block1a]);
51143 0 : problemcost = problemcost*(blocks2->ptr.p_int[block2b]-blocks2->ptr.p_int[block2a]);
51144 0 : maxbs = 0;
51145 0 : maxbs = ae_maxint(maxbs, block0b-block0a, _state);
51146 0 : maxbs = ae_maxint(maxbs, block1b-block1a, _state);
51147 0 : maxbs = ae_maxint(maxbs, block2b-block2a, _state);
51148 0 : if( ae_fp_greater_eq(problemcost,rbfv1_minbasecasecost)&&maxbs>=2 )
51149 : {
51150 0 : if( block0b-block0a==maxbs )
51151 : {
51152 0 : rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0a+maxbs/2, blocks1, block1a, block1b, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state);
51153 0 : rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a+maxbs/2, block0b, blocks1, block1a, block1b, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state);
51154 0 : ae_frame_leave(_state);
51155 0 : return;
51156 : }
51157 0 : if( block1b-block1a==maxbs )
51158 : {
51159 0 : rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a, block1a+maxbs/2, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state);
51160 0 : rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a+maxbs/2, block1b, blocks2, block2a, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state);
51161 0 : ae_frame_leave(_state);
51162 0 : return;
51163 : }
51164 0 : if( block2b-block2a==maxbs )
51165 : {
51166 0 : rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a, block2a+maxbs/2, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state);
51167 0 : rbfv1gridcalc3vrec(s, x0, n0, x1, n1, x2, n2, blocks0, block0a, block0b, blocks1, block1a, block1b, blocks2, block2a+maxbs/2, block2b, flagy, sparsey, searchradius, avgfuncpernode, bufpool, y, _state);
51168 0 : ae_frame_leave(_state);
51169 0 : return;
51170 : }
51171 : }
51172 :
51173 : /*
51174 : * Retrieve buffer object from pool (it will be returned later)
51175 : */
51176 0 : ae_shared_pool_retrieve(bufpool, &_pbuf, _state);
51177 :
51178 : /*
51179 : * Calculate RBF model
51180 : */
51181 0 : for(i2=block2a; i2<=block2b-1; i2++)
51182 : {
51183 0 : for(i1=block1a; i1<=block1b-1; i1++)
51184 : {
51185 0 : for(i0=block0a; i0<=block0b-1; i0++)
51186 : {
51187 :
51188 : /*
51189 : * Analyze block - determine what elements are needed and what are not.
51190 : *
51191 : * After this block is done, two flag variables can be used:
51192 : * * SomeNodes, which is True when there are at least one node which have
51193 : * to be calculated
51194 : * * AllNodes, which is True when all nodes are required
51195 : */
51196 0 : somenodes = ae_true;
51197 0 : allnodes = ae_true;
51198 0 : flag12dim1 = blocks1->ptr.p_int[i1+1]-blocks1->ptr.p_int[i1];
51199 0 : flag12dim2 = blocks2->ptr.p_int[i2+1]-blocks2->ptr.p_int[i2];
51200 0 : if( sparsey )
51201 : {
51202 :
51203 : /*
51204 : * Use FlagY to determine what is required.
51205 : */
51206 0 : bvectorsetlengthatleast(&pbuf->flag0, n0, _state);
51207 0 : bvectorsetlengthatleast(&pbuf->flag1, n1, _state);
51208 0 : bvectorsetlengthatleast(&pbuf->flag2, n2, _state);
51209 0 : bvectorsetlengthatleast(&pbuf->flag12, flag12dim1*flag12dim2, _state);
51210 0 : for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++)
51211 : {
51212 0 : pbuf->flag0.ptr.p_bool[i] = ae_false;
51213 : }
51214 0 : for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++)
51215 : {
51216 0 : pbuf->flag1.ptr.p_bool[j] = ae_false;
51217 : }
51218 0 : for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++)
51219 : {
51220 0 : pbuf->flag2.ptr.p_bool[k] = ae_false;
51221 : }
51222 0 : for(i=0; i<=flag12dim1*flag12dim2-1; i++)
51223 : {
51224 0 : pbuf->flag12.ptr.p_bool[i] = ae_false;
51225 : }
51226 0 : somenodes = ae_false;
51227 0 : allnodes = ae_true;
51228 0 : for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++)
51229 : {
51230 0 : for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++)
51231 : {
51232 0 : dstoffs = j-blocks1->ptr.p_int[i1]+flag12dim1*(k-blocks2->ptr.p_int[i2]);
51233 0 : srcoffs = j*n0+k*n0*n1;
51234 0 : for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++)
51235 : {
51236 0 : if( flagy->ptr.p_bool[srcoffs+i] )
51237 : {
51238 0 : pbuf->flag0.ptr.p_bool[i] = ae_true;
51239 0 : pbuf->flag1.ptr.p_bool[j] = ae_true;
51240 0 : pbuf->flag2.ptr.p_bool[k] = ae_true;
51241 0 : pbuf->flag12.ptr.p_bool[dstoffs] = ae_true;
51242 0 : somenodes = ae_true;
51243 : }
51244 : else
51245 : {
51246 0 : allnodes = ae_false;
51247 : }
51248 : }
51249 : }
51250 : }
51251 : }
51252 :
51253 : /*
51254 : * Skip block if it is completely empty.
51255 : */
51256 0 : if( !somenodes )
51257 : {
51258 0 : continue;
51259 : }
51260 :
51261 : /*
51262 : * compute linear term for block (I0,I1,I2)
51263 : */
51264 0 : for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++)
51265 : {
51266 0 : for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++)
51267 : {
51268 :
51269 : /*
51270 : * do we need this micro-row?
51271 : */
51272 0 : if( !allnodes&&!pbuf->flag12.ptr.p_bool[j-blocks1->ptr.p_int[i1]+flag12dim1*(k-blocks2->ptr.p_int[i2])] )
51273 : {
51274 0 : continue;
51275 : }
51276 :
51277 : /*
51278 : * Compute linear term
51279 : */
51280 0 : for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++)
51281 : {
51282 0 : pbuf->tx.ptr.p_double[0] = x0->ptr.p_double[i];
51283 0 : pbuf->tx.ptr.p_double[1] = x1->ptr.p_double[j];
51284 0 : pbuf->tx.ptr.p_double[2] = x2->ptr.p_double[k];
51285 0 : for(l=0; l<=s->ny-1; l++)
51286 : {
51287 0 : v = s->v.ptr.pp_double[l][rbfv1_mxnx];
51288 0 : for(t=0; t<=nx-1; t++)
51289 : {
51290 0 : v = v+s->v.ptr.pp_double[l][t]*pbuf->tx.ptr.p_double[t];
51291 : }
51292 0 : y->ptr.p_double[l+ny*(i+j*n0+k*n0*n1)] = v;
51293 : }
51294 : }
51295 : }
51296 : }
51297 :
51298 : /*
51299 : * compute RBF term for block (I0,I1,I2)
51300 : */
51301 0 : pbuf->tx.ptr.p_double[0] = 0.5*(x0->ptr.p_double[blocks0->ptr.p_int[i0]]+x0->ptr.p_double[blocks0->ptr.p_int[i0+1]-1]);
51302 0 : pbuf->tx.ptr.p_double[1] = 0.5*(x1->ptr.p_double[blocks1->ptr.p_int[i1]]+x1->ptr.p_double[blocks1->ptr.p_int[i1+1]-1]);
51303 0 : pbuf->tx.ptr.p_double[2] = 0.5*(x2->ptr.p_double[blocks2->ptr.p_int[i2]]+x2->ptr.p_double[blocks2->ptr.p_int[i2+1]-1]);
51304 0 : kc = kdtreetsqueryrnn(&s->tree, &pbuf->requestbuf, &pbuf->tx, searchradius, ae_true, _state);
51305 0 : kdtreetsqueryresultsx(&s->tree, &pbuf->requestbuf, &pbuf->calcbufx, _state);
51306 0 : kdtreetsqueryresultstags(&s->tree, &pbuf->requestbuf, &pbuf->calcbuftags, _state);
51307 0 : for(ic=0; ic<=kc-1; ic++)
51308 : {
51309 0 : pbuf->cx.ptr.p_double[0] = pbuf->calcbufx.ptr.pp_double[ic][0];
51310 0 : pbuf->cx.ptr.p_double[1] = pbuf->calcbufx.ptr.pp_double[ic][1];
51311 0 : pbuf->cx.ptr.p_double[2] = pbuf->calcbufx.ptr.pp_double[ic][2];
51312 0 : tg = pbuf->calcbuftags.ptr.p_int[ic];
51313 0 : rcur = s->wr.ptr.pp_double[tg][0];
51314 0 : rcur2 = rcur*rcur;
51315 0 : for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++)
51316 : {
51317 0 : if( allnodes||pbuf->flag0.ptr.p_bool[i] )
51318 : {
51319 0 : pbuf->expbuf0.ptr.p_double[i] = ae_exp(-ae_sqr(x0->ptr.p_double[i]-pbuf->cx.ptr.p_double[0], _state)/rcur2, _state);
51320 : }
51321 : else
51322 : {
51323 0 : pbuf->expbuf0.ptr.p_double[i] = 0.0;
51324 : }
51325 : }
51326 0 : for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++)
51327 : {
51328 0 : if( allnodes||pbuf->flag1.ptr.p_bool[j] )
51329 : {
51330 0 : pbuf->expbuf1.ptr.p_double[j] = ae_exp(-ae_sqr(x1->ptr.p_double[j]-pbuf->cx.ptr.p_double[1], _state)/rcur2, _state);
51331 : }
51332 : else
51333 : {
51334 0 : pbuf->expbuf1.ptr.p_double[j] = 0.0;
51335 : }
51336 : }
51337 0 : for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++)
51338 : {
51339 0 : if( allnodes||pbuf->flag2.ptr.p_bool[k] )
51340 : {
51341 0 : pbuf->expbuf2.ptr.p_double[k] = ae_exp(-ae_sqr(x2->ptr.p_double[k]-pbuf->cx.ptr.p_double[2], _state)/rcur2, _state);
51342 : }
51343 : else
51344 : {
51345 0 : pbuf->expbuf2.ptr.p_double[k] = 0.0;
51346 : }
51347 : }
51348 0 : for(t=0; t<=s->nl-1; t++)
51349 : {
51350 :
51351 : /*
51352 : * Calculate
51353 : */
51354 0 : for(k=blocks2->ptr.p_int[i2]; k<=blocks2->ptr.p_int[i2+1]-1; k++)
51355 : {
51356 0 : for(j=blocks1->ptr.p_int[i1]; j<=blocks1->ptr.p_int[i1+1]-1; j++)
51357 : {
51358 :
51359 : /*
51360 : * do we need this micro-row?
51361 : */
51362 0 : if( !allnodes&&!pbuf->flag12.ptr.p_bool[j-blocks1->ptr.p_int[i1]+flag12dim1*(k-blocks2->ptr.p_int[i2])] )
51363 : {
51364 0 : continue;
51365 : }
51366 :
51367 : /*
51368 : * Prepare local variables
51369 : */
51370 0 : dstoffs = ny*(blocks0->ptr.p_int[i0]+j*n0+k*n0*n1);
51371 0 : v = pbuf->expbuf1.ptr.p_double[j]*pbuf->expbuf2.ptr.p_double[k];
51372 :
51373 : /*
51374 : * Optimized for NY=1
51375 : */
51376 0 : if( s->ny==1 )
51377 : {
51378 0 : w0 = s->wr.ptr.pp_double[tg][1+t*s->ny+0];
51379 0 : ubnd = blocks0->ptr.p_int[i0+1]-1;
51380 0 : for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++)
51381 : {
51382 0 : basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v;
51383 0 : y->ptr.p_double[dstoffs] = y->ptr.p_double[dstoffs]+basisfuncval*w0;
51384 0 : dstoffs = dstoffs+1;
51385 : }
51386 0 : continue;
51387 : }
51388 :
51389 : /*
51390 : * Optimized for NY=2
51391 : */
51392 0 : if( s->ny==2 )
51393 : {
51394 0 : w0 = s->wr.ptr.pp_double[tg][1+t*s->ny+0];
51395 0 : w1 = s->wr.ptr.pp_double[tg][1+t*s->ny+1];
51396 0 : ubnd = blocks0->ptr.p_int[i0+1]-1;
51397 0 : for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++)
51398 : {
51399 0 : basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v;
51400 0 : y->ptr.p_double[dstoffs+0] = y->ptr.p_double[dstoffs+0]+basisfuncval*w0;
51401 0 : y->ptr.p_double[dstoffs+1] = y->ptr.p_double[dstoffs+1]+basisfuncval*w1;
51402 0 : dstoffs = dstoffs+2;
51403 : }
51404 0 : continue;
51405 : }
51406 :
51407 : /*
51408 : * Optimized for NY=3
51409 : */
51410 0 : if( s->ny==3 )
51411 : {
51412 0 : w0 = s->wr.ptr.pp_double[tg][1+t*s->ny+0];
51413 0 : w1 = s->wr.ptr.pp_double[tg][1+t*s->ny+1];
51414 0 : w2 = s->wr.ptr.pp_double[tg][1+t*s->ny+2];
51415 0 : ubnd = blocks0->ptr.p_int[i0+1]-1;
51416 0 : for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++)
51417 : {
51418 0 : basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v;
51419 0 : y->ptr.p_double[dstoffs+0] = y->ptr.p_double[dstoffs+0]+basisfuncval*w0;
51420 0 : y->ptr.p_double[dstoffs+1] = y->ptr.p_double[dstoffs+1]+basisfuncval*w1;
51421 0 : y->ptr.p_double[dstoffs+2] = y->ptr.p_double[dstoffs+2]+basisfuncval*w2;
51422 0 : dstoffs = dstoffs+3;
51423 : }
51424 0 : continue;
51425 : }
51426 :
51427 : /*
51428 : * General case
51429 : */
51430 0 : for(i=blocks0->ptr.p_int[i0]; i<=blocks0->ptr.p_int[i0+1]-1; i++)
51431 : {
51432 0 : basisfuncval = pbuf->expbuf0.ptr.p_double[i]*v;
51433 0 : for(l=0; l<=s->ny-1; l++)
51434 : {
51435 0 : y->ptr.p_double[l+dstoffs] = y->ptr.p_double[l+dstoffs]+basisfuncval*s->wr.ptr.pp_double[tg][1+t*s->ny+l];
51436 : }
51437 0 : dstoffs = dstoffs+ny;
51438 : }
51439 : }
51440 : }
51441 :
51442 : /*
51443 : * Update basis functions
51444 : */
51445 0 : if( t!=s->nl-1 )
51446 : {
51447 0 : ubnd = blocks0->ptr.p_int[i0+1]-1;
51448 0 : for(i=blocks0->ptr.p_int[i0]; i<=ubnd; i++)
51449 : {
51450 0 : if( allnodes||pbuf->flag0.ptr.p_bool[i] )
51451 : {
51452 0 : v = pbuf->expbuf0.ptr.p_double[i]*pbuf->expbuf0.ptr.p_double[i];
51453 0 : pbuf->expbuf0.ptr.p_double[i] = v*v;
51454 : }
51455 : }
51456 0 : ubnd = blocks1->ptr.p_int[i1+1]-1;
51457 0 : for(j=blocks1->ptr.p_int[i1]; j<=ubnd; j++)
51458 : {
51459 0 : if( allnodes||pbuf->flag1.ptr.p_bool[j] )
51460 : {
51461 0 : v = pbuf->expbuf1.ptr.p_double[j]*pbuf->expbuf1.ptr.p_double[j];
51462 0 : pbuf->expbuf1.ptr.p_double[j] = v*v;
51463 : }
51464 : }
51465 0 : ubnd = blocks2->ptr.p_int[i2+1]-1;
51466 0 : for(k=blocks2->ptr.p_int[i2]; k<=ubnd; k++)
51467 : {
51468 0 : if( allnodes||pbuf->flag2.ptr.p_bool[k] )
51469 : {
51470 0 : v = pbuf->expbuf2.ptr.p_double[k]*pbuf->expbuf2.ptr.p_double[k];
51471 0 : pbuf->expbuf2.ptr.p_double[k] = v*v;
51472 : }
51473 : }
51474 : }
51475 : }
51476 : }
51477 : }
51478 : }
51479 : }
51480 :
51481 : /*
51482 : * Recycle buffer object back to pool
51483 : */
51484 0 : ae_shared_pool_recycle(bufpool, &_pbuf, _state);
51485 0 : ae_frame_leave(_state);
51486 : }
51487 :
51488 :
51489 : /*************************************************************************
51490 : Serial stub for GPL edition.
51491 : *************************************************************************/
51492 0 : ae_bool _trypexec_rbfv1gridcalc3vrec(rbfv1model* s,
51493 : /* Real */ ae_vector* x0,
51494 : ae_int_t n0,
51495 : /* Real */ ae_vector* x1,
51496 : ae_int_t n1,
51497 : /* Real */ ae_vector* x2,
51498 : ae_int_t n2,
51499 : /* Integer */ ae_vector* blocks0,
51500 : ae_int_t block0a,
51501 : ae_int_t block0b,
51502 : /* Integer */ ae_vector* blocks1,
51503 : ae_int_t block1a,
51504 : ae_int_t block1b,
51505 : /* Integer */ ae_vector* blocks2,
51506 : ae_int_t block2a,
51507 : ae_int_t block2b,
51508 : /* Boolean */ ae_vector* flagy,
51509 : ae_bool sparsey,
51510 : double searchradius,
51511 : double avgfuncpernode,
51512 : ae_shared_pool* bufpool,
51513 : /* Real */ ae_vector* y,
51514 : ae_state *_state)
51515 : {
51516 0 : return ae_false;
51517 : }
51518 :
51519 :
51520 : /*************************************************************************
51521 : This function "unpacks" RBF model by extracting its coefficients.
51522 :
51523 : INPUT PARAMETERS:
51524 : S - RBF model
51525 :
51526 : OUTPUT PARAMETERS:
51527 : NX - dimensionality of argument
51528 : NY - dimensionality of the target function
51529 : XWR - model information, array[NC,NX+NY+1].
51530 : One row of the array corresponds to one basis function:
51531 : * first NX columns - coordinates of the center
51532 : * next NY columns - weights, one per dimension of the
51533 : function being modelled
51534 : * last column - radius, same for all dimensions of
51535 : the function being modelled
51536 : NC - number of the centers
51537 : V - polynomial term , array[NY,NX+1]. One row per one
51538 : dimension of the function being modelled. First NX
51539 : elements are linear coefficients, V[NX] is equal to the
51540 : constant part.
51541 :
51542 : -- ALGLIB --
51543 : Copyright 13.12.2011 by Bochkanov Sergey
51544 : *************************************************************************/
51545 0 : void rbfv1unpack(rbfv1model* s,
51546 : ae_int_t* nx,
51547 : ae_int_t* ny,
51548 : /* Real */ ae_matrix* xwr,
51549 : ae_int_t* nc,
51550 : /* Real */ ae_matrix* v,
51551 : ae_state *_state)
51552 : {
51553 : ae_int_t i;
51554 : ae_int_t j;
51555 : double rcur;
51556 :
51557 0 : *nx = 0;
51558 0 : *ny = 0;
51559 0 : ae_matrix_clear(xwr);
51560 0 : *nc = 0;
51561 0 : ae_matrix_clear(v);
51562 :
51563 0 : *nx = s->nx;
51564 0 : *ny = s->ny;
51565 0 : *nc = s->nc;
51566 :
51567 : /*
51568 : * Fill V
51569 : */
51570 0 : ae_matrix_set_length(v, s->ny, s->nx+1, _state);
51571 0 : for(i=0; i<=s->ny-1; i++)
51572 : {
51573 0 : ae_v_move(&v->ptr.pp_double[i][0], 1, &s->v.ptr.pp_double[i][0], 1, ae_v_len(0,s->nx-1));
51574 0 : v->ptr.pp_double[i][s->nx] = s->v.ptr.pp_double[i][rbfv1_mxnx];
51575 : }
51576 :
51577 : /*
51578 : * Fill XWR and V
51579 : */
51580 0 : if( *nc*s->nl>0 )
51581 : {
51582 0 : ae_matrix_set_length(xwr, s->nc*s->nl, s->nx+s->ny+1, _state);
51583 0 : for(i=0; i<=s->nc-1; i++)
51584 : {
51585 0 : rcur = s->wr.ptr.pp_double[i][0];
51586 0 : for(j=0; j<=s->nl-1; j++)
51587 : {
51588 0 : ae_v_move(&xwr->ptr.pp_double[i*s->nl+j][0], 1, &s->xc.ptr.pp_double[i][0], 1, ae_v_len(0,s->nx-1));
51589 0 : ae_v_move(&xwr->ptr.pp_double[i*s->nl+j][s->nx], 1, &s->wr.ptr.pp_double[i][1+j*s->ny], 1, ae_v_len(s->nx,s->nx+s->ny-1));
51590 0 : xwr->ptr.pp_double[i*s->nl+j][s->nx+s->ny] = rcur;
51591 0 : rcur = 0.5*rcur;
51592 : }
51593 : }
51594 : }
51595 0 : }
51596 :
51597 :
51598 0 : static ae_bool rbfv1_rbfv1buildlinearmodel(/* Real */ ae_matrix* x,
51599 : /* Real */ ae_matrix* y,
51600 : ae_int_t n,
51601 : ae_int_t ny,
51602 : ae_int_t modeltype,
51603 : /* Real */ ae_matrix* v,
51604 : ae_state *_state)
51605 : {
51606 : ae_frame _frame_block;
51607 : ae_vector tmpy;
51608 : ae_matrix a;
51609 : double scaling;
51610 : ae_vector shifting;
51611 : double mn;
51612 : double mx;
51613 : ae_vector c;
51614 : lsfitreport rep;
51615 : ae_int_t i;
51616 : ae_int_t j;
51617 : ae_int_t k;
51618 : ae_int_t info;
51619 : ae_bool result;
51620 :
51621 0 : ae_frame_make(_state, &_frame_block);
51622 0 : memset(&tmpy, 0, sizeof(tmpy));
51623 0 : memset(&a, 0, sizeof(a));
51624 0 : memset(&shifting, 0, sizeof(shifting));
51625 0 : memset(&c, 0, sizeof(c));
51626 0 : memset(&rep, 0, sizeof(rep));
51627 0 : ae_matrix_clear(v);
51628 0 : ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
51629 0 : ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
51630 0 : ae_vector_init(&shifting, 0, DT_REAL, _state, ae_true);
51631 0 : ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
51632 0 : _lsfitreport_init(&rep, _state, ae_true);
51633 :
51634 0 : ae_assert(n>=0, "BuildLinearModel: N<0", _state);
51635 0 : ae_assert(ny>0, "BuildLinearModel: NY<=0", _state);
51636 :
51637 : /*
51638 : * Handle degenerate case (N=0)
51639 : */
51640 0 : result = ae_true;
51641 0 : ae_matrix_set_length(v, ny, rbfv1_mxnx+1, _state);
51642 0 : if( n==0 )
51643 : {
51644 0 : for(j=0; j<=rbfv1_mxnx; j++)
51645 : {
51646 0 : for(i=0; i<=ny-1; i++)
51647 : {
51648 0 : v->ptr.pp_double[i][j] = (double)(0);
51649 : }
51650 : }
51651 0 : ae_frame_leave(_state);
51652 0 : return result;
51653 : }
51654 :
51655 : /*
51656 : * Allocate temporaries
51657 : */
51658 0 : ae_vector_set_length(&tmpy, n, _state);
51659 :
51660 : /*
51661 : * General linear model.
51662 : */
51663 0 : if( modeltype==1 )
51664 : {
51665 :
51666 : /*
51667 : * Calculate scaling/shifting, transform variables, prepare LLS problem
51668 : */
51669 0 : ae_matrix_set_length(&a, n, rbfv1_mxnx+1, _state);
51670 0 : ae_vector_set_length(&shifting, rbfv1_mxnx, _state);
51671 0 : scaling = (double)(0);
51672 0 : for(i=0; i<=rbfv1_mxnx-1; i++)
51673 : {
51674 0 : mn = x->ptr.pp_double[0][i];
51675 0 : mx = mn;
51676 0 : for(j=1; j<=n-1; j++)
51677 : {
51678 0 : if( ae_fp_greater(mn,x->ptr.pp_double[j][i]) )
51679 : {
51680 0 : mn = x->ptr.pp_double[j][i];
51681 : }
51682 0 : if( ae_fp_less(mx,x->ptr.pp_double[j][i]) )
51683 : {
51684 0 : mx = x->ptr.pp_double[j][i];
51685 : }
51686 : }
51687 0 : scaling = ae_maxreal(scaling, mx-mn, _state);
51688 0 : shifting.ptr.p_double[i] = 0.5*(mx+mn);
51689 : }
51690 0 : if( ae_fp_eq(scaling,(double)(0)) )
51691 : {
51692 0 : scaling = (double)(1);
51693 : }
51694 : else
51695 : {
51696 0 : scaling = 0.5*scaling;
51697 : }
51698 0 : for(i=0; i<=n-1; i++)
51699 : {
51700 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
51701 : {
51702 0 : a.ptr.pp_double[i][j] = (x->ptr.pp_double[i][j]-shifting.ptr.p_double[j])/scaling;
51703 : }
51704 : }
51705 0 : for(i=0; i<=n-1; i++)
51706 : {
51707 0 : a.ptr.pp_double[i][rbfv1_mxnx] = (double)(1);
51708 : }
51709 :
51710 : /*
51711 : * Solve linear system in transformed variables, make backward
51712 : */
51713 0 : for(i=0; i<=ny-1; i++)
51714 : {
51715 0 : for(j=0; j<=n-1; j++)
51716 : {
51717 0 : tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i];
51718 : }
51719 0 : lsfitlinear(&tmpy, &a, n, rbfv1_mxnx+1, &info, &c, &rep, _state);
51720 0 : if( info<=0 )
51721 : {
51722 0 : result = ae_false;
51723 0 : ae_frame_leave(_state);
51724 0 : return result;
51725 : }
51726 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
51727 : {
51728 0 : v->ptr.pp_double[i][j] = c.ptr.p_double[j]/scaling;
51729 : }
51730 0 : v->ptr.pp_double[i][rbfv1_mxnx] = c.ptr.p_double[rbfv1_mxnx];
51731 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
51732 : {
51733 0 : v->ptr.pp_double[i][rbfv1_mxnx] = v->ptr.pp_double[i][rbfv1_mxnx]-shifting.ptr.p_double[j]*v->ptr.pp_double[i][j];
51734 : }
51735 0 : for(j=0; j<=n-1; j++)
51736 : {
51737 0 : for(k=0; k<=rbfv1_mxnx-1; k++)
51738 : {
51739 0 : y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-x->ptr.pp_double[j][k]*v->ptr.pp_double[i][k];
51740 : }
51741 0 : y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][rbfv1_mxnx];
51742 : }
51743 : }
51744 0 : ae_frame_leave(_state);
51745 0 : return result;
51746 : }
51747 :
51748 : /*
51749 : * Constant model, very simple
51750 : */
51751 0 : if( modeltype==2 )
51752 : {
51753 0 : for(i=0; i<=ny-1; i++)
51754 : {
51755 0 : for(j=0; j<=rbfv1_mxnx; j++)
51756 : {
51757 0 : v->ptr.pp_double[i][j] = (double)(0);
51758 : }
51759 0 : for(j=0; j<=n-1; j++)
51760 : {
51761 0 : v->ptr.pp_double[i][rbfv1_mxnx] = v->ptr.pp_double[i][rbfv1_mxnx]+y->ptr.pp_double[j][i];
51762 : }
51763 0 : if( n>0 )
51764 : {
51765 0 : v->ptr.pp_double[i][rbfv1_mxnx] = v->ptr.pp_double[i][rbfv1_mxnx]/n;
51766 : }
51767 0 : for(j=0; j<=n-1; j++)
51768 : {
51769 0 : y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][rbfv1_mxnx];
51770 : }
51771 : }
51772 0 : ae_frame_leave(_state);
51773 0 : return result;
51774 : }
51775 :
51776 : /*
51777 : * Zero model
51778 : */
51779 0 : ae_assert(modeltype==3, "BuildLinearModel: unknown model type", _state);
51780 0 : for(i=0; i<=ny-1; i++)
51781 : {
51782 0 : for(j=0; j<=rbfv1_mxnx; j++)
51783 : {
51784 0 : v->ptr.pp_double[i][j] = (double)(0);
51785 : }
51786 : }
51787 0 : ae_frame_leave(_state);
51788 0 : return result;
51789 : }
51790 :
51791 :
51792 0 : static void rbfv1_buildrbfmodellsqr(/* Real */ ae_matrix* x,
51793 : /* Real */ ae_matrix* y,
51794 : /* Real */ ae_matrix* xc,
51795 : /* Real */ ae_vector* r,
51796 : ae_int_t n,
51797 : ae_int_t nc,
51798 : ae_int_t ny,
51799 : kdtree* pointstree,
51800 : kdtree* centerstree,
51801 : double epsort,
51802 : double epserr,
51803 : ae_int_t maxits,
51804 : ae_int_t* gnnz,
51805 : ae_int_t* snnz,
51806 : /* Real */ ae_matrix* w,
51807 : ae_int_t* info,
51808 : ae_int_t* iterationscount,
51809 : ae_int_t* nmv,
51810 : ae_state *_state)
51811 : {
51812 : ae_frame _frame_block;
51813 : linlsqrstate state;
51814 : linlsqrreport lsqrrep;
51815 : sparsematrix spg;
51816 : sparsematrix sps;
51817 : ae_vector nearcenterscnt;
51818 : ae_vector nearpointscnt;
51819 : ae_vector skipnearpointscnt;
51820 : ae_vector farpointscnt;
51821 : ae_int_t maxnearcenterscnt;
51822 : ae_int_t maxnearpointscnt;
51823 : ae_int_t maxfarpointscnt;
51824 : ae_int_t sumnearcenterscnt;
51825 : ae_int_t sumnearpointscnt;
51826 : ae_int_t sumfarpointscnt;
51827 : double maxrad;
51828 : ae_vector pointstags;
51829 : ae_vector centerstags;
51830 : ae_matrix nearpoints;
51831 : ae_matrix nearcenters;
51832 : ae_matrix farpoints;
51833 : ae_int_t tmpi;
51834 : ae_int_t pointscnt;
51835 : ae_int_t centerscnt;
51836 : ae_vector xcx;
51837 : ae_vector tmpy;
51838 : ae_vector tc;
51839 : ae_vector g;
51840 : ae_vector c;
51841 : ae_int_t i;
51842 : ae_int_t j;
51843 : ae_int_t k;
51844 : ae_int_t sind;
51845 : ae_matrix a;
51846 : double vv;
51847 : double vx;
51848 : double vy;
51849 : double vz;
51850 : double vr;
51851 : double gnorm2;
51852 : ae_vector tmp0;
51853 : ae_vector tmp1;
51854 : ae_vector tmp2;
51855 : double fx;
51856 : ae_matrix xx;
51857 : ae_matrix cx;
51858 : double mrad;
51859 :
51860 0 : ae_frame_make(_state, &_frame_block);
51861 0 : memset(&state, 0, sizeof(state));
51862 0 : memset(&lsqrrep, 0, sizeof(lsqrrep));
51863 0 : memset(&spg, 0, sizeof(spg));
51864 0 : memset(&sps, 0, sizeof(sps));
51865 0 : memset(&nearcenterscnt, 0, sizeof(nearcenterscnt));
51866 0 : memset(&nearpointscnt, 0, sizeof(nearpointscnt));
51867 0 : memset(&skipnearpointscnt, 0, sizeof(skipnearpointscnt));
51868 0 : memset(&farpointscnt, 0, sizeof(farpointscnt));
51869 0 : memset(&pointstags, 0, sizeof(pointstags));
51870 0 : memset(¢erstags, 0, sizeof(centerstags));
51871 0 : memset(&nearpoints, 0, sizeof(nearpoints));
51872 0 : memset(&nearcenters, 0, sizeof(nearcenters));
51873 0 : memset(&farpoints, 0, sizeof(farpoints));
51874 0 : memset(&xcx, 0, sizeof(xcx));
51875 0 : memset(&tmpy, 0, sizeof(tmpy));
51876 0 : memset(&tc, 0, sizeof(tc));
51877 0 : memset(&g, 0, sizeof(g));
51878 0 : memset(&c, 0, sizeof(c));
51879 0 : memset(&a, 0, sizeof(a));
51880 0 : memset(&tmp0, 0, sizeof(tmp0));
51881 0 : memset(&tmp1, 0, sizeof(tmp1));
51882 0 : memset(&tmp2, 0, sizeof(tmp2));
51883 0 : memset(&xx, 0, sizeof(xx));
51884 0 : memset(&cx, 0, sizeof(cx));
51885 0 : *gnnz = 0;
51886 0 : *snnz = 0;
51887 0 : ae_matrix_clear(w);
51888 0 : *info = 0;
51889 0 : *iterationscount = 0;
51890 0 : *nmv = 0;
51891 0 : _linlsqrstate_init(&state, _state, ae_true);
51892 0 : _linlsqrreport_init(&lsqrrep, _state, ae_true);
51893 0 : _sparsematrix_init(&spg, _state, ae_true);
51894 0 : _sparsematrix_init(&sps, _state, ae_true);
51895 0 : ae_vector_init(&nearcenterscnt, 0, DT_INT, _state, ae_true);
51896 0 : ae_vector_init(&nearpointscnt, 0, DT_INT, _state, ae_true);
51897 0 : ae_vector_init(&skipnearpointscnt, 0, DT_INT, _state, ae_true);
51898 0 : ae_vector_init(&farpointscnt, 0, DT_INT, _state, ae_true);
51899 0 : ae_vector_init(&pointstags, 0, DT_INT, _state, ae_true);
51900 0 : ae_vector_init(¢erstags, 0, DT_INT, _state, ae_true);
51901 0 : ae_matrix_init(&nearpoints, 0, 0, DT_REAL, _state, ae_true);
51902 0 : ae_matrix_init(&nearcenters, 0, 0, DT_REAL, _state, ae_true);
51903 0 : ae_matrix_init(&farpoints, 0, 0, DT_REAL, _state, ae_true);
51904 0 : ae_vector_init(&xcx, 0, DT_REAL, _state, ae_true);
51905 0 : ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
51906 0 : ae_vector_init(&tc, 0, DT_REAL, _state, ae_true);
51907 0 : ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
51908 0 : ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
51909 0 : ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
51910 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
51911 0 : ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
51912 0 : ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
51913 0 : ae_matrix_init(&xx, 0, 0, DT_REAL, _state, ae_true);
51914 0 : ae_matrix_init(&cx, 0, 0, DT_REAL, _state, ae_true);
51915 :
51916 :
51917 : /*
51918 : * Handle special cases: NC=0
51919 : */
51920 0 : if( nc==0 )
51921 : {
51922 0 : *info = 1;
51923 0 : *iterationscount = 0;
51924 0 : *nmv = 0;
51925 0 : ae_frame_leave(_state);
51926 0 : return;
51927 : }
51928 :
51929 : /*
51930 : * Prepare for general case, NC>0
51931 : */
51932 0 : ae_vector_set_length(&xcx, rbfv1_mxnx, _state);
51933 0 : ae_vector_set_length(&pointstags, n, _state);
51934 0 : ae_vector_set_length(¢erstags, nc, _state);
51935 0 : *info = -1;
51936 0 : *iterationscount = 0;
51937 0 : *nmv = 0;
51938 :
51939 : /*
51940 : * This block prepares quantities used to compute approximate cardinal basis functions (ACBFs):
51941 : * * NearCentersCnt[] - array[NC], whose elements store number of near centers used to build ACBF
51942 : * * NearPointsCnt[] - array[NC], number of near points used to build ACBF
51943 : * * FarPointsCnt[] - array[NC], number of far points (ones where ACBF is nonzero)
51944 : * * MaxNearCentersCnt - max(NearCentersCnt)
51945 : * * MaxNearPointsCnt - max(NearPointsCnt)
51946 : * * SumNearCentersCnt - sum(NearCentersCnt)
51947 : * * SumNearPointsCnt - sum(NearPointsCnt)
51948 : * * SumFarPointsCnt - sum(FarPointsCnt)
51949 : */
51950 0 : ae_vector_set_length(&nearcenterscnt, nc, _state);
51951 0 : ae_vector_set_length(&nearpointscnt, nc, _state);
51952 0 : ae_vector_set_length(&skipnearpointscnt, nc, _state);
51953 0 : ae_vector_set_length(&farpointscnt, nc, _state);
51954 0 : maxnearcenterscnt = 0;
51955 0 : maxnearpointscnt = 0;
51956 0 : maxfarpointscnt = 0;
51957 0 : sumnearcenterscnt = 0;
51958 0 : sumnearpointscnt = 0;
51959 0 : sumfarpointscnt = 0;
51960 0 : for(i=0; i<=nc-1; i++)
51961 : {
51962 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
51963 : {
51964 0 : xcx.ptr.p_double[j] = xc->ptr.pp_double[i][j];
51965 : }
51966 :
51967 : /*
51968 : * Determine number of near centers and maximum radius of near centers
51969 : */
51970 0 : nearcenterscnt.ptr.p_int[i] = kdtreequeryrnn(centerstree, &xcx, r->ptr.p_double[i]*rbfv1_rbfnearradius, ae_true, _state);
51971 0 : kdtreequeryresultstags(centerstree, ¢erstags, _state);
51972 0 : maxrad = (double)(0);
51973 0 : for(j=0; j<=nearcenterscnt.ptr.p_int[i]-1; j++)
51974 : {
51975 0 : maxrad = ae_maxreal(maxrad, ae_fabs(r->ptr.p_double[centerstags.ptr.p_int[j]], _state), _state);
51976 : }
51977 :
51978 : /*
51979 : * Determine number of near points (ones which used to build ACBF)
51980 : * and skipped points (the most near points which are NOT used to build ACBF
51981 : * and are NOT included in the near points count
51982 : */
51983 0 : skipnearpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, 0.1*r->ptr.p_double[i], ae_true, _state);
51984 0 : nearpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, (r->ptr.p_double[i]+maxrad)*rbfv1_rbfnearradius, ae_true, _state)-skipnearpointscnt.ptr.p_int[i];
51985 0 : ae_assert(nearpointscnt.ptr.p_int[i]>=0, "BuildRBFModelLSQR: internal error", _state);
51986 :
51987 : /*
51988 : * Determine number of far points
51989 : */
51990 0 : farpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, ae_maxreal(r->ptr.p_double[i]*rbfv1_rbfnearradius+maxrad*rbfv1_rbffarradius, r->ptr.p_double[i]*rbfv1_rbffarradius, _state), ae_true, _state);
51991 :
51992 : /*
51993 : * calculate sum and max, make some basic checks
51994 : */
51995 0 : ae_assert(nearcenterscnt.ptr.p_int[i]>0, "BuildRBFModelLSQR: internal error", _state);
51996 0 : maxnearcenterscnt = ae_maxint(maxnearcenterscnt, nearcenterscnt.ptr.p_int[i], _state);
51997 0 : maxnearpointscnt = ae_maxint(maxnearpointscnt, nearpointscnt.ptr.p_int[i], _state);
51998 0 : maxfarpointscnt = ae_maxint(maxfarpointscnt, farpointscnt.ptr.p_int[i], _state);
51999 0 : sumnearcenterscnt = sumnearcenterscnt+nearcenterscnt.ptr.p_int[i];
52000 0 : sumnearpointscnt = sumnearpointscnt+nearpointscnt.ptr.p_int[i];
52001 0 : sumfarpointscnt = sumfarpointscnt+farpointscnt.ptr.p_int[i];
52002 : }
52003 0 : *snnz = sumnearcenterscnt;
52004 0 : *gnnz = sumfarpointscnt;
52005 0 : ae_assert(maxnearcenterscnt>0, "BuildRBFModelLSQR: internal error", _state);
52006 :
52007 : /*
52008 : * Allocate temporaries.
52009 : *
52010 : * NOTE: we want to avoid allocation of zero-size arrays, so we
52011 : * use max(desired_size,1) instead of desired_size when performing
52012 : * memory allocation.
52013 : */
52014 0 : ae_matrix_set_length(&a, maxnearpointscnt+maxnearcenterscnt, maxnearcenterscnt, _state);
52015 0 : ae_vector_set_length(&tmpy, maxnearpointscnt+maxnearcenterscnt, _state);
52016 0 : ae_vector_set_length(&g, maxnearcenterscnt, _state);
52017 0 : ae_vector_set_length(&c, maxnearcenterscnt, _state);
52018 0 : ae_matrix_set_length(&nearcenters, maxnearcenterscnt, rbfv1_mxnx, _state);
52019 0 : ae_matrix_set_length(&nearpoints, ae_maxint(maxnearpointscnt, 1, _state), rbfv1_mxnx, _state);
52020 0 : ae_matrix_set_length(&farpoints, ae_maxint(maxfarpointscnt, 1, _state), rbfv1_mxnx, _state);
52021 :
52022 : /*
52023 : * fill matrix SpG
52024 : */
52025 0 : sparsecreate(n, nc, *gnnz, &spg, _state);
52026 0 : sparsecreate(nc, nc, *snnz, &sps, _state);
52027 0 : for(i=0; i<=nc-1; i++)
52028 : {
52029 0 : centerscnt = nearcenterscnt.ptr.p_int[i];
52030 :
52031 : /*
52032 : * main center
52033 : */
52034 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
52035 : {
52036 0 : xcx.ptr.p_double[j] = xc->ptr.pp_double[i][j];
52037 : }
52038 :
52039 : /*
52040 : * center's tree
52041 : */
52042 0 : tmpi = kdtreequeryknn(centerstree, &xcx, centerscnt, ae_true, _state);
52043 0 : ae_assert(tmpi==centerscnt, "BuildRBFModelLSQR: internal error", _state);
52044 0 : kdtreequeryresultsx(centerstree, &cx, _state);
52045 0 : kdtreequeryresultstags(centerstree, ¢erstags, _state);
52046 :
52047 : /*
52048 : * point's tree
52049 : */
52050 0 : mrad = (double)(0);
52051 0 : for(j=0; j<=centerscnt-1; j++)
52052 : {
52053 0 : mrad = ae_maxreal(mrad, r->ptr.p_double[centerstags.ptr.p_int[j]], _state);
52054 : }
52055 :
52056 : /*
52057 : * we need to be sure that 'CTree' contains
52058 : * at least one side center
52059 : */
52060 0 : sparseset(&sps, i, i, (double)(1), _state);
52061 0 : c.ptr.p_double[0] = 1.0;
52062 0 : for(j=1; j<=centerscnt-1; j++)
52063 : {
52064 0 : c.ptr.p_double[j] = 0.0;
52065 : }
52066 0 : if( centerscnt>1&&nearpointscnt.ptr.p_int[i]>0 )
52067 : {
52068 :
52069 : /*
52070 : * first KDTree request for points
52071 : */
52072 0 : pointscnt = nearpointscnt.ptr.p_int[i];
52073 0 : tmpi = kdtreequeryknn(pointstree, &xcx, skipnearpointscnt.ptr.p_int[i]+nearpointscnt.ptr.p_int[i], ae_true, _state);
52074 0 : ae_assert(tmpi==skipnearpointscnt.ptr.p_int[i]+nearpointscnt.ptr.p_int[i], "BuildRBFModelLSQR: internal error", _state);
52075 0 : kdtreequeryresultsx(pointstree, &xx, _state);
52076 0 : sind = skipnearpointscnt.ptr.p_int[i];
52077 0 : for(j=0; j<=pointscnt-1; j++)
52078 : {
52079 0 : vx = xx.ptr.pp_double[sind+j][0];
52080 0 : vy = xx.ptr.pp_double[sind+j][1];
52081 0 : vz = xx.ptr.pp_double[sind+j][2];
52082 0 : for(k=0; k<=centerscnt-1; k++)
52083 : {
52084 0 : vr = 0.0;
52085 0 : vv = vx-cx.ptr.pp_double[k][0];
52086 0 : vr = vr+vv*vv;
52087 0 : vv = vy-cx.ptr.pp_double[k][1];
52088 0 : vr = vr+vv*vv;
52089 0 : vv = vz-cx.ptr.pp_double[k][2];
52090 0 : vr = vr+vv*vv;
52091 0 : vv = r->ptr.p_double[centerstags.ptr.p_int[k]];
52092 0 : a.ptr.pp_double[j][k] = ae_exp(-vr/(vv*vv), _state);
52093 : }
52094 : }
52095 0 : for(j=0; j<=centerscnt-1; j++)
52096 : {
52097 0 : g.ptr.p_double[j] = ae_exp(-(ae_sqr(xcx.ptr.p_double[0]-cx.ptr.pp_double[j][0], _state)+ae_sqr(xcx.ptr.p_double[1]-cx.ptr.pp_double[j][1], _state)+ae_sqr(xcx.ptr.p_double[2]-cx.ptr.pp_double[j][2], _state))/ae_sqr(r->ptr.p_double[centerstags.ptr.p_int[j]], _state), _state);
52098 : }
52099 :
52100 : /*
52101 : * calculate the problem
52102 : */
52103 0 : gnorm2 = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
52104 0 : for(j=0; j<=pointscnt-1; j++)
52105 : {
52106 0 : vv = ae_v_dotproduct(&a.ptr.pp_double[j][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
52107 0 : vv = vv/gnorm2;
52108 0 : tmpy.ptr.p_double[j] = -vv;
52109 0 : ae_v_subd(&a.ptr.pp_double[j][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv);
52110 : }
52111 0 : for(j=pointscnt; j<=pointscnt+centerscnt-1; j++)
52112 : {
52113 0 : for(k=0; k<=centerscnt-1; k++)
52114 : {
52115 0 : a.ptr.pp_double[j][k] = 0.0;
52116 : }
52117 0 : a.ptr.pp_double[j][j-pointscnt] = 1.0E-6;
52118 0 : tmpy.ptr.p_double[j] = 0.0;
52119 : }
52120 0 : fblssolvels(&a, &tmpy, pointscnt+centerscnt, centerscnt, &tmp0, &tmp1, &tmp2, _state);
52121 0 : ae_v_move(&c.ptr.p_double[0], 1, &tmpy.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
52122 0 : vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
52123 0 : vv = vv/gnorm2;
52124 0 : ae_v_subd(&c.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv);
52125 0 : vv = 1/gnorm2;
52126 0 : ae_v_addd(&c.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv);
52127 0 : for(j=0; j<=centerscnt-1; j++)
52128 : {
52129 0 : sparseset(&sps, i, centerstags.ptr.p_int[j], c.ptr.p_double[j], _state);
52130 : }
52131 : }
52132 :
52133 : /*
52134 : * second KDTree request for points
52135 : */
52136 0 : pointscnt = farpointscnt.ptr.p_int[i];
52137 0 : tmpi = kdtreequeryknn(pointstree, &xcx, pointscnt, ae_true, _state);
52138 0 : ae_assert(tmpi==pointscnt, "BuildRBFModelLSQR: internal error", _state);
52139 0 : kdtreequeryresultsx(pointstree, &xx, _state);
52140 0 : kdtreequeryresultstags(pointstree, &pointstags, _state);
52141 :
52142 : /*
52143 : *fill SpG matrix
52144 : */
52145 0 : for(j=0; j<=pointscnt-1; j++)
52146 : {
52147 0 : fx = (double)(0);
52148 0 : vx = xx.ptr.pp_double[j][0];
52149 0 : vy = xx.ptr.pp_double[j][1];
52150 0 : vz = xx.ptr.pp_double[j][2];
52151 0 : for(k=0; k<=centerscnt-1; k++)
52152 : {
52153 0 : vr = 0.0;
52154 0 : vv = vx-cx.ptr.pp_double[k][0];
52155 0 : vr = vr+vv*vv;
52156 0 : vv = vy-cx.ptr.pp_double[k][1];
52157 0 : vr = vr+vv*vv;
52158 0 : vv = vz-cx.ptr.pp_double[k][2];
52159 0 : vr = vr+vv*vv;
52160 0 : vv = r->ptr.p_double[centerstags.ptr.p_int[k]];
52161 0 : vv = vv*vv;
52162 0 : fx = fx+c.ptr.p_double[k]*ae_exp(-vr/vv, _state);
52163 : }
52164 0 : sparseset(&spg, pointstags.ptr.p_int[j], i, fx, _state);
52165 : }
52166 : }
52167 0 : sparseconverttocrs(&spg, _state);
52168 0 : sparseconverttocrs(&sps, _state);
52169 :
52170 : /*
52171 : * solve by LSQR method
52172 : */
52173 0 : ae_vector_set_length(&tmpy, n, _state);
52174 0 : ae_vector_set_length(&tc, nc, _state);
52175 0 : ae_matrix_set_length(w, nc, ny, _state);
52176 0 : linlsqrcreate(n, nc, &state, _state);
52177 0 : linlsqrsetcond(&state, epsort, epserr, maxits, _state);
52178 0 : for(i=0; i<=ny-1; i++)
52179 : {
52180 0 : for(j=0; j<=n-1; j++)
52181 : {
52182 0 : tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i];
52183 : }
52184 0 : linlsqrsolvesparse(&state, &spg, &tmpy, _state);
52185 0 : linlsqrresults(&state, &c, &lsqrrep, _state);
52186 0 : if( lsqrrep.terminationtype<=0 )
52187 : {
52188 0 : *info = -4;
52189 0 : ae_frame_leave(_state);
52190 0 : return;
52191 : }
52192 0 : sparsemtv(&sps, &c, &tc, _state);
52193 0 : for(j=0; j<=nc-1; j++)
52194 : {
52195 0 : w->ptr.pp_double[j][i] = tc.ptr.p_double[j];
52196 : }
52197 0 : *iterationscount = *iterationscount+lsqrrep.iterationscount;
52198 0 : *nmv = *nmv+lsqrrep.nmv;
52199 : }
52200 0 : *info = 1;
52201 0 : ae_frame_leave(_state);
52202 : }
52203 :
52204 :
52205 0 : static void rbfv1_buildrbfmlayersmodellsqr(/* Real */ ae_matrix* x,
52206 : /* Real */ ae_matrix* y,
52207 : /* Real */ ae_matrix* xc,
52208 : double rval,
52209 : /* Real */ ae_vector* r,
52210 : ae_int_t n,
52211 : ae_int_t* nc,
52212 : ae_int_t ny,
52213 : ae_int_t nlayers,
52214 : kdtree* centerstree,
52215 : double epsort,
52216 : double epserr,
52217 : ae_int_t maxits,
52218 : double lambdav,
52219 : ae_int_t* annz,
52220 : /* Real */ ae_matrix* w,
52221 : ae_int_t* info,
52222 : ae_int_t* iterationscount,
52223 : ae_int_t* nmv,
52224 : ae_state *_state)
52225 : {
52226 : ae_frame _frame_block;
52227 : linlsqrstate state;
52228 : linlsqrreport lsqrrep;
52229 : sparsematrix spa;
52230 : double anorm;
52231 : ae_vector omega;
52232 : ae_vector xx;
52233 : ae_vector tmpy;
52234 : ae_matrix cx;
52235 : double yval;
52236 : ae_int_t nec;
52237 : ae_vector centerstags;
52238 : ae_int_t layer;
52239 : ae_int_t i;
52240 : ae_int_t j;
52241 : ae_int_t k;
52242 : double v;
52243 : double rmaxbefore;
52244 : double rmaxafter;
52245 :
52246 0 : ae_frame_make(_state, &_frame_block);
52247 0 : memset(&state, 0, sizeof(state));
52248 0 : memset(&lsqrrep, 0, sizeof(lsqrrep));
52249 0 : memset(&spa, 0, sizeof(spa));
52250 0 : memset(&omega, 0, sizeof(omega));
52251 0 : memset(&xx, 0, sizeof(xx));
52252 0 : memset(&tmpy, 0, sizeof(tmpy));
52253 0 : memset(&cx, 0, sizeof(cx));
52254 0 : memset(¢erstags, 0, sizeof(centerstags));
52255 0 : ae_matrix_clear(xc);
52256 0 : ae_vector_clear(r);
52257 0 : *nc = 0;
52258 0 : *annz = 0;
52259 0 : ae_matrix_clear(w);
52260 0 : *info = 0;
52261 0 : *iterationscount = 0;
52262 0 : *nmv = 0;
52263 0 : _linlsqrstate_init(&state, _state, ae_true);
52264 0 : _linlsqrreport_init(&lsqrrep, _state, ae_true);
52265 0 : _sparsematrix_init(&spa, _state, ae_true);
52266 0 : ae_vector_init(&omega, 0, DT_REAL, _state, ae_true);
52267 0 : ae_vector_init(&xx, 0, DT_REAL, _state, ae_true);
52268 0 : ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
52269 0 : ae_matrix_init(&cx, 0, 0, DT_REAL, _state, ae_true);
52270 0 : ae_vector_init(¢erstags, 0, DT_INT, _state, ae_true);
52271 :
52272 0 : ae_assert(nlayers>=0, "BuildRBFMLayersModelLSQR: invalid argument(NLayers<0)", _state);
52273 0 : ae_assert(n>=0, "BuildRBFMLayersModelLSQR: invalid argument(N<0)", _state);
52274 0 : ae_assert(rbfv1_mxnx>0&&rbfv1_mxnx<=3, "BuildRBFMLayersModelLSQR: internal error(invalid global const MxNX: either MxNX<=0 or MxNX>3)", _state);
52275 0 : *annz = 0;
52276 0 : if( n==0||nlayers==0 )
52277 : {
52278 0 : *info = 1;
52279 0 : *iterationscount = 0;
52280 0 : *nmv = 0;
52281 0 : ae_frame_leave(_state);
52282 0 : return;
52283 : }
52284 0 : *nc = n*nlayers;
52285 0 : ae_vector_set_length(&xx, rbfv1_mxnx, _state);
52286 0 : ae_vector_set_length(¢erstags, n, _state);
52287 0 : ae_matrix_set_length(xc, *nc, rbfv1_mxnx, _state);
52288 0 : ae_vector_set_length(r, *nc, _state);
52289 0 : for(i=0; i<=*nc-1; i++)
52290 : {
52291 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
52292 : {
52293 0 : xc->ptr.pp_double[i][j] = x->ptr.pp_double[i%n][j];
52294 : }
52295 : }
52296 0 : for(i=0; i<=*nc-1; i++)
52297 : {
52298 0 : r->ptr.p_double[i] = rval/ae_pow((double)(2), (double)(i/n), _state);
52299 : }
52300 0 : for(i=0; i<=n-1; i++)
52301 : {
52302 0 : centerstags.ptr.p_int[i] = i;
52303 : }
52304 0 : kdtreebuildtagged(xc, ¢erstags, n, rbfv1_mxnx, 0, 2, centerstree, _state);
52305 0 : ae_vector_set_length(&omega, n, _state);
52306 0 : ae_vector_set_length(&tmpy, n, _state);
52307 0 : ae_matrix_set_length(w, *nc, ny, _state);
52308 0 : *info = -1;
52309 0 : *iterationscount = 0;
52310 0 : *nmv = 0;
52311 0 : linlsqrcreate(n, n, &state, _state);
52312 0 : linlsqrsetcond(&state, epsort, epserr, maxits, _state);
52313 0 : linlsqrsetlambdai(&state, 1.0E-6, _state);
52314 :
52315 : /*
52316 : * calculate number of non-zero elements for sparse matrix
52317 : */
52318 0 : for(i=0; i<=n-1; i++)
52319 : {
52320 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
52321 : {
52322 0 : xx.ptr.p_double[j] = x->ptr.pp_double[i][j];
52323 : }
52324 0 : *annz = *annz+kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[0]*rbfv1_rbfmlradius, ae_true, _state);
52325 : }
52326 0 : for(layer=0; layer<=nlayers-1; layer++)
52327 : {
52328 :
52329 : /*
52330 : * Fill sparse matrix, calculate norm(A)
52331 : */
52332 0 : anorm = 0.0;
52333 0 : sparsecreate(n, n, *annz, &spa, _state);
52334 0 : for(i=0; i<=n-1; i++)
52335 : {
52336 0 : for(j=0; j<=rbfv1_mxnx-1; j++)
52337 : {
52338 0 : xx.ptr.p_double[j] = x->ptr.pp_double[i][j];
52339 : }
52340 0 : nec = kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[layer*n]*rbfv1_rbfmlradius, ae_true, _state);
52341 0 : kdtreequeryresultsx(centerstree, &cx, _state);
52342 0 : kdtreequeryresultstags(centerstree, ¢erstags, _state);
52343 0 : for(j=0; j<=nec-1; j++)
52344 : {
52345 0 : v = ae_exp(-(ae_sqr(xx.ptr.p_double[0]-cx.ptr.pp_double[j][0], _state)+ae_sqr(xx.ptr.p_double[1]-cx.ptr.pp_double[j][1], _state)+ae_sqr(xx.ptr.p_double[2]-cx.ptr.pp_double[j][2], _state))/ae_sqr(r->ptr.p_double[layer*n+centerstags.ptr.p_int[j]], _state), _state);
52346 0 : sparseset(&spa, i, centerstags.ptr.p_int[j], v, _state);
52347 0 : anorm = anorm+ae_sqr(v, _state);
52348 : }
52349 : }
52350 0 : anorm = ae_sqrt(anorm, _state);
52351 0 : sparseconverttocrs(&spa, _state);
52352 :
52353 : /*
52354 : * Calculate maximum residual before adding new layer.
52355 : * This value is not used by algorithm, the only purpose is to make debugging easier.
52356 : */
52357 0 : rmaxbefore = 0.0;
52358 0 : for(j=0; j<=n-1; j++)
52359 : {
52360 0 : for(i=0; i<=ny-1; i++)
52361 : {
52362 0 : rmaxbefore = ae_maxreal(rmaxbefore, ae_fabs(y->ptr.pp_double[j][i], _state), _state);
52363 : }
52364 : }
52365 :
52366 : /*
52367 : * Process NY dimensions of the target function
52368 : */
52369 0 : for(i=0; i<=ny-1; i++)
52370 : {
52371 0 : for(j=0; j<=n-1; j++)
52372 : {
52373 0 : tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i];
52374 : }
52375 :
52376 : /*
52377 : * calculate Omega for current layer
52378 : */
52379 0 : linlsqrsetlambdai(&state, lambdav*anorm/n, _state);
52380 0 : linlsqrsolvesparse(&state, &spa, &tmpy, _state);
52381 0 : linlsqrresults(&state, &omega, &lsqrrep, _state);
52382 0 : if( lsqrrep.terminationtype<=0 )
52383 : {
52384 0 : *info = -4;
52385 0 : ae_frame_leave(_state);
52386 0 : return;
52387 : }
52388 :
52389 : /*
52390 : * calculate error for current layer
52391 : */
52392 0 : for(j=0; j<=n-1; j++)
52393 : {
52394 0 : yval = (double)(0);
52395 0 : for(k=0; k<=rbfv1_mxnx-1; k++)
52396 : {
52397 0 : xx.ptr.p_double[k] = x->ptr.pp_double[j][k];
52398 : }
52399 0 : nec = kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[layer*n]*rbfv1_rbffarradius, ae_true, _state);
52400 0 : kdtreequeryresultsx(centerstree, &cx, _state);
52401 0 : kdtreequeryresultstags(centerstree, ¢erstags, _state);
52402 0 : for(k=0; k<=nec-1; k++)
52403 : {
52404 0 : yval = yval+omega.ptr.p_double[centerstags.ptr.p_int[k]]*ae_exp(-(ae_sqr(xx.ptr.p_double[0]-cx.ptr.pp_double[k][0], _state)+ae_sqr(xx.ptr.p_double[1]-cx.ptr.pp_double[k][1], _state)+ae_sqr(xx.ptr.p_double[2]-cx.ptr.pp_double[k][2], _state))/ae_sqr(r->ptr.p_double[layer*n+centerstags.ptr.p_int[k]], _state), _state);
52405 : }
52406 0 : y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-yval;
52407 : }
52408 :
52409 : /*
52410 : * write Omega in out parameter W
52411 : */
52412 0 : for(j=0; j<=n-1; j++)
52413 : {
52414 0 : w->ptr.pp_double[layer*n+j][i] = omega.ptr.p_double[j];
52415 : }
52416 0 : *iterationscount = *iterationscount+lsqrrep.iterationscount;
52417 0 : *nmv = *nmv+lsqrrep.nmv;
52418 : }
52419 :
52420 : /*
52421 : * Calculate maximum residual before adding new layer.
52422 : * This value is not used by algorithm, the only purpose is to make debugging easier.
52423 : */
52424 0 : rmaxafter = 0.0;
52425 0 : for(j=0; j<=n-1; j++)
52426 : {
52427 0 : for(i=0; i<=ny-1; i++)
52428 : {
52429 0 : rmaxafter = ae_maxreal(rmaxafter, ae_fabs(y->ptr.pp_double[j][i], _state), _state);
52430 : }
52431 : }
52432 : }
52433 0 : *info = 1;
52434 0 : ae_frame_leave(_state);
52435 : }
52436 :
52437 :
52438 0 : void _rbfv1calcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic)
52439 : {
52440 0 : rbfv1calcbuffer *p = (rbfv1calcbuffer*)_p;
52441 0 : ae_touch_ptr((void*)p);
52442 0 : ae_vector_init(&p->calcbufxcx, 0, DT_REAL, _state, make_automatic);
52443 0 : ae_matrix_init(&p->calcbufx, 0, 0, DT_REAL, _state, make_automatic);
52444 0 : ae_vector_init(&p->calcbuftags, 0, DT_INT, _state, make_automatic);
52445 0 : _kdtreerequestbuffer_init(&p->requestbuffer, _state, make_automatic);
52446 0 : }
52447 :
52448 :
52449 0 : void _rbfv1calcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
52450 : {
52451 0 : rbfv1calcbuffer *dst = (rbfv1calcbuffer*)_dst;
52452 0 : rbfv1calcbuffer *src = (rbfv1calcbuffer*)_src;
52453 0 : ae_vector_init_copy(&dst->calcbufxcx, &src->calcbufxcx, _state, make_automatic);
52454 0 : ae_matrix_init_copy(&dst->calcbufx, &src->calcbufx, _state, make_automatic);
52455 0 : ae_vector_init_copy(&dst->calcbuftags, &src->calcbuftags, _state, make_automatic);
52456 0 : _kdtreerequestbuffer_init_copy(&dst->requestbuffer, &src->requestbuffer, _state, make_automatic);
52457 0 : }
52458 :
52459 :
52460 0 : void _rbfv1calcbuffer_clear(void* _p)
52461 : {
52462 0 : rbfv1calcbuffer *p = (rbfv1calcbuffer*)_p;
52463 0 : ae_touch_ptr((void*)p);
52464 0 : ae_vector_clear(&p->calcbufxcx);
52465 0 : ae_matrix_clear(&p->calcbufx);
52466 0 : ae_vector_clear(&p->calcbuftags);
52467 0 : _kdtreerequestbuffer_clear(&p->requestbuffer);
52468 0 : }
52469 :
52470 :
52471 0 : void _rbfv1calcbuffer_destroy(void* _p)
52472 : {
52473 0 : rbfv1calcbuffer *p = (rbfv1calcbuffer*)_p;
52474 0 : ae_touch_ptr((void*)p);
52475 0 : ae_vector_destroy(&p->calcbufxcx);
52476 0 : ae_matrix_destroy(&p->calcbufx);
52477 0 : ae_vector_destroy(&p->calcbuftags);
52478 0 : _kdtreerequestbuffer_destroy(&p->requestbuffer);
52479 0 : }
52480 :
52481 :
52482 0 : void _rbfv1model_init(void* _p, ae_state *_state, ae_bool make_automatic)
52483 : {
52484 0 : rbfv1model *p = (rbfv1model*)_p;
52485 0 : ae_touch_ptr((void*)p);
52486 0 : _kdtree_init(&p->tree, _state, make_automatic);
52487 0 : ae_matrix_init(&p->xc, 0, 0, DT_REAL, _state, make_automatic);
52488 0 : ae_matrix_init(&p->wr, 0, 0, DT_REAL, _state, make_automatic);
52489 0 : ae_matrix_init(&p->v, 0, 0, DT_REAL, _state, make_automatic);
52490 0 : ae_vector_init(&p->calcbufxcx, 0, DT_REAL, _state, make_automatic);
52491 0 : ae_matrix_init(&p->calcbufx, 0, 0, DT_REAL, _state, make_automatic);
52492 0 : ae_vector_init(&p->calcbuftags, 0, DT_INT, _state, make_automatic);
52493 0 : }
52494 :
52495 :
52496 0 : void _rbfv1model_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
52497 : {
52498 0 : rbfv1model *dst = (rbfv1model*)_dst;
52499 0 : rbfv1model *src = (rbfv1model*)_src;
52500 0 : dst->ny = src->ny;
52501 0 : dst->nx = src->nx;
52502 0 : dst->nc = src->nc;
52503 0 : dst->nl = src->nl;
52504 0 : _kdtree_init_copy(&dst->tree, &src->tree, _state, make_automatic);
52505 0 : ae_matrix_init_copy(&dst->xc, &src->xc, _state, make_automatic);
52506 0 : ae_matrix_init_copy(&dst->wr, &src->wr, _state, make_automatic);
52507 0 : dst->rmax = src->rmax;
52508 0 : ae_matrix_init_copy(&dst->v, &src->v, _state, make_automatic);
52509 0 : ae_vector_init_copy(&dst->calcbufxcx, &src->calcbufxcx, _state, make_automatic);
52510 0 : ae_matrix_init_copy(&dst->calcbufx, &src->calcbufx, _state, make_automatic);
52511 0 : ae_vector_init_copy(&dst->calcbuftags, &src->calcbuftags, _state, make_automatic);
52512 0 : }
52513 :
52514 :
52515 0 : void _rbfv1model_clear(void* _p)
52516 : {
52517 0 : rbfv1model *p = (rbfv1model*)_p;
52518 0 : ae_touch_ptr((void*)p);
52519 0 : _kdtree_clear(&p->tree);
52520 0 : ae_matrix_clear(&p->xc);
52521 0 : ae_matrix_clear(&p->wr);
52522 0 : ae_matrix_clear(&p->v);
52523 0 : ae_vector_clear(&p->calcbufxcx);
52524 0 : ae_matrix_clear(&p->calcbufx);
52525 0 : ae_vector_clear(&p->calcbuftags);
52526 0 : }
52527 :
52528 :
52529 0 : void _rbfv1model_destroy(void* _p)
52530 : {
52531 0 : rbfv1model *p = (rbfv1model*)_p;
52532 0 : ae_touch_ptr((void*)p);
52533 0 : _kdtree_destroy(&p->tree);
52534 0 : ae_matrix_destroy(&p->xc);
52535 0 : ae_matrix_destroy(&p->wr);
52536 0 : ae_matrix_destroy(&p->v);
52537 0 : ae_vector_destroy(&p->calcbufxcx);
52538 0 : ae_matrix_destroy(&p->calcbufx);
52539 0 : ae_vector_destroy(&p->calcbuftags);
52540 0 : }
52541 :
52542 :
52543 0 : void _gridcalc3v1buf_init(void* _p, ae_state *_state, ae_bool make_automatic)
52544 : {
52545 0 : gridcalc3v1buf *p = (gridcalc3v1buf*)_p;
52546 0 : ae_touch_ptr((void*)p);
52547 0 : ae_vector_init(&p->tx, 0, DT_REAL, _state, make_automatic);
52548 0 : ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic);
52549 0 : ae_vector_init(&p->ty, 0, DT_REAL, _state, make_automatic);
52550 0 : ae_vector_init(&p->flag0, 0, DT_BOOL, _state, make_automatic);
52551 0 : ae_vector_init(&p->flag1, 0, DT_BOOL, _state, make_automatic);
52552 0 : ae_vector_init(&p->flag2, 0, DT_BOOL, _state, make_automatic);
52553 0 : ae_vector_init(&p->flag12, 0, DT_BOOL, _state, make_automatic);
52554 0 : ae_vector_init(&p->expbuf0, 0, DT_REAL, _state, make_automatic);
52555 0 : ae_vector_init(&p->expbuf1, 0, DT_REAL, _state, make_automatic);
52556 0 : ae_vector_init(&p->expbuf2, 0, DT_REAL, _state, make_automatic);
52557 0 : _kdtreerequestbuffer_init(&p->requestbuf, _state, make_automatic);
52558 0 : ae_matrix_init(&p->calcbufx, 0, 0, DT_REAL, _state, make_automatic);
52559 0 : ae_vector_init(&p->calcbuftags, 0, DT_INT, _state, make_automatic);
52560 0 : }
52561 :
52562 :
52563 0 : void _gridcalc3v1buf_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
52564 : {
52565 0 : gridcalc3v1buf *dst = (gridcalc3v1buf*)_dst;
52566 0 : gridcalc3v1buf *src = (gridcalc3v1buf*)_src;
52567 0 : ae_vector_init_copy(&dst->tx, &src->tx, _state, make_automatic);
52568 0 : ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic);
52569 0 : ae_vector_init_copy(&dst->ty, &src->ty, _state, make_automatic);
52570 0 : ae_vector_init_copy(&dst->flag0, &src->flag0, _state, make_automatic);
52571 0 : ae_vector_init_copy(&dst->flag1, &src->flag1, _state, make_automatic);
52572 0 : ae_vector_init_copy(&dst->flag2, &src->flag2, _state, make_automatic);
52573 0 : ae_vector_init_copy(&dst->flag12, &src->flag12, _state, make_automatic);
52574 0 : ae_vector_init_copy(&dst->expbuf0, &src->expbuf0, _state, make_automatic);
52575 0 : ae_vector_init_copy(&dst->expbuf1, &src->expbuf1, _state, make_automatic);
52576 0 : ae_vector_init_copy(&dst->expbuf2, &src->expbuf2, _state, make_automatic);
52577 0 : _kdtreerequestbuffer_init_copy(&dst->requestbuf, &src->requestbuf, _state, make_automatic);
52578 0 : ae_matrix_init_copy(&dst->calcbufx, &src->calcbufx, _state, make_automatic);
52579 0 : ae_vector_init_copy(&dst->calcbuftags, &src->calcbuftags, _state, make_automatic);
52580 0 : }
52581 :
52582 :
52583 0 : void _gridcalc3v1buf_clear(void* _p)
52584 : {
52585 0 : gridcalc3v1buf *p = (gridcalc3v1buf*)_p;
52586 0 : ae_touch_ptr((void*)p);
52587 0 : ae_vector_clear(&p->tx);
52588 0 : ae_vector_clear(&p->cx);
52589 0 : ae_vector_clear(&p->ty);
52590 0 : ae_vector_clear(&p->flag0);
52591 0 : ae_vector_clear(&p->flag1);
52592 0 : ae_vector_clear(&p->flag2);
52593 0 : ae_vector_clear(&p->flag12);
52594 0 : ae_vector_clear(&p->expbuf0);
52595 0 : ae_vector_clear(&p->expbuf1);
52596 0 : ae_vector_clear(&p->expbuf2);
52597 0 : _kdtreerequestbuffer_clear(&p->requestbuf);
52598 0 : ae_matrix_clear(&p->calcbufx);
52599 0 : ae_vector_clear(&p->calcbuftags);
52600 0 : }
52601 :
52602 :
52603 0 : void _gridcalc3v1buf_destroy(void* _p)
52604 : {
52605 0 : gridcalc3v1buf *p = (gridcalc3v1buf*)_p;
52606 0 : ae_touch_ptr((void*)p);
52607 0 : ae_vector_destroy(&p->tx);
52608 0 : ae_vector_destroy(&p->cx);
52609 0 : ae_vector_destroy(&p->ty);
52610 0 : ae_vector_destroy(&p->flag0);
52611 0 : ae_vector_destroy(&p->flag1);
52612 0 : ae_vector_destroy(&p->flag2);
52613 0 : ae_vector_destroy(&p->flag12);
52614 0 : ae_vector_destroy(&p->expbuf0);
52615 0 : ae_vector_destroy(&p->expbuf1);
52616 0 : ae_vector_destroy(&p->expbuf2);
52617 0 : _kdtreerequestbuffer_destroy(&p->requestbuf);
52618 0 : ae_matrix_destroy(&p->calcbufx);
52619 0 : ae_vector_destroy(&p->calcbuftags);
52620 0 : }
52621 :
52622 :
52623 0 : void _rbfv1report_init(void* _p, ae_state *_state, ae_bool make_automatic)
52624 : {
52625 0 : rbfv1report *p = (rbfv1report*)_p;
52626 0 : ae_touch_ptr((void*)p);
52627 0 : }
52628 :
52629 :
52630 0 : void _rbfv1report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
52631 : {
52632 0 : rbfv1report *dst = (rbfv1report*)_dst;
52633 0 : rbfv1report *src = (rbfv1report*)_src;
52634 0 : dst->arows = src->arows;
52635 0 : dst->acols = src->acols;
52636 0 : dst->annz = src->annz;
52637 0 : dst->iterationscount = src->iterationscount;
52638 0 : dst->nmv = src->nmv;
52639 0 : dst->terminationtype = src->terminationtype;
52640 0 : }
52641 :
52642 :
52643 0 : void _rbfv1report_clear(void* _p)
52644 : {
52645 0 : rbfv1report *p = (rbfv1report*)_p;
52646 0 : ae_touch_ptr((void*)p);
52647 0 : }
52648 :
52649 :
52650 0 : void _rbfv1report_destroy(void* _p)
52651 : {
52652 0 : rbfv1report *p = (rbfv1report*)_p;
52653 0 : ae_touch_ptr((void*)p);
52654 0 : }
52655 :
52656 :
52657 : #endif
52658 : #if defined(AE_COMPILE_RBF) || !defined(AE_PARTIAL_BUILD)
52659 :
52660 :
52661 : /*************************************************************************
52662 : This function creates RBF model for a scalar (NY=1) or vector (NY>1)
52663 : function in a NX-dimensional space (NX>=1).
52664 :
52665 : Newly created model is empty. It can be used for interpolation right after
52666 : creation, but it just returns zeros. You have to add points to the model,
52667 : tune interpolation settings, and then call model construction function
52668 : rbfbuildmodel() which will update model according to your specification.
52669 :
52670 : USAGE:
52671 : 1. User creates model with rbfcreate()
52672 : 2. User adds dataset with rbfsetpoints() (points do NOT have to be on a
52673 : regular grid) or rbfsetpointsandscales().
52674 : 3. (OPTIONAL) User chooses polynomial term by calling:
52675 : * rbflinterm() to set linear term
52676 : * rbfconstterm() to set constant term
52677 : * rbfzeroterm() to set zero term
52678 : By default, linear term is used.
52679 : 4. User tweaks algorithm properties with rbfsetalgohierarchical() method
52680 : (or chooses one of the legacy algorithms - QNN (rbfsetalgoqnn) or ML
52681 : (rbfsetalgomultilayer)).
52682 : 5. User calls rbfbuildmodel() function which rebuilds model according to
52683 : the specification
52684 : 6. User may call rbfcalc() to calculate model value at the specified point,
52685 : rbfgridcalc() to calculate model values at the points of the regular
52686 : grid. User may extract model coefficients with rbfunpack() call.
52687 :
52688 : IMPORTANT: we recommend you to use latest model construction algorithm -
52689 : hierarchical RBFs, which is activated by rbfsetalgohierarchical()
52690 : function. This algorithm is the fastest one, and most memory-
52691 : efficient.
52692 : However, it is incompatible with older versions of ALGLIB
52693 : (pre-3.11). So, if you serialize hierarchical model, you will
52694 : be unable to load it in pre-3.11 ALGLIB. Other model types (QNN
52695 : and RBF-ML) are still backward-compatible.
52696 :
52697 : INPUT PARAMETERS:
52698 : NX - dimension of the space, NX>=1
52699 : NY - function dimension, NY>=1
52700 :
52701 : OUTPUT PARAMETERS:
52702 : S - RBF model (initially equals to zero)
52703 :
52704 : NOTE 1: memory requirements. RBF models require amount of memory which is
52705 : proportional to the number of data points. Some additional memory
52706 : is allocated during model construction, but most of this memory is
52707 : freed after model coefficients are calculated. Amount of this
52708 : additional memory depends on model construction algorithm being
52709 : used.
52710 :
52711 : NOTE 2: prior to ALGLIB version 3.11, RBF models supported only NX=2 or
52712 : NX=3. Any attempt to create single-dimensional or more than
52713 : 3-dimensional RBF model resulted in exception.
52714 :
52715 : ALGLIB 3.11 supports any NX>0, but models created with NX!=2 and
52716 : NX!=3 are incompatible with (a) older versions of ALGLIB, (b) old
52717 : model construction algorithms (QNN or RBF-ML).
52718 :
52719 : So, if you create a model with NX=2 or NX=3, then, depending on
52720 : specific model construction algorithm being chosen, you will (QNN
52721 : and RBF-ML) or will not (HierarchicalRBF) get backward compatibility
52722 : with older versions of ALGLIB. You have a choice here.
52723 :
52724 : However, if you create a model with NX neither 2 nor 3, you have
52725 : no backward compatibility from the start, and you are forced to
52726 : use hierarchical RBFs and ALGLIB 3.11 or later.
52727 :
52728 : -- ALGLIB --
52729 : Copyright 13.12.2011, 20.06.2016 by Bochkanov Sergey
52730 : *************************************************************************/
52731 0 : void rbfcreate(ae_int_t nx, ae_int_t ny, rbfmodel* s, ae_state *_state)
52732 : {
52733 :
52734 0 : _rbfmodel_clear(s);
52735 :
52736 0 : ae_assert(nx>=1, "RBFCreate: NX<1", _state);
52737 0 : ae_assert(ny>=1, "RBFCreate: NY<1", _state);
52738 0 : s->nx = nx;
52739 0 : s->ny = ny;
52740 0 : rbf_rbfpreparenonserializablefields(s, _state);
52741 :
52742 : /*
52743 : * Select default model version according to NX.
52744 : *
52745 : * The idea is that when we call this function with NX=2 or NX=3, backward
52746 : * compatible dummy (zero) V1 model is created, so serialization produces
52747 : * model which are compatible with pre-3.11 ALGLIB.
52748 : */
52749 0 : rbf_initializev1(nx, ny, &s->model1, _state);
52750 0 : rbf_initializev2(nx, ny, &s->model2, _state);
52751 0 : if( nx==2||nx==3 )
52752 : {
52753 0 : s->modelversion = 1;
52754 : }
52755 : else
52756 : {
52757 0 : s->modelversion = 2;
52758 : }
52759 :
52760 : /*
52761 : * Report fields
52762 : */
52763 0 : s->progress10000 = 0;
52764 0 : s->terminationrequest = ae_false;
52765 0 : }
52766 :
52767 :
52768 : /*************************************************************************
52769 : This function creates buffer structure which can be used to perform
52770 : parallel RBF model evaluations (with one RBF model instance being
52771 : used from multiple threads, as long as different threads use different
52772 : instances of buffer).
52773 :
52774 : This buffer object can be used with rbftscalcbuf() function (here "ts"
52775 : stands for "thread-safe", "buf" is a suffix which denotes function which
52776 : reuses previously allocated output space).
52777 :
52778 : How to use it:
52779 : * create RBF model structure with rbfcreate()
52780 : * load data, tune parameters
52781 : * call rbfbuildmodel()
52782 : * call rbfcreatecalcbuffer(), once per thread working with RBF model (you
52783 : should call this function only AFTER call to rbfbuildmodel(), see below
52784 : for more information)
52785 : * call rbftscalcbuf() from different threads, with each thread working
52786 : with its own copy of buffer object.
52787 :
52788 : INPUT PARAMETERS
52789 : S - RBF model
52790 :
52791 : OUTPUT PARAMETERS
52792 : Buf - external buffer.
52793 :
52794 :
52795 : IMPORTANT: buffer object should be used only with RBF model object which
52796 : was used to initialize buffer. Any attempt to use buffer with
52797 : different object is dangerous - you may get memory violation
52798 : error because sizes of internal arrays do not fit to dimensions
52799 : of RBF structure.
52800 :
52801 : IMPORTANT: you should call this function only for model which was built
52802 : with rbfbuildmodel() function, after successful invocation of
52803 : rbfbuildmodel(). Sizes of some internal structures are
52804 : determined only after model is built, so buffer object created
52805 : before model construction stage will be useless (and any
52806 : attempt to use it will result in exception).
52807 :
52808 : -- ALGLIB --
52809 : Copyright 02.04.2016 by Sergey Bochkanov
52810 : *************************************************************************/
52811 0 : void rbfcreatecalcbuffer(rbfmodel* s,
52812 : rbfcalcbuffer* buf,
52813 : ae_state *_state)
52814 : {
52815 :
52816 0 : _rbfcalcbuffer_clear(buf);
52817 :
52818 0 : if( s->modelversion==1 )
52819 : {
52820 0 : buf->modelversion = 1;
52821 0 : rbfv1createcalcbuffer(&s->model1, &buf->bufv1, _state);
52822 0 : return;
52823 : }
52824 0 : if( s->modelversion==2 )
52825 : {
52826 0 : buf->modelversion = 2;
52827 0 : rbfv2createcalcbuffer(&s->model2, &buf->bufv2, _state);
52828 0 : return;
52829 : }
52830 0 : ae_assert(ae_false, "RBFCreateCalcBuffer: integrity check failed", _state);
52831 : }
52832 :
52833 :
52834 : /*************************************************************************
52835 : This function adds dataset.
52836 :
52837 : This function overrides results of the previous calls, i.e. multiple calls
52838 : of this function will result in only the last set being added.
52839 :
52840 : IMPORTANT: ALGLIB version 3.11 and later allows you to specify a set of
52841 : per-dimension scales. Interpolation radii are multiplied by the
52842 : scale vector. It may be useful if you have mixed spatio-temporal
52843 : data (say, a set of 3D slices recorded at different times).
52844 : You should call rbfsetpointsandscales() function to use this
52845 : feature.
52846 :
52847 : INPUT PARAMETERS:
52848 : S - RBF model, initialized by rbfcreate() call.
52849 : XY - points, array[N,NX+NY]. One row corresponds to one point
52850 : in the dataset. First NX elements are coordinates, next
52851 : NY elements are function values. Array may be larger than
52852 : specified, in this case only leading [N,NX+NY] elements
52853 : will be used.
52854 : N - number of points in the dataset
52855 :
52856 : After you've added dataset and (optionally) tuned algorithm settings you
52857 : should call rbfbuildmodel() in order to build a model for you.
52858 :
52859 : NOTE: dataset added by this function is not saved during model serialization.
52860 : MODEL ITSELF is serialized, but data used to build it are not.
52861 :
52862 : So, if you 1) add dataset to empty RBF model, 2) serialize and
52863 : unserialize it, then you will get an empty RBF model with no dataset
52864 : being attached.
52865 :
52866 : From the other side, if you call rbfbuildmodel() between (1) and (2),
52867 : then after (2) you will get your fully constructed RBF model - but
52868 : again with no dataset attached, so subsequent calls to rbfbuildmodel()
52869 : will produce empty model.
52870 :
52871 :
52872 : -- ALGLIB --
52873 : Copyright 13.12.2011 by Bochkanov Sergey
52874 : *************************************************************************/
52875 0 : void rbfsetpoints(rbfmodel* s,
52876 : /* Real */ ae_matrix* xy,
52877 : ae_int_t n,
52878 : ae_state *_state)
52879 : {
52880 : ae_int_t i;
52881 : ae_int_t j;
52882 :
52883 :
52884 0 : ae_assert(n>0, "RBFSetPoints: N<0", _state);
52885 0 : ae_assert(xy->rows>=n, "RBFSetPoints: Rows(XY)<N", _state);
52886 0 : ae_assert(xy->cols>=s->nx+s->ny, "RBFSetPoints: Cols(XY)<NX+NY", _state);
52887 0 : ae_assert(apservisfinitematrix(xy, n, s->nx+s->ny, _state), "RBFSetPoints: XY contains infinite or NaN values!", _state);
52888 0 : s->n = n;
52889 0 : s->hasscale = ae_false;
52890 0 : ae_matrix_set_length(&s->x, s->n, s->nx, _state);
52891 0 : ae_matrix_set_length(&s->y, s->n, s->ny, _state);
52892 0 : for(i=0; i<=s->n-1; i++)
52893 : {
52894 0 : for(j=0; j<=s->nx-1; j++)
52895 : {
52896 0 : s->x.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j];
52897 : }
52898 0 : for(j=0; j<=s->ny-1; j++)
52899 : {
52900 0 : s->y.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j+s->nx];
52901 : }
52902 : }
52903 0 : }
52904 :
52905 :
52906 : /*************************************************************************
52907 : This function adds dataset and a vector of per-dimension scales.
52908 :
52909 : It may be useful if you have mixed spatio-temporal data - say, a set of 3D
52910 : slices recorded at different times. Such data typically require different
52911 : RBF radii for spatial and temporal dimensions. ALGLIB solves this problem
52912 : by specifying single RBF radius, which is (optionally) multiplied by the
52913 : scale vector.
52914 :
52915 : This function overrides results of the previous calls, i.e. multiple calls
52916 : of this function will result in only the last set being added.
52917 :
52918 : IMPORTANT: only HierarchicalRBF algorithm can work with scaled points. So,
52919 : using this function results in RBF models which can be used in
52920 : ALGLIB 3.11 or later. Previous versions of the library will be
52921 : unable to unserialize models produced by HierarchicalRBF algo.
52922 :
52923 : Any attempt to use this function with RBF-ML or QNN algorithms
52924 : will result in -3 error code being returned (incorrect
52925 : algorithm).
52926 :
52927 : INPUT PARAMETERS:
52928 : R - RBF model, initialized by rbfcreate() call.
52929 : XY - points, array[N,NX+NY]. One row corresponds to one point
52930 : in the dataset. First NX elements are coordinates, next
52931 : NY elements are function values. Array may be larger than
52932 : specified, in this case only leading [N,NX+NY] elements
52933 : will be used.
52934 : N - number of points in the dataset
52935 : S - array[NX], scale vector, S[i]>0.
52936 :
52937 : After you've added dataset and (optionally) tuned algorithm settings you
52938 : should call rbfbuildmodel() in order to build a model for you.
52939 :
52940 : NOTE: dataset added by this function is not saved during model serialization.
52941 : MODEL ITSELF is serialized, but data used to build it are not.
52942 :
52943 : So, if you 1) add dataset to empty RBF model, 2) serialize and
52944 : unserialize it, then you will get an empty RBF model with no dataset
52945 : being attached.
52946 :
52947 : From the other side, if you call rbfbuildmodel() between (1) and (2),
52948 : then after (2) you will get your fully constructed RBF model - but
52949 : again with no dataset attached, so subsequent calls to rbfbuildmodel()
52950 : will produce empty model.
52951 :
52952 :
52953 : -- ALGLIB --
52954 : Copyright 20.06.2016 by Bochkanov Sergey
52955 : *************************************************************************/
52956 0 : void rbfsetpointsandscales(rbfmodel* r,
52957 : /* Real */ ae_matrix* xy,
52958 : ae_int_t n,
52959 : /* Real */ ae_vector* s,
52960 : ae_state *_state)
52961 : {
52962 : ae_int_t i;
52963 : ae_int_t j;
52964 :
52965 :
52966 0 : ae_assert(n>0, "RBFSetPointsAndScales: N<0", _state);
52967 0 : ae_assert(xy->rows>=n, "RBFSetPointsAndScales: Rows(XY)<N", _state);
52968 0 : ae_assert(xy->cols>=r->nx+r->ny, "RBFSetPointsAndScales: Cols(XY)<NX+NY", _state);
52969 0 : ae_assert(s->cnt>=r->nx, "RBFSetPointsAndScales: Length(S)<NX", _state);
52970 0 : r->n = n;
52971 0 : r->hasscale = ae_true;
52972 0 : ae_matrix_set_length(&r->x, r->n, r->nx, _state);
52973 0 : ae_matrix_set_length(&r->y, r->n, r->ny, _state);
52974 0 : for(i=0; i<=r->n-1; i++)
52975 : {
52976 0 : for(j=0; j<=r->nx-1; j++)
52977 : {
52978 0 : r->x.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j];
52979 : }
52980 0 : for(j=0; j<=r->ny-1; j++)
52981 : {
52982 0 : r->y.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j+r->nx];
52983 : }
52984 : }
52985 0 : ae_vector_set_length(&r->s, r->nx, _state);
52986 0 : for(i=0; i<=r->nx-1; i++)
52987 : {
52988 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "RBFSetPointsAndScales: S[i] is not finite number", _state);
52989 0 : ae_assert(ae_fp_greater(s->ptr.p_double[i],(double)(0)), "RBFSetPointsAndScales: S[i]<=0", _state);
52990 0 : r->s.ptr.p_double[i] = s->ptr.p_double[i];
52991 : }
52992 0 : }
52993 :
52994 :
52995 : /*************************************************************************
52996 : DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction
52997 : algorithm, Hierarchical RBF. This algorithm is faster and
52998 : requires less memory than QNN and RBF-ML. It is especially good
52999 : for large-scale interpolation problems. So, we recommend you to
53000 : consider Hierarchical RBF as default option.
53001 :
53002 : ==========================================================================
53003 :
53004 : This function sets RBF interpolation algorithm. ALGLIB supports several
53005 : RBF algorithms with different properties.
53006 :
53007 : This algorithm is called RBF-QNN and it is good for point sets with
53008 : following properties:
53009 : a) all points are distinct
53010 : b) all points are well separated.
53011 : c) points distribution is approximately uniform. There is no "contour
53012 : lines", clusters of points, or other small-scale structures.
53013 :
53014 : Algorithm description:
53015 : 1) interpolation centers are allocated to data points
53016 : 2) interpolation radii are calculated as distances to the nearest centers
53017 : times Q coefficient (where Q is a value from [0.75,1.50]).
53018 : 3) after performing (2) radii are transformed in order to avoid situation
53019 : when single outlier has very large radius and influences many points
53020 : across all dataset. Transformation has following form:
53021 : new_r[i] = min(r[i],Z*median(r[]))
53022 : where r[i] is I-th radius, median() is a median radius across entire
53023 : dataset, Z is user-specified value which controls amount of deviation
53024 : from median radius.
53025 :
53026 : When (a) is violated, we will be unable to build RBF model. When (b) or
53027 : (c) are violated, model will be built, but interpolation quality will be
53028 : low. See http://www.alglib.net/interpolation/ for more information on this
53029 : subject.
53030 :
53031 : This algorithm is used by default.
53032 :
53033 : Additional Q parameter controls smoothness properties of the RBF basis:
53034 : * Q<0.75 will give perfectly conditioned basis, but terrible smoothness
53035 : properties (RBF interpolant will have sharp peaks around function values)
53036 : * Q around 1.0 gives good balance between smoothness and condition number
53037 : * Q>1.5 will lead to badly conditioned systems and slow convergence of the
53038 : underlying linear solver (although smoothness will be very good)
53039 : * Q>2.0 will effectively make optimizer useless because it won't converge
53040 : within reasonable amount of iterations. It is possible to set such large
53041 : Q, but it is advised not to do so.
53042 :
53043 : INPUT PARAMETERS:
53044 : S - RBF model, initialized by RBFCreate() call
53045 : Q - Q parameter, Q>0, recommended value - 1.0
53046 : Z - Z parameter, Z>0, recommended value - 5.0
53047 :
53048 : NOTE: this function has some serialization-related subtleties. We
53049 : recommend you to study serialization examples from ALGLIB Reference
53050 : Manual if you want to perform serialization of your models.
53051 :
53052 :
53053 : -- ALGLIB --
53054 : Copyright 13.12.2011 by Bochkanov Sergey
53055 : *************************************************************************/
53056 0 : void rbfsetalgoqnn(rbfmodel* s, double q, double z, ae_state *_state)
53057 : {
53058 :
53059 :
53060 0 : ae_assert(ae_isfinite(q, _state), "RBFSetAlgoQNN: Q is infinite or NAN", _state);
53061 0 : ae_assert(ae_fp_greater(q,(double)(0)), "RBFSetAlgoQNN: Q<=0", _state);
53062 0 : ae_assert(ae_isfinite(z, _state), "RBFSetAlgoQNN: Z is infinite or NAN", _state);
53063 0 : ae_assert(ae_fp_greater(z,(double)(0)), "RBFSetAlgoQNN: Z<=0", _state);
53064 0 : s->radvalue = q;
53065 0 : s->radzvalue = z;
53066 0 : s->algorithmtype = 1;
53067 0 : }
53068 :
53069 :
53070 : /*************************************************************************
53071 : DEPRECATED:since version 3.11 ALGLIB includes new RBF model construction
53072 : algorithm, Hierarchical RBF. This algorithm is faster and
53073 : requires less memory than QNN and RBF-ML. It is especially good
53074 : for large-scale interpolation problems. So, we recommend you to
53075 : consider Hierarchical RBF as default option.
53076 :
53077 : ==========================================================================
53078 :
53079 : This function sets RBF interpolation algorithm. ALGLIB supports several
53080 : RBF algorithms with different properties.
53081 :
53082 : This algorithm is called RBF-ML. It builds multilayer RBF model, i.e.
53083 : model with subsequently decreasing radii, which allows us to combine
53084 : smoothness (due to large radii of the first layers) with exactness (due
53085 : to small radii of the last layers) and fast convergence.
53086 :
53087 : Internally RBF-ML uses many different means of acceleration, from sparse
53088 : matrices to KD-trees, which results in algorithm whose working time is
53089 : roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a
53090 : number of points, Density is an average density if points per unit of the
53091 : interpolation space, RBase is an initial radius, NLayers is a number of
53092 : layers.
53093 :
53094 : RBF-ML is good for following kinds of interpolation problems:
53095 : 1. "exact" problems (perfect fit) with well separated points
53096 : 2. least squares problems with arbitrary distribution of points (algorithm
53097 : gives perfect fit where it is possible, and resorts to least squares
53098 : fit in the hard areas).
53099 : 3. noisy problems where we want to apply some controlled amount of
53100 : smoothing.
53101 :
53102 : INPUT PARAMETERS:
53103 : S - RBF model, initialized by RBFCreate() call
53104 : RBase - RBase parameter, RBase>0
53105 : NLayers - NLayers parameter, NLayers>0, recommended value to start
53106 : with - about 5.
53107 : LambdaV - regularization value, can be useful when solving problem
53108 : in the least squares sense. Optimal lambda is problem-
53109 : dependent and require trial and error. In our experience,
53110 : good lambda can be as large as 0.1, and you can use 0.001
53111 : as initial guess.
53112 : Default value - 0.01, which is used when LambdaV is not
53113 : given. You can specify zero value, but it is not
53114 : recommended to do so.
53115 :
53116 : TUNING ALGORITHM
53117 :
53118 : In order to use this algorithm you have to choose three parameters:
53119 : * initial radius RBase
53120 : * number of layers in the model NLayers
53121 : * regularization coefficient LambdaV
53122 :
53123 : Initial radius is easy to choose - you can pick any number several times
53124 : larger than the average distance between points. Algorithm won't break
53125 : down if you choose radius which is too large (model construction time will
53126 : increase, but model will be built correctly).
53127 :
53128 : Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
53129 : by the last layer) will be smaller than the typical distance between
53130 : points. In case model error is too large, you can increase number of
53131 : layers. Having more layers will make model construction and evaluation
53132 : proportionally slower, but it will allow you to have model which precisely
53133 : fits your data. From the other side, if you want to suppress noise, you
53134 : can DECREASE number of layers to make your model less flexible.
53135 :
53136 : Regularization coefficient LambdaV controls smoothness of the individual
53137 : models built for each layer. We recommend you to use default value in case
53138 : you don't want to tune this parameter, because having non-zero LambdaV
53139 : accelerates and stabilizes internal iterative algorithm. In case you want
53140 : to suppress noise you can use LambdaV as additional parameter (larger
53141 : value = more smoothness) to tune.
53142 :
53143 : TYPICAL ERRORS
53144 :
53145 : 1. Using initial radius which is too large. Memory requirements of the
53146 : RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is
53147 : an average density of points per unit of the interpolation space). In
53148 : the extreme case of the very large RBase we will need O(N^2) units of
53149 : memory - and many layers in order to decrease radius to some reasonably
53150 : small value.
53151 :
53152 : 2. Using too small number of layers - RBF models with large radius are not
53153 : flexible enough to reproduce small variations in the target function.
53154 : You need many layers with different radii, from large to small, in
53155 : order to have good model.
53156 :
53157 : 3. Using initial radius which is too small. You will get model with
53158 : "holes" in the areas which are too far away from interpolation centers.
53159 : However, algorithm will work correctly (and quickly) in this case.
53160 :
53161 : 4. Using too many layers - you will get too large and too slow model. This
53162 : model will perfectly reproduce your function, but maybe you will be
53163 : able to achieve similar results with less layers (and less memory).
53164 :
53165 : -- ALGLIB --
53166 : Copyright 02.03.2012 by Bochkanov Sergey
53167 : *************************************************************************/
53168 0 : void rbfsetalgomultilayer(rbfmodel* s,
53169 : double rbase,
53170 : ae_int_t nlayers,
53171 : double lambdav,
53172 : ae_state *_state)
53173 : {
53174 :
53175 :
53176 0 : ae_assert(ae_isfinite(rbase, _state), "RBFSetAlgoMultiLayer: RBase is infinite or NaN", _state);
53177 0 : ae_assert(ae_fp_greater(rbase,(double)(0)), "RBFSetAlgoMultiLayer: RBase<=0", _state);
53178 0 : ae_assert(nlayers>=0, "RBFSetAlgoMultiLayer: NLayers<0", _state);
53179 0 : ae_assert(ae_isfinite(lambdav, _state), "RBFSetAlgoMultiLayer: LambdaV is infinite or NAN", _state);
53180 0 : ae_assert(ae_fp_greater_eq(lambdav,(double)(0)), "RBFSetAlgoMultiLayer: LambdaV<0", _state);
53181 0 : s->radvalue = rbase;
53182 0 : s->nlayers = nlayers;
53183 0 : s->algorithmtype = 2;
53184 0 : s->lambdav = lambdav;
53185 0 : }
53186 :
53187 :
53188 : /*************************************************************************
53189 : This function sets RBF interpolation algorithm. ALGLIB supports several
53190 : RBF algorithms with different properties.
53191 :
53192 : This algorithm is called Hierarchical RBF. It similar to its previous
53193 : incarnation, RBF-ML, i.e. it also builds a sequence of models with
53194 : decreasing radii. However, it uses more economical way of building upper
53195 : layers (ones with large radii), which results in faster model construction
53196 : and evaluation, as well as smaller memory footprint during construction.
53197 :
53198 : This algorithm has following important features:
53199 : * ability to handle millions of points
53200 : * controllable smoothing via nonlinearity penalization
53201 : * support for NX-dimensional models with NX=1 or NX>3 (unlike QNN or RBF-ML)
53202 : * support for specification of per-dimensional radii via scale vector,
53203 : which is set by means of rbfsetpointsandscales() function. This feature
53204 : is useful if you solve spatio-temporal interpolation problems, where
53205 : different radii are required for spatial and temporal dimensions.
53206 :
53207 : Running times are roughly proportional to:
53208 : * N*log(N)*NLayers - for model construction
53209 : * N*NLayers - for model evaluation
53210 : You may see that running time does not depend on search radius or points
53211 : density, just on number of layers in the hierarchy.
53212 :
53213 : IMPORTANT: this model construction algorithm was introduced in ALGLIB 3.11
53214 : and produces models which are INCOMPATIBLE with previous
53215 : versions of ALGLIB. You can not unserialize models produced
53216 : with this function in ALGLIB 3.10 or earlier.
53217 :
53218 : INPUT PARAMETERS:
53219 : S - RBF model, initialized by rbfcreate() call
53220 : RBase - RBase parameter, RBase>0
53221 : NLayers - NLayers parameter, NLayers>0, recommended value to start
53222 : with - about 5.
53223 : LambdaNS- >=0, nonlinearity penalty coefficient, negative values are
53224 : not allowed. This parameter adds controllable smoothing to
53225 : the problem, which may reduce noise. Specification of non-
53226 : zero lambda means that in addition to fitting error solver
53227 : will also minimize LambdaNS*|S''(x)|^2 (appropriately
53228 : generalized to multiple dimensions.
53229 :
53230 : Specification of exactly zero value means that no penalty
53231 : is added (we do not even evaluate matrix of second
53232 : derivatives which is necessary for smoothing).
53233 :
53234 : Calculation of nonlinearity penalty is costly - it results
53235 : in several-fold increase of model construction time.
53236 : Evaluation time remains the same.
53237 :
53238 : Optimal lambda is problem-dependent and requires trial
53239 : and error. Good value to start from is 1e-5...1e-6,
53240 : which corresponds to slightly noticeable smoothing of the
53241 : function. Value 1e-2 usually means that quite heavy
53242 : smoothing is applied.
53243 :
53244 : TUNING ALGORITHM
53245 :
53246 : In order to use this algorithm you have to choose three parameters:
53247 : * initial radius RBase
53248 : * number of layers in the model NLayers
53249 : * penalty coefficient LambdaNS
53250 :
53251 : Initial radius is easy to choose - you can pick any number several times
53252 : larger than the average distance between points. Algorithm won't break
53253 : down if you choose radius which is too large (model construction time will
53254 : increase, but model will be built correctly).
53255 :
53256 : Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
53257 : by the last layer) will be smaller than the typical distance between
53258 : points. In case model error is too large, you can increase number of
53259 : layers. Having more layers will make model construction and evaluation
53260 : proportionally slower, but it will allow you to have model which precisely
53261 : fits your data. From the other side, if you want to suppress noise, you
53262 : can DECREASE number of layers to make your model less flexible (or specify
53263 : non-zero LambdaNS).
53264 :
53265 : TYPICAL ERRORS
53266 :
53267 : 1. Using too small number of layers - RBF models with large radius are not
53268 : flexible enough to reproduce small variations in the target function.
53269 : You need many layers with different radii, from large to small, in
53270 : order to have good model.
53271 :
53272 : 2. Using initial radius which is too small. You will get model with
53273 : "holes" in the areas which are too far away from interpolation centers.
53274 : However, algorithm will work correctly (and quickly) in this case.
53275 :
53276 : -- ALGLIB --
53277 : Copyright 20.06.2016 by Bochkanov Sergey
53278 : *************************************************************************/
53279 0 : void rbfsetalgohierarchical(rbfmodel* s,
53280 : double rbase,
53281 : ae_int_t nlayers,
53282 : double lambdans,
53283 : ae_state *_state)
53284 : {
53285 :
53286 :
53287 0 : ae_assert(ae_isfinite(rbase, _state), "RBFSetAlgoHierarchical: RBase is infinite or NaN", _state);
53288 0 : ae_assert(ae_fp_greater(rbase,(double)(0)), "RBFSetAlgoHierarchical: RBase<=0", _state);
53289 0 : ae_assert(nlayers>=0, "RBFSetAlgoHierarchical: NLayers<0", _state);
53290 0 : ae_assert(ae_isfinite(lambdans, _state)&&ae_fp_greater_eq(lambdans,(double)(0)), "RBFSetAlgoHierarchical: LambdaNS<0 or infinite", _state);
53291 0 : s->radvalue = rbase;
53292 0 : s->nlayers = nlayers;
53293 0 : s->algorithmtype = 3;
53294 0 : s->lambdav = lambdans;
53295 0 : }
53296 :
53297 :
53298 : /*************************************************************************
53299 : This function sets linear term (model is a sum of radial basis functions
53300 : plus linear polynomial). This function won't have effect until next call
53301 : to RBFBuildModel().
53302 :
53303 : INPUT PARAMETERS:
53304 : S - RBF model, initialized by RBFCreate() call
53305 :
53306 : NOTE: this function has some serialization-related subtleties. We
53307 : recommend you to study serialization examples from ALGLIB Reference
53308 : Manual if you want to perform serialization of your models.
53309 :
53310 : -- ALGLIB --
53311 : Copyright 13.12.2011 by Bochkanov Sergey
53312 : *************************************************************************/
53313 0 : void rbfsetlinterm(rbfmodel* s, ae_state *_state)
53314 : {
53315 :
53316 :
53317 0 : s->aterm = 1;
53318 0 : }
53319 :
53320 :
53321 : /*************************************************************************
53322 : This function sets constant term (model is a sum of radial basis functions
53323 : plus constant). This function won't have effect until next call to
53324 : RBFBuildModel().
53325 :
53326 : INPUT PARAMETERS:
53327 : S - RBF model, initialized by RBFCreate() call
53328 :
53329 : NOTE: this function has some serialization-related subtleties. We
53330 : recommend you to study serialization examples from ALGLIB Reference
53331 : Manual if you want to perform serialization of your models.
53332 :
53333 : -- ALGLIB --
53334 : Copyright 13.12.2011 by Bochkanov Sergey
53335 : *************************************************************************/
53336 0 : void rbfsetconstterm(rbfmodel* s, ae_state *_state)
53337 : {
53338 :
53339 :
53340 0 : s->aterm = 2;
53341 0 : }
53342 :
53343 :
53344 : /*************************************************************************
53345 : This function sets zero term (model is a sum of radial basis functions
53346 : without polynomial term). This function won't have effect until next call
53347 : to RBFBuildModel().
53348 :
53349 : INPUT PARAMETERS:
53350 : S - RBF model, initialized by RBFCreate() call
53351 :
53352 : NOTE: this function has some serialization-related subtleties. We
53353 : recommend you to study serialization examples from ALGLIB Reference
53354 : Manual if you want to perform serialization of your models.
53355 :
53356 : -- ALGLIB --
53357 : Copyright 13.12.2011 by Bochkanov Sergey
53358 : *************************************************************************/
53359 0 : void rbfsetzeroterm(rbfmodel* s, ae_state *_state)
53360 : {
53361 :
53362 :
53363 0 : s->aterm = 3;
53364 0 : }
53365 :
53366 :
53367 : /*************************************************************************
53368 : This function sets basis function type, which can be:
53369 : * 0 for classic Gaussian
53370 : * 1 for fast and compact bell-like basis function, which becomes exactly
53371 : zero at distance equal to 3*R (default option).
53372 :
53373 : INPUT PARAMETERS:
53374 : S - RBF model, initialized by RBFCreate() call
53375 : BF - basis function type:
53376 : * 0 - classic Gaussian
53377 : * 1 - fast and compact one
53378 :
53379 : -- ALGLIB --
53380 : Copyright 01.02.2017 by Bochkanov Sergey
53381 : *************************************************************************/
53382 0 : void rbfsetv2bf(rbfmodel* s, ae_int_t bf, ae_state *_state)
53383 : {
53384 :
53385 :
53386 0 : ae_assert(bf==0||bf==1, "RBFSetV2Its: BF<>0 and BF<>1", _state);
53387 0 : s->model2.basisfunction = bf;
53388 0 : }
53389 :
53390 :
53391 : /*************************************************************************
53392 : This function sets stopping criteria of the underlying linear solver for
53393 : hierarchical (version 2) RBF constructor.
53394 :
53395 : INPUT PARAMETERS:
53396 : S - RBF model, initialized by RBFCreate() call
53397 : MaxIts - this criterion will stop algorithm after MaxIts iterations.
53398 : Typically a few hundreds iterations is required, with 400
53399 : being a good default value to start experimentation.
53400 : Zero value means that default value will be selected.
53401 :
53402 : -- ALGLIB --
53403 : Copyright 01.02.2017 by Bochkanov Sergey
53404 : *************************************************************************/
53405 0 : void rbfsetv2its(rbfmodel* s, ae_int_t maxits, ae_state *_state)
53406 : {
53407 :
53408 :
53409 0 : ae_assert(maxits>=0, "RBFSetV2Its: MaxIts is negative", _state);
53410 0 : s->model2.maxits = maxits;
53411 0 : }
53412 :
53413 :
53414 : /*************************************************************************
53415 : This function sets support radius parameter of hierarchical (version 2)
53416 : RBF constructor.
53417 :
53418 : Hierarchical RBF model achieves great speed-up by removing from the model
53419 : excessive (too dense) nodes. Say, if you have RBF radius equal to 1 meter,
53420 : and two nodes are just 1 millimeter apart, you may remove one of them
53421 : without reducing model quality.
53422 :
53423 : Support radius parameter is used to justify which points need removal, and
53424 : which do not. If two points are less than SUPPORT_R*CUR_RADIUS units of
53425 : distance apart, one of them is removed from the model. The larger support
53426 : radius is, the faster model construction AND evaluation are. However,
53427 : too large values result in "bumpy" models.
53428 :
53429 : INPUT PARAMETERS:
53430 : S - RBF model, initialized by RBFCreate() call
53431 : R - support radius coefficient, >=0.
53432 : Recommended values are [0.1,0.4] range, with 0.1 being
53433 : default value.
53434 :
53435 : -- ALGLIB --
53436 : Copyright 01.02.2017 by Bochkanov Sergey
53437 : *************************************************************************/
53438 0 : void rbfsetv2supportr(rbfmodel* s, double r, ae_state *_state)
53439 : {
53440 :
53441 :
53442 0 : ae_assert(ae_isfinite(r, _state), "RBFSetV2SupportR: R is not finite", _state);
53443 0 : ae_assert(ae_fp_greater_eq(r,(double)(0)), "RBFSetV2SupportR: R<0", _state);
53444 0 : s->model2.supportr = r;
53445 0 : }
53446 :
53447 :
53448 : /*************************************************************************
53449 : This function sets stopping criteria of the underlying linear solver.
53450 :
53451 : INPUT PARAMETERS:
53452 : S - RBF model, initialized by RBFCreate() call
53453 : EpsOrt - orthogonality stopping criterion, EpsOrt>=0. Algorithm will
53454 : stop when ||A'*r||<=EpsOrt where A' is a transpose of the
53455 : system matrix, r is a residual vector.
53456 : Recommended value of EpsOrt is equal to 1E-6.
53457 : This criterion will stop algorithm when we have "bad fit"
53458 : situation, i.e. when we should stop in a point with large,
53459 : nonzero residual.
53460 : EpsErr - residual stopping criterion. Algorithm will stop when
53461 : ||r||<=EpsErr*||b||, where r is a residual vector, b is a
53462 : right part of the system (function values).
53463 : Recommended value of EpsErr is equal to 1E-3 or 1E-6.
53464 : This criterion will stop algorithm in a "good fit"
53465 : situation when we have near-zero residual near the desired
53466 : solution.
53467 : MaxIts - this criterion will stop algorithm after MaxIts iterations.
53468 : It should be used for debugging purposes only!
53469 : Zero MaxIts means that no limit is placed on the number of
53470 : iterations.
53471 :
53472 : We recommend to set moderate non-zero values EpsOrt and EpsErr
53473 : simultaneously. Values equal to 10E-6 are good to start with. In case you
53474 : need high performance and do not need high precision , you may decrease
53475 : EpsErr down to 0.001. However, we do not recommend decreasing EpsOrt.
53476 :
53477 : As for MaxIts, we recommend to leave it zero unless you know what you do.
53478 :
53479 : NOTE: this function has some serialization-related subtleties. We
53480 : recommend you to study serialization examples from ALGLIB Reference
53481 : Manual if you want to perform serialization of your models.
53482 :
53483 : -- ALGLIB --
53484 : Copyright 13.12.2011 by Bochkanov Sergey
53485 : *************************************************************************/
53486 0 : void rbfsetcond(rbfmodel* s,
53487 : double epsort,
53488 : double epserr,
53489 : ae_int_t maxits,
53490 : ae_state *_state)
53491 : {
53492 :
53493 :
53494 0 : ae_assert(ae_isfinite(epsort, _state)&&ae_fp_greater_eq(epsort,(double)(0)), "RBFSetCond: EpsOrt is negative, INF or NAN", _state);
53495 0 : ae_assert(ae_isfinite(epserr, _state)&&ae_fp_greater_eq(epserr,(double)(0)), "RBFSetCond: EpsB is negative, INF or NAN", _state);
53496 0 : ae_assert(maxits>=0, "RBFSetCond: MaxIts is negative", _state);
53497 0 : if( (ae_fp_eq(epsort,(double)(0))&&ae_fp_eq(epserr,(double)(0)))&&maxits==0 )
53498 : {
53499 0 : s->epsort = rbf_eps;
53500 0 : s->epserr = rbf_eps;
53501 0 : s->maxits = 0;
53502 : }
53503 : else
53504 : {
53505 0 : s->epsort = epsort;
53506 0 : s->epserr = epserr;
53507 0 : s->maxits = maxits;
53508 : }
53509 0 : }
53510 :
53511 :
53512 : /*************************************************************************
53513 : This function builds RBF model and returns report (contains some
53514 : information which can be used for evaluation of the algorithm properties).
53515 :
53516 : Call to this function modifies RBF model by calculating its centers/radii/
53517 : weights and saving them into RBFModel structure. Initially RBFModel
53518 : contain zero coefficients, but after call to this function we will have
53519 : coefficients which were calculated in order to fit our dataset.
53520 :
53521 : After you called this function you can call RBFCalc(), RBFGridCalc() and
53522 : other model calculation functions.
53523 :
53524 : INPUT PARAMETERS:
53525 : S - RBF model, initialized by RBFCreate() call
53526 : Rep - report:
53527 : * Rep.TerminationType:
53528 : * -5 - non-distinct basis function centers were detected,
53529 : interpolation aborted; only QNN returns this
53530 : error code, other algorithms can handle non-
53531 : distinct nodes.
53532 : * -4 - nonconvergence of the internal SVD solver
53533 : * -3 incorrect model construction algorithm was chosen:
53534 : QNN or RBF-ML, combined with one of the incompatible
53535 : features - NX=1 or NX>3; points with per-dimension
53536 : scales.
53537 : * 1 - successful termination
53538 : * 8 - a termination request was submitted via
53539 : rbfrequesttermination() function.
53540 :
53541 : Fields which are set only by modern RBF solvers (hierarchical
53542 : or nonnegative; older solvers like QNN and ML initialize these
53543 : fields by NANs):
53544 : * rep.rmserror - root-mean-square error at nodes
53545 : * rep.maxerror - maximum error at nodes
53546 :
53547 : Fields are used for debugging purposes:
53548 : * Rep.IterationsCount - iterations count of the LSQR solver
53549 : * Rep.NMV - number of matrix-vector products
53550 : * Rep.ARows - rows count for the system matrix
53551 : * Rep.ACols - columns count for the system matrix
53552 : * Rep.ANNZ - number of significantly non-zero elements
53553 : (elements above some algorithm-determined threshold)
53554 :
53555 : NOTE: failure to build model will leave current state of the structure
53556 : unchanged.
53557 :
53558 : -- ALGLIB --
53559 : Copyright 13.12.2011 by Bochkanov Sergey
53560 : *************************************************************************/
53561 0 : void rbfbuildmodel(rbfmodel* s, rbfreport* rep, ae_state *_state)
53562 : {
53563 : ae_frame _frame_block;
53564 : rbfv1report rep1;
53565 : rbfv2report rep2;
53566 : ae_matrix x3;
53567 : ae_vector scalevec;
53568 : ae_int_t i;
53569 : ae_int_t curalgorithmtype;
53570 :
53571 0 : ae_frame_make(_state, &_frame_block);
53572 0 : memset(&rep1, 0, sizeof(rep1));
53573 0 : memset(&rep2, 0, sizeof(rep2));
53574 0 : memset(&x3, 0, sizeof(x3));
53575 0 : memset(&scalevec, 0, sizeof(scalevec));
53576 0 : _rbfreport_clear(rep);
53577 0 : _rbfv1report_init(&rep1, _state, ae_true);
53578 0 : _rbfv2report_init(&rep2, _state, ae_true);
53579 0 : ae_matrix_init(&x3, 0, 0, DT_REAL, _state, ae_true);
53580 0 : ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true);
53581 :
53582 :
53583 : /*
53584 : * Clean fields prior to processing
53585 : */
53586 0 : rbf_clearreportfields(rep, _state);
53587 0 : s->progress10000 = 0;
53588 0 : s->terminationrequest = ae_false;
53589 :
53590 : /*
53591 : * Autoselect algorithm
53592 : */
53593 0 : if( s->algorithmtype==0 )
53594 : {
53595 0 : if( (s->nx<2||s->nx>3)||s->hasscale )
53596 : {
53597 0 : curalgorithmtype = 3;
53598 : }
53599 : else
53600 : {
53601 0 : curalgorithmtype = 1;
53602 : }
53603 : }
53604 : else
53605 : {
53606 0 : curalgorithmtype = s->algorithmtype;
53607 : }
53608 :
53609 : /*
53610 : * Algorithms which generate V1 models
53611 : */
53612 0 : if( curalgorithmtype==1||curalgorithmtype==2 )
53613 : {
53614 :
53615 : /*
53616 : * Perform compatibility checks
53617 : */
53618 0 : if( (s->nx<2||s->nx>3)||s->hasscale )
53619 : {
53620 0 : rep->terminationtype = -3;
53621 0 : ae_frame_leave(_state);
53622 0 : return;
53623 : }
53624 :
53625 : /*
53626 : * Try to build model.
53627 : *
53628 : * NOTE: due to historical reasons RBFV1BuildModel() accepts points
53629 : * cast to 3-dimensional space, even if they are really 2-dimensional.
53630 : * So, for 2D data we have to explicitly convert them to 3D.
53631 : */
53632 0 : if( s->nx==2 )
53633 : {
53634 :
53635 : /*
53636 : * Convert data to 3D
53637 : */
53638 0 : rmatrixsetlengthatleast(&x3, s->n, 3, _state);
53639 0 : for(i=0; i<=s->n-1; i++)
53640 : {
53641 0 : x3.ptr.pp_double[i][0] = s->x.ptr.pp_double[i][0];
53642 0 : x3.ptr.pp_double[i][1] = s->x.ptr.pp_double[i][1];
53643 0 : x3.ptr.pp_double[i][2] = (double)(0);
53644 : }
53645 0 : rbfv1buildmodel(&x3, &s->y, s->n, s->aterm, curalgorithmtype, s->nlayers, s->radvalue, s->radzvalue, s->lambdav, s->epsort, s->epserr, s->maxits, &s->model1, &rep1, _state);
53646 : }
53647 : else
53648 : {
53649 :
53650 : /*
53651 : * Work with raw data
53652 : */
53653 0 : rbfv1buildmodel(&s->x, &s->y, s->n, s->aterm, curalgorithmtype, s->nlayers, s->radvalue, s->radzvalue, s->lambdav, s->epsort, s->epserr, s->maxits, &s->model1, &rep1, _state);
53654 : }
53655 0 : s->modelversion = 1;
53656 :
53657 : /*
53658 : * Convert report fields
53659 : */
53660 0 : rep->arows = rep1.arows;
53661 0 : rep->acols = rep1.acols;
53662 0 : rep->annz = rep1.annz;
53663 0 : rep->iterationscount = rep1.iterationscount;
53664 0 : rep->nmv = rep1.nmv;
53665 0 : rep->terminationtype = rep1.terminationtype;
53666 :
53667 : /*
53668 : * Done
53669 : */
53670 0 : ae_frame_leave(_state);
53671 0 : return;
53672 : }
53673 :
53674 : /*
53675 : * Algorithms which generate V2 models
53676 : */
53677 0 : if( curalgorithmtype==3 )
53678 : {
53679 :
53680 : /*
53681 : * Prepare scale vector - use unit values or user supplied ones
53682 : */
53683 0 : ae_vector_set_length(&scalevec, s->nx, _state);
53684 0 : for(i=0; i<=s->nx-1; i++)
53685 : {
53686 0 : if( s->hasscale )
53687 : {
53688 0 : scalevec.ptr.p_double[i] = s->s.ptr.p_double[i];
53689 : }
53690 : else
53691 : {
53692 0 : scalevec.ptr.p_double[i] = (double)(1);
53693 : }
53694 : }
53695 :
53696 : /*
53697 : * Build model
53698 : */
53699 0 : rbfv2buildhierarchical(&s->x, &s->y, s->n, &scalevec, s->aterm, s->nlayers, s->radvalue, s->lambdav, &s->model2, &s->progress10000, &s->terminationrequest, &rep2, _state);
53700 0 : s->modelversion = 2;
53701 :
53702 : /*
53703 : * Convert report fields
53704 : */
53705 0 : rep->terminationtype = rep2.terminationtype;
53706 0 : rep->rmserror = rep2.rmserror;
53707 0 : rep->maxerror = rep2.maxerror;
53708 :
53709 : /*
53710 : * Done
53711 : */
53712 0 : ae_frame_leave(_state);
53713 0 : return;
53714 : }
53715 :
53716 : /*
53717 : * Critical error
53718 : */
53719 0 : ae_assert(ae_false, "RBFBuildModel: integrity check failure", _state);
53720 0 : ae_frame_leave(_state);
53721 : }
53722 :
53723 :
53724 : /*************************************************************************
53725 : This function calculates values of the RBF model in the given point.
53726 :
53727 : IMPORTANT: this function works only with modern (hierarchical) RBFs. It
53728 : can not be used with legacy (version 1) RBFs because older RBF
53729 : code does not support 1-dimensional models.
53730 :
53731 : This function should be used when we have NY=1 (scalar function) and NX=1
53732 : (1-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If
53733 : you have 2-dimensional space, use rbfcalc3(). If you have general
53734 : situation (NX-dimensional space, NY-dimensional function) you should use
53735 : generic rbfcalc().
53736 :
53737 : If you want to perform parallel model evaluation from multiple threads,
53738 : use rbftscalcbuf() with per-thread buffer object.
53739 :
53740 : This function returns 0.0 when:
53741 : * model is not initialized
53742 : * NX<>1
53743 : * NY<>1
53744 :
53745 : INPUT PARAMETERS:
53746 : S - RBF model
53747 : X0 - X-coordinate, finite number
53748 :
53749 : RESULT:
53750 : value of the model or 0.0 (as defined above)
53751 :
53752 : -- ALGLIB --
53753 : Copyright 13.12.2011 by Bochkanov Sergey
53754 : *************************************************************************/
53755 0 : double rbfcalc1(rbfmodel* s, double x0, ae_state *_state)
53756 : {
53757 : double result;
53758 :
53759 :
53760 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc1: invalid value for X0 (X0 is Inf)!", _state);
53761 0 : result = (double)(0);
53762 0 : if( s->ny!=1||s->nx!=1 )
53763 : {
53764 0 : return result;
53765 : }
53766 0 : if( s->modelversion==1 )
53767 : {
53768 0 : result = (double)(0);
53769 0 : return result;
53770 : }
53771 0 : if( s->modelversion==2 )
53772 : {
53773 0 : result = rbfv2calc1(&s->model2, x0, _state);
53774 0 : return result;
53775 : }
53776 0 : ae_assert(ae_false, "RBFCalc1: integrity check failed", _state);
53777 0 : return result;
53778 : }
53779 :
53780 :
53781 : /*************************************************************************
53782 : This function calculates values of the RBF model in the given point.
53783 :
53784 : This function should be used when we have NY=1 (scalar function) and NX=2
53785 : (2-dimensional space). If you have 3-dimensional space, use rbfcalc3(). If
53786 : you have general situation (NX-dimensional space, NY-dimensional function)
53787 : you should use generic rbfcalc().
53788 :
53789 : If you want to calculate function values many times, consider using
53790 : rbfgridcalc2v(), which is far more efficient than many subsequent calls to
53791 : rbfcalc2().
53792 :
53793 : If you want to perform parallel model evaluation from multiple threads,
53794 : use rbftscalcbuf() with per-thread buffer object.
53795 :
53796 : This function returns 0.0 when:
53797 : * model is not initialized
53798 : * NX<>2
53799 : *NY<>1
53800 :
53801 : INPUT PARAMETERS:
53802 : S - RBF model
53803 : X0 - first coordinate, finite number
53804 : X1 - second coordinate, finite number
53805 :
53806 : RESULT:
53807 : value of the model or 0.0 (as defined above)
53808 :
53809 : -- ALGLIB --
53810 : Copyright 13.12.2011 by Bochkanov Sergey
53811 : *************************************************************************/
53812 0 : double rbfcalc2(rbfmodel* s, double x0, double x1, ae_state *_state)
53813 : {
53814 : double result;
53815 :
53816 :
53817 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc2: invalid value for X0 (X0 is Inf)!", _state);
53818 0 : ae_assert(ae_isfinite(x1, _state), "RBFCalc2: invalid value for X1 (X1 is Inf)!", _state);
53819 0 : result = (double)(0);
53820 0 : if( s->ny!=1||s->nx!=2 )
53821 : {
53822 0 : return result;
53823 : }
53824 0 : if( s->modelversion==1 )
53825 : {
53826 0 : result = rbfv1calc2(&s->model1, x0, x1, _state);
53827 0 : return result;
53828 : }
53829 0 : if( s->modelversion==2 )
53830 : {
53831 0 : result = rbfv2calc2(&s->model2, x0, x1, _state);
53832 0 : return result;
53833 : }
53834 0 : ae_assert(ae_false, "RBFCalc2: integrity check failed", _state);
53835 0 : return result;
53836 : }
53837 :
53838 :
53839 : /*************************************************************************
53840 : This function calculates value of the RBF model in the given point.
53841 :
53842 : This function should be used when we have NY=1 (scalar function) and NX=3
53843 : (3-dimensional space). If you have 2-dimensional space, use rbfcalc2(). If
53844 : you have general situation (NX-dimensional space, NY-dimensional function)
53845 : you should use generic rbfcalc().
53846 :
53847 : If you want to calculate function values many times, consider using
53848 : rbfgridcalc3v(), which is far more efficient than many subsequent calls to
53849 : rbfcalc3().
53850 :
53851 : If you want to perform parallel model evaluation from multiple threads,
53852 : use rbftscalcbuf() with per-thread buffer object.
53853 :
53854 : This function returns 0.0 when:
53855 : * model is not initialized
53856 : * NX<>3
53857 : *NY<>1
53858 :
53859 : INPUT PARAMETERS:
53860 : S - RBF model
53861 : X0 - first coordinate, finite number
53862 : X1 - second coordinate, finite number
53863 : X2 - third coordinate, finite number
53864 :
53865 : RESULT:
53866 : value of the model or 0.0 (as defined above)
53867 :
53868 : -- ALGLIB --
53869 : Copyright 13.12.2011 by Bochkanov Sergey
53870 : *************************************************************************/
53871 0 : double rbfcalc3(rbfmodel* s,
53872 : double x0,
53873 : double x1,
53874 : double x2,
53875 : ae_state *_state)
53876 : {
53877 : double result;
53878 :
53879 :
53880 0 : ae_assert(ae_isfinite(x0, _state), "RBFCalc3: invalid value for X0 (X0 is Inf or NaN)!", _state);
53881 0 : ae_assert(ae_isfinite(x1, _state), "RBFCalc3: invalid value for X1 (X1 is Inf or NaN)!", _state);
53882 0 : ae_assert(ae_isfinite(x2, _state), "RBFCalc3: invalid value for X2 (X2 is Inf or NaN)!", _state);
53883 0 : result = (double)(0);
53884 0 : if( s->ny!=1||s->nx!=3 )
53885 : {
53886 0 : return result;
53887 : }
53888 0 : if( s->modelversion==1 )
53889 : {
53890 0 : result = rbfv1calc3(&s->model1, x0, x1, x2, _state);
53891 0 : return result;
53892 : }
53893 0 : if( s->modelversion==2 )
53894 : {
53895 0 : result = rbfv2calc3(&s->model2, x0, x1, x2, _state);
53896 0 : return result;
53897 : }
53898 0 : ae_assert(ae_false, "RBFCalc3: integrity check failed", _state);
53899 0 : return result;
53900 : }
53901 :
53902 :
53903 : /*************************************************************************
53904 : This function calculates values of the RBF model at the given point.
53905 :
53906 : This is general function which can be used for arbitrary NX (dimension of
53907 : the space of arguments) and NY (dimension of the function itself). However
53908 : when you have NY=1 you may find more convenient to use rbfcalc2() or
53909 : rbfcalc3().
53910 :
53911 : If you want to perform parallel model evaluation from multiple threads,
53912 : use rbftscalcbuf() with per-thread buffer object.
53913 :
53914 : This function returns 0.0 when model is not initialized.
53915 :
53916 : INPUT PARAMETERS:
53917 : S - RBF model
53918 : X - coordinates, array[NX].
53919 : X may have more than NX elements, in this case only
53920 : leading NX will be used.
53921 :
53922 : OUTPUT PARAMETERS:
53923 : Y - function value, array[NY]. Y is out-parameter and
53924 : reallocated after call to this function. In case you want
53925 : to reuse previously allocated Y, you may use RBFCalcBuf(),
53926 : which reallocates Y only when it is too small.
53927 :
53928 : -- ALGLIB --
53929 : Copyright 13.12.2011 by Bochkanov Sergey
53930 : *************************************************************************/
53931 0 : void rbfcalc(rbfmodel* s,
53932 : /* Real */ ae_vector* x,
53933 : /* Real */ ae_vector* y,
53934 : ae_state *_state)
53935 : {
53936 :
53937 0 : ae_vector_clear(y);
53938 :
53939 0 : ae_assert(x->cnt>=s->nx, "RBFCalc: Length(X)<NX", _state);
53940 0 : ae_assert(isfinitevector(x, s->nx, _state), "RBFCalc: X contains infinite or NaN values", _state);
53941 0 : rbfcalcbuf(s, x, y, _state);
53942 0 : }
53943 :
53944 :
53945 : /*************************************************************************
53946 : This function calculates values of the RBF model at the given point.
53947 :
53948 : Same as rbfcalc(), but does not reallocate Y when in is large enough to
53949 : store function values.
53950 :
53951 : If you want to perform parallel model evaluation from multiple threads,
53952 : use rbftscalcbuf() with per-thread buffer object.
53953 :
53954 : INPUT PARAMETERS:
53955 : S - RBF model
53956 : X - coordinates, array[NX].
53957 : X may have more than NX elements, in this case only
53958 : leading NX will be used.
53959 : Y - possibly preallocated array
53960 :
53961 : OUTPUT PARAMETERS:
53962 : Y - function value, array[NY]. Y is not reallocated when it
53963 : is larger than NY.
53964 :
53965 : -- ALGLIB --
53966 : Copyright 13.12.2011 by Bochkanov Sergey
53967 : *************************************************************************/
53968 0 : void rbfcalcbuf(rbfmodel* s,
53969 : /* Real */ ae_vector* x,
53970 : /* Real */ ae_vector* y,
53971 : ae_state *_state)
53972 : {
53973 : ae_int_t i;
53974 :
53975 :
53976 0 : ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)<NX", _state);
53977 0 : ae_assert(isfinitevector(x, s->nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state);
53978 0 : if( y->cnt<s->ny )
53979 : {
53980 0 : ae_vector_set_length(y, s->ny, _state);
53981 : }
53982 0 : for(i=0; i<=s->ny-1; i++)
53983 : {
53984 0 : y->ptr.p_double[i] = (double)(0);
53985 : }
53986 0 : if( s->modelversion==1 )
53987 : {
53988 0 : rbfv1calcbuf(&s->model1, x, y, _state);
53989 0 : return;
53990 : }
53991 0 : if( s->modelversion==2 )
53992 : {
53993 0 : rbfv2calcbuf(&s->model2, x, y, _state);
53994 0 : return;
53995 : }
53996 0 : ae_assert(ae_false, "RBFCalcBuf: integrity check failed", _state);
53997 : }
53998 :
53999 :
54000 : /*************************************************************************
54001 : This function calculates values of the RBF model at the given point, using
54002 : external buffer object (internal temporaries of RBF model are not
54003 : modified).
54004 :
54005 : This function allows to use same RBF model object in different threads,
54006 : assuming that different threads use different instances of buffer
54007 : structure.
54008 :
54009 : INPUT PARAMETERS:
54010 : S - RBF model, may be shared between different threads
54011 : Buf - buffer object created for this particular instance of RBF
54012 : model with rbfcreatecalcbuffer().
54013 : X - coordinates, array[NX].
54014 : X may have more than NX elements, in this case only
54015 : leading NX will be used.
54016 : Y - possibly preallocated array
54017 :
54018 : OUTPUT PARAMETERS:
54019 : Y - function value, array[NY]. Y is not reallocated when it
54020 : is larger than NY.
54021 :
54022 : -- ALGLIB --
54023 : Copyright 13.12.2011 by Bochkanov Sergey
54024 : *************************************************************************/
54025 0 : void rbftscalcbuf(rbfmodel* s,
54026 : rbfcalcbuffer* buf,
54027 : /* Real */ ae_vector* x,
54028 : /* Real */ ae_vector* y,
54029 : ae_state *_state)
54030 : {
54031 : ae_int_t i;
54032 :
54033 :
54034 0 : ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)<NX", _state);
54035 0 : ae_assert(isfinitevector(x, s->nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state);
54036 0 : ae_assert(s->modelversion==buf->modelversion, "RBFCalcBuf: buffer object is not compatible with RBF model", _state);
54037 0 : if( y->cnt<s->ny )
54038 : {
54039 0 : ae_vector_set_length(y, s->ny, _state);
54040 : }
54041 0 : for(i=0; i<=s->ny-1; i++)
54042 : {
54043 0 : y->ptr.p_double[i] = (double)(0);
54044 : }
54045 0 : if( s->modelversion==1 )
54046 : {
54047 0 : rbfv1tscalcbuf(&s->model1, &buf->bufv1, x, y, _state);
54048 0 : return;
54049 : }
54050 0 : if( s->modelversion==2 )
54051 : {
54052 0 : rbfv2tscalcbuf(&s->model2, &buf->bufv2, x, y, _state);
54053 0 : return;
54054 : }
54055 0 : ae_assert(ae_false, "RBFTsCalcBuf: integrity check failed", _state);
54056 : }
54057 :
54058 :
54059 : /*************************************************************************
54060 : This is legacy function for gridded calculation of RBF model.
54061 :
54062 : It is superseded by rbfgridcalc2v() and rbfgridcalc2vsubset() functions.
54063 :
54064 : -- ALGLIB --
54065 : Copyright 13.12.2011 by Bochkanov Sergey
54066 : *************************************************************************/
54067 0 : void rbfgridcalc2(rbfmodel* s,
54068 : /* Real */ ae_vector* x0,
54069 : ae_int_t n0,
54070 : /* Real */ ae_vector* x1,
54071 : ae_int_t n1,
54072 : /* Real */ ae_matrix* y,
54073 : ae_state *_state)
54074 : {
54075 : ae_frame _frame_block;
54076 : ae_vector cpx0;
54077 : ae_vector cpx1;
54078 : ae_vector p01;
54079 : ae_vector p11;
54080 : ae_vector p2;
54081 :
54082 0 : ae_frame_make(_state, &_frame_block);
54083 0 : memset(&cpx0, 0, sizeof(cpx0));
54084 0 : memset(&cpx1, 0, sizeof(cpx1));
54085 0 : memset(&p01, 0, sizeof(p01));
54086 0 : memset(&p11, 0, sizeof(p11));
54087 0 : memset(&p2, 0, sizeof(p2));
54088 0 : ae_matrix_clear(y);
54089 0 : ae_vector_init(&cpx0, 0, DT_REAL, _state, ae_true);
54090 0 : ae_vector_init(&cpx1, 0, DT_REAL, _state, ae_true);
54091 0 : ae_vector_init(&p01, 0, DT_INT, _state, ae_true);
54092 0 : ae_vector_init(&p11, 0, DT_INT, _state, ae_true);
54093 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
54094 :
54095 0 : ae_assert(n0>0, "RBFGridCalc2: invalid value for N0 (N0<=0)!", _state);
54096 0 : ae_assert(n1>0, "RBFGridCalc2: invalid value for N1 (N1<=0)!", _state);
54097 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc2: Length(X0)<N0", _state);
54098 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc2: Length(X1)<N1", _state);
54099 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc2: X0 contains infinite or NaN values!", _state);
54100 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc2: X1 contains infinite or NaN values!", _state);
54101 0 : if( s->modelversion==1 )
54102 : {
54103 0 : rbfv1gridcalc2(&s->model1, x0, n0, x1, n1, y, _state);
54104 0 : ae_frame_leave(_state);
54105 0 : return;
54106 : }
54107 0 : if( s->modelversion==2 )
54108 : {
54109 0 : rbfv2gridcalc2(&s->model2, x0, n0, x1, n1, y, _state);
54110 0 : ae_frame_leave(_state);
54111 0 : return;
54112 : }
54113 0 : ae_assert(ae_false, "RBFGridCalc2: integrity check failed", _state);
54114 0 : ae_frame_leave(_state);
54115 : }
54116 :
54117 :
54118 : /*************************************************************************
54119 : This function calculates values of the RBF model at the regular grid,
54120 : which has N0*N1 points, with Point[I,J] = (X0[I], X1[J]). Vector-valued
54121 : RBF models are supported.
54122 :
54123 : This function returns 0.0 when:
54124 : * model is not initialized
54125 : * NX<>2
54126 :
54127 : ! COMMERCIAL EDITION OF ALGLIB:
54128 : !
54129 : ! Commercial Edition of ALGLIB includes following important improvements
54130 : ! of this function:
54131 : ! * high-performance native backend with same C# interface (C# version)
54132 : ! * multithreading support (C++ and C# versions)
54133 : !
54134 : ! We recommend you to read 'Working with commercial version' section of
54135 : ! ALGLIB Reference Manual in order to find out how to use performance-
54136 : ! related features provided by commercial edition of ALGLIB.
54137 :
54138 : NOTE: Parallel processing is implemented only for modern (hierarchical)
54139 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
54140 : processed serially.
54141 :
54142 : INPUT PARAMETERS:
54143 : S - RBF model, used in read-only mode, can be shared between
54144 : multiple invocations of this function from multiple
54145 : threads.
54146 :
54147 : X0 - array of grid nodes, first coordinates, array[N0].
54148 : Must be ordered by ascending. Exception is generated
54149 : if the array is not correctly ordered.
54150 : N0 - grid size (number of nodes) in the first dimension
54151 :
54152 : X1 - array of grid nodes, second coordinates, array[N1]
54153 : Must be ordered by ascending. Exception is generated
54154 : if the array is not correctly ordered.
54155 : N1 - grid size (number of nodes) in the second dimension
54156 :
54157 : OUTPUT PARAMETERS:
54158 : Y - function values, array[NY*N0*N1], where NY is a number of
54159 : "output" vector values (this function supports vector-
54160 : valued RBF models). Y is out-variable and is reallocated
54161 : by this function.
54162 : Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]), for:
54163 : * K=0...NY-1
54164 : * I0=0...N0-1
54165 : * I1=0...N1-1
54166 :
54167 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
54168 : X[i]=X[i+1] for some i. It does not provide you any performance
54169 : benefits due to duplication of points, just convenience and
54170 : flexibility.
54171 :
54172 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
54173 : structure in multiple threads calling this function for different
54174 : grids.
54175 :
54176 : NOTE: if you need function values on some subset of regular grid, which
54177 : may be described as "several compact and dense islands", you may
54178 : use rbfgridcalc2vsubset().
54179 :
54180 : -- ALGLIB --
54181 : Copyright 27.01.2017 by Bochkanov Sergey
54182 : *************************************************************************/
54183 0 : void rbfgridcalc2v(rbfmodel* s,
54184 : /* Real */ ae_vector* x0,
54185 : ae_int_t n0,
54186 : /* Real */ ae_vector* x1,
54187 : ae_int_t n1,
54188 : /* Real */ ae_vector* y,
54189 : ae_state *_state)
54190 : {
54191 : ae_frame _frame_block;
54192 : ae_int_t i;
54193 : ae_vector dummy;
54194 :
54195 0 : ae_frame_make(_state, &_frame_block);
54196 0 : memset(&dummy, 0, sizeof(dummy));
54197 0 : ae_vector_clear(y);
54198 0 : ae_vector_init(&dummy, 0, DT_BOOL, _state, ae_true);
54199 :
54200 0 : ae_assert(n0>0, "RBFGridCalc2V: invalid value for N0 (N0<=0)!", _state);
54201 0 : ae_assert(n1>0, "RBFGridCalc2V: invalid value for N1 (N1<=0)!", _state);
54202 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc2V: Length(X0)<N0", _state);
54203 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc2V: Length(X1)<N1", _state);
54204 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc2V: X0 contains infinite or NaN values!", _state);
54205 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc2V: X1 contains infinite or NaN values!", _state);
54206 0 : for(i=0; i<=n0-2; i++)
54207 : {
54208 0 : ae_assert(ae_fp_less_eq(x0->ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc2V: X0 is not ordered by ascending", _state);
54209 : }
54210 0 : for(i=0; i<=n1-2; i++)
54211 : {
54212 0 : ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc2V: X1 is not ordered by ascending", _state);
54213 : }
54214 0 : rbfgridcalc2vx(s, x0, n0, x1, n1, &dummy, ae_false, y, _state);
54215 0 : ae_frame_leave(_state);
54216 0 : }
54217 :
54218 :
54219 : /*************************************************************************
54220 : This function calculates values of the RBF model at some subset of regular
54221 : grid:
54222 : * grid has N0*N1 points, with Point[I,J] = (X0[I], X1[J])
54223 : * only values at some subset of this grid are required
54224 : Vector-valued RBF models are supported.
54225 :
54226 : This function returns 0.0 when:
54227 : * model is not initialized
54228 : * NX<>2
54229 :
54230 : ! COMMERCIAL EDITION OF ALGLIB:
54231 : !
54232 : ! Commercial Edition of ALGLIB includes following important improvements
54233 : ! of this function:
54234 : ! * high-performance native backend with same C# interface (C# version)
54235 : ! * multithreading support (C++ and C# versions)
54236 : !
54237 : ! We recommend you to read 'Working with commercial version' section of
54238 : ! ALGLIB Reference Manual in order to find out how to use performance-
54239 : ! related features provided by commercial edition of ALGLIB.
54240 :
54241 : NOTE: Parallel processing is implemented only for modern (hierarchical)
54242 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
54243 : processed serially.
54244 :
54245 : INPUT PARAMETERS:
54246 : S - RBF model, used in read-only mode, can be shared between
54247 : multiple invocations of this function from multiple
54248 : threads.
54249 :
54250 : X0 - array of grid nodes, first coordinates, array[N0].
54251 : Must be ordered by ascending. Exception is generated
54252 : if the array is not correctly ordered.
54253 : N0 - grid size (number of nodes) in the first dimension
54254 :
54255 : X1 - array of grid nodes, second coordinates, array[N1]
54256 : Must be ordered by ascending. Exception is generated
54257 : if the array is not correctly ordered.
54258 : N1 - grid size (number of nodes) in the second dimension
54259 :
54260 : FlagY - array[N0*N1]:
54261 : * Y[I0+I1*N0] corresponds to node (X0[I0],X1[I1])
54262 : * it is a "bitmap" array which contains False for nodes
54263 : which are NOT calculated, and True for nodes which are
54264 : required.
54265 :
54266 : OUTPUT PARAMETERS:
54267 : Y - function values, array[NY*N0*N1*N2], where NY is a number
54268 : of "output" vector values (this function supports vector-
54269 : valued RBF models):
54270 : * Y[K+NY*(I0+I1*N0)]=F_k(X0[I0],X1[I1]),
54271 : for K=0...NY-1, I0=0...N0-1, I1=0...N1-1.
54272 : * elements of Y[] which correspond to FlagY[]=True are
54273 : loaded by model values (which may be exactly zero for
54274 : some nodes).
54275 : * elements of Y[] which correspond to FlagY[]=False MAY be
54276 : initialized by zeros OR may be calculated. This function
54277 : processes grid as a hierarchy of nested blocks and
54278 : micro-rows. If just one element of micro-row is required,
54279 : entire micro-row (up to 8 nodes in the current version,
54280 : but no promises) is calculated.
54281 :
54282 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
54283 : X[i]=X[i+1] for some i. It does not provide you any performance
54284 : benefits due to duplication of points, just convenience and
54285 : flexibility.
54286 :
54287 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
54288 : structure in multiple threads calling this function for different
54289 : grids.
54290 :
54291 : -- ALGLIB --
54292 : Copyright 04.03.2016 by Bochkanov Sergey
54293 : *************************************************************************/
54294 0 : void rbfgridcalc2vsubset(rbfmodel* s,
54295 : /* Real */ ae_vector* x0,
54296 : ae_int_t n0,
54297 : /* Real */ ae_vector* x1,
54298 : ae_int_t n1,
54299 : /* Boolean */ ae_vector* flagy,
54300 : /* Real */ ae_vector* y,
54301 : ae_state *_state)
54302 : {
54303 : ae_int_t i;
54304 :
54305 0 : ae_vector_clear(y);
54306 :
54307 0 : ae_assert(n0>0, "RBFGridCalc2VSubset: invalid value for N0 (N0<=0)!", _state);
54308 0 : ae_assert(n1>0, "RBFGridCalc2VSubset: invalid value for N1 (N1<=0)!", _state);
54309 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc2VSubset: Length(X0)<N0", _state);
54310 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc2VSubset: Length(X1)<N1", _state);
54311 0 : ae_assert(flagy->cnt>=n0*n1, "RBFGridCalc2VSubset: Length(FlagY)<N0*N1*N2", _state);
54312 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc2VSubset: X0 contains infinite or NaN values!", _state);
54313 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc2VSubset: X1 contains infinite or NaN values!", _state);
54314 0 : for(i=0; i<=n0-2; i++)
54315 : {
54316 0 : ae_assert(ae_fp_less_eq(x0->ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc2VSubset: X0 is not ordered by ascending", _state);
54317 : }
54318 0 : for(i=0; i<=n1-2; i++)
54319 : {
54320 0 : ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc2VSubset: X1 is not ordered by ascending", _state);
54321 : }
54322 0 : rbfgridcalc2vx(s, x0, n0, x1, n1, flagy, ae_true, y, _state);
54323 0 : }
54324 :
54325 :
54326 : /*************************************************************************
54327 : This function calculates values of the RBF model at the regular grid,
54328 : which has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K]).
54329 : Vector-valued RBF models are supported.
54330 :
54331 : This function returns 0.0 when:
54332 : * model is not initialized
54333 : * NX<>3
54334 :
54335 : ! COMMERCIAL EDITION OF ALGLIB:
54336 : !
54337 : ! Commercial Edition of ALGLIB includes following important improvements
54338 : ! of this function:
54339 : ! * high-performance native backend with same C# interface (C# version)
54340 : ! * multithreading support (C++ and C# versions)
54341 : !
54342 : ! We recommend you to read 'Working with commercial version' section of
54343 : ! ALGLIB Reference Manual in order to find out how to use performance-
54344 : ! related features provided by commercial edition of ALGLIB.
54345 :
54346 : NOTE: Parallel processing is implemented only for modern (hierarchical)
54347 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
54348 : processed serially.
54349 :
54350 : INPUT PARAMETERS:
54351 : S - RBF model, used in read-only mode, can be shared between
54352 : multiple invocations of this function from multiple
54353 : threads.
54354 :
54355 : X0 - array of grid nodes, first coordinates, array[N0].
54356 : Must be ordered by ascending. Exception is generated
54357 : if the array is not correctly ordered.
54358 : N0 - grid size (number of nodes) in the first dimension
54359 :
54360 : X1 - array of grid nodes, second coordinates, array[N1]
54361 : Must be ordered by ascending. Exception is generated
54362 : if the array is not correctly ordered.
54363 : N1 - grid size (number of nodes) in the second dimension
54364 :
54365 : X2 - array of grid nodes, third coordinates, array[N2]
54366 : Must be ordered by ascending. Exception is generated
54367 : if the array is not correctly ordered.
54368 : N2 - grid size (number of nodes) in the third dimension
54369 :
54370 : OUTPUT PARAMETERS:
54371 : Y - function values, array[NY*N0*N1*N2], where NY is a number
54372 : of "output" vector values (this function supports vector-
54373 : valued RBF models). Y is out-variable and is reallocated
54374 : by this function.
54375 : Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]), for:
54376 : * K=0...NY-1
54377 : * I0=0...N0-1
54378 : * I1=0...N1-1
54379 : * I2=0...N2-1
54380 :
54381 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
54382 : X[i]=X[i+1] for some i. It does not provide you any performance
54383 : benefits due to duplication of points, just convenience and
54384 : flexibility.
54385 :
54386 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
54387 : structure in multiple threads calling this function for different
54388 : grids.
54389 :
54390 : NOTE: if you need function values on some subset of regular grid, which
54391 : may be described as "several compact and dense islands", you may
54392 : use rbfgridcalc3vsubset().
54393 :
54394 : -- ALGLIB --
54395 : Copyright 04.03.2016 by Bochkanov Sergey
54396 : *************************************************************************/
54397 0 : void rbfgridcalc3v(rbfmodel* s,
54398 : /* Real */ ae_vector* x0,
54399 : ae_int_t n0,
54400 : /* Real */ ae_vector* x1,
54401 : ae_int_t n1,
54402 : /* Real */ ae_vector* x2,
54403 : ae_int_t n2,
54404 : /* Real */ ae_vector* y,
54405 : ae_state *_state)
54406 : {
54407 : ae_frame _frame_block;
54408 : ae_int_t i;
54409 : ae_vector dummy;
54410 :
54411 0 : ae_frame_make(_state, &_frame_block);
54412 0 : memset(&dummy, 0, sizeof(dummy));
54413 0 : ae_vector_clear(y);
54414 0 : ae_vector_init(&dummy, 0, DT_BOOL, _state, ae_true);
54415 :
54416 0 : ae_assert(n0>0, "RBFGridCalc3V: invalid value for N0 (N0<=0)!", _state);
54417 0 : ae_assert(n1>0, "RBFGridCalc3V: invalid value for N1 (N1<=0)!", _state);
54418 0 : ae_assert(n2>0, "RBFGridCalc3V: invalid value for N2 (N2<=0)!", _state);
54419 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc3V: Length(X0)<N0", _state);
54420 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc3V: Length(X1)<N1", _state);
54421 0 : ae_assert(x2->cnt>=n2, "RBFGridCalc3V: Length(X2)<N2", _state);
54422 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc3V: X0 contains infinite or NaN values!", _state);
54423 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc3V: X1 contains infinite or NaN values!", _state);
54424 0 : ae_assert(isfinitevector(x2, n2, _state), "RBFGridCalc3V: X2 contains infinite or NaN values!", _state);
54425 0 : for(i=0; i<=n0-2; i++)
54426 : {
54427 0 : ae_assert(ae_fp_less_eq(x0->ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc3V: X0 is not ordered by ascending", _state);
54428 : }
54429 0 : for(i=0; i<=n1-2; i++)
54430 : {
54431 0 : ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc3V: X1 is not ordered by ascending", _state);
54432 : }
54433 0 : for(i=0; i<=n2-2; i++)
54434 : {
54435 0 : ae_assert(ae_fp_less_eq(x2->ptr.p_double[i],x2->ptr.p_double[i+1]), "RBFGridCalc3V: X2 is not ordered by ascending", _state);
54436 : }
54437 0 : rbfgridcalc3vx(s, x0, n0, x1, n1, x2, n2, &dummy, ae_false, y, _state);
54438 0 : ae_frame_leave(_state);
54439 0 : }
54440 :
54441 :
54442 : /*************************************************************************
54443 : This function calculates values of the RBF model at some subset of regular
54444 : grid:
54445 : * grid has N0*N1*N2 points, with Point[I,J,K] = (X0[I], X1[J], X2[K])
54446 : * only values at some subset of this grid are required
54447 : Vector-valued RBF models are supported.
54448 :
54449 : This function returns 0.0 when:
54450 : * model is not initialized
54451 : * NX<>3
54452 :
54453 : ! COMMERCIAL EDITION OF ALGLIB:
54454 : !
54455 : ! Commercial Edition of ALGLIB includes following important improvements
54456 : ! of this function:
54457 : ! * high-performance native backend with same C# interface (C# version)
54458 : ! * multithreading support (C++ and C# versions)
54459 : !
54460 : ! We recommend you to read 'Working with commercial version' section of
54461 : ! ALGLIB Reference Manual in order to find out how to use performance-
54462 : ! related features provided by commercial edition of ALGLIB.
54463 :
54464 : NOTE: Parallel processing is implemented only for modern (hierarchical)
54465 : RBFs. Legacy version 1 RBFs (created by QNN or RBF-ML) are still
54466 : processed serially.
54467 :
54468 : INPUT PARAMETERS:
54469 : S - RBF model, used in read-only mode, can be shared between
54470 : multiple invocations of this function from multiple
54471 : threads.
54472 :
54473 : X0 - array of grid nodes, first coordinates, array[N0].
54474 : Must be ordered by ascending. Exception is generated
54475 : if the array is not correctly ordered.
54476 : N0 - grid size (number of nodes) in the first dimension
54477 :
54478 : X1 - array of grid nodes, second coordinates, array[N1]
54479 : Must be ordered by ascending. Exception is generated
54480 : if the array is not correctly ordered.
54481 : N1 - grid size (number of nodes) in the second dimension
54482 :
54483 : X2 - array of grid nodes, third coordinates, array[N2]
54484 : Must be ordered by ascending. Exception is generated
54485 : if the array is not correctly ordered.
54486 : N2 - grid size (number of nodes) in the third dimension
54487 :
54488 : FlagY - array[N0*N1*N2]:
54489 : * Y[I0+I1*N0+I2*N0*N1] corresponds to node (X0[I0],X1[I1],X2[I2])
54490 : * it is a "bitmap" array which contains False for nodes
54491 : which are NOT calculated, and True for nodes which are
54492 : required.
54493 :
54494 : OUTPUT PARAMETERS:
54495 : Y - function values, array[NY*N0*N1*N2], where NY is a number
54496 : of "output" vector values (this function supports vector-
54497 : valued RBF models):
54498 : * Y[K+NY*(I0+I1*N0+I2*N0*N1)]=F_k(X0[I0],X1[I1],X2[I2]),
54499 : for K=0...NY-1, I0=0...N0-1, I1=0...N1-1, I2=0...N2-1.
54500 : * elements of Y[] which correspond to FlagY[]=True are
54501 : loaded by model values (which may be exactly zero for
54502 : some nodes).
54503 : * elements of Y[] which correspond to FlagY[]=False MAY be
54504 : initialized by zeros OR may be calculated. This function
54505 : processes grid as a hierarchy of nested blocks and
54506 : micro-rows. If just one element of micro-row is required,
54507 : entire micro-row (up to 8 nodes in the current version,
54508 : but no promises) is calculated.
54509 :
54510 : NOTE: this function supports weakly ordered grid nodes, i.e. you may have
54511 : X[i]=X[i+1] for some i. It does not provide you any performance
54512 : benefits due to duplication of points, just convenience and
54513 : flexibility.
54514 :
54515 : NOTE: this function is re-entrant, i.e. you may use same rbfmodel
54516 : structure in multiple threads calling this function for different
54517 : grids.
54518 :
54519 : -- ALGLIB --
54520 : Copyright 04.03.2016 by Bochkanov Sergey
54521 : *************************************************************************/
54522 0 : void rbfgridcalc3vsubset(rbfmodel* s,
54523 : /* Real */ ae_vector* x0,
54524 : ae_int_t n0,
54525 : /* Real */ ae_vector* x1,
54526 : ae_int_t n1,
54527 : /* Real */ ae_vector* x2,
54528 : ae_int_t n2,
54529 : /* Boolean */ ae_vector* flagy,
54530 : /* Real */ ae_vector* y,
54531 : ae_state *_state)
54532 : {
54533 : ae_int_t i;
54534 :
54535 0 : ae_vector_clear(y);
54536 :
54537 0 : ae_assert(n0>0, "RBFGridCalc3VSubset: invalid value for N0 (N0<=0)!", _state);
54538 0 : ae_assert(n1>0, "RBFGridCalc3VSubset: invalid value for N1 (N1<=0)!", _state);
54539 0 : ae_assert(n2>0, "RBFGridCalc3VSubset: invalid value for N2 (N2<=0)!", _state);
54540 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc3VSubset: Length(X0)<N0", _state);
54541 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc3VSubset: Length(X1)<N1", _state);
54542 0 : ae_assert(x2->cnt>=n2, "RBFGridCalc3VSubset: Length(X2)<N2", _state);
54543 0 : ae_assert(flagy->cnt>=n0*n1*n2, "RBFGridCalc3VSubset: Length(FlagY)<N0*N1*N2", _state);
54544 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc3VSubset: X0 contains infinite or NaN values!", _state);
54545 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc3VSubset: X1 contains infinite or NaN values!", _state);
54546 0 : ae_assert(isfinitevector(x2, n2, _state), "RBFGridCalc3VSubset: X2 contains infinite or NaN values!", _state);
54547 0 : for(i=0; i<=n0-2; i++)
54548 : {
54549 0 : ae_assert(ae_fp_less_eq(x0->ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc3VSubset: X0 is not ordered by ascending", _state);
54550 : }
54551 0 : for(i=0; i<=n1-2; i++)
54552 : {
54553 0 : ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc3VSubset: X1 is not ordered by ascending", _state);
54554 : }
54555 0 : for(i=0; i<=n2-2; i++)
54556 : {
54557 0 : ae_assert(ae_fp_less_eq(x2->ptr.p_double[i],x2->ptr.p_double[i+1]), "RBFGridCalc3VSubset: X2 is not ordered by ascending", _state);
54558 : }
54559 0 : rbfgridcalc3vx(s, x0, n0, x1, n1, x2, n2, flagy, ae_true, y, _state);
54560 0 : }
54561 :
54562 :
54563 : /*************************************************************************
54564 : This function, depending on SparseY, acts as RBFGridCalc2V (SparseY=False)
54565 : or RBFGridCalc2VSubset (SparseY=True) function. See comments for these
54566 : functions for more information
54567 :
54568 : -- ALGLIB --
54569 : Copyright 04.03.2016 by Bochkanov Sergey
54570 : *************************************************************************/
54571 0 : void rbfgridcalc2vx(rbfmodel* s,
54572 : /* Real */ ae_vector* x0,
54573 : ae_int_t n0,
54574 : /* Real */ ae_vector* x1,
54575 : ae_int_t n1,
54576 : /* Boolean */ ae_vector* flagy,
54577 : ae_bool sparsey,
54578 : /* Real */ ae_vector* y,
54579 : ae_state *_state)
54580 : {
54581 : ae_frame _frame_block;
54582 : ae_int_t nx;
54583 : ae_int_t ny;
54584 : ae_int_t ylen;
54585 : hqrndstate rs;
54586 : ae_vector dummyx2;
54587 : ae_vector dummyx3;
54588 : ae_int_t i;
54589 : ae_int_t j;
54590 : ae_int_t k;
54591 : ae_int_t l;
54592 : ae_vector tx;
54593 : ae_vector ty;
54594 : ae_int_t dstoffs;
54595 : rbfcalcbuffer calcbuf;
54596 :
54597 0 : ae_frame_make(_state, &_frame_block);
54598 0 : memset(&rs, 0, sizeof(rs));
54599 0 : memset(&dummyx2, 0, sizeof(dummyx2));
54600 0 : memset(&dummyx3, 0, sizeof(dummyx3));
54601 0 : memset(&tx, 0, sizeof(tx));
54602 0 : memset(&ty, 0, sizeof(ty));
54603 0 : memset(&calcbuf, 0, sizeof(calcbuf));
54604 0 : _hqrndstate_init(&rs, _state, ae_true);
54605 0 : ae_vector_init(&dummyx2, 0, DT_REAL, _state, ae_true);
54606 0 : ae_vector_init(&dummyx3, 0, DT_REAL, _state, ae_true);
54607 0 : ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
54608 0 : ae_vector_init(&ty, 0, DT_REAL, _state, ae_true);
54609 0 : _rbfcalcbuffer_init(&calcbuf, _state, ae_true);
54610 :
54611 0 : ae_assert(n0>0, "RBFGridCalc2VX: invalid value for N0 (N0<=0)!", _state);
54612 0 : ae_assert(n1>0, "RBFGridCalc2VX: invalid value for N1 (N1<=0)!", _state);
54613 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc2VX: Length(X0)<N0", _state);
54614 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc2VX: Length(X1)<N1", _state);
54615 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc2VX: X0 contains infinite or NaN values!", _state);
54616 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc2VX: X1 contains infinite or NaN values!", _state);
54617 0 : for(i=0; i<=n0-2; i++)
54618 : {
54619 0 : ae_assert(ae_fp_less_eq(x0->ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc2VX: X0 is not ordered by ascending", _state);
54620 : }
54621 0 : for(i=0; i<=n1-2; i++)
54622 : {
54623 0 : ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc2VX: X1 is not ordered by ascending", _state);
54624 : }
54625 :
54626 : /*
54627 : * Prepare local variables
54628 : */
54629 0 : nx = s->nx;
54630 0 : ny = s->ny;
54631 0 : hqrndseed(325, 46345, &rs, _state);
54632 :
54633 : /*
54634 : * Prepare output array
54635 : */
54636 0 : ylen = ny*n0*n1;
54637 0 : ae_vector_set_length(y, ylen, _state);
54638 0 : for(i=0; i<=ylen-1; i++)
54639 : {
54640 0 : y->ptr.p_double[i] = (double)(0);
54641 : }
54642 0 : if( s->nx!=2 )
54643 : {
54644 0 : ae_frame_leave(_state);
54645 0 : return;
54646 : }
54647 :
54648 : /*
54649 : * Process V2 model
54650 : */
54651 0 : if( s->modelversion==2 )
54652 : {
54653 0 : ae_vector_set_length(&dummyx2, 1, _state);
54654 0 : dummyx2.ptr.p_double[0] = (double)(0);
54655 0 : ae_vector_set_length(&dummyx3, 1, _state);
54656 0 : dummyx3.ptr.p_double[0] = (double)(0);
54657 0 : rbfv2gridcalcvx(&s->model2, x0, n0, x1, n1, &dummyx2, 1, &dummyx3, 1, flagy, sparsey, y, _state);
54658 0 : ae_frame_leave(_state);
54659 0 : return;
54660 : }
54661 :
54662 : /*
54663 : * Reference code for V1 models
54664 : */
54665 0 : if( s->modelversion==1 )
54666 : {
54667 0 : ae_vector_set_length(&tx, nx, _state);
54668 0 : rbfcreatecalcbuffer(s, &calcbuf, _state);
54669 0 : for(i=0; i<=n0-1; i++)
54670 : {
54671 0 : for(j=0; j<=n1-1; j++)
54672 : {
54673 0 : k = i+j*n0;
54674 0 : dstoffs = ny*k;
54675 0 : if( sparsey&&!flagy->ptr.p_bool[k] )
54676 : {
54677 0 : for(l=0; l<=ny-1; l++)
54678 : {
54679 0 : y->ptr.p_double[l+dstoffs] = (double)(0);
54680 : }
54681 0 : continue;
54682 : }
54683 0 : tx.ptr.p_double[0] = x0->ptr.p_double[i];
54684 0 : tx.ptr.p_double[1] = x1->ptr.p_double[j];
54685 0 : rbftscalcbuf(s, &calcbuf, &tx, &ty, _state);
54686 0 : for(l=0; l<=ny-1; l++)
54687 : {
54688 0 : y->ptr.p_double[l+dstoffs] = ty.ptr.p_double[l];
54689 : }
54690 : }
54691 : }
54692 0 : ae_frame_leave(_state);
54693 0 : return;
54694 : }
54695 :
54696 : /*
54697 : * Unknown model
54698 : */
54699 0 : ae_assert(ae_false, "RBFGradCalc3VX: integrity check failed", _state);
54700 0 : ae_frame_leave(_state);
54701 : }
54702 :
54703 :
54704 : /*************************************************************************
54705 : This function, depending on SparseY, acts as RBFGridCalc3V (SparseY=False)
54706 : or RBFGridCalc3VSubset (SparseY=True) function. See comments for these
54707 : functions for more information
54708 :
54709 : -- ALGLIB --
54710 : Copyright 04.03.2016 by Bochkanov Sergey
54711 : *************************************************************************/
54712 0 : void rbfgridcalc3vx(rbfmodel* s,
54713 : /* Real */ ae_vector* x0,
54714 : ae_int_t n0,
54715 : /* Real */ ae_vector* x1,
54716 : ae_int_t n1,
54717 : /* Real */ ae_vector* x2,
54718 : ae_int_t n2,
54719 : /* Boolean */ ae_vector* flagy,
54720 : ae_bool sparsey,
54721 : /* Real */ ae_vector* y,
54722 : ae_state *_state)
54723 : {
54724 : ae_frame _frame_block;
54725 : ae_int_t i;
54726 : ae_int_t ylen;
54727 : ae_int_t nx;
54728 : ae_int_t ny;
54729 : double rmax;
54730 : ae_vector blocks0;
54731 : ae_vector blocks1;
54732 : ae_vector blocks2;
54733 : ae_int_t blockscnt0;
54734 : ae_int_t blockscnt1;
54735 : ae_int_t blockscnt2;
54736 : double blockwidth;
54737 : double searchradius;
54738 : double avgfuncpernode;
54739 : ae_int_t ntrials;
54740 : ae_int_t maxblocksize;
54741 : gridcalc3v1buf bufseedv1;
54742 : ae_shared_pool bufpool;
54743 : hqrndstate rs;
54744 : ae_vector dummyx3;
54745 :
54746 0 : ae_frame_make(_state, &_frame_block);
54747 0 : memset(&blocks0, 0, sizeof(blocks0));
54748 0 : memset(&blocks1, 0, sizeof(blocks1));
54749 0 : memset(&blocks2, 0, sizeof(blocks2));
54750 0 : memset(&bufseedv1, 0, sizeof(bufseedv1));
54751 0 : memset(&bufpool, 0, sizeof(bufpool));
54752 0 : memset(&rs, 0, sizeof(rs));
54753 0 : memset(&dummyx3, 0, sizeof(dummyx3));
54754 0 : ae_vector_init(&blocks0, 0, DT_INT, _state, ae_true);
54755 0 : ae_vector_init(&blocks1, 0, DT_INT, _state, ae_true);
54756 0 : ae_vector_init(&blocks2, 0, DT_INT, _state, ae_true);
54757 0 : _gridcalc3v1buf_init(&bufseedv1, _state, ae_true);
54758 0 : ae_shared_pool_init(&bufpool, _state, ae_true);
54759 0 : _hqrndstate_init(&rs, _state, ae_true);
54760 0 : ae_vector_init(&dummyx3, 0, DT_REAL, _state, ae_true);
54761 :
54762 0 : ae_assert(n0>0, "RBFGridCalc3V: invalid value for N0 (N0<=0)!", _state);
54763 0 : ae_assert(n1>0, "RBFGridCalc3V: invalid value for N1 (N1<=0)!", _state);
54764 0 : ae_assert(n2>0, "RBFGridCalc3V: invalid value for N2 (N2<=0)!", _state);
54765 0 : ae_assert(x0->cnt>=n0, "RBFGridCalc3V: Length(X0)<N0", _state);
54766 0 : ae_assert(x1->cnt>=n1, "RBFGridCalc3V: Length(X1)<N1", _state);
54767 0 : ae_assert(x2->cnt>=n2, "RBFGridCalc3V: Length(X2)<N2", _state);
54768 0 : ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc3V: X0 contains infinite or NaN values!", _state);
54769 0 : ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc3V: X1 contains infinite or NaN values!", _state);
54770 0 : ae_assert(isfinitevector(x2, n2, _state), "RBFGridCalc3V: X2 contains infinite or NaN values!", _state);
54771 0 : for(i=0; i<=n0-2; i++)
54772 : {
54773 0 : ae_assert(ae_fp_less_eq(x0->ptr.p_double[i],x0->ptr.p_double[i+1]), "RBFGridCalc3V: X0 is not ordered by ascending", _state);
54774 : }
54775 0 : for(i=0; i<=n1-2; i++)
54776 : {
54777 0 : ae_assert(ae_fp_less_eq(x1->ptr.p_double[i],x1->ptr.p_double[i+1]), "RBFGridCalc3V: X1 is not ordered by ascending", _state);
54778 : }
54779 0 : for(i=0; i<=n2-2; i++)
54780 : {
54781 0 : ae_assert(ae_fp_less_eq(x2->ptr.p_double[i],x2->ptr.p_double[i+1]), "RBFGridCalc3V: X2 is not ordered by ascending", _state);
54782 : }
54783 :
54784 : /*
54785 : * Prepare local variables
54786 : */
54787 0 : nx = s->nx;
54788 0 : ny = s->ny;
54789 0 : hqrndseed(325, 46345, &rs, _state);
54790 :
54791 : /*
54792 : * Prepare output array
54793 : */
54794 0 : ylen = ny*n0*n1*n2;
54795 0 : ae_vector_set_length(y, ylen, _state);
54796 0 : for(i=0; i<=ylen-1; i++)
54797 : {
54798 0 : y->ptr.p_double[i] = (double)(0);
54799 : }
54800 0 : if( s->nx!=3 )
54801 : {
54802 0 : ae_frame_leave(_state);
54803 0 : return;
54804 : }
54805 :
54806 : /*
54807 : * Process V1 model
54808 : */
54809 0 : if( s->modelversion==1 )
54810 : {
54811 :
54812 : /*
54813 : * Fast exit for models without centers
54814 : */
54815 0 : if( s->model1.nc==0 )
54816 : {
54817 0 : ae_frame_leave(_state);
54818 0 : return;
54819 : }
54820 :
54821 : /*
54822 : * Prepare seed, create shared pool of temporary buffers
54823 : */
54824 0 : ae_vector_set_length(&bufseedv1.cx, nx, _state);
54825 0 : ae_vector_set_length(&bufseedv1.tx, nx, _state);
54826 0 : ae_vector_set_length(&bufseedv1.ty, ny, _state);
54827 0 : ae_vector_set_length(&bufseedv1.expbuf0, n0, _state);
54828 0 : ae_vector_set_length(&bufseedv1.expbuf1, n1, _state);
54829 0 : ae_vector_set_length(&bufseedv1.expbuf2, n2, _state);
54830 0 : kdtreecreaterequestbuffer(&s->model1.tree, &bufseedv1.requestbuf, _state);
54831 0 : ae_shared_pool_set_seed(&bufpool, &bufseedv1, sizeof(bufseedv1), _gridcalc3v1buf_init, _gridcalc3v1buf_init_copy, _gridcalc3v1buf_destroy, _state);
54832 :
54833 : /*
54834 : * Analyze input grid:
54835 : * * analyze average number of basis functions per grid node
54836 : * * partition grid in into blocks
54837 : */
54838 0 : rmax = s->model1.rmax;
54839 0 : blockwidth = 2*rmax;
54840 0 : maxblocksize = 8;
54841 0 : searchradius = rmax*rbf_rbffarradius+0.5*ae_sqrt((double)(s->nx), _state)*blockwidth;
54842 0 : ntrials = 100;
54843 0 : avgfuncpernode = 0.0;
54844 0 : for(i=0; i<=ntrials-1; i++)
54845 : {
54846 0 : bufseedv1.tx.ptr.p_double[0] = x0->ptr.p_double[hqrnduniformi(&rs, n0, _state)];
54847 0 : bufseedv1.tx.ptr.p_double[1] = x1->ptr.p_double[hqrnduniformi(&rs, n1, _state)];
54848 0 : bufseedv1.tx.ptr.p_double[2] = x2->ptr.p_double[hqrnduniformi(&rs, n2, _state)];
54849 0 : avgfuncpernode = avgfuncpernode+(double)kdtreetsqueryrnn(&s->model1.tree, &bufseedv1.requestbuf, &bufseedv1.tx, searchradius, ae_true, _state)/(double)ntrials;
54850 : }
54851 0 : ae_vector_set_length(&blocks0, n0+1, _state);
54852 0 : blockscnt0 = 0;
54853 0 : blocks0.ptr.p_int[0] = 0;
54854 0 : for(i=1; i<=n0-1; i++)
54855 : {
54856 0 : if( ae_fp_greater(x0->ptr.p_double[i]-x0->ptr.p_double[blocks0.ptr.p_int[blockscnt0]],blockwidth)||i-blocks0.ptr.p_int[blockscnt0]>=maxblocksize )
54857 : {
54858 0 : inc(&blockscnt0, _state);
54859 0 : blocks0.ptr.p_int[blockscnt0] = i;
54860 : }
54861 : }
54862 0 : inc(&blockscnt0, _state);
54863 0 : blocks0.ptr.p_int[blockscnt0] = n0;
54864 0 : ae_vector_set_length(&blocks1, n1+1, _state);
54865 0 : blockscnt1 = 0;
54866 0 : blocks1.ptr.p_int[0] = 0;
54867 0 : for(i=1; i<=n1-1; i++)
54868 : {
54869 0 : if( ae_fp_greater(x1->ptr.p_double[i]-x1->ptr.p_double[blocks1.ptr.p_int[blockscnt1]],blockwidth)||i-blocks1.ptr.p_int[blockscnt1]>=maxblocksize )
54870 : {
54871 0 : inc(&blockscnt1, _state);
54872 0 : blocks1.ptr.p_int[blockscnt1] = i;
54873 : }
54874 : }
54875 0 : inc(&blockscnt1, _state);
54876 0 : blocks1.ptr.p_int[blockscnt1] = n1;
54877 0 : ae_vector_set_length(&blocks2, n2+1, _state);
54878 0 : blockscnt2 = 0;
54879 0 : blocks2.ptr.p_int[0] = 0;
54880 0 : for(i=1; i<=n2-1; i++)
54881 : {
54882 0 : if( ae_fp_greater(x2->ptr.p_double[i]-x2->ptr.p_double[blocks2.ptr.p_int[blockscnt2]],blockwidth)||i-blocks2.ptr.p_int[blockscnt2]>=maxblocksize )
54883 : {
54884 0 : inc(&blockscnt2, _state);
54885 0 : blocks2.ptr.p_int[blockscnt2] = i;
54886 : }
54887 : }
54888 0 : inc(&blockscnt2, _state);
54889 0 : blocks2.ptr.p_int[blockscnt2] = n2;
54890 :
54891 : /*
54892 : * Perform calculation in multithreaded mode
54893 : */
54894 0 : rbfv1gridcalc3vrec(&s->model1, x0, n0, x1, n1, x2, n2, &blocks0, 0, blockscnt0, &blocks1, 0, blockscnt1, &blocks2, 0, blockscnt2, flagy, sparsey, searchradius, avgfuncpernode, &bufpool, y, _state);
54895 :
54896 : /*
54897 : * Done
54898 : */
54899 0 : ae_frame_leave(_state);
54900 0 : return;
54901 : }
54902 :
54903 : /*
54904 : * Process V2 model
54905 : */
54906 0 : if( s->modelversion==2 )
54907 : {
54908 0 : ae_vector_set_length(&dummyx3, 1, _state);
54909 0 : dummyx3.ptr.p_double[0] = (double)(0);
54910 0 : rbfv2gridcalcvx(&s->model2, x0, n0, x1, n1, x2, n2, &dummyx3, 1, flagy, sparsey, y, _state);
54911 0 : ae_frame_leave(_state);
54912 0 : return;
54913 : }
54914 :
54915 : /*
54916 : * Unknown model
54917 : */
54918 0 : ae_assert(ae_false, "RBFGradCalc3VX: integrity check failed", _state);
54919 0 : ae_frame_leave(_state);
54920 : }
54921 :
54922 :
54923 : /*************************************************************************
54924 : This function "unpacks" RBF model by extracting its coefficients.
54925 :
54926 : INPUT PARAMETERS:
54927 : S - RBF model
54928 :
54929 : OUTPUT PARAMETERS:
54930 : NX - dimensionality of argument
54931 : NY - dimensionality of the target function
54932 : XWR - model information, array[NC,NX+NY+1].
54933 : One row of the array corresponds to one basis function:
54934 : * first NX columns - coordinates of the center
54935 : * next NY columns - weights, one per dimension of the
54936 : function being modelled
54937 : For ModelVersion=1:
54938 : * last column - radius, same for all dimensions of
54939 : the function being modelled
54940 : For ModelVersion=2:
54941 : * last NX columns - radii, one per dimension
54942 : NC - number of the centers
54943 : V - polynomial term , array[NY,NX+1]. One row per one
54944 : dimension of the function being modelled. First NX
54945 : elements are linear coefficients, V[NX] is equal to the
54946 : constant part.
54947 : ModelVersion-version of the RBF model:
54948 : * 1 - for models created by QNN and RBF-ML algorithms,
54949 : compatible with ALGLIB 3.10 or earlier.
54950 : * 2 - for models created by HierarchicalRBF, requires
54951 : ALGLIB 3.11 or later
54952 :
54953 : -- ALGLIB --
54954 : Copyright 13.12.2011 by Bochkanov Sergey
54955 : *************************************************************************/
54956 0 : void rbfunpack(rbfmodel* s,
54957 : ae_int_t* nx,
54958 : ae_int_t* ny,
54959 : /* Real */ ae_matrix* xwr,
54960 : ae_int_t* nc,
54961 : /* Real */ ae_matrix* v,
54962 : ae_int_t* modelversion,
54963 : ae_state *_state)
54964 : {
54965 :
54966 0 : *nx = 0;
54967 0 : *ny = 0;
54968 0 : ae_matrix_clear(xwr);
54969 0 : *nc = 0;
54970 0 : ae_matrix_clear(v);
54971 0 : *modelversion = 0;
54972 :
54973 0 : if( s->modelversion==1 )
54974 : {
54975 0 : *modelversion = 1;
54976 0 : rbfv1unpack(&s->model1, nx, ny, xwr, nc, v, _state);
54977 0 : return;
54978 : }
54979 0 : if( s->modelversion==2 )
54980 : {
54981 0 : *modelversion = 2;
54982 0 : rbfv2unpack(&s->model2, nx, ny, xwr, nc, v, _state);
54983 0 : return;
54984 : }
54985 0 : ae_assert(ae_false, "RBFUnpack: integrity check failure", _state);
54986 : }
54987 :
54988 :
54989 : /*************************************************************************
54990 : This function returns model version.
54991 :
54992 : INPUT PARAMETERS:
54993 : S - RBF model
54994 :
54995 : RESULT:
54996 : * 1 - for models created by QNN and RBF-ML algorithms,
54997 : compatible with ALGLIB 3.10 or earlier.
54998 : * 2 - for models created by HierarchicalRBF, requires
54999 : ALGLIB 3.11 or later
55000 :
55001 : -- ALGLIB --
55002 : Copyright 06.07.2016 by Bochkanov Sergey
55003 : *************************************************************************/
55004 0 : ae_int_t rbfgetmodelversion(rbfmodel* s, ae_state *_state)
55005 : {
55006 : ae_int_t result;
55007 :
55008 :
55009 0 : result = s->modelversion;
55010 0 : return result;
55011 : }
55012 :
55013 :
55014 : /*************************************************************************
55015 : This function is used to peek into hierarchical RBF construction process
55016 : from some other thread and get current progress indicator. It returns
55017 : value in [0,1].
55018 :
55019 : IMPORTANT: only HRBFs (hierarchical RBFs) support peeking into progress
55020 : indicator. Legacy RBF-ML and RBF-QNN do not support it. You
55021 : will always get 0 value.
55022 :
55023 : INPUT PARAMETERS:
55024 : S - RBF model object
55025 :
55026 : RESULT:
55027 : progress value, in [0,1]
55028 :
55029 : -- ALGLIB --
55030 : Copyright 17.11.2018 by Bochkanov Sergey
55031 : *************************************************************************/
55032 0 : double rbfpeekprogress(rbfmodel* s, ae_state *_state)
55033 : {
55034 : double result;
55035 :
55036 :
55037 0 : result = (double)s->progress10000/(double)10000;
55038 0 : return result;
55039 : }
55040 :
55041 :
55042 : /*************************************************************************
55043 : This function is used to submit a request for termination of the
55044 : hierarchical RBF construction process from some other thread. As result,
55045 : RBF construction is terminated smoothly (with proper deallocation of all
55046 : necessary resources) and resultant model is filled by zeros.
55047 :
55048 : A rep.terminationtype=8 will be returned upon receiving such request.
55049 :
55050 : IMPORTANT: only HRBFs (hierarchical RBFs) support termination requests.
55051 : Legacy RBF-ML and RBF-QNN do not support it. An attempt to
55052 : terminate their construction will be ignored.
55053 :
55054 : IMPORTANT: termination request flag is cleared when the model construction
55055 : starts. Thus, any pre-construction termination requests will be
55056 : silently ignored - only ones submitted AFTER construction has
55057 : actually began will be handled.
55058 :
55059 : INPUT PARAMETERS:
55060 : S - RBF model object
55061 :
55062 : -- ALGLIB --
55063 : Copyright 17.11.2018 by Bochkanov Sergey
55064 : *************************************************************************/
55065 0 : void rbfrequesttermination(rbfmodel* s, ae_state *_state)
55066 : {
55067 :
55068 :
55069 0 : s->terminationrequest = ae_true;
55070 0 : }
55071 :
55072 :
55073 : /*************************************************************************
55074 : Serializer: allocation
55075 :
55076 : -- ALGLIB --
55077 : Copyright 02.02.2012 by Bochkanov Sergey
55078 : *************************************************************************/
55079 0 : void rbfalloc(ae_serializer* s, rbfmodel* model, ae_state *_state)
55080 : {
55081 :
55082 :
55083 :
55084 : /*
55085 : * Header
55086 : */
55087 0 : ae_serializer_alloc_entry(s);
55088 :
55089 : /*
55090 : * V1 model
55091 : */
55092 0 : if( model->modelversion==1 )
55093 : {
55094 :
55095 : /*
55096 : * Header
55097 : */
55098 0 : ae_serializer_alloc_entry(s);
55099 0 : rbfv1alloc(s, &model->model1, _state);
55100 0 : return;
55101 : }
55102 :
55103 : /*
55104 : * V2 model
55105 : */
55106 0 : if( model->modelversion==2 )
55107 : {
55108 :
55109 : /*
55110 : * Header
55111 : */
55112 0 : ae_serializer_alloc_entry(s);
55113 0 : rbfv2alloc(s, &model->model2, _state);
55114 0 : return;
55115 : }
55116 0 : ae_assert(ae_false, "Assertion failed", _state);
55117 : }
55118 :
55119 :
55120 : /*************************************************************************
55121 : Serializer: serialization
55122 :
55123 : -- ALGLIB --
55124 : Copyright 02.02.2012 by Bochkanov Sergey
55125 : *************************************************************************/
55126 0 : void rbfserialize(ae_serializer* s, rbfmodel* model, ae_state *_state)
55127 : {
55128 :
55129 :
55130 :
55131 : /*
55132 : * Header
55133 : */
55134 0 : ae_serializer_serialize_int(s, getrbfserializationcode(_state), _state);
55135 :
55136 : /*
55137 : * V1 model
55138 : */
55139 0 : if( model->modelversion==1 )
55140 : {
55141 0 : ae_serializer_serialize_int(s, rbf_rbffirstversion, _state);
55142 0 : rbfv1serialize(s, &model->model1, _state);
55143 0 : return;
55144 : }
55145 :
55146 : /*
55147 : * V2 model
55148 : */
55149 0 : if( model->modelversion==2 )
55150 : {
55151 :
55152 : /*
55153 : * Header
55154 : */
55155 0 : ae_serializer_serialize_int(s, rbf_rbfversion2, _state);
55156 0 : rbfv2serialize(s, &model->model2, _state);
55157 0 : return;
55158 : }
55159 0 : ae_assert(ae_false, "Assertion failed", _state);
55160 : }
55161 :
55162 :
55163 : /*************************************************************************
55164 : Serializer: unserialization
55165 :
55166 : -- ALGLIB --
55167 : Copyright 02.02.2012 by Bochkanov Sergey
55168 : *************************************************************************/
55169 0 : void rbfunserialize(ae_serializer* s, rbfmodel* model, ae_state *_state)
55170 : {
55171 : ae_int_t i0;
55172 : ae_int_t i1;
55173 :
55174 0 : _rbfmodel_clear(model);
55175 :
55176 0 : rbf_rbfpreparenonserializablefields(model, _state);
55177 :
55178 : /*
55179 : * Header
55180 : */
55181 0 : ae_serializer_unserialize_int(s, &i0, _state);
55182 0 : ae_assert(i0==getrbfserializationcode(_state), "RBFUnserialize: stream header corrupted", _state);
55183 0 : ae_serializer_unserialize_int(s, &i1, _state);
55184 0 : ae_assert(i1==rbf_rbffirstversion||i1==rbf_rbfversion2, "RBFUnserialize: stream header corrupted", _state);
55185 :
55186 : /*
55187 : * V1 model
55188 : */
55189 0 : if( i1==rbf_rbffirstversion )
55190 : {
55191 0 : rbfv1unserialize(s, &model->model1, _state);
55192 0 : model->modelversion = 1;
55193 0 : model->ny = model->model1.ny;
55194 0 : model->nx = model->model1.nx;
55195 0 : rbf_initializev2(model->nx, model->ny, &model->model2, _state);
55196 0 : return;
55197 : }
55198 :
55199 : /*
55200 : * V2 model
55201 : */
55202 0 : if( i1==rbf_rbfversion2 )
55203 : {
55204 0 : rbfv2unserialize(s, &model->model2, _state);
55205 0 : model->modelversion = 2;
55206 0 : model->ny = model->model2.ny;
55207 0 : model->nx = model->model2.nx;
55208 0 : rbf_initializev1(model->nx, model->ny, &model->model1, _state);
55209 0 : return;
55210 : }
55211 0 : ae_assert(ae_false, "Assertion failed", _state);
55212 : }
55213 :
55214 :
55215 : /*************************************************************************
55216 : Initialize empty model
55217 :
55218 : -- ALGLIB --
55219 : Copyright 12.05.2016 by Bochkanov Sergey
55220 : *************************************************************************/
55221 0 : static void rbf_rbfpreparenonserializablefields(rbfmodel* s,
55222 : ae_state *_state)
55223 : {
55224 :
55225 :
55226 0 : s->n = 0;
55227 0 : s->hasscale = ae_false;
55228 0 : s->radvalue = (double)(1);
55229 0 : s->radzvalue = (double)(5);
55230 0 : s->nlayers = 0;
55231 0 : s->lambdav = (double)(0);
55232 0 : s->aterm = 1;
55233 0 : s->algorithmtype = 0;
55234 0 : s->epsort = rbf_eps;
55235 0 : s->epserr = rbf_eps;
55236 0 : s->maxits = 0;
55237 0 : s->nnmaxits = 100;
55238 0 : }
55239 :
55240 :
55241 : /*************************************************************************
55242 : Initialize V1 model (skip initialization for NX=1 or NX>3)
55243 :
55244 : -- ALGLIB --
55245 : Copyright 12.05.2016 by Bochkanov Sergey
55246 : *************************************************************************/
55247 0 : static void rbf_initializev1(ae_int_t nx,
55248 : ae_int_t ny,
55249 : rbfv1model* s,
55250 : ae_state *_state)
55251 : {
55252 :
55253 0 : _rbfv1model_clear(s);
55254 :
55255 0 : if( nx==2||nx==3 )
55256 : {
55257 0 : rbfv1create(nx, ny, s, _state);
55258 : }
55259 0 : }
55260 :
55261 :
55262 : /*************************************************************************
55263 : Initialize V2 model
55264 :
55265 : -- ALGLIB --
55266 : Copyright 12.05.2016 by Bochkanov Sergey
55267 : *************************************************************************/
55268 0 : static void rbf_initializev2(ae_int_t nx,
55269 : ae_int_t ny,
55270 : rbfv2model* s,
55271 : ae_state *_state)
55272 : {
55273 :
55274 0 : _rbfv2model_clear(s);
55275 :
55276 0 : rbfv2create(nx, ny, s, _state);
55277 0 : }
55278 :
55279 :
55280 : /*************************************************************************
55281 : Cleans report fields
55282 :
55283 : -- ALGLIB --
55284 : Copyright 16.06.2016 by Bochkanov Sergey
55285 : *************************************************************************/
55286 0 : static void rbf_clearreportfields(rbfreport* rep, ae_state *_state)
55287 : {
55288 :
55289 :
55290 0 : rep->rmserror = _state->v_nan;
55291 0 : rep->maxerror = _state->v_nan;
55292 0 : rep->arows = 0;
55293 0 : rep->acols = 0;
55294 0 : rep->annz = 0;
55295 0 : rep->iterationscount = 0;
55296 0 : rep->nmv = 0;
55297 0 : rep->terminationtype = 0;
55298 0 : }
55299 :
55300 :
55301 0 : void _rbfcalcbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic)
55302 : {
55303 0 : rbfcalcbuffer *p = (rbfcalcbuffer*)_p;
55304 0 : ae_touch_ptr((void*)p);
55305 0 : _rbfv1calcbuffer_init(&p->bufv1, _state, make_automatic);
55306 0 : _rbfv2calcbuffer_init(&p->bufv2, _state, make_automatic);
55307 0 : }
55308 :
55309 :
55310 0 : void _rbfcalcbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
55311 : {
55312 0 : rbfcalcbuffer *dst = (rbfcalcbuffer*)_dst;
55313 0 : rbfcalcbuffer *src = (rbfcalcbuffer*)_src;
55314 0 : dst->modelversion = src->modelversion;
55315 0 : _rbfv1calcbuffer_init_copy(&dst->bufv1, &src->bufv1, _state, make_automatic);
55316 0 : _rbfv2calcbuffer_init_copy(&dst->bufv2, &src->bufv2, _state, make_automatic);
55317 0 : }
55318 :
55319 :
55320 0 : void _rbfcalcbuffer_clear(void* _p)
55321 : {
55322 0 : rbfcalcbuffer *p = (rbfcalcbuffer*)_p;
55323 0 : ae_touch_ptr((void*)p);
55324 0 : _rbfv1calcbuffer_clear(&p->bufv1);
55325 0 : _rbfv2calcbuffer_clear(&p->bufv2);
55326 0 : }
55327 :
55328 :
55329 0 : void _rbfcalcbuffer_destroy(void* _p)
55330 : {
55331 0 : rbfcalcbuffer *p = (rbfcalcbuffer*)_p;
55332 0 : ae_touch_ptr((void*)p);
55333 0 : _rbfv1calcbuffer_destroy(&p->bufv1);
55334 0 : _rbfv2calcbuffer_destroy(&p->bufv2);
55335 0 : }
55336 :
55337 :
55338 0 : void _rbfmodel_init(void* _p, ae_state *_state, ae_bool make_automatic)
55339 : {
55340 0 : rbfmodel *p = (rbfmodel*)_p;
55341 0 : ae_touch_ptr((void*)p);
55342 0 : _rbfv1model_init(&p->model1, _state, make_automatic);
55343 0 : _rbfv2model_init(&p->model2, _state, make_automatic);
55344 0 : ae_matrix_init(&p->x, 0, 0, DT_REAL, _state, make_automatic);
55345 0 : ae_matrix_init(&p->y, 0, 0, DT_REAL, _state, make_automatic);
55346 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
55347 0 : }
55348 :
55349 :
55350 0 : void _rbfmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
55351 : {
55352 0 : rbfmodel *dst = (rbfmodel*)_dst;
55353 0 : rbfmodel *src = (rbfmodel*)_src;
55354 0 : dst->nx = src->nx;
55355 0 : dst->ny = src->ny;
55356 0 : dst->modelversion = src->modelversion;
55357 0 : _rbfv1model_init_copy(&dst->model1, &src->model1, _state, make_automatic);
55358 0 : _rbfv2model_init_copy(&dst->model2, &src->model2, _state, make_automatic);
55359 0 : dst->lambdav = src->lambdav;
55360 0 : dst->radvalue = src->radvalue;
55361 0 : dst->radzvalue = src->radzvalue;
55362 0 : dst->nlayers = src->nlayers;
55363 0 : dst->aterm = src->aterm;
55364 0 : dst->algorithmtype = src->algorithmtype;
55365 0 : dst->epsort = src->epsort;
55366 0 : dst->epserr = src->epserr;
55367 0 : dst->maxits = src->maxits;
55368 0 : dst->nnmaxits = src->nnmaxits;
55369 0 : dst->n = src->n;
55370 0 : ae_matrix_init_copy(&dst->x, &src->x, _state, make_automatic);
55371 0 : ae_matrix_init_copy(&dst->y, &src->y, _state, make_automatic);
55372 0 : dst->hasscale = src->hasscale;
55373 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
55374 0 : dst->progress10000 = src->progress10000;
55375 0 : dst->terminationrequest = src->terminationrequest;
55376 0 : }
55377 :
55378 :
55379 0 : void _rbfmodel_clear(void* _p)
55380 : {
55381 0 : rbfmodel *p = (rbfmodel*)_p;
55382 0 : ae_touch_ptr((void*)p);
55383 0 : _rbfv1model_clear(&p->model1);
55384 0 : _rbfv2model_clear(&p->model2);
55385 0 : ae_matrix_clear(&p->x);
55386 0 : ae_matrix_clear(&p->y);
55387 0 : ae_vector_clear(&p->s);
55388 0 : }
55389 :
55390 :
55391 0 : void _rbfmodel_destroy(void* _p)
55392 : {
55393 0 : rbfmodel *p = (rbfmodel*)_p;
55394 0 : ae_touch_ptr((void*)p);
55395 0 : _rbfv1model_destroy(&p->model1);
55396 0 : _rbfv2model_destroy(&p->model2);
55397 0 : ae_matrix_destroy(&p->x);
55398 0 : ae_matrix_destroy(&p->y);
55399 0 : ae_vector_destroy(&p->s);
55400 0 : }
55401 :
55402 :
55403 0 : void _rbfreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
55404 : {
55405 0 : rbfreport *p = (rbfreport*)_p;
55406 0 : ae_touch_ptr((void*)p);
55407 0 : }
55408 :
55409 :
55410 0 : void _rbfreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
55411 : {
55412 0 : rbfreport *dst = (rbfreport*)_dst;
55413 0 : rbfreport *src = (rbfreport*)_src;
55414 0 : dst->rmserror = src->rmserror;
55415 0 : dst->maxerror = src->maxerror;
55416 0 : dst->arows = src->arows;
55417 0 : dst->acols = src->acols;
55418 0 : dst->annz = src->annz;
55419 0 : dst->iterationscount = src->iterationscount;
55420 0 : dst->nmv = src->nmv;
55421 0 : dst->terminationtype = src->terminationtype;
55422 0 : }
55423 :
55424 :
55425 0 : void _rbfreport_clear(void* _p)
55426 : {
55427 0 : rbfreport *p = (rbfreport*)_p;
55428 0 : ae_touch_ptr((void*)p);
55429 0 : }
55430 :
55431 :
55432 0 : void _rbfreport_destroy(void* _p)
55433 : {
55434 0 : rbfreport *p = (rbfreport*)_p;
55435 0 : ae_touch_ptr((void*)p);
55436 0 : }
55437 :
55438 :
55439 : #endif
55440 : #if defined(AE_COMPILE_INTCOMP) || !defined(AE_PARTIAL_BUILD)
55441 :
55442 :
55443 : /*************************************************************************
55444 : This function is left for backward compatibility.
55445 : Use fitspheremc() instead.
55446 :
55447 :
55448 : -- ALGLIB --
55449 : Copyright 14.04.2017 by Bochkanov Sergey
55450 : *************************************************************************/
55451 0 : void nsfitspheremcc(/* Real */ ae_matrix* xy,
55452 : ae_int_t npoints,
55453 : ae_int_t nx,
55454 : /* Real */ ae_vector* cx,
55455 : double* rhi,
55456 : ae_state *_state)
55457 : {
55458 : double dummy;
55459 :
55460 0 : ae_vector_clear(cx);
55461 0 : *rhi = 0;
55462 :
55463 0 : nsfitspherex(xy, npoints, nx, 1, 0.0, 0, 0.0, cx, &dummy, rhi, _state);
55464 0 : }
55465 :
55466 :
55467 : /*************************************************************************
55468 : This function is left for backward compatibility.
55469 : Use fitspheremi() instead.
55470 :
55471 : -- ALGLIB --
55472 : Copyright 14.04.2017 by Bochkanov Sergey
55473 : *************************************************************************/
55474 0 : void nsfitspheremic(/* Real */ ae_matrix* xy,
55475 : ae_int_t npoints,
55476 : ae_int_t nx,
55477 : /* Real */ ae_vector* cx,
55478 : double* rlo,
55479 : ae_state *_state)
55480 : {
55481 : double dummy;
55482 :
55483 0 : ae_vector_clear(cx);
55484 0 : *rlo = 0;
55485 :
55486 0 : nsfitspherex(xy, npoints, nx, 2, 0.0, 0, 0.0, cx, rlo, &dummy, _state);
55487 0 : }
55488 :
55489 :
55490 : /*************************************************************************
55491 : This function is left for backward compatibility.
55492 : Use fitspheremz() instead.
55493 :
55494 : -- ALGLIB --
55495 : Copyright 14.04.2017 by Bochkanov Sergey
55496 : *************************************************************************/
55497 0 : void nsfitspheremzc(/* Real */ ae_matrix* xy,
55498 : ae_int_t npoints,
55499 : ae_int_t nx,
55500 : /* Real */ ae_vector* cx,
55501 : double* rlo,
55502 : double* rhi,
55503 : ae_state *_state)
55504 : {
55505 :
55506 0 : ae_vector_clear(cx);
55507 0 : *rlo = 0;
55508 0 : *rhi = 0;
55509 :
55510 0 : nsfitspherex(xy, npoints, nx, 3, 0.0, 0, 0.0, cx, rlo, rhi, _state);
55511 0 : }
55512 :
55513 :
55514 : /*************************************************************************
55515 : This function is left for backward compatibility.
55516 : Use fitspherex() instead.
55517 :
55518 : -- ALGLIB --
55519 : Copyright 14.04.2017 by Bochkanov Sergey
55520 : *************************************************************************/
55521 0 : void nsfitspherex(/* Real */ ae_matrix* xy,
55522 : ae_int_t npoints,
55523 : ae_int_t nx,
55524 : ae_int_t problemtype,
55525 : double epsx,
55526 : ae_int_t aulits,
55527 : double penalty,
55528 : /* Real */ ae_vector* cx,
55529 : double* rlo,
55530 : double* rhi,
55531 : ae_state *_state)
55532 : {
55533 :
55534 0 : ae_vector_clear(cx);
55535 0 : *rlo = 0;
55536 0 : *rhi = 0;
55537 :
55538 0 : fitspherex(xy, npoints, nx, problemtype, epsx, aulits, penalty, cx, rlo, rhi, _state);
55539 0 : }
55540 :
55541 :
55542 : /*************************************************************************
55543 : This function is an obsolete and deprecated version of fitting by
55544 : penalized cubic spline.
55545 :
55546 : It was superseded by spline1dfit(), which is an orders of magnitude faster
55547 : and more memory-efficient implementation.
55548 :
55549 : Do NOT use this function in the new code!
55550 :
55551 : -- ALGLIB PROJECT --
55552 : Copyright 18.08.2009 by Bochkanov Sergey
55553 : *************************************************************************/
55554 0 : void spline1dfitpenalized(/* Real */ ae_vector* x,
55555 : /* Real */ ae_vector* y,
55556 : ae_int_t n,
55557 : ae_int_t m,
55558 : double rho,
55559 : ae_int_t* info,
55560 : spline1dinterpolant* s,
55561 : spline1dfitreport* rep,
55562 : ae_state *_state)
55563 : {
55564 : ae_frame _frame_block;
55565 : ae_vector _x;
55566 : ae_vector _y;
55567 : ae_vector w;
55568 : ae_int_t i;
55569 :
55570 0 : ae_frame_make(_state, &_frame_block);
55571 0 : memset(&_x, 0, sizeof(_x));
55572 0 : memset(&_y, 0, sizeof(_y));
55573 0 : memset(&w, 0, sizeof(w));
55574 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
55575 0 : x = &_x;
55576 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
55577 0 : y = &_y;
55578 0 : *info = 0;
55579 0 : _spline1dinterpolant_clear(s);
55580 0 : _spline1dfitreport_clear(rep);
55581 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
55582 :
55583 0 : ae_assert(n>=1, "Spline1DFitPenalized: N<1!", _state);
55584 0 : ae_assert(m>=4, "Spline1DFitPenalized: M<4!", _state);
55585 0 : ae_assert(x->cnt>=n, "Spline1DFitPenalized: Length(X)<N!", _state);
55586 0 : ae_assert(y->cnt>=n, "Spline1DFitPenalized: Length(Y)<N!", _state);
55587 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DFitPenalized: X contains infinite or NAN values!", _state);
55588 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DFitPenalized: Y contains infinite or NAN values!", _state);
55589 0 : ae_assert(ae_isfinite(rho, _state), "Spline1DFitPenalized: Rho is infinite!", _state);
55590 0 : ae_vector_set_length(&w, n, _state);
55591 0 : for(i=0; i<=n-1; i++)
55592 : {
55593 0 : w.ptr.p_double[i] = (double)(1);
55594 : }
55595 0 : spline1dfitpenalizedw(x, y, &w, n, m, rho, info, s, rep, _state);
55596 0 : ae_frame_leave(_state);
55597 0 : }
55598 :
55599 :
55600 : /*************************************************************************
55601 : This function is an obsolete and deprecated version of fitting by
55602 : penalized cubic spline.
55603 :
55604 : It was superseded by spline1dfit(), which is an orders of magnitude faster
55605 : and more memory-efficient implementation.
55606 :
55607 : Do NOT use this function in the new code!
55608 :
55609 : -- ALGLIB PROJECT --
55610 : Copyright 19.10.2010 by Bochkanov Sergey
55611 : *************************************************************************/
55612 0 : void spline1dfitpenalizedw(/* Real */ ae_vector* x,
55613 : /* Real */ ae_vector* y,
55614 : /* Real */ ae_vector* w,
55615 : ae_int_t n,
55616 : ae_int_t m,
55617 : double rho,
55618 : ae_int_t* info,
55619 : spline1dinterpolant* s,
55620 : spline1dfitreport* rep,
55621 : ae_state *_state)
55622 : {
55623 : ae_frame _frame_block;
55624 : ae_vector _x;
55625 : ae_vector _y;
55626 : ae_vector _w;
55627 : ae_int_t i;
55628 : ae_int_t j;
55629 : ae_int_t b;
55630 : double v;
55631 : double relcnt;
55632 : double xa;
55633 : double xb;
55634 : double sa;
55635 : double sb;
55636 : ae_vector xoriginal;
55637 : ae_vector yoriginal;
55638 : double pdecay;
55639 : double tdecay;
55640 : ae_matrix fmatrix;
55641 : ae_vector fcolumn;
55642 : ae_vector y2;
55643 : ae_vector w2;
55644 : ae_vector xc;
55645 : ae_vector yc;
55646 : ae_vector dc;
55647 : double fdmax;
55648 : double admax;
55649 : ae_matrix amatrix;
55650 : ae_matrix d2matrix;
55651 : double fa;
55652 : double ga;
55653 : double fb;
55654 : double gb;
55655 : double lambdav;
55656 : ae_vector bx;
55657 : ae_vector by;
55658 : ae_vector bd1;
55659 : ae_vector bd2;
55660 : ae_vector tx;
55661 : ae_vector ty;
55662 : ae_vector td;
55663 : spline1dinterpolant bs;
55664 : ae_matrix nmatrix;
55665 : ae_vector rightpart;
55666 : fblslincgstate cgstate;
55667 : ae_vector c;
55668 : ae_vector tmp0;
55669 :
55670 0 : ae_frame_make(_state, &_frame_block);
55671 0 : memset(&_x, 0, sizeof(_x));
55672 0 : memset(&_y, 0, sizeof(_y));
55673 0 : memset(&_w, 0, sizeof(_w));
55674 0 : memset(&xoriginal, 0, sizeof(xoriginal));
55675 0 : memset(&yoriginal, 0, sizeof(yoriginal));
55676 0 : memset(&fmatrix, 0, sizeof(fmatrix));
55677 0 : memset(&fcolumn, 0, sizeof(fcolumn));
55678 0 : memset(&y2, 0, sizeof(y2));
55679 0 : memset(&w2, 0, sizeof(w2));
55680 0 : memset(&xc, 0, sizeof(xc));
55681 0 : memset(&yc, 0, sizeof(yc));
55682 0 : memset(&dc, 0, sizeof(dc));
55683 0 : memset(&amatrix, 0, sizeof(amatrix));
55684 0 : memset(&d2matrix, 0, sizeof(d2matrix));
55685 0 : memset(&bx, 0, sizeof(bx));
55686 0 : memset(&by, 0, sizeof(by));
55687 0 : memset(&bd1, 0, sizeof(bd1));
55688 0 : memset(&bd2, 0, sizeof(bd2));
55689 0 : memset(&tx, 0, sizeof(tx));
55690 0 : memset(&ty, 0, sizeof(ty));
55691 0 : memset(&td, 0, sizeof(td));
55692 0 : memset(&bs, 0, sizeof(bs));
55693 0 : memset(&nmatrix, 0, sizeof(nmatrix));
55694 0 : memset(&rightpart, 0, sizeof(rightpart));
55695 0 : memset(&cgstate, 0, sizeof(cgstate));
55696 0 : memset(&c, 0, sizeof(c));
55697 0 : memset(&tmp0, 0, sizeof(tmp0));
55698 0 : ae_vector_init_copy(&_x, x, _state, ae_true);
55699 0 : x = &_x;
55700 0 : ae_vector_init_copy(&_y, y, _state, ae_true);
55701 0 : y = &_y;
55702 0 : ae_vector_init_copy(&_w, w, _state, ae_true);
55703 0 : w = &_w;
55704 0 : *info = 0;
55705 0 : _spline1dinterpolant_clear(s);
55706 0 : _spline1dfitreport_clear(rep);
55707 0 : ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
55708 0 : ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
55709 0 : ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
55710 0 : ae_vector_init(&fcolumn, 0, DT_REAL, _state, ae_true);
55711 0 : ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
55712 0 : ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
55713 0 : ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
55714 0 : ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
55715 0 : ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
55716 0 : ae_matrix_init(&amatrix, 0, 0, DT_REAL, _state, ae_true);
55717 0 : ae_matrix_init(&d2matrix, 0, 0, DT_REAL, _state, ae_true);
55718 0 : ae_vector_init(&bx, 0, DT_REAL, _state, ae_true);
55719 0 : ae_vector_init(&by, 0, DT_REAL, _state, ae_true);
55720 0 : ae_vector_init(&bd1, 0, DT_REAL, _state, ae_true);
55721 0 : ae_vector_init(&bd2, 0, DT_REAL, _state, ae_true);
55722 0 : ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
55723 0 : ae_vector_init(&ty, 0, DT_REAL, _state, ae_true);
55724 0 : ae_vector_init(&td, 0, DT_REAL, _state, ae_true);
55725 0 : _spline1dinterpolant_init(&bs, _state, ae_true);
55726 0 : ae_matrix_init(&nmatrix, 0, 0, DT_REAL, _state, ae_true);
55727 0 : ae_vector_init(&rightpart, 0, DT_REAL, _state, ae_true);
55728 0 : _fblslincgstate_init(&cgstate, _state, ae_true);
55729 0 : ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
55730 0 : ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
55731 :
55732 0 : ae_assert(n>=1, "Spline1DFitPenalizedW: N<1!", _state);
55733 0 : ae_assert(m>=4, "Spline1DFitPenalizedW: M<4!", _state);
55734 0 : ae_assert(x->cnt>=n, "Spline1DFitPenalizedW: Length(X)<N!", _state);
55735 0 : ae_assert(y->cnt>=n, "Spline1DFitPenalizedW: Length(Y)<N!", _state);
55736 0 : ae_assert(w->cnt>=n, "Spline1DFitPenalizedW: Length(W)<N!", _state);
55737 0 : ae_assert(isfinitevector(x, n, _state), "Spline1DFitPenalizedW: X contains infinite or NAN values!", _state);
55738 0 : ae_assert(isfinitevector(y, n, _state), "Spline1DFitPenalizedW: Y contains infinite or NAN values!", _state);
55739 0 : ae_assert(isfinitevector(w, n, _state), "Spline1DFitPenalizedW: Y contains infinite or NAN values!", _state);
55740 0 : ae_assert(ae_isfinite(rho, _state), "Spline1DFitPenalizedW: Rho is infinite!", _state);
55741 :
55742 : /*
55743 : * Prepare LambdaV
55744 : */
55745 0 : v = -ae_log(ae_machineepsilon, _state)/ae_log((double)(10), _state);
55746 0 : if( ae_fp_less(rho,-v) )
55747 : {
55748 0 : rho = -v;
55749 : }
55750 0 : if( ae_fp_greater(rho,v) )
55751 : {
55752 0 : rho = v;
55753 : }
55754 0 : lambdav = ae_pow((double)(10), rho, _state);
55755 :
55756 : /*
55757 : * Sort X, Y, W
55758 : */
55759 0 : heapsortdpoints(x, y, w, n, _state);
55760 :
55761 : /*
55762 : * Scale X, Y, XC, YC
55763 : */
55764 0 : lsfitscalexy(x, y, w, n, &xc, &yc, &dc, 0, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
55765 :
55766 : /*
55767 : * Allocate space
55768 : */
55769 0 : ae_matrix_set_length(&fmatrix, n, m, _state);
55770 0 : ae_matrix_set_length(&amatrix, m, m, _state);
55771 0 : ae_matrix_set_length(&d2matrix, m, m, _state);
55772 0 : ae_vector_set_length(&bx, m, _state);
55773 0 : ae_vector_set_length(&by, m, _state);
55774 0 : ae_vector_set_length(&fcolumn, n, _state);
55775 0 : ae_matrix_set_length(&nmatrix, m, m, _state);
55776 0 : ae_vector_set_length(&rightpart, m, _state);
55777 0 : ae_vector_set_length(&tmp0, ae_maxint(m, n, _state), _state);
55778 0 : ae_vector_set_length(&c, m, _state);
55779 :
55780 : /*
55781 : * Fill:
55782 : * * FMatrix by values of basis functions
55783 : * * TmpAMatrix by second derivatives of I-th function at J-th point
55784 : * * CMatrix by constraints
55785 : */
55786 0 : fdmax = (double)(0);
55787 0 : for(b=0; b<=m-1; b++)
55788 : {
55789 :
55790 : /*
55791 : * Prepare I-th basis function
55792 : */
55793 0 : for(j=0; j<=m-1; j++)
55794 : {
55795 0 : bx.ptr.p_double[j] = (double)(2*j)/(double)(m-1)-1;
55796 0 : by.ptr.p_double[j] = (double)(0);
55797 : }
55798 0 : by.ptr.p_double[b] = (double)(1);
55799 0 : spline1dgriddiff2cubic(&bx, &by, m, 2, 0.0, 2, 0.0, &bd1, &bd2, _state);
55800 0 : spline1dbuildcubic(&bx, &by, m, 2, 0.0, 2, 0.0, &bs, _state);
55801 :
55802 : /*
55803 : * Calculate B-th column of FMatrix
55804 : * Update FDMax (maximum column norm)
55805 : */
55806 0 : spline1dconvcubic(&bx, &by, m, 2, 0.0, 2, 0.0, x, n, &fcolumn, _state);
55807 0 : ae_v_move(&fmatrix.ptr.pp_double[0][b], fmatrix.stride, &fcolumn.ptr.p_double[0], 1, ae_v_len(0,n-1));
55808 0 : v = (double)(0);
55809 0 : for(i=0; i<=n-1; i++)
55810 : {
55811 0 : v = v+ae_sqr(w->ptr.p_double[i]*fcolumn.ptr.p_double[i], _state);
55812 : }
55813 0 : fdmax = ae_maxreal(fdmax, v, _state);
55814 :
55815 : /*
55816 : * Fill temporary with second derivatives of basis function
55817 : */
55818 0 : ae_v_move(&d2matrix.ptr.pp_double[b][0], 1, &bd2.ptr.p_double[0], 1, ae_v_len(0,m-1));
55819 : }
55820 :
55821 : /*
55822 : * * calculate penalty matrix A
55823 : * * calculate max of diagonal elements of A
55824 : * * calculate PDecay - coefficient before penalty matrix
55825 : */
55826 0 : for(i=0; i<=m-1; i++)
55827 : {
55828 0 : for(j=i; j<=m-1; j++)
55829 : {
55830 :
55831 : /*
55832 : * calculate integral(B_i''*B_j'') where B_i and B_j are
55833 : * i-th and j-th basis splines.
55834 : * B_i and B_j are piecewise linear functions.
55835 : */
55836 0 : v = (double)(0);
55837 0 : for(b=0; b<=m-2; b++)
55838 : {
55839 0 : fa = d2matrix.ptr.pp_double[i][b];
55840 0 : fb = d2matrix.ptr.pp_double[i][b+1];
55841 0 : ga = d2matrix.ptr.pp_double[j][b];
55842 0 : gb = d2matrix.ptr.pp_double[j][b+1];
55843 0 : v = v+(bx.ptr.p_double[b+1]-bx.ptr.p_double[b])*(fa*ga+(fa*(gb-ga)+ga*(fb-fa))/2+(fb-fa)*(gb-ga)/3);
55844 : }
55845 0 : amatrix.ptr.pp_double[i][j] = v;
55846 0 : amatrix.ptr.pp_double[j][i] = v;
55847 : }
55848 : }
55849 0 : admax = (double)(0);
55850 0 : for(i=0; i<=m-1; i++)
55851 : {
55852 0 : admax = ae_maxreal(admax, ae_fabs(amatrix.ptr.pp_double[i][i], _state), _state);
55853 : }
55854 0 : pdecay = lambdav*fdmax/admax;
55855 :
55856 : /*
55857 : * Calculate TDecay for Tikhonov regularization
55858 : */
55859 0 : tdecay = fdmax*(1+pdecay)*10*ae_machineepsilon;
55860 :
55861 : /*
55862 : * Prepare system
55863 : *
55864 : * NOTE: FMatrix is spoiled during this process
55865 : */
55866 0 : for(i=0; i<=n-1; i++)
55867 : {
55868 0 : v = w->ptr.p_double[i];
55869 0 : ae_v_muld(&fmatrix.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
55870 : }
55871 0 : rmatrixgemm(m, m, n, 1.0, &fmatrix, 0, 0, 1, &fmatrix, 0, 0, 0, 0.0, &nmatrix, 0, 0, _state);
55872 0 : for(i=0; i<=m-1; i++)
55873 : {
55874 0 : for(j=0; j<=m-1; j++)
55875 : {
55876 0 : nmatrix.ptr.pp_double[i][j] = nmatrix.ptr.pp_double[i][j]+pdecay*amatrix.ptr.pp_double[i][j];
55877 : }
55878 : }
55879 0 : for(i=0; i<=m-1; i++)
55880 : {
55881 0 : nmatrix.ptr.pp_double[i][i] = nmatrix.ptr.pp_double[i][i]+tdecay;
55882 : }
55883 0 : for(i=0; i<=m-1; i++)
55884 : {
55885 0 : rightpart.ptr.p_double[i] = (double)(0);
55886 : }
55887 0 : for(i=0; i<=n-1; i++)
55888 : {
55889 0 : v = y->ptr.p_double[i]*w->ptr.p_double[i];
55890 0 : ae_v_addd(&rightpart.ptr.p_double[0], 1, &fmatrix.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
55891 : }
55892 :
55893 : /*
55894 : * Solve system
55895 : */
55896 0 : if( !spdmatrixcholesky(&nmatrix, m, ae_true, _state) )
55897 : {
55898 0 : *info = -4;
55899 0 : ae_frame_leave(_state);
55900 0 : return;
55901 : }
55902 0 : fblscholeskysolve(&nmatrix, 1.0, m, ae_true, &rightpart, &tmp0, _state);
55903 0 : ae_v_move(&c.ptr.p_double[0], 1, &rightpart.ptr.p_double[0], 1, ae_v_len(0,m-1));
55904 :
55905 : /*
55906 : * add nodes to force linearity outside of the fitting interval
55907 : */
55908 0 : spline1dgriddiffcubic(&bx, &c, m, 2, 0.0, 2, 0.0, &bd1, _state);
55909 0 : ae_vector_set_length(&tx, m+2, _state);
55910 0 : ae_vector_set_length(&ty, m+2, _state);
55911 0 : ae_vector_set_length(&td, m+2, _state);
55912 0 : ae_v_move(&tx.ptr.p_double[1], 1, &bx.ptr.p_double[0], 1, ae_v_len(1,m));
55913 0 : ae_v_move(&ty.ptr.p_double[1], 1, &rightpart.ptr.p_double[0], 1, ae_v_len(1,m));
55914 0 : ae_v_move(&td.ptr.p_double[1], 1, &bd1.ptr.p_double[0], 1, ae_v_len(1,m));
55915 0 : tx.ptr.p_double[0] = tx.ptr.p_double[1]-(tx.ptr.p_double[2]-tx.ptr.p_double[1]);
55916 0 : ty.ptr.p_double[0] = ty.ptr.p_double[1]-td.ptr.p_double[1]*(tx.ptr.p_double[2]-tx.ptr.p_double[1]);
55917 0 : td.ptr.p_double[0] = td.ptr.p_double[1];
55918 0 : tx.ptr.p_double[m+1] = tx.ptr.p_double[m]+(tx.ptr.p_double[m]-tx.ptr.p_double[m-1]);
55919 0 : ty.ptr.p_double[m+1] = ty.ptr.p_double[m]+td.ptr.p_double[m]*(tx.ptr.p_double[m]-tx.ptr.p_double[m-1]);
55920 0 : td.ptr.p_double[m+1] = td.ptr.p_double[m];
55921 0 : spline1dbuildhermite(&tx, &ty, &td, m+2, s, _state);
55922 0 : spline1dlintransx(s, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
55923 0 : spline1dlintransy(s, sb-sa, sa, _state);
55924 0 : *info = 1;
55925 :
55926 : /*
55927 : * Fill report
55928 : */
55929 0 : rep->rmserror = (double)(0);
55930 0 : rep->avgerror = (double)(0);
55931 0 : rep->avgrelerror = (double)(0);
55932 0 : rep->maxerror = (double)(0);
55933 0 : relcnt = (double)(0);
55934 0 : spline1dconvcubic(&bx, &rightpart, m, 2, 0.0, 2, 0.0, x, n, &fcolumn, _state);
55935 0 : for(i=0; i<=n-1; i++)
55936 : {
55937 0 : v = (sb-sa)*fcolumn.ptr.p_double[i]+sa;
55938 0 : rep->rmserror = rep->rmserror+ae_sqr(v-yoriginal.ptr.p_double[i], _state);
55939 0 : rep->avgerror = rep->avgerror+ae_fabs(v-yoriginal.ptr.p_double[i], _state);
55940 0 : if( ae_fp_neq(yoriginal.ptr.p_double[i],(double)(0)) )
55941 : {
55942 0 : rep->avgrelerror = rep->avgrelerror+ae_fabs(v-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state);
55943 0 : relcnt = relcnt+1;
55944 : }
55945 0 : rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v-yoriginal.ptr.p_double[i], _state), _state);
55946 : }
55947 0 : rep->rmserror = ae_sqrt(rep->rmserror/n, _state);
55948 0 : rep->avgerror = rep->avgerror/n;
55949 0 : if( ae_fp_neq(relcnt,(double)(0)) )
55950 : {
55951 0 : rep->avgrelerror = rep->avgrelerror/relcnt;
55952 : }
55953 0 : ae_frame_leave(_state);
55954 : }
55955 :
55956 :
55957 : #endif
55958 :
55959 : }
55960 :
|