Xmipp  v3.23.11-Nereus
interpolation.cpp
Go to the documentation of this file.
1 /*************************************************************************
2 Copyright (c) Sergey Bochkanov (ALGLIB project).
3 
4 >>> SOURCE LICENSE >>>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation (www.fsf.org); either version 2 of the
8 License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 A copy of the GNU General Public License is available at
16 http://www.fsf.org/licensing/licenses
17 >>> END OF LICENSE >>>
18 *************************************************************************/
19 #include "stdafx.h"
20 #include "interpolation.h"
21 
22 // disable some irrelevant warnings
23 #if (AE_COMPILER==AE_MSVC)
24 #pragma warning(disable:4100)
25 #pragma warning(disable:4127)
26 #pragma warning(disable:4702)
27 #pragma warning(disable:4996)
28 #endif
29 using namespace std;
30 
32 //
33 // THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
34 //
36 namespace alglib
37 {
38 
39 
40 /*************************************************************************
41 IDW interpolant.
42 *************************************************************************/
43 _idwinterpolant_owner::_idwinterpolant_owner()
44 {
46  if( p_struct==NULL )
47  throw ap_error("ALGLIB: malloc error");
48  if( !alglib_impl::_idwinterpolant_init(p_struct, NULL, ae_false) )
49  throw ap_error("ALGLIB: malloc error");
50 }
51 
52 _idwinterpolant_owner::_idwinterpolant_owner(const _idwinterpolant_owner &rhs)
53 {
55  if( p_struct==NULL )
56  throw ap_error("ALGLIB: malloc error");
57  if( !alglib_impl::_idwinterpolant_init_copy(p_struct, const_cast<alglib_impl::idwinterpolant*>(rhs.p_struct), NULL, ae_false) )
58  throw ap_error("ALGLIB: malloc error");
59 }
60 
61 _idwinterpolant_owner& _idwinterpolant_owner::operator=(const _idwinterpolant_owner &rhs)
62 {
63  if( this==&rhs )
64  return *this;
66  if( !alglib_impl::_idwinterpolant_init_copy(p_struct, const_cast<alglib_impl::idwinterpolant*>(rhs.p_struct), NULL, ae_false) )
67  throw ap_error("ALGLIB: malloc error");
68  return *this;
69 }
70 
71 _idwinterpolant_owner::~_idwinterpolant_owner()
72 {
74  ae_free(p_struct);
75 }
76 
77 alglib_impl::idwinterpolant* _idwinterpolant_owner::c_ptr()
78 {
79  return p_struct;
80 }
81 
82 alglib_impl::idwinterpolant* _idwinterpolant_owner::c_ptr() const
83 {
84  return const_cast<alglib_impl::idwinterpolant*>(p_struct);
85 }
86 idwinterpolant::idwinterpolant() : _idwinterpolant_owner()
87 {
88 }
89 
91 {
92 }
93 
95 {
96  if( this==&rhs )
97  return *this;
99  return *this;
100 }
101 
103 {
104 }
105 
106 /*************************************************************************
107 IDW interpolation
108 
109 INPUT PARAMETERS:
110  Z - IDW interpolant built with one of model building
111  subroutines.
112  X - array[0..NX-1], interpolation point
113 
114 Result:
115  IDW interpolant Z(X)
116 
117  -- ALGLIB --
118  Copyright 02.03.2010 by Bochkanov Sergey
119 *************************************************************************/
120 double idwcalc(const idwinterpolant &z, const real_1d_array &x)
121 {
122  alglib_impl::ae_state _alglib_env_state;
123  alglib_impl::ae_state_init(&_alglib_env_state);
124  try
125  {
126  double result = alglib_impl::idwcalc(const_cast<alglib_impl::idwinterpolant*>(z.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
127  alglib_impl::ae_state_clear(&_alglib_env_state);
128  return *(reinterpret_cast<double*>(&result));
129  }
131  {
132  throw ap_error(_alglib_env_state.error_msg);
133  }
134 }
135 
136 /*************************************************************************
137 IDW interpolant using modified Shepard method for uniform point
138 distributions.
139 
140 INPUT PARAMETERS:
141  XY - X and Y values, array[0..N-1,0..NX].
142  First NX columns contain X-values, last column contain
143  Y-values.
144  N - number of nodes, N>0.
145  NX - space dimension, NX>=1.
146  D - nodal function type, either:
147  * 0 constant model. Just for demonstration only, worst
148  model ever.
149  * 1 linear model, least squares fitting. Simpe model for
150  datasets too small for quadratic models
151  * 2 quadratic model, least squares fitting. Best model
152  available (if your dataset is large enough).
153  * -1 "fast" linear model, use with caution!!! It is
154  significantly faster than linear/quadratic and better
155  than constant model. But it is less robust (especially
156  in the presence of noise).
157  NQ - number of points used to calculate nodal functions (ignored
158  for constant models). NQ should be LARGER than:
159  * max(1.5*(1+NX),2^NX+1) for linear model,
160  * max(3/4*(NX+2)*(NX+1),2^NX+1) for quadratic model.
161  Values less than this threshold will be silently increased.
162  NW - number of points used to calculate weights and to interpolate.
163  Required: >=2^NX+1, values less than this threshold will be
164  silently increased.
165  Recommended value: about 2*NQ
166 
167 OUTPUT PARAMETERS:
168  Z - IDW interpolant.
169 
170 NOTES:
171  * best results are obtained with quadratic models, worst - with constant
172  models
173  * when N is large, NQ and NW must be significantly smaller than N both
174  to obtain optimal performance and to obtain optimal accuracy. In 2 or
175  3-dimensional tasks NQ=15 and NW=25 are good values to start with.
176  * NQ and NW may be greater than N. In such cases they will be
177  automatically decreased.
178  * this subroutine is always succeeds (as long as correct parameters are
179  passed).
180  * see 'Multivariate Interpolation of Large Sets of Scattered Data' by
181  Robert J. Renka for more information on this algorithm.
182  * this subroutine assumes that point distribution is uniform at the small
183  scales. If it isn't - for example, points are concentrated along
184  "lines", but "lines" distribution is uniform at the larger scale - then
185  you should use IDWBuildModifiedShepardR()
186 
187 
188  -- ALGLIB PROJECT --
189  Copyright 02.03.2010 by Bochkanov Sergey
190 *************************************************************************/
191 void idwbuildmodifiedshepard(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const ae_int_t d, const ae_int_t nq, const ae_int_t nw, idwinterpolant &z)
192 {
193  alglib_impl::ae_state _alglib_env_state;
194  alglib_impl::ae_state_init(&_alglib_env_state);
195  try
196  {
197  alglib_impl::idwbuildmodifiedshepard(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, nx, d, nq, nw, const_cast<alglib_impl::idwinterpolant*>(z.c_ptr()), &_alglib_env_state);
198  alglib_impl::ae_state_clear(&_alglib_env_state);
199  return;
200  }
202  {
203  throw ap_error(_alglib_env_state.error_msg);
204  }
205 }
206 
207 /*************************************************************************
208 IDW interpolant using modified Shepard method for non-uniform datasets.
209 
210 This type of model uses constant nodal functions and interpolates using
211 all nodes which are closer than user-specified radius R. It may be used
212 when points distribution is non-uniform at the small scale, but it is at
213 the distances as large as R.
214 
215 INPUT PARAMETERS:
216  XY - X and Y values, array[0..N-1,0..NX].
217  First NX columns contain X-values, last column contain
218  Y-values.
219  N - number of nodes, N>0.
220  NX - space dimension, NX>=1.
221  R - radius, R>0
222 
223 OUTPUT PARAMETERS:
224  Z - IDW interpolant.
225 
226 NOTES:
227 * if there is less than IDWKMin points within R-ball, algorithm selects
228  IDWKMin closest ones, so that continuity properties of interpolant are
229  preserved even far from points.
230 
231  -- ALGLIB PROJECT --
232  Copyright 11.04.2010 by Bochkanov Sergey
233 *************************************************************************/
234 void idwbuildmodifiedshepardr(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const double r, idwinterpolant &z)
235 {
236  alglib_impl::ae_state _alglib_env_state;
237  alglib_impl::ae_state_init(&_alglib_env_state);
238  try
239  {
240  alglib_impl::idwbuildmodifiedshepardr(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, nx, r, const_cast<alglib_impl::idwinterpolant*>(z.c_ptr()), &_alglib_env_state);
241  alglib_impl::ae_state_clear(&_alglib_env_state);
242  return;
243  }
245  {
246  throw ap_error(_alglib_env_state.error_msg);
247  }
248 }
249 
250 /*************************************************************************
251 IDW model for noisy data.
252 
253 This subroutine may be used to handle noisy data, i.e. data with noise in
254 OUTPUT values. It differs from IDWBuildModifiedShepard() in the following
255 aspects:
256 * nodal functions are not constrained to pass through nodes: Qi(xi)<>yi,
257  i.e. we have fitting instead of interpolation.
258 * weights which are used during least squares fitting stage are all equal
259  to 1.0 (independently of distance)
260 * "fast"-linear or constant nodal functions are not supported (either not
261  robust enough or too rigid)
262 
263 This problem require far more complex tuning than interpolation problems.
264 Below you can find some recommendations regarding this problem:
265 * focus on tuning NQ; it controls noise reduction. As for NW, you can just
266  make it equal to 2*NQ.
267 * you can use cross-validation to determine optimal NQ.
268 * optimal NQ is a result of complex tradeoff between noise level (more
269  noise = larger NQ required) and underlying function complexity (given
270  fixed N, larger NQ means smoothing of compex features in the data). For
271  example, NQ=N will reduce noise to the minimum level possible, but you
272  will end up with just constant/linear/quadratic (depending on D) least
273  squares model for the whole dataset.
274 
275 INPUT PARAMETERS:
276  XY - X and Y values, array[0..N-1,0..NX].
277  First NX columns contain X-values, last column contain
278  Y-values.
279  N - number of nodes, N>0.
280  NX - space dimension, NX>=1.
281  D - nodal function degree, either:
282  * 1 linear model, least squares fitting. Simpe model for
283  datasets too small for quadratic models (or for very
284  noisy problems).
285  * 2 quadratic model, least squares fitting. Best model
286  available (if your dataset is large enough).
287  NQ - number of points used to calculate nodal functions. NQ should
288  be significantly larger than 1.5 times the number of
289  coefficients in a nodal function to overcome effects of noise:
290  * larger than 1.5*(1+NX) for linear model,
291  * larger than 3/4*(NX+2)*(NX+1) for quadratic model.
292  Values less than this threshold will be silently increased.
293  NW - number of points used to calculate weights and to interpolate.
294  Required: >=2^NX+1, values less than this threshold will be
295  silently increased.
296  Recommended value: about 2*NQ or larger
297 
298 OUTPUT PARAMETERS:
299  Z - IDW interpolant.
300 
301 NOTES:
302  * best results are obtained with quadratic models, linear models are not
303  recommended to use unless you are pretty sure that it is what you want
304  * this subroutine is always succeeds (as long as correct parameters are
305  passed).
306  * see 'Multivariate Interpolation of Large Sets of Scattered Data' by
307  Robert J. Renka for more information on this algorithm.
308 
309 
310  -- ALGLIB PROJECT --
311  Copyright 02.03.2010 by Bochkanov Sergey
312 *************************************************************************/
313 void idwbuildnoisy(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const ae_int_t d, const ae_int_t nq, const ae_int_t nw, idwinterpolant &z)
314 {
315  alglib_impl::ae_state _alglib_env_state;
316  alglib_impl::ae_state_init(&_alglib_env_state);
317  try
318  {
319  alglib_impl::idwbuildnoisy(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, nx, d, nq, nw, const_cast<alglib_impl::idwinterpolant*>(z.c_ptr()), &_alglib_env_state);
320  alglib_impl::ae_state_clear(&_alglib_env_state);
321  return;
322  }
324  {
325  throw ap_error(_alglib_env_state.error_msg);
326  }
327 }
328 
329 /*************************************************************************
330 Barycentric interpolant.
331 *************************************************************************/
333 {
335  if( p_struct==NULL )
336  throw ap_error("ALGLIB: malloc error");
338  throw ap_error("ALGLIB: malloc error");
339 }
340 
342 {
344  if( p_struct==NULL )
345  throw ap_error("ALGLIB: malloc error");
346  if( !alglib_impl::_barycentricinterpolant_init_copy(p_struct, const_cast<alglib_impl::barycentricinterpolant*>(rhs.p_struct), NULL, ae_false) )
347  throw ap_error("ALGLIB: malloc error");
348 }
349 
351 {
352  if( this==&rhs )
353  return *this;
355  if( !alglib_impl::_barycentricinterpolant_init_copy(p_struct, const_cast<alglib_impl::barycentricinterpolant*>(rhs.p_struct), NULL, ae_false) )
356  throw ap_error("ALGLIB: malloc error");
357  return *this;
358 }
359 
361 {
363  ae_free(p_struct);
364 }
365 
367 {
368  return p_struct;
369 }
370 
372 {
373  return const_cast<alglib_impl::barycentricinterpolant*>(p_struct);
374 }
376 {
377 }
378 
380 {
381 }
382 
384 {
385  if( this==&rhs )
386  return *this;
388  return *this;
389 }
390 
392 {
393 }
394 
395 /*************************************************************************
396 Rational interpolation using barycentric formula
397 
398 F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
399 
400 Input parameters:
401  B - barycentric interpolant built with one of model building
402  subroutines.
403  T - interpolation point
404 
405 Result:
406  barycentric interpolant F(t)
407 
408  -- ALGLIB --
409  Copyright 17.08.2009 by Bochkanov Sergey
410 *************************************************************************/
411 double barycentriccalc(const barycentricinterpolant &b, const double t)
412 {
413  alglib_impl::ae_state _alglib_env_state;
414  alglib_impl::ae_state_init(&_alglib_env_state);
415  try
416  {
417  double result = alglib_impl::barycentriccalc(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), t, &_alglib_env_state);
418  alglib_impl::ae_state_clear(&_alglib_env_state);
419  return *(reinterpret_cast<double*>(&result));
420  }
422  {
423  throw ap_error(_alglib_env_state.error_msg);
424  }
425 }
426 
427 /*************************************************************************
428 Differentiation of barycentric interpolant: first derivative.
429 
430 Algorithm used in this subroutine is very robust and should not fail until
431 provided with values too close to MaxRealNumber (usually MaxRealNumber/N
432 or greater will overflow).
433 
434 INPUT PARAMETERS:
435  B - barycentric interpolant built with one of model building
436  subroutines.
437  T - interpolation point
438 
439 OUTPUT PARAMETERS:
440  F - barycentric interpolant at T
441  DF - first derivative
442 
443 NOTE
444 
445 
446  -- ALGLIB --
447  Copyright 17.08.2009 by Bochkanov Sergey
448 *************************************************************************/
449 void barycentricdiff1(const barycentricinterpolant &b, const double t, double &f, double &df)
450 {
451  alglib_impl::ae_state _alglib_env_state;
452  alglib_impl::ae_state_init(&_alglib_env_state);
453  try
454  {
455  alglib_impl::barycentricdiff1(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), t, &f, &df, &_alglib_env_state);
456  alglib_impl::ae_state_clear(&_alglib_env_state);
457  return;
458  }
460  {
461  throw ap_error(_alglib_env_state.error_msg);
462  }
463 }
464 
465 /*************************************************************************
466 Differentiation of barycentric interpolant: first/second derivatives.
467 
468 INPUT PARAMETERS:
469  B - barycentric interpolant built with one of model building
470  subroutines.
471  T - interpolation point
472 
473 OUTPUT PARAMETERS:
474  F - barycentric interpolant at T
475  DF - first derivative
476  D2F - second derivative
477 
478 NOTE: this algorithm may fail due to overflow/underflor if used on data
479 whose values are close to MaxRealNumber or MinRealNumber. Use more robust
480 BarycentricDiff1() subroutine in such cases.
481 
482 
483  -- ALGLIB --
484  Copyright 17.08.2009 by Bochkanov Sergey
485 *************************************************************************/
486 void barycentricdiff2(const barycentricinterpolant &b, const double t, double &f, double &df, double &d2f)
487 {
488  alglib_impl::ae_state _alglib_env_state;
489  alglib_impl::ae_state_init(&_alglib_env_state);
490  try
491  {
492  alglib_impl::barycentricdiff2(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), t, &f, &df, &d2f, &_alglib_env_state);
493  alglib_impl::ae_state_clear(&_alglib_env_state);
494  return;
495  }
497  {
498  throw ap_error(_alglib_env_state.error_msg);
499  }
500 }
501 
502 /*************************************************************************
503 This subroutine performs linear transformation of the argument.
504 
505 INPUT PARAMETERS:
506  B - rational interpolant in barycentric form
507  CA, CB - transformation coefficients: x = CA*t + CB
508 
509 OUTPUT PARAMETERS:
510  B - transformed interpolant with X replaced by T
511 
512  -- ALGLIB PROJECT --
513  Copyright 19.08.2009 by Bochkanov Sergey
514 *************************************************************************/
515 void barycentriclintransx(const barycentricinterpolant &b, const double ca, const double cb)
516 {
517  alglib_impl::ae_state _alglib_env_state;
518  alglib_impl::ae_state_init(&_alglib_env_state);
519  try
520  {
521  alglib_impl::barycentriclintransx(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), ca, cb, &_alglib_env_state);
522  alglib_impl::ae_state_clear(&_alglib_env_state);
523  return;
524  }
526  {
527  throw ap_error(_alglib_env_state.error_msg);
528  }
529 }
530 
531 /*************************************************************************
532 This subroutine performs linear transformation of the barycentric
533 interpolant.
534 
535 INPUT PARAMETERS:
536  B - rational interpolant in barycentric form
537  CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB
538 
539 OUTPUT PARAMETERS:
540  B - transformed interpolant
541 
542  -- ALGLIB PROJECT --
543  Copyright 19.08.2009 by Bochkanov Sergey
544 *************************************************************************/
545 void barycentriclintransy(const barycentricinterpolant &b, const double ca, const double cb)
546 {
547  alglib_impl::ae_state _alglib_env_state;
548  alglib_impl::ae_state_init(&_alglib_env_state);
549  try
550  {
551  alglib_impl::barycentriclintransy(const_cast<alglib_impl::barycentricinterpolant*>(b.c_ptr()), ca, cb, &_alglib_env_state);
552  alglib_impl::ae_state_clear(&_alglib_env_state);
553  return;
554  }
556  {
557  throw ap_error(_alglib_env_state.error_msg);
558  }
559 }
560 
561 /*************************************************************************
562 Extracts X/Y/W arrays from rational interpolant
563 
564 INPUT PARAMETERS:
565  B - barycentric interpolant
566 
567 OUTPUT PARAMETERS:
568  N - nodes count, N>0
569  X - interpolation nodes, array[0..N-1]
570  F - function values, array[0..N-1]
571  W - barycentric weights, array[0..N-1]
572 
573  -- ALGLIB --
574  Copyright 17.08.2009 by Bochkanov Sergey
575 *************************************************************************/
577 {
578  alglib_impl::ae_state _alglib_env_state;
579  alglib_impl::ae_state_init(&_alglib_env_state);
580  try
581  {
582  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);
583  alglib_impl::ae_state_clear(&_alglib_env_state);
584  return;
585  }
587  {
588  throw ap_error(_alglib_env_state.error_msg);
589  }
590 }
591 
592 /*************************************************************************
593 Rational interpolant from X/Y/W arrays
594 
595 F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
596 
597 INPUT PARAMETERS:
598  X - interpolation nodes, array[0..N-1]
599  F - function values, array[0..N-1]
600  W - barycentric weights, array[0..N-1]
601  N - nodes count, N>0
602 
603 OUTPUT PARAMETERS:
604  B - barycentric interpolant built from (X, Y, W)
605 
606  -- ALGLIB --
607  Copyright 17.08.2009 by Bochkanov Sergey
608 *************************************************************************/
610 {
611  alglib_impl::ae_state _alglib_env_state;
612  alglib_impl::ae_state_init(&_alglib_env_state);
613  try
614  {
615  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);
616  alglib_impl::ae_state_clear(&_alglib_env_state);
617  return;
618  }
620  {
621  throw ap_error(_alglib_env_state.error_msg);
622  }
623 }
624 
625 /*************************************************************************
626 Rational interpolant without poles
627 
628 The subroutine constructs the rational interpolating function without real
629 poles (see 'Barycentric rational interpolation with no poles and high
630 rates of approximation', Michael S. Floater. and Kai Hormann, for more
631 information on this subject).
632 
633 Input parameters:
634  X - interpolation nodes, array[0..N-1].
635  Y - function values, array[0..N-1].
636  N - number of nodes, N>0.
637  D - order of the interpolation scheme, 0 <= D <= N-1.
638  D<0 will cause an error.
639  D>=N it will be replaced with D=N-1.
640  if you don't know what D to choose, use small value about 3-5.
641 
642 Output parameters:
643  B - barycentric interpolant.
644 
645 Note:
646  this algorithm always succeeds and calculates the weights with close
647  to machine precision.
648 
649  -- ALGLIB PROJECT --
650  Copyright 17.06.2007 by Bochkanov Sergey
651 *************************************************************************/
653 {
654  alglib_impl::ae_state _alglib_env_state;
655  alglib_impl::ae_state_init(&_alglib_env_state);
656  try
657  {
658  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);
659  alglib_impl::ae_state_clear(&_alglib_env_state);
660  return;
661  }
663  {
664  throw ap_error(_alglib_env_state.error_msg);
665  }
666 }
667 
668 /*************************************************************************
669 Conversion from barycentric representation to Chebyshev basis.
670 This function has O(N^2) complexity.
671 
672 INPUT PARAMETERS:
673  P - polynomial in barycentric form
674  A,B - base interval for Chebyshev polynomials (see below)
675  A<>B
676 
677 OUTPUT PARAMETERS
678  T - coefficients of Chebyshev representation;
679  P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 },
680  where Ti - I-th Chebyshev polynomial.
681 
682 NOTES:
683  barycentric interpolant passed as P may be either polynomial obtained
684  from polynomial interpolation/ fitting or rational function which is
685  NOT polynomial. We can't distinguish between these two cases, and this
686  algorithm just tries to work assuming that P IS a polynomial. If not,
687  algorithm will return results, but they won't have any meaning.
688 
689  -- ALGLIB --
690  Copyright 30.09.2010 by Bochkanov Sergey
691 *************************************************************************/
692 void polynomialbar2cheb(const barycentricinterpolant &p, const double a, const double b, real_1d_array &t)
693 {
694  alglib_impl::ae_state _alglib_env_state;
695  alglib_impl::ae_state_init(&_alglib_env_state);
696  try
697  {
698  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);
699  alglib_impl::ae_state_clear(&_alglib_env_state);
700  return;
701  }
703  {
704  throw ap_error(_alglib_env_state.error_msg);
705  }
706 }
707 
708 /*************************************************************************
709 Conversion from Chebyshev basis to barycentric representation.
710 This function has O(N^2) complexity.
711 
712 INPUT PARAMETERS:
713  T - coefficients of Chebyshev representation;
714  P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N },
715  where Ti - I-th Chebyshev polynomial.
716  N - number of coefficients:
717  * if given, only leading N elements of T are used
718  * if not given, automatically determined from size of T
719  A,B - base interval for Chebyshev polynomials (see above)
720  A<B
721 
722 OUTPUT PARAMETERS
723  P - polynomial in barycentric form
724 
725  -- ALGLIB --
726  Copyright 30.09.2010 by Bochkanov Sergey
727 *************************************************************************/
728 void polynomialcheb2bar(const real_1d_array &t, const ae_int_t n, const double a, const double b, barycentricinterpolant &p)
729 {
730  alglib_impl::ae_state _alglib_env_state;
731  alglib_impl::ae_state_init(&_alglib_env_state);
732  try
733  {
734  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);
735  alglib_impl::ae_state_clear(&_alglib_env_state);
736  return;
737  }
739  {
740  throw ap_error(_alglib_env_state.error_msg);
741  }
742 }
743 
744 /*************************************************************************
745 Conversion from Chebyshev basis to barycentric representation.
746 This function has O(N^2) complexity.
747 
748 INPUT PARAMETERS:
749  T - coefficients of Chebyshev representation;
750  P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N },
751  where Ti - I-th Chebyshev polynomial.
752  N - number of coefficients:
753  * if given, only leading N elements of T are used
754  * if not given, automatically determined from size of T
755  A,B - base interval for Chebyshev polynomials (see above)
756  A<B
757 
758 OUTPUT PARAMETERS
759  P - polynomial in barycentric form
760 
761  -- ALGLIB --
762  Copyright 30.09.2010 by Bochkanov Sergey
763 *************************************************************************/
764 void polynomialcheb2bar(const real_1d_array &t, const double a, const double b, barycentricinterpolant &p)
765 {
766  alglib_impl::ae_state _alglib_env_state;
767  ae_int_t n;
768 
769  n = t.length();
770  alglib_impl::ae_state_init(&_alglib_env_state);
771  try
772  {
773  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);
774 
775  alglib_impl::ae_state_clear(&_alglib_env_state);
776  return;
777  }
779  {
780  throw ap_error(_alglib_env_state.error_msg);
781  }
782 }
783 
784 /*************************************************************************
785 Conversion from barycentric representation to power basis.
786 This function has O(N^2) complexity.
787 
788 INPUT PARAMETERS:
789  P - polynomial in barycentric form
790  C - offset (see below); 0.0 is used as default value.
791  S - scale (see below); 1.0 is used as default value. S<>0.
792 
793 OUTPUT PARAMETERS
794  A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
795  N - number of coefficients (polynomial degree plus 1)
796 
797 NOTES:
798 1. this function accepts offset and scale, which can be set to improve
799  numerical properties of polynomial. For example, if P was obtained as
800  result of interpolation on [-1,+1], you can set C=0 and S=1 and
801  represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it
802  is exactly what you need.
803 
804  However, if your interpolation model was built on [999,1001], you will
805  see significant growth of numerical errors when using {1, x, x^2, x^3}
806  as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
807  will be better option. Such representation can be obtained by using
808  1000.0 as offset C and 1.0 as scale S.
809 
810 2. power basis is ill-conditioned and tricks described above can't solve
811  this problem completely. This function will return coefficients in
812  any case, but for N>8 they will become unreliable. However, N's
813  less than 5 are pretty safe.
814 
815 3. barycentric interpolant passed as P may be either polynomial obtained
816  from polynomial interpolation/ fitting or rational function which is
817  NOT polynomial. We can't distinguish between these two cases, and this
818  algorithm just tries to work assuming that P IS a polynomial. If not,
819  algorithm will return results, but they won't have any meaning.
820 
821  -- ALGLIB --
822  Copyright 30.09.2010 by Bochkanov Sergey
823 *************************************************************************/
824 void polynomialbar2pow(const barycentricinterpolant &p, const double c, const double s, real_1d_array &a)
825 {
826  alglib_impl::ae_state _alglib_env_state;
827  alglib_impl::ae_state_init(&_alglib_env_state);
828  try
829  {
830  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);
831  alglib_impl::ae_state_clear(&_alglib_env_state);
832  return;
833  }
835  {
836  throw ap_error(_alglib_env_state.error_msg);
837  }
838 }
839 
840 /*************************************************************************
841 Conversion from barycentric representation to power basis.
842 This function has O(N^2) complexity.
843 
844 INPUT PARAMETERS:
845  P - polynomial in barycentric form
846  C - offset (see below); 0.0 is used as default value.
847  S - scale (see below); 1.0 is used as default value. S<>0.
848 
849 OUTPUT PARAMETERS
850  A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
851  N - number of coefficients (polynomial degree plus 1)
852 
853 NOTES:
854 1. this function accepts offset and scale, which can be set to improve
855  numerical properties of polynomial. For example, if P was obtained as
856  result of interpolation on [-1,+1], you can set C=0 and S=1 and
857  represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it
858  is exactly what you need.
859 
860  However, if your interpolation model was built on [999,1001], you will
861  see significant growth of numerical errors when using {1, x, x^2, x^3}
862  as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
863  will be better option. Such representation can be obtained by using
864  1000.0 as offset C and 1.0 as scale S.
865 
866 2. power basis is ill-conditioned and tricks described above can't solve
867  this problem completely. This function will return coefficients in
868  any case, but for N>8 they will become unreliable. However, N's
869  less than 5 are pretty safe.
870 
871 3. barycentric interpolant passed as P may be either polynomial obtained
872  from polynomial interpolation/ fitting or rational function which is
873  NOT polynomial. We can't distinguish between these two cases, and this
874  algorithm just tries to work assuming that P IS a polynomial. If not,
875  algorithm will return results, but they won't have any meaning.
876 
877  -- ALGLIB --
878  Copyright 30.09.2010 by Bochkanov Sergey
879 *************************************************************************/
881 {
882  alglib_impl::ae_state _alglib_env_state;
883  double c;
884  double s;
885 
886  c = 0;
887  s = 1;
888  alglib_impl::ae_state_init(&_alglib_env_state);
889  try
890  {
891  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);
892 
893  alglib_impl::ae_state_clear(&_alglib_env_state);
894  return;
895  }
897  {
898  throw ap_error(_alglib_env_state.error_msg);
899  }
900 }
901 
902 /*************************************************************************
903 Conversion from power basis to barycentric representation.
904 This function has O(N^2) complexity.
905 
906 INPUT PARAMETERS:
907  A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
908  N - number of coefficients (polynomial degree plus 1)
909  * if given, only leading N elements of A are used
910  * if not given, automatically determined from size of A
911  C - offset (see below); 0.0 is used as default value.
912  S - scale (see below); 1.0 is used as default value. S<>0.
913 
914 OUTPUT PARAMETERS
915  P - polynomial in barycentric form
916 
917 
918 NOTES:
919 1. this function accepts offset and scale, which can be set to improve
920  numerical properties of polynomial. For example, if you interpolate on
921  [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2,
922  x^3 and so on. In most cases you it is exactly what you need.
923 
924  However, if your interpolation model was built on [999,1001], you will
925  see significant growth of numerical errors when using {1, x, x^2, x^3}
926  as input basis. Converting from sum of 1, (x-1000), (x-1000)^2,
927  (x-1000)^3 will be better option (you have to specify 1000.0 as offset
928  C and 1.0 as scale S).
929 
930 2. power basis is ill-conditioned and tricks described above can't solve
931  this problem completely. This function will return barycentric model
932  in any case, but for N>8 accuracy well degrade. However, N's less than
933  5 are pretty safe.
934 
935  -- ALGLIB --
936  Copyright 30.09.2010 by Bochkanov Sergey
937 *************************************************************************/
938 void polynomialpow2bar(const real_1d_array &a, const ae_int_t n, const double c, const double s, barycentricinterpolant &p)
939 {
940  alglib_impl::ae_state _alglib_env_state;
941  alglib_impl::ae_state_init(&_alglib_env_state);
942  try
943  {
944  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);
945  alglib_impl::ae_state_clear(&_alglib_env_state);
946  return;
947  }
949  {
950  throw ap_error(_alglib_env_state.error_msg);
951  }
952 }
953 
954 /*************************************************************************
955 Conversion from power basis to barycentric representation.
956 This function has O(N^2) complexity.
957 
958 INPUT PARAMETERS:
959  A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
960  N - number of coefficients (polynomial degree plus 1)
961  * if given, only leading N elements of A are used
962  * if not given, automatically determined from size of A
963  C - offset (see below); 0.0 is used as default value.
964  S - scale (see below); 1.0 is used as default value. S<>0.
965 
966 OUTPUT PARAMETERS
967  P - polynomial in barycentric form
968 
969 
970 NOTES:
971 1. this function accepts offset and scale, which can be set to improve
972  numerical properties of polynomial. For example, if you interpolate on
973  [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2,
974  x^3 and so on. In most cases you it is exactly what you need.
975 
976  However, if your interpolation model was built on [999,1001], you will
977  see significant growth of numerical errors when using {1, x, x^2, x^3}
978  as input basis. Converting from sum of 1, (x-1000), (x-1000)^2,
979  (x-1000)^3 will be better option (you have to specify 1000.0 as offset
980  C and 1.0 as scale S).
981 
982 2. power basis is ill-conditioned and tricks described above can't solve
983  this problem completely. This function will return barycentric model
984  in any case, but for N>8 accuracy well degrade. However, N's less than
985  5 are pretty safe.
986 
987  -- ALGLIB --
988  Copyright 30.09.2010 by Bochkanov Sergey
989 *************************************************************************/
991 {
992  alglib_impl::ae_state _alglib_env_state;
993  ae_int_t n;
994  double c;
995  double s;
996 
997  n = a.length();
998  c = 0;
999  s = 1;
1000  alglib_impl::ae_state_init(&_alglib_env_state);
1001  try
1002  {
1003  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);
1004 
1005  alglib_impl::ae_state_clear(&_alglib_env_state);
1006  return;
1007  }
1009  {
1010  throw ap_error(_alglib_env_state.error_msg);
1011  }
1012 }
1013 
1014 /*************************************************************************
1015 Lagrange intepolant: generation of the model on the general grid.
1016 This function has O(N^2) complexity.
1017 
1018 INPUT PARAMETERS:
1019  X - abscissas, array[0..N-1]
1020  Y - function values, array[0..N-1]
1021  N - number of points, N>=1
1022 
1023 OUTPUT PARAMETERS
1024  P - barycentric model which represents Lagrange interpolant
1025  (see ratint unit info and BarycentricCalc() description for
1026  more information).
1027 
1028  -- ALGLIB --
1029  Copyright 02.12.2009 by Bochkanov Sergey
1030 *************************************************************************/
1032 {
1033  alglib_impl::ae_state _alglib_env_state;
1034  alglib_impl::ae_state_init(&_alglib_env_state);
1035  try
1036  {
1037  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);
1038  alglib_impl::ae_state_clear(&_alglib_env_state);
1039  return;
1040  }
1042  {
1043  throw ap_error(_alglib_env_state.error_msg);
1044  }
1045 }
1046 
1047 /*************************************************************************
1048 Lagrange intepolant: generation of the model on the general grid.
1049 This function has O(N^2) complexity.
1050 
1051 INPUT PARAMETERS:
1052  X - abscissas, array[0..N-1]
1053  Y - function values, array[0..N-1]
1054  N - number of points, N>=1
1055 
1056 OUTPUT PARAMETERS
1057  P - barycentric model which represents Lagrange interpolant
1058  (see ratint unit info and BarycentricCalc() description for
1059  more information).
1060 
1061  -- ALGLIB --
1062  Copyright 02.12.2009 by Bochkanov Sergey
1063 *************************************************************************/
1065 {
1066  alglib_impl::ae_state _alglib_env_state;
1067  ae_int_t n;
1068  if( (x.length()!=y.length()))
1069  throw ap_error("Error while calling 'polynomialbuild': looks like one of arguments has wrong size");
1070  n = x.length();
1071  alglib_impl::ae_state_init(&_alglib_env_state);
1072  try
1073  {
1074  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);
1075 
1076  alglib_impl::ae_state_clear(&_alglib_env_state);
1077  return;
1078  }
1080  {
1081  throw ap_error(_alglib_env_state.error_msg);
1082  }
1083 }
1084 
1085 /*************************************************************************
1086 Lagrange intepolant: generation of the model on equidistant grid.
1087 This function has O(N) complexity.
1088 
1089 INPUT PARAMETERS:
1090  A - left boundary of [A,B]
1091  B - right boundary of [A,B]
1092  Y - function values at the nodes, array[0..N-1]
1093  N - number of points, N>=1
1094  for N=1 a constant model is constructed.
1095 
1096 OUTPUT PARAMETERS
1097  P - barycentric model which represents Lagrange interpolant
1098  (see ratint unit info and BarycentricCalc() description for
1099  more information).
1100 
1101  -- ALGLIB --
1102  Copyright 03.12.2009 by Bochkanov Sergey
1103 *************************************************************************/
1104 void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p)
1105 {
1106  alglib_impl::ae_state _alglib_env_state;
1107  alglib_impl::ae_state_init(&_alglib_env_state);
1108  try
1109  {
1110  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);
1111  alglib_impl::ae_state_clear(&_alglib_env_state);
1112  return;
1113  }
1115  {
1116  throw ap_error(_alglib_env_state.error_msg);
1117  }
1118 }
1119 
1120 /*************************************************************************
1121 Lagrange intepolant: generation of the model on equidistant grid.
1122 This function has O(N) complexity.
1123 
1124 INPUT PARAMETERS:
1125  A - left boundary of [A,B]
1126  B - right boundary of [A,B]
1127  Y - function values at the nodes, array[0..N-1]
1128  N - number of points, N>=1
1129  for N=1 a constant model is constructed.
1130 
1131 OUTPUT PARAMETERS
1132  P - barycentric model which represents Lagrange interpolant
1133  (see ratint unit info and BarycentricCalc() description for
1134  more information).
1135 
1136  -- ALGLIB --
1137  Copyright 03.12.2009 by Bochkanov Sergey
1138 *************************************************************************/
1139 void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p)
1140 {
1141  alglib_impl::ae_state _alglib_env_state;
1142  ae_int_t n;
1143 
1144  n = y.length();
1145  alglib_impl::ae_state_init(&_alglib_env_state);
1146  try
1147  {
1148  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);
1149 
1150  alglib_impl::ae_state_clear(&_alglib_env_state);
1151  return;
1152  }
1154  {
1155  throw ap_error(_alglib_env_state.error_msg);
1156  }
1157 }
1158 
1159 /*************************************************************************
1160 Lagrange intepolant on Chebyshev grid (first kind).
1161 This function has O(N) complexity.
1162 
1163 INPUT PARAMETERS:
1164  A - left boundary of [A,B]
1165  B - right boundary of [A,B]
1166  Y - function values at the nodes, array[0..N-1],
1167  Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
1168  N - number of points, N>=1
1169  for N=1 a constant model is constructed.
1170 
1171 OUTPUT PARAMETERS
1172  P - barycentric model which represents Lagrange interpolant
1173  (see ratint unit info and BarycentricCalc() description for
1174  more information).
1175 
1176  -- ALGLIB --
1177  Copyright 03.12.2009 by Bochkanov Sergey
1178 *************************************************************************/
1179 void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p)
1180 {
1181  alglib_impl::ae_state _alglib_env_state;
1182  alglib_impl::ae_state_init(&_alglib_env_state);
1183  try
1184  {
1185  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);
1186  alglib_impl::ae_state_clear(&_alglib_env_state);
1187  return;
1188  }
1190  {
1191  throw ap_error(_alglib_env_state.error_msg);
1192  }
1193 }
1194 
1195 /*************************************************************************
1196 Lagrange intepolant on Chebyshev grid (first kind).
1197 This function has O(N) complexity.
1198 
1199 INPUT PARAMETERS:
1200  A - left boundary of [A,B]
1201  B - right boundary of [A,B]
1202  Y - function values at the nodes, array[0..N-1],
1203  Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
1204  N - number of points, N>=1
1205  for N=1 a constant model is constructed.
1206 
1207 OUTPUT PARAMETERS
1208  P - barycentric model which represents Lagrange interpolant
1209  (see ratint unit info and BarycentricCalc() description for
1210  more information).
1211 
1212  -- ALGLIB --
1213  Copyright 03.12.2009 by Bochkanov Sergey
1214 *************************************************************************/
1215 void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p)
1216 {
1217  alglib_impl::ae_state _alglib_env_state;
1218  ae_int_t n;
1219 
1220  n = y.length();
1221  alglib_impl::ae_state_init(&_alglib_env_state);
1222  try
1223  {
1224  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);
1225 
1226  alglib_impl::ae_state_clear(&_alglib_env_state);
1227  return;
1228  }
1230  {
1231  throw ap_error(_alglib_env_state.error_msg);
1232  }
1233 }
1234 
1235 /*************************************************************************
1236 Lagrange intepolant on Chebyshev grid (second kind).
1237 This function has O(N) complexity.
1238 
1239 INPUT PARAMETERS:
1240  A - left boundary of [A,B]
1241  B - right boundary of [A,B]
1242  Y - function values at the nodes, array[0..N-1],
1243  Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
1244  N - number of points, N>=1
1245  for N=1 a constant model is constructed.
1246 
1247 OUTPUT PARAMETERS
1248  P - barycentric model which represents Lagrange interpolant
1249  (see ratint unit info and BarycentricCalc() description for
1250  more information).
1251 
1252  -- ALGLIB --
1253  Copyright 03.12.2009 by Bochkanov Sergey
1254 *************************************************************************/
1255 void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p)
1256 {
1257  alglib_impl::ae_state _alglib_env_state;
1258  alglib_impl::ae_state_init(&_alglib_env_state);
1259  try
1260  {
1261  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);
1262  alglib_impl::ae_state_clear(&_alglib_env_state);
1263  return;
1264  }
1266  {
1267  throw ap_error(_alglib_env_state.error_msg);
1268  }
1269 }
1270 
1271 /*************************************************************************
1272 Lagrange intepolant on Chebyshev grid (second kind).
1273 This function has O(N) complexity.
1274 
1275 INPUT PARAMETERS:
1276  A - left boundary of [A,B]
1277  B - right boundary of [A,B]
1278  Y - function values at the nodes, array[0..N-1],
1279  Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
1280  N - number of points, N>=1
1281  for N=1 a constant model is constructed.
1282 
1283 OUTPUT PARAMETERS
1284  P - barycentric model which represents Lagrange interpolant
1285  (see ratint unit info and BarycentricCalc() description for
1286  more information).
1287 
1288  -- ALGLIB --
1289  Copyright 03.12.2009 by Bochkanov Sergey
1290 *************************************************************************/
1291 void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, barycentricinterpolant &p)
1292 {
1293  alglib_impl::ae_state _alglib_env_state;
1294  ae_int_t n;
1295 
1296  n = y.length();
1297  alglib_impl::ae_state_init(&_alglib_env_state);
1298  try
1299  {
1300  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);
1301 
1302  alglib_impl::ae_state_clear(&_alglib_env_state);
1303  return;
1304  }
1306  {
1307  throw ap_error(_alglib_env_state.error_msg);
1308  }
1309 }
1310 
1311 /*************************************************************************
1312 Fast equidistant polynomial interpolation function with O(N) complexity
1313 
1314 INPUT PARAMETERS:
1315  A - left boundary of [A,B]
1316  B - right boundary of [A,B]
1317  F - function values, array[0..N-1]
1318  N - number of points on equidistant grid, N>=1
1319  for N=1 a constant model is constructed.
1320  T - position where P(x) is calculated
1321 
1322 RESULT
1323  value of the Lagrange interpolant at T
1324 
1325 IMPORTANT
1326  this function provides fast interface which is not overflow-safe
1327  nor it is very precise.
1328  the best option is to use PolynomialBuildEqDist()/BarycentricCalc()
1329  subroutines unless you are pretty sure that your data will not result
1330  in overflow.
1331 
1332  -- ALGLIB --
1333  Copyright 02.12.2009 by Bochkanov Sergey
1334 *************************************************************************/
1335 double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t)
1336 {
1337  alglib_impl::ae_state _alglib_env_state;
1338  alglib_impl::ae_state_init(&_alglib_env_state);
1339  try
1340  {
1341  double result = alglib_impl::polynomialcalceqdist(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
1342  alglib_impl::ae_state_clear(&_alglib_env_state);
1343  return *(reinterpret_cast<double*>(&result));
1344  }
1346  {
1347  throw ap_error(_alglib_env_state.error_msg);
1348  }
1349 }
1350 
1351 /*************************************************************************
1352 Fast equidistant polynomial interpolation function with O(N) complexity
1353 
1354 INPUT PARAMETERS:
1355  A - left boundary of [A,B]
1356  B - right boundary of [A,B]
1357  F - function values, array[0..N-1]
1358  N - number of points on equidistant grid, N>=1
1359  for N=1 a constant model is constructed.
1360  T - position where P(x) is calculated
1361 
1362 RESULT
1363  value of the Lagrange interpolant at T
1364 
1365 IMPORTANT
1366  this function provides fast interface which is not overflow-safe
1367  nor it is very precise.
1368  the best option is to use PolynomialBuildEqDist()/BarycentricCalc()
1369  subroutines unless you are pretty sure that your data will not result
1370  in overflow.
1371 
1372  -- ALGLIB --
1373  Copyright 02.12.2009 by Bochkanov Sergey
1374 *************************************************************************/
1375 double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const double t)
1376 {
1377  alglib_impl::ae_state _alglib_env_state;
1378  ae_int_t n;
1379 
1380  n = f.length();
1381  alglib_impl::ae_state_init(&_alglib_env_state);
1382  try
1383  {
1384  double result = alglib_impl::polynomialcalceqdist(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
1385 
1386  alglib_impl::ae_state_clear(&_alglib_env_state);
1387  return *(reinterpret_cast<double*>(&result));
1388  }
1390  {
1391  throw ap_error(_alglib_env_state.error_msg);
1392  }
1393 }
1394 
1395 /*************************************************************************
1396 Fast polynomial interpolation function on Chebyshev points (first kind)
1397 with O(N) complexity.
1398 
1399 INPUT PARAMETERS:
1400  A - left boundary of [A,B]
1401  B - right boundary of [A,B]
1402  F - function values, array[0..N-1]
1403  N - number of points on Chebyshev grid (first kind),
1404  X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))
1405  for N=1 a constant model is constructed.
1406  T - position where P(x) is calculated
1407 
1408 RESULT
1409  value of the Lagrange interpolant at T
1410 
1411 IMPORTANT
1412  this function provides fast interface which is not overflow-safe
1413  nor it is very precise.
1414  the best option is to use PolIntBuildCheb1()/BarycentricCalc()
1415  subroutines unless you are pretty sure that your data will not result
1416  in overflow.
1417 
1418  -- ALGLIB --
1419  Copyright 02.12.2009 by Bochkanov Sergey
1420 *************************************************************************/
1421 double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t)
1422 {
1423  alglib_impl::ae_state _alglib_env_state;
1424  alglib_impl::ae_state_init(&_alglib_env_state);
1425  try
1426  {
1427  double result = alglib_impl::polynomialcalccheb1(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
1428  alglib_impl::ae_state_clear(&_alglib_env_state);
1429  return *(reinterpret_cast<double*>(&result));
1430  }
1432  {
1433  throw ap_error(_alglib_env_state.error_msg);
1434  }
1435 }
1436 
1437 /*************************************************************************
1438 Fast polynomial interpolation function on Chebyshev points (first kind)
1439 with O(N) complexity.
1440 
1441 INPUT PARAMETERS:
1442  A - left boundary of [A,B]
1443  B - right boundary of [A,B]
1444  F - function values, array[0..N-1]
1445  N - number of points on Chebyshev grid (first kind),
1446  X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))
1447  for N=1 a constant model is constructed.
1448  T - position where P(x) is calculated
1449 
1450 RESULT
1451  value of the Lagrange interpolant at T
1452 
1453 IMPORTANT
1454  this function provides fast interface which is not overflow-safe
1455  nor it is very precise.
1456  the best option is to use PolIntBuildCheb1()/BarycentricCalc()
1457  subroutines unless you are pretty sure that your data will not result
1458  in overflow.
1459 
1460  -- ALGLIB --
1461  Copyright 02.12.2009 by Bochkanov Sergey
1462 *************************************************************************/
1463 double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const double t)
1464 {
1465  alglib_impl::ae_state _alglib_env_state;
1466  ae_int_t n;
1467 
1468  n = f.length();
1469  alglib_impl::ae_state_init(&_alglib_env_state);
1470  try
1471  {
1472  double result = alglib_impl::polynomialcalccheb1(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
1473 
1474  alglib_impl::ae_state_clear(&_alglib_env_state);
1475  return *(reinterpret_cast<double*>(&result));
1476  }
1478  {
1479  throw ap_error(_alglib_env_state.error_msg);
1480  }
1481 }
1482 
1483 /*************************************************************************
1484 Fast polynomial interpolation function on Chebyshev points (second kind)
1485 with O(N) complexity.
1486 
1487 INPUT PARAMETERS:
1488  A - left boundary of [A,B]
1489  B - right boundary of [A,B]
1490  F - function values, array[0..N-1]
1491  N - number of points on Chebyshev grid (second kind),
1492  X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))
1493  for N=1 a constant model is constructed.
1494  T - position where P(x) is calculated
1495 
1496 RESULT
1497  value of the Lagrange interpolant at T
1498 
1499 IMPORTANT
1500  this function provides fast interface which is not overflow-safe
1501  nor it is very precise.
1502  the best option is to use PolIntBuildCheb2()/BarycentricCalc()
1503  subroutines unless you are pretty sure that your data will not result
1504  in overflow.
1505 
1506  -- ALGLIB --
1507  Copyright 02.12.2009 by Bochkanov Sergey
1508 *************************************************************************/
1509 double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t)
1510 {
1511  alglib_impl::ae_state _alglib_env_state;
1512  alglib_impl::ae_state_init(&_alglib_env_state);
1513  try
1514  {
1515  double result = alglib_impl::polynomialcalccheb2(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
1516  alglib_impl::ae_state_clear(&_alglib_env_state);
1517  return *(reinterpret_cast<double*>(&result));
1518  }
1520  {
1521  throw ap_error(_alglib_env_state.error_msg);
1522  }
1523 }
1524 
1525 /*************************************************************************
1526 Fast polynomial interpolation function on Chebyshev points (second kind)
1527 with O(N) complexity.
1528 
1529 INPUT PARAMETERS:
1530  A - left boundary of [A,B]
1531  B - right boundary of [A,B]
1532  F - function values, array[0..N-1]
1533  N - number of points on Chebyshev grid (second kind),
1534  X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))
1535  for N=1 a constant model is constructed.
1536  T - position where P(x) is calculated
1537 
1538 RESULT
1539  value of the Lagrange interpolant at T
1540 
1541 IMPORTANT
1542  this function provides fast interface which is not overflow-safe
1543  nor it is very precise.
1544  the best option is to use PolIntBuildCheb2()/BarycentricCalc()
1545  subroutines unless you are pretty sure that your data will not result
1546  in overflow.
1547 
1548  -- ALGLIB --
1549  Copyright 02.12.2009 by Bochkanov Sergey
1550 *************************************************************************/
1551 double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const double t)
1552 {
1553  alglib_impl::ae_state _alglib_env_state;
1554  ae_int_t n;
1555 
1556  n = f.length();
1557  alglib_impl::ae_state_init(&_alglib_env_state);
1558  try
1559  {
1560  double result = alglib_impl::polynomialcalccheb2(a, b, const_cast<alglib_impl::ae_vector*>(f.c_ptr()), n, t, &_alglib_env_state);
1561 
1562  alglib_impl::ae_state_clear(&_alglib_env_state);
1563  return *(reinterpret_cast<double*>(&result));
1564  }
1566  {
1567  throw ap_error(_alglib_env_state.error_msg);
1568  }
1569 }
1570 
1571 /*************************************************************************
1572 1-dimensional spline interpolant
1573 *************************************************************************/
1575 {
1577  if( p_struct==NULL )
1578  throw ap_error("ALGLIB: malloc error");
1580  throw ap_error("ALGLIB: malloc error");
1581 }
1582 
1584 {
1586  if( p_struct==NULL )
1587  throw ap_error("ALGLIB: malloc error");
1588  if( !alglib_impl::_spline1dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline1dinterpolant*>(rhs.p_struct), NULL, ae_false) )
1589  throw ap_error("ALGLIB: malloc error");
1590 }
1591 
1593 {
1594  if( this==&rhs )
1595  return *this;
1597  if( !alglib_impl::_spline1dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline1dinterpolant*>(rhs.p_struct), NULL, ae_false) )
1598  throw ap_error("ALGLIB: malloc error");
1599  return *this;
1600 }
1601 
1603 {
1605  ae_free(p_struct);
1606 }
1607 
1609 {
1610  return p_struct;
1611 }
1612 
1614 {
1615  return const_cast<alglib_impl::spline1dinterpolant*>(p_struct);
1616 }
1618 {
1619 }
1620 
1622 {
1623 }
1624 
1626 {
1627  if( this==&rhs )
1628  return *this;
1630  return *this;
1631 }
1632 
1634 {
1635 }
1636 
1637 /*************************************************************************
1638 This subroutine builds linear spline interpolant
1639 
1640 INPUT PARAMETERS:
1641  X - spline nodes, array[0..N-1]
1642  Y - function values, array[0..N-1]
1643  N - points count (optional):
1644  * N>=2
1645  * if given, only first N points are used to build spline
1646  * if not given, automatically detected from X/Y sizes
1647  (len(X) must be equal to len(Y))
1648 
1649 OUTPUT PARAMETERS:
1650  C - spline interpolant
1651 
1652 
1653 ORDER OF POINTS
1654 
1655 Subroutine automatically sorts points, so caller may pass unsorted array.
1656 
1657  -- ALGLIB PROJECT --
1658  Copyright 24.06.2007 by Bochkanov Sergey
1659 *************************************************************************/
1661 {
1662  alglib_impl::ae_state _alglib_env_state;
1663  alglib_impl::ae_state_init(&_alglib_env_state);
1664  try
1665  {
1666  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);
1667  alglib_impl::ae_state_clear(&_alglib_env_state);
1668  return;
1669  }
1671  {
1672  throw ap_error(_alglib_env_state.error_msg);
1673  }
1674 }
1675 
1676 /*************************************************************************
1677 This subroutine builds linear spline interpolant
1678 
1679 INPUT PARAMETERS:
1680  X - spline nodes, array[0..N-1]
1681  Y - function values, array[0..N-1]
1682  N - points count (optional):
1683  * N>=2
1684  * if given, only first N points are used to build spline
1685  * if not given, automatically detected from X/Y sizes
1686  (len(X) must be equal to len(Y))
1687 
1688 OUTPUT PARAMETERS:
1689  C - spline interpolant
1690 
1691 
1692 ORDER OF POINTS
1693 
1694 Subroutine automatically sorts points, so caller may pass unsorted array.
1695 
1696  -- ALGLIB PROJECT --
1697  Copyright 24.06.2007 by Bochkanov Sergey
1698 *************************************************************************/
1700 {
1701  alglib_impl::ae_state _alglib_env_state;
1702  ae_int_t n;
1703  if( (x.length()!=y.length()))
1704  throw ap_error("Error while calling 'spline1dbuildlinear': looks like one of arguments has wrong size");
1705  n = x.length();
1706  alglib_impl::ae_state_init(&_alglib_env_state);
1707  try
1708  {
1709  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);
1710 
1711  alglib_impl::ae_state_clear(&_alglib_env_state);
1712  return;
1713  }
1715  {
1716  throw ap_error(_alglib_env_state.error_msg);
1717  }
1718 }
1719 
1720 /*************************************************************************
1721 This subroutine builds cubic spline interpolant.
1722 
1723 INPUT PARAMETERS:
1724  X - spline nodes, array[0..N-1].
1725  Y - function values, array[0..N-1].
1726 
1727 OPTIONAL PARAMETERS:
1728  N - points count:
1729  * N>=2
1730  * if given, only first N points are used to build spline
1731  * if not given, automatically detected from X/Y sizes
1732  (len(X) must be equal to len(Y))
1733  BoundLType - boundary condition type for the left boundary
1734  BoundL - left boundary condition (first or second derivative,
1735  depending on the BoundLType)
1736  BoundRType - boundary condition type for the right boundary
1737  BoundR - right boundary condition (first or second derivative,
1738  depending on the BoundRType)
1739 
1740 OUTPUT PARAMETERS:
1741  C - spline interpolant
1742 
1743 ORDER OF POINTS
1744 
1745 Subroutine automatically sorts points, so caller may pass unsorted array.
1746 
1747 SETTING BOUNDARY VALUES:
1748 
1749 The BoundLType/BoundRType parameters can have the following values:
1750  * -1, which corresonds to the periodic (cyclic) boundary conditions.
1751  In this case:
1752  * both BoundLType and BoundRType must be equal to -1.
1753  * BoundL/BoundR are ignored
1754  * Y[last] is ignored (it is assumed to be equal to Y[first]).
1755  * 0, which corresponds to the parabolically terminated spline
1756  (BoundL and/or BoundR are ignored).
1757  * 1, which corresponds to the first derivative boundary condition
1758  * 2, which corresponds to the second derivative boundary condition
1759  * by default, BoundType=0 is used
1760 
1761 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
1762 
1763 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
1764 However, this subroutine doesn't require you to specify equal values for
1765 the first and last points - it automatically forces them to be equal by
1766 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
1767 Y[last_point]. However it is recommended to pass consistent values of Y[],
1768 i.e. to make Y[first_point]=Y[last_point].
1769 
1770  -- ALGLIB PROJECT --
1771  Copyright 23.06.2007 by Bochkanov Sergey
1772 *************************************************************************/
1773 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)
1774 {
1775  alglib_impl::ae_state _alglib_env_state;
1776  alglib_impl::ae_state_init(&_alglib_env_state);
1777  try
1778  {
1779  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);
1780  alglib_impl::ae_state_clear(&_alglib_env_state);
1781  return;
1782  }
1784  {
1785  throw ap_error(_alglib_env_state.error_msg);
1786  }
1787 }
1788 
1789 /*************************************************************************
1790 This subroutine builds cubic spline interpolant.
1791 
1792 INPUT PARAMETERS:
1793  X - spline nodes, array[0..N-1].
1794  Y - function values, array[0..N-1].
1795 
1796 OPTIONAL PARAMETERS:
1797  N - points count:
1798  * N>=2
1799  * if given, only first N points are used to build spline
1800  * if not given, automatically detected from X/Y sizes
1801  (len(X) must be equal to len(Y))
1802  BoundLType - boundary condition type for the left boundary
1803  BoundL - left boundary condition (first or second derivative,
1804  depending on the BoundLType)
1805  BoundRType - boundary condition type for the right boundary
1806  BoundR - right boundary condition (first or second derivative,
1807  depending on the BoundRType)
1808 
1809 OUTPUT PARAMETERS:
1810  C - spline interpolant
1811 
1812 ORDER OF POINTS
1813 
1814 Subroutine automatically sorts points, so caller may pass unsorted array.
1815 
1816 SETTING BOUNDARY VALUES:
1817 
1818 The BoundLType/BoundRType parameters can have the following values:
1819  * -1, which corresonds to the periodic (cyclic) boundary conditions.
1820  In this case:
1821  * both BoundLType and BoundRType must be equal to -1.
1822  * BoundL/BoundR are ignored
1823  * Y[last] is ignored (it is assumed to be equal to Y[first]).
1824  * 0, which corresponds to the parabolically terminated spline
1825  (BoundL and/or BoundR are ignored).
1826  * 1, which corresponds to the first derivative boundary condition
1827  * 2, which corresponds to the second derivative boundary condition
1828  * by default, BoundType=0 is used
1829 
1830 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
1831 
1832 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
1833 However, this subroutine doesn't require you to specify equal values for
1834 the first and last points - it automatically forces them to be equal by
1835 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
1836 Y[last_point]. However it is recommended to pass consistent values of Y[],
1837 i.e. to make Y[first_point]=Y[last_point].
1838 
1839  -- ALGLIB PROJECT --
1840  Copyright 23.06.2007 by Bochkanov Sergey
1841 *************************************************************************/
1843 {
1844  alglib_impl::ae_state _alglib_env_state;
1845  ae_int_t n;
1846  ae_int_t boundltype;
1847  double boundl;
1848  ae_int_t boundrtype;
1849  double boundr;
1850  if( (x.length()!=y.length()))
1851  throw ap_error("Error while calling 'spline1dbuildcubic': looks like one of arguments has wrong size");
1852  n = x.length();
1853  boundltype = 0;
1854  boundl = 0;
1855  boundrtype = 0;
1856  boundr = 0;
1857  alglib_impl::ae_state_init(&_alglib_env_state);
1858  try
1859  {
1860  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);
1861 
1862  alglib_impl::ae_state_clear(&_alglib_env_state);
1863  return;
1864  }
1866  {
1867  throw ap_error(_alglib_env_state.error_msg);
1868  }
1869 }
1870 
1871 /*************************************************************************
1872 This function solves following problem: given table y[] of function values
1873 at nodes x[], it calculates and returns table of function derivatives d[]
1874 (calculated at the same nodes x[]).
1875 
1876 This function yields same result as Spline1DBuildCubic() call followed by
1877 sequence of Spline1DDiff() calls, but it can be several times faster when
1878 called for ordered X[] and X2[].
1879 
1880 INPUT PARAMETERS:
1881  X - spline nodes
1882  Y - function values
1883 
1884 OPTIONAL PARAMETERS:
1885  N - points count:
1886  * N>=2
1887  * if given, only first N points are used
1888  * if not given, automatically detected from X/Y sizes
1889  (len(X) must be equal to len(Y))
1890  BoundLType - boundary condition type for the left boundary
1891  BoundL - left boundary condition (first or second derivative,
1892  depending on the BoundLType)
1893  BoundRType - boundary condition type for the right boundary
1894  BoundR - right boundary condition (first or second derivative,
1895  depending on the BoundRType)
1896 
1897 OUTPUT PARAMETERS:
1898  D - derivative values at X[]
1899 
1900 ORDER OF POINTS
1901 
1902 Subroutine automatically sorts points, so caller may pass unsorted array.
1903 Derivative values are correctly reordered on return, so D[I] is always
1904 equal to S'(X[I]) independently of points order.
1905 
1906 SETTING BOUNDARY VALUES:
1907 
1908 The BoundLType/BoundRType parameters can have the following values:
1909  * -1, which corresonds to the periodic (cyclic) boundary conditions.
1910  In this case:
1911  * both BoundLType and BoundRType must be equal to -1.
1912  * BoundL/BoundR are ignored
1913  * Y[last] is ignored (it is assumed to be equal to Y[first]).
1914  * 0, which corresponds to the parabolically terminated spline
1915  (BoundL and/or BoundR are ignored).
1916  * 1, which corresponds to the first derivative boundary condition
1917  * 2, which corresponds to the second derivative boundary condition
1918  * by default, BoundType=0 is used
1919 
1920 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
1921 
1922 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
1923 However, this subroutine doesn't require you to specify equal values for
1924 the first and last points - it automatically forces them to be equal by
1925 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
1926 Y[last_point]. However it is recommended to pass consistent values of Y[],
1927 i.e. to make Y[first_point]=Y[last_point].
1928 
1929  -- ALGLIB PROJECT --
1930  Copyright 03.09.2010 by Bochkanov Sergey
1931 *************************************************************************/
1932 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)
1933 {
1934  alglib_impl::ae_state _alglib_env_state;
1935  alglib_impl::ae_state_init(&_alglib_env_state);
1936  try
1937  {
1938  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);
1939  alglib_impl::ae_state_clear(&_alglib_env_state);
1940  return;
1941  }
1943  {
1944  throw ap_error(_alglib_env_state.error_msg);
1945  }
1946 }
1947 
1948 /*************************************************************************
1949 This function solves following problem: given table y[] of function values
1950 at nodes x[], it calculates and returns table of function derivatives d[]
1951 (calculated at the same nodes x[]).
1952 
1953 This function yields same result as Spline1DBuildCubic() call followed by
1954 sequence of Spline1DDiff() calls, but it can be several times faster when
1955 called for ordered X[] and X2[].
1956 
1957 INPUT PARAMETERS:
1958  X - spline nodes
1959  Y - function values
1960 
1961 OPTIONAL PARAMETERS:
1962  N - points count:
1963  * N>=2
1964  * if given, only first N points are used
1965  * if not given, automatically detected from X/Y sizes
1966  (len(X) must be equal to len(Y))
1967  BoundLType - boundary condition type for the left boundary
1968  BoundL - left boundary condition (first or second derivative,
1969  depending on the BoundLType)
1970  BoundRType - boundary condition type for the right boundary
1971  BoundR - right boundary condition (first or second derivative,
1972  depending on the BoundRType)
1973 
1974 OUTPUT PARAMETERS:
1975  D - derivative values at X[]
1976 
1977 ORDER OF POINTS
1978 
1979 Subroutine automatically sorts points, so caller may pass unsorted array.
1980 Derivative values are correctly reordered on return, so D[I] is always
1981 equal to S'(X[I]) independently of points order.
1982 
1983 SETTING BOUNDARY VALUES:
1984 
1985 The BoundLType/BoundRType parameters can have the following values:
1986  * -1, which corresonds to the periodic (cyclic) boundary conditions.
1987  In this case:
1988  * both BoundLType and BoundRType must be equal to -1.
1989  * BoundL/BoundR are ignored
1990  * Y[last] is ignored (it is assumed to be equal to Y[first]).
1991  * 0, which corresponds to the parabolically terminated spline
1992  (BoundL and/or BoundR are ignored).
1993  * 1, which corresponds to the first derivative boundary condition
1994  * 2, which corresponds to the second derivative boundary condition
1995  * by default, BoundType=0 is used
1996 
1997 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
1998 
1999 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2000 However, this subroutine doesn't require you to specify equal values for
2001 the first and last points - it automatically forces them to be equal by
2002 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2003 Y[last_point]. However it is recommended to pass consistent values of Y[],
2004 i.e. to make Y[first_point]=Y[last_point].
2005 
2006  -- ALGLIB PROJECT --
2007  Copyright 03.09.2010 by Bochkanov Sergey
2008 *************************************************************************/
2010 {
2011  alglib_impl::ae_state _alglib_env_state;
2012  ae_int_t n;
2013  ae_int_t boundltype;
2014  double boundl;
2015  ae_int_t boundrtype;
2016  double boundr;
2017  if( (x.length()!=y.length()))
2018  throw ap_error("Error while calling 'spline1dgriddiffcubic': looks like one of arguments has wrong size");
2019  n = x.length();
2020  boundltype = 0;
2021  boundl = 0;
2022  boundrtype = 0;
2023  boundr = 0;
2024  alglib_impl::ae_state_init(&_alglib_env_state);
2025  try
2026  {
2027  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);
2028 
2029  alglib_impl::ae_state_clear(&_alglib_env_state);
2030  return;
2031  }
2033  {
2034  throw ap_error(_alglib_env_state.error_msg);
2035  }
2036 }
2037 
2038 /*************************************************************************
2039 This function solves following problem: given table y[] of function values
2040 at nodes x[], it calculates and returns tables of first and second
2041 function derivatives d1[] and d2[] (calculated at the same nodes x[]).
2042 
2043 This function yields same result as Spline1DBuildCubic() call followed by
2044 sequence of Spline1DDiff() calls, but it can be several times faster when
2045 called for ordered X[] and X2[].
2046 
2047 INPUT PARAMETERS:
2048  X - spline nodes
2049  Y - function values
2050 
2051 OPTIONAL PARAMETERS:
2052  N - points count:
2053  * N>=2
2054  * if given, only first N points are used
2055  * if not given, automatically detected from X/Y sizes
2056  (len(X) must be equal to len(Y))
2057  BoundLType - boundary condition type for the left boundary
2058  BoundL - left boundary condition (first or second derivative,
2059  depending on the BoundLType)
2060  BoundRType - boundary condition type for the right boundary
2061  BoundR - right boundary condition (first or second derivative,
2062  depending on the BoundRType)
2063 
2064 OUTPUT PARAMETERS:
2065  D1 - S' values at X[]
2066  D2 - S'' values at X[]
2067 
2068 ORDER OF POINTS
2069 
2070 Subroutine automatically sorts points, so caller may pass unsorted array.
2071 Derivative values are correctly reordered on return, so D[I] is always
2072 equal to S'(X[I]) independently of points order.
2073 
2074 SETTING BOUNDARY VALUES:
2075 
2076 The BoundLType/BoundRType parameters can have the following values:
2077  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2078  In this case:
2079  * both BoundLType and BoundRType must be equal to -1.
2080  * BoundL/BoundR are ignored
2081  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2082  * 0, which corresponds to the parabolically terminated spline
2083  (BoundL and/or BoundR are ignored).
2084  * 1, which corresponds to the first derivative boundary condition
2085  * 2, which corresponds to the second derivative boundary condition
2086  * by default, BoundType=0 is used
2087 
2088 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2089 
2090 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2091 However, this subroutine doesn't require you to specify equal values for
2092 the first and last points - it automatically forces them to be equal by
2093 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2094 Y[last_point]. However it is recommended to pass consistent values of Y[],
2095 i.e. to make Y[first_point]=Y[last_point].
2096 
2097  -- ALGLIB PROJECT --
2098  Copyright 03.09.2010 by Bochkanov Sergey
2099 *************************************************************************/
2100 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)
2101 {
2102  alglib_impl::ae_state _alglib_env_state;
2103  alglib_impl::ae_state_init(&_alglib_env_state);
2104  try
2105  {
2106  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);
2107  alglib_impl::ae_state_clear(&_alglib_env_state);
2108  return;
2109  }
2111  {
2112  throw ap_error(_alglib_env_state.error_msg);
2113  }
2114 }
2115 
2116 /*************************************************************************
2117 This function solves following problem: given table y[] of function values
2118 at nodes x[], it calculates and returns tables of first and second
2119 function derivatives d1[] and d2[] (calculated at the same nodes x[]).
2120 
2121 This function yields same result as Spline1DBuildCubic() call followed by
2122 sequence of Spline1DDiff() calls, but it can be several times faster when
2123 called for ordered X[] and X2[].
2124 
2125 INPUT PARAMETERS:
2126  X - spline nodes
2127  Y - function values
2128 
2129 OPTIONAL PARAMETERS:
2130  N - points count:
2131  * N>=2
2132  * if given, only first N points are used
2133  * if not given, automatically detected from X/Y sizes
2134  (len(X) must be equal to len(Y))
2135  BoundLType - boundary condition type for the left boundary
2136  BoundL - left boundary condition (first or second derivative,
2137  depending on the BoundLType)
2138  BoundRType - boundary condition type for the right boundary
2139  BoundR - right boundary condition (first or second derivative,
2140  depending on the BoundRType)
2141 
2142 OUTPUT PARAMETERS:
2143  D1 - S' values at X[]
2144  D2 - S'' values at X[]
2145 
2146 ORDER OF POINTS
2147 
2148 Subroutine automatically sorts points, so caller may pass unsorted array.
2149 Derivative values are correctly reordered on return, so D[I] is always
2150 equal to S'(X[I]) independently of points order.
2151 
2152 SETTING BOUNDARY VALUES:
2153 
2154 The BoundLType/BoundRType parameters can have the following values:
2155  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2156  In this case:
2157  * both BoundLType and BoundRType must be equal to -1.
2158  * BoundL/BoundR are ignored
2159  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2160  * 0, which corresponds to the parabolically terminated spline
2161  (BoundL and/or BoundR are ignored).
2162  * 1, which corresponds to the first derivative boundary condition
2163  * 2, which corresponds to the second derivative boundary condition
2164  * by default, BoundType=0 is used
2165 
2166 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2167 
2168 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2169 However, this subroutine doesn't require you to specify equal values for
2170 the first and last points - it automatically forces them to be equal by
2171 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2172 Y[last_point]. However it is recommended to pass consistent values of Y[],
2173 i.e. to make Y[first_point]=Y[last_point].
2174 
2175  -- ALGLIB PROJECT --
2176  Copyright 03.09.2010 by Bochkanov Sergey
2177 *************************************************************************/
2179 {
2180  alglib_impl::ae_state _alglib_env_state;
2181  ae_int_t n;
2182  ae_int_t boundltype;
2183  double boundl;
2184  ae_int_t boundrtype;
2185  double boundr;
2186  if( (x.length()!=y.length()))
2187  throw ap_error("Error while calling 'spline1dgriddiff2cubic': looks like one of arguments has wrong size");
2188  n = x.length();
2189  boundltype = 0;
2190  boundl = 0;
2191  boundrtype = 0;
2192  boundr = 0;
2193  alglib_impl::ae_state_init(&_alglib_env_state);
2194  try
2195  {
2196  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);
2197 
2198  alglib_impl::ae_state_clear(&_alglib_env_state);
2199  return;
2200  }
2202  {
2203  throw ap_error(_alglib_env_state.error_msg);
2204  }
2205 }
2206 
2207 /*************************************************************************
2208 This function solves following problem: given table y[] of function values
2209 at old nodes x[] and new nodes x2[], it calculates and returns table of
2210 function values y2[] (calculated at x2[]).
2211 
2212 This function yields same result as Spline1DBuildCubic() call followed by
2213 sequence of Spline1DDiff() calls, but it can be several times faster when
2214 called for ordered X[] and X2[].
2215 
2216 INPUT PARAMETERS:
2217  X - old spline nodes
2218  Y - function values
2219  X2 - new spline nodes
2220 
2221 OPTIONAL PARAMETERS:
2222  N - points count:
2223  * N>=2
2224  * if given, only first N points from X/Y are used
2225  * if not given, automatically detected from X/Y sizes
2226  (len(X) must be equal to len(Y))
2227  BoundLType - boundary condition type for the left boundary
2228  BoundL - left boundary condition (first or second derivative,
2229  depending on the BoundLType)
2230  BoundRType - boundary condition type for the right boundary
2231  BoundR - right boundary condition (first or second derivative,
2232  depending on the BoundRType)
2233  N2 - new points count:
2234  * N2>=2
2235  * if given, only first N2 points from X2 are used
2236  * if not given, automatically detected from X2 size
2237 
2238 OUTPUT PARAMETERS:
2239  F2 - function values at X2[]
2240 
2241 ORDER OF POINTS
2242 
2243 Subroutine automatically sorts points, so caller may pass unsorted array.
2244 Function values are correctly reordered on return, so F2[I] is always
2245 equal to S(X2[I]) independently of points order.
2246 
2247 SETTING BOUNDARY VALUES:
2248 
2249 The BoundLType/BoundRType parameters can have the following values:
2250  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2251  In this case:
2252  * both BoundLType and BoundRType must be equal to -1.
2253  * BoundL/BoundR are ignored
2254  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2255  * 0, which corresponds to the parabolically terminated spline
2256  (BoundL and/or BoundR are ignored).
2257  * 1, which corresponds to the first derivative boundary condition
2258  * 2, which corresponds to the second derivative boundary condition
2259  * by default, BoundType=0 is used
2260 
2261 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2262 
2263 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2264 However, this subroutine doesn't require you to specify equal values for
2265 the first and last points - it automatically forces them to be equal by
2266 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2267 Y[last_point]. However it is recommended to pass consistent values of Y[],
2268 i.e. to make Y[first_point]=Y[last_point].
2269 
2270  -- ALGLIB PROJECT --
2271  Copyright 03.09.2010 by Bochkanov Sergey
2272 *************************************************************************/
2273 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)
2274 {
2275  alglib_impl::ae_state _alglib_env_state;
2276  alglib_impl::ae_state_init(&_alglib_env_state);
2277  try
2278  {
2279  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);
2280  alglib_impl::ae_state_clear(&_alglib_env_state);
2281  return;
2282  }
2284  {
2285  throw ap_error(_alglib_env_state.error_msg);
2286  }
2287 }
2288 
2289 /*************************************************************************
2290 This function solves following problem: given table y[] of function values
2291 at old nodes x[] and new nodes x2[], it calculates and returns table of
2292 function values y2[] (calculated at x2[]).
2293 
2294 This function yields same result as Spline1DBuildCubic() call followed by
2295 sequence of Spline1DDiff() calls, but it can be several times faster when
2296 called for ordered X[] and X2[].
2297 
2298 INPUT PARAMETERS:
2299  X - old spline nodes
2300  Y - function values
2301  X2 - new spline nodes
2302 
2303 OPTIONAL PARAMETERS:
2304  N - points count:
2305  * N>=2
2306  * if given, only first N points from X/Y are used
2307  * if not given, automatically detected from X/Y sizes
2308  (len(X) must be equal to len(Y))
2309  BoundLType - boundary condition type for the left boundary
2310  BoundL - left boundary condition (first or second derivative,
2311  depending on the BoundLType)
2312  BoundRType - boundary condition type for the right boundary
2313  BoundR - right boundary condition (first or second derivative,
2314  depending on the BoundRType)
2315  N2 - new points count:
2316  * N2>=2
2317  * if given, only first N2 points from X2 are used
2318  * if not given, automatically detected from X2 size
2319 
2320 OUTPUT PARAMETERS:
2321  F2 - function values at X2[]
2322 
2323 ORDER OF POINTS
2324 
2325 Subroutine automatically sorts points, so caller may pass unsorted array.
2326 Function values are correctly reordered on return, so F2[I] is always
2327 equal to S(X2[I]) independently of points order.
2328 
2329 SETTING BOUNDARY VALUES:
2330 
2331 The BoundLType/BoundRType parameters can have the following values:
2332  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2333  In this case:
2334  * both BoundLType and BoundRType must be equal to -1.
2335  * BoundL/BoundR are ignored
2336  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2337  * 0, which corresponds to the parabolically terminated spline
2338  (BoundL and/or BoundR are ignored).
2339  * 1, which corresponds to the first derivative boundary condition
2340  * 2, which corresponds to the second derivative boundary condition
2341  * by default, BoundType=0 is used
2342 
2343 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2344 
2345 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2346 However, this subroutine doesn't require you to specify equal values for
2347 the first and last points - it automatically forces them to be equal by
2348 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2349 Y[last_point]. However it is recommended to pass consistent values of Y[],
2350 i.e. to make Y[first_point]=Y[last_point].
2351 
2352  -- ALGLIB PROJECT --
2353  Copyright 03.09.2010 by Bochkanov Sergey
2354 *************************************************************************/
2356 {
2357  alglib_impl::ae_state _alglib_env_state;
2358  ae_int_t n;
2359  ae_int_t boundltype;
2360  double boundl;
2361  ae_int_t boundrtype;
2362  double boundr;
2363  ae_int_t n2;
2364  if( (x.length()!=y.length()))
2365  throw ap_error("Error while calling 'spline1dconvcubic': looks like one of arguments has wrong size");
2366  n = x.length();
2367  boundltype = 0;
2368  boundl = 0;
2369  boundrtype = 0;
2370  boundr = 0;
2371  n2 = x2.length();
2372  alglib_impl::ae_state_init(&_alglib_env_state);
2373  try
2374  {
2375  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);
2376 
2377  alglib_impl::ae_state_clear(&_alglib_env_state);
2378  return;
2379  }
2381  {
2382  throw ap_error(_alglib_env_state.error_msg);
2383  }
2384 }
2385 
2386 /*************************************************************************
2387 This function solves following problem: given table y[] of function values
2388 at old nodes x[] and new nodes x2[], it calculates and returns table of
2389 function values y2[] and derivatives d2[] (calculated at x2[]).
2390 
2391 This function yields same result as Spline1DBuildCubic() call followed by
2392 sequence of Spline1DDiff() calls, but it can be several times faster when
2393 called for ordered X[] and X2[].
2394 
2395 INPUT PARAMETERS:
2396  X - old spline nodes
2397  Y - function values
2398  X2 - new spline nodes
2399 
2400 OPTIONAL PARAMETERS:
2401  N - points count:
2402  * N>=2
2403  * if given, only first N points from X/Y are used
2404  * if not given, automatically detected from X/Y sizes
2405  (len(X) must be equal to len(Y))
2406  BoundLType - boundary condition type for the left boundary
2407  BoundL - left boundary condition (first or second derivative,
2408  depending on the BoundLType)
2409  BoundRType - boundary condition type for the right boundary
2410  BoundR - right boundary condition (first or second derivative,
2411  depending on the BoundRType)
2412  N2 - new points count:
2413  * N2>=2
2414  * if given, only first N2 points from X2 are used
2415  * if not given, automatically detected from X2 size
2416 
2417 OUTPUT PARAMETERS:
2418  F2 - function values at X2[]
2419  D2 - first derivatives at X2[]
2420 
2421 ORDER OF POINTS
2422 
2423 Subroutine automatically sorts points, so caller may pass unsorted array.
2424 Function values are correctly reordered on return, so F2[I] is always
2425 equal to S(X2[I]) independently of points order.
2426 
2427 SETTING BOUNDARY VALUES:
2428 
2429 The BoundLType/BoundRType parameters can have the following values:
2430  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2431  In this case:
2432  * both BoundLType and BoundRType must be equal to -1.
2433  * BoundL/BoundR are ignored
2434  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2435  * 0, which corresponds to the parabolically terminated spline
2436  (BoundL and/or BoundR are ignored).
2437  * 1, which corresponds to the first derivative boundary condition
2438  * 2, which corresponds to the second derivative boundary condition
2439  * by default, BoundType=0 is used
2440 
2441 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2442 
2443 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2444 However, this subroutine doesn't require you to specify equal values for
2445 the first and last points - it automatically forces them to be equal by
2446 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2447 Y[last_point]. However it is recommended to pass consistent values of Y[],
2448 i.e. to make Y[first_point]=Y[last_point].
2449 
2450  -- ALGLIB PROJECT --
2451  Copyright 03.09.2010 by Bochkanov Sergey
2452 *************************************************************************/
2453 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)
2454 {
2455  alglib_impl::ae_state _alglib_env_state;
2456  alglib_impl::ae_state_init(&_alglib_env_state);
2457  try
2458  {
2459  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);
2460  alglib_impl::ae_state_clear(&_alglib_env_state);
2461  return;
2462  }
2464  {
2465  throw ap_error(_alglib_env_state.error_msg);
2466  }
2467 }
2468 
2469 /*************************************************************************
2470 This function solves following problem: given table y[] of function values
2471 at old nodes x[] and new nodes x2[], it calculates and returns table of
2472 function values y2[] and derivatives d2[] (calculated at x2[]).
2473 
2474 This function yields same result as Spline1DBuildCubic() call followed by
2475 sequence of Spline1DDiff() calls, but it can be several times faster when
2476 called for ordered X[] and X2[].
2477 
2478 INPUT PARAMETERS:
2479  X - old spline nodes
2480  Y - function values
2481  X2 - new spline nodes
2482 
2483 OPTIONAL PARAMETERS:
2484  N - points count:
2485  * N>=2
2486  * if given, only first N points from X/Y are used
2487  * if not given, automatically detected from X/Y sizes
2488  (len(X) must be equal to len(Y))
2489  BoundLType - boundary condition type for the left boundary
2490  BoundL - left boundary condition (first or second derivative,
2491  depending on the BoundLType)
2492  BoundRType - boundary condition type for the right boundary
2493  BoundR - right boundary condition (first or second derivative,
2494  depending on the BoundRType)
2495  N2 - new points count:
2496  * N2>=2
2497  * if given, only first N2 points from X2 are used
2498  * if not given, automatically detected from X2 size
2499 
2500 OUTPUT PARAMETERS:
2501  F2 - function values at X2[]
2502  D2 - first derivatives at X2[]
2503 
2504 ORDER OF POINTS
2505 
2506 Subroutine automatically sorts points, so caller may pass unsorted array.
2507 Function values are correctly reordered on return, so F2[I] is always
2508 equal to S(X2[I]) independently of points order.
2509 
2510 SETTING BOUNDARY VALUES:
2511 
2512 The BoundLType/BoundRType parameters can have the following values:
2513  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2514  In this case:
2515  * both BoundLType and BoundRType must be equal to -1.
2516  * BoundL/BoundR are ignored
2517  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2518  * 0, which corresponds to the parabolically terminated spline
2519  (BoundL and/or BoundR are ignored).
2520  * 1, which corresponds to the first derivative boundary condition
2521  * 2, which corresponds to the second derivative boundary condition
2522  * by default, BoundType=0 is used
2523 
2524 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2525 
2526 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2527 However, this subroutine doesn't require you to specify equal values for
2528 the first and last points - it automatically forces them to be equal by
2529 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2530 Y[last_point]. However it is recommended to pass consistent values of Y[],
2531 i.e. to make Y[first_point]=Y[last_point].
2532 
2533  -- ALGLIB PROJECT --
2534  Copyright 03.09.2010 by Bochkanov Sergey
2535 *************************************************************************/
2537 {
2538  alglib_impl::ae_state _alglib_env_state;
2539  ae_int_t n;
2540  ae_int_t boundltype;
2541  double boundl;
2542  ae_int_t boundrtype;
2543  double boundr;
2544  ae_int_t n2;
2545  if( (x.length()!=y.length()))
2546  throw ap_error("Error while calling 'spline1dconvdiffcubic': looks like one of arguments has wrong size");
2547  n = x.length();
2548  boundltype = 0;
2549  boundl = 0;
2550  boundrtype = 0;
2551  boundr = 0;
2552  n2 = x2.length();
2553  alglib_impl::ae_state_init(&_alglib_env_state);
2554  try
2555  {
2556  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);
2557 
2558  alglib_impl::ae_state_clear(&_alglib_env_state);
2559  return;
2560  }
2562  {
2563  throw ap_error(_alglib_env_state.error_msg);
2564  }
2565 }
2566 
2567 /*************************************************************************
2568 This function solves following problem: given table y[] of function values
2569 at old nodes x[] and new nodes x2[], it calculates and returns table of
2570 function values y2[], first and second derivatives d2[] and dd2[]
2571 (calculated at x2[]).
2572 
2573 This function yields same result as Spline1DBuildCubic() call followed by
2574 sequence of Spline1DDiff() calls, but it can be several times faster when
2575 called for ordered X[] and X2[].
2576 
2577 INPUT PARAMETERS:
2578  X - old spline nodes
2579  Y - function values
2580  X2 - new spline nodes
2581 
2582 OPTIONAL PARAMETERS:
2583  N - points count:
2584  * N>=2
2585  * if given, only first N points from X/Y are used
2586  * if not given, automatically detected from X/Y sizes
2587  (len(X) must be equal to len(Y))
2588  BoundLType - boundary condition type for the left boundary
2589  BoundL - left boundary condition (first or second derivative,
2590  depending on the BoundLType)
2591  BoundRType - boundary condition type for the right boundary
2592  BoundR - right boundary condition (first or second derivative,
2593  depending on the BoundRType)
2594  N2 - new points count:
2595  * N2>=2
2596  * if given, only first N2 points from X2 are used
2597  * if not given, automatically detected from X2 size
2598 
2599 OUTPUT PARAMETERS:
2600  F2 - function values at X2[]
2601  D2 - first derivatives at X2[]
2602  DD2 - second derivatives at X2[]
2603 
2604 ORDER OF POINTS
2605 
2606 Subroutine automatically sorts points, so caller may pass unsorted array.
2607 Function values are correctly reordered on return, so F2[I] is always
2608 equal to S(X2[I]) independently of points order.
2609 
2610 SETTING BOUNDARY VALUES:
2611 
2612 The BoundLType/BoundRType parameters can have the following values:
2613  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2614  In this case:
2615  * both BoundLType and BoundRType must be equal to -1.
2616  * BoundL/BoundR are ignored
2617  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2618  * 0, which corresponds to the parabolically terminated spline
2619  (BoundL and/or BoundR are ignored).
2620  * 1, which corresponds to the first derivative boundary condition
2621  * 2, which corresponds to the second derivative boundary condition
2622  * by default, BoundType=0 is used
2623 
2624 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2625 
2626 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2627 However, this subroutine doesn't require you to specify equal values for
2628 the first and last points - it automatically forces them to be equal by
2629 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2630 Y[last_point]. However it is recommended to pass consistent values of Y[],
2631 i.e. to make Y[first_point]=Y[last_point].
2632 
2633  -- ALGLIB PROJECT --
2634  Copyright 03.09.2010 by Bochkanov Sergey
2635 *************************************************************************/
2636 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)
2637 {
2638  alglib_impl::ae_state _alglib_env_state;
2639  alglib_impl::ae_state_init(&_alglib_env_state);
2640  try
2641  {
2642  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);
2643  alglib_impl::ae_state_clear(&_alglib_env_state);
2644  return;
2645  }
2647  {
2648  throw ap_error(_alglib_env_state.error_msg);
2649  }
2650 }
2651 
2652 /*************************************************************************
2653 This function solves following problem: given table y[] of function values
2654 at old nodes x[] and new nodes x2[], it calculates and returns table of
2655 function values y2[], first and second derivatives d2[] and dd2[]
2656 (calculated at x2[]).
2657 
2658 This function yields same result as Spline1DBuildCubic() call followed by
2659 sequence of Spline1DDiff() calls, but it can be several times faster when
2660 called for ordered X[] and X2[].
2661 
2662 INPUT PARAMETERS:
2663  X - old spline nodes
2664  Y - function values
2665  X2 - new spline nodes
2666 
2667 OPTIONAL PARAMETERS:
2668  N - points count:
2669  * N>=2
2670  * if given, only first N points from X/Y are used
2671  * if not given, automatically detected from X/Y sizes
2672  (len(X) must be equal to len(Y))
2673  BoundLType - boundary condition type for the left boundary
2674  BoundL - left boundary condition (first or second derivative,
2675  depending on the BoundLType)
2676  BoundRType - boundary condition type for the right boundary
2677  BoundR - right boundary condition (first or second derivative,
2678  depending on the BoundRType)
2679  N2 - new points count:
2680  * N2>=2
2681  * if given, only first N2 points from X2 are used
2682  * if not given, automatically detected from X2 size
2683 
2684 OUTPUT PARAMETERS:
2685  F2 - function values at X2[]
2686  D2 - first derivatives at X2[]
2687  DD2 - second derivatives at X2[]
2688 
2689 ORDER OF POINTS
2690 
2691 Subroutine automatically sorts points, so caller may pass unsorted array.
2692 Function values are correctly reordered on return, so F2[I] is always
2693 equal to S(X2[I]) independently of points order.
2694 
2695 SETTING BOUNDARY VALUES:
2696 
2697 The BoundLType/BoundRType parameters can have the following values:
2698  * -1, which corresonds to the periodic (cyclic) boundary conditions.
2699  In this case:
2700  * both BoundLType and BoundRType must be equal to -1.
2701  * BoundL/BoundR are ignored
2702  * Y[last] is ignored (it is assumed to be equal to Y[first]).
2703  * 0, which corresponds to the parabolically terminated spline
2704  (BoundL and/or BoundR are ignored).
2705  * 1, which corresponds to the first derivative boundary condition
2706  * 2, which corresponds to the second derivative boundary condition
2707  * by default, BoundType=0 is used
2708 
2709 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2710 
2711 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2712 However, this subroutine doesn't require you to specify equal values for
2713 the first and last points - it automatically forces them to be equal by
2714 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2715 Y[last_point]. However it is recommended to pass consistent values of Y[],
2716 i.e. to make Y[first_point]=Y[last_point].
2717 
2718  -- ALGLIB PROJECT --
2719  Copyright 03.09.2010 by Bochkanov Sergey
2720 *************************************************************************/
2722 {
2723  alglib_impl::ae_state _alglib_env_state;
2724  ae_int_t n;
2725  ae_int_t boundltype;
2726  double boundl;
2727  ae_int_t boundrtype;
2728  double boundr;
2729  ae_int_t n2;
2730  if( (x.length()!=y.length()))
2731  throw ap_error("Error while calling 'spline1dconvdiff2cubic': looks like one of arguments has wrong size");
2732  n = x.length();
2733  boundltype = 0;
2734  boundl = 0;
2735  boundrtype = 0;
2736  boundr = 0;
2737  n2 = x2.length();
2738  alglib_impl::ae_state_init(&_alglib_env_state);
2739  try
2740  {
2741  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);
2742 
2743  alglib_impl::ae_state_clear(&_alglib_env_state);
2744  return;
2745  }
2747  {
2748  throw ap_error(_alglib_env_state.error_msg);
2749  }
2750 }
2751 
2752 /*************************************************************************
2753 This subroutine builds Catmull-Rom spline interpolant.
2754 
2755 INPUT PARAMETERS:
2756  X - spline nodes, array[0..N-1].
2757  Y - function values, array[0..N-1].
2758 
2759 OPTIONAL PARAMETERS:
2760  N - points count:
2761  * N>=2
2762  * if given, only first N points are used to build spline
2763  * if not given, automatically detected from X/Y sizes
2764  (len(X) must be equal to len(Y))
2765  BoundType - boundary condition type:
2766  * -1 for periodic boundary condition
2767  * 0 for parabolically terminated spline (default)
2768  Tension - tension parameter:
2769  * tension=0 corresponds to classic Catmull-Rom spline (default)
2770  * 0<tension<1 corresponds to more general form - cardinal spline
2771 
2772 OUTPUT PARAMETERS:
2773  C - spline interpolant
2774 
2775 
2776 ORDER OF POINTS
2777 
2778 Subroutine automatically sorts points, so caller may pass unsorted array.
2779 
2780 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2781 
2782 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2783 However, this subroutine doesn't require you to specify equal values for
2784 the first and last points - it automatically forces them to be equal by
2785 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2786 Y[last_point]. However it is recommended to pass consistent values of Y[],
2787 i.e. to make Y[first_point]=Y[last_point].
2788 
2789  -- ALGLIB PROJECT --
2790  Copyright 23.06.2007 by Bochkanov Sergey
2791 *************************************************************************/
2792 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)
2793 {
2794  alglib_impl::ae_state _alglib_env_state;
2795  alglib_impl::ae_state_init(&_alglib_env_state);
2796  try
2797  {
2798  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);
2799  alglib_impl::ae_state_clear(&_alglib_env_state);
2800  return;
2801  }
2803  {
2804  throw ap_error(_alglib_env_state.error_msg);
2805  }
2806 }
2807 
2808 /*************************************************************************
2809 This subroutine builds Catmull-Rom spline interpolant.
2810 
2811 INPUT PARAMETERS:
2812  X - spline nodes, array[0..N-1].
2813  Y - function values, array[0..N-1].
2814 
2815 OPTIONAL PARAMETERS:
2816  N - points count:
2817  * N>=2
2818  * if given, only first N points are used to build spline
2819  * if not given, automatically detected from X/Y sizes
2820  (len(X) must be equal to len(Y))
2821  BoundType - boundary condition type:
2822  * -1 for periodic boundary condition
2823  * 0 for parabolically terminated spline (default)
2824  Tension - tension parameter:
2825  * tension=0 corresponds to classic Catmull-Rom spline (default)
2826  * 0<tension<1 corresponds to more general form - cardinal spline
2827 
2828 OUTPUT PARAMETERS:
2829  C - spline interpolant
2830 
2831 
2832 ORDER OF POINTS
2833 
2834 Subroutine automatically sorts points, so caller may pass unsorted array.
2835 
2836 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
2837 
2838 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
2839 However, this subroutine doesn't require you to specify equal values for
2840 the first and last points - it automatically forces them to be equal by
2841 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
2842 Y[last_point]. However it is recommended to pass consistent values of Y[],
2843 i.e. to make Y[first_point]=Y[last_point].
2844 
2845  -- ALGLIB PROJECT --
2846  Copyright 23.06.2007 by Bochkanov Sergey
2847 *************************************************************************/
2849 {
2850  alglib_impl::ae_state _alglib_env_state;
2851  ae_int_t n;
2852  ae_int_t boundtype;
2853  double tension;
2854  if( (x.length()!=y.length()))
2855  throw ap_error("Error while calling 'spline1dbuildcatmullrom': looks like one of arguments has wrong size");
2856  n = x.length();
2857  boundtype = 0;
2858  tension = 0;
2859  alglib_impl::ae_state_init(&_alglib_env_state);
2860  try
2861  {
2862  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);
2863 
2864  alglib_impl::ae_state_clear(&_alglib_env_state);
2865  return;
2866  }
2868  {
2869  throw ap_error(_alglib_env_state.error_msg);
2870  }
2871 }
2872 
2873 /*************************************************************************
2874 This subroutine builds Hermite spline interpolant.
2875 
2876 INPUT PARAMETERS:
2877  X - spline nodes, array[0..N-1]
2878  Y - function values, array[0..N-1]
2879  D - derivatives, array[0..N-1]
2880  N - points count (optional):
2881  * N>=2
2882  * if given, only first N points are used to build spline
2883  * if not given, automatically detected from X/Y sizes
2884  (len(X) must be equal to len(Y))
2885 
2886 OUTPUT PARAMETERS:
2887  C - spline interpolant.
2888 
2889 
2890 ORDER OF POINTS
2891 
2892 Subroutine automatically sorts points, so caller may pass unsorted array.
2893 
2894  -- ALGLIB PROJECT --
2895  Copyright 23.06.2007 by Bochkanov Sergey
2896 *************************************************************************/
2898 {
2899  alglib_impl::ae_state _alglib_env_state;
2900  alglib_impl::ae_state_init(&_alglib_env_state);
2901  try
2902  {
2903  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);
2904  alglib_impl::ae_state_clear(&_alglib_env_state);
2905  return;
2906  }
2908  {
2909  throw ap_error(_alglib_env_state.error_msg);
2910  }
2911 }
2912 
2913 /*************************************************************************
2914 This subroutine builds Hermite spline interpolant.
2915 
2916 INPUT PARAMETERS:
2917  X - spline nodes, array[0..N-1]
2918  Y - function values, array[0..N-1]
2919  D - derivatives, array[0..N-1]
2920  N - points count (optional):
2921  * N>=2
2922  * if given, only first N points are used to build spline
2923  * if not given, automatically detected from X/Y sizes
2924  (len(X) must be equal to len(Y))
2925 
2926 OUTPUT PARAMETERS:
2927  C - spline interpolant.
2928 
2929 
2930 ORDER OF POINTS
2931 
2932 Subroutine automatically sorts points, so caller may pass unsorted array.
2933 
2934  -- ALGLIB PROJECT --
2935  Copyright 23.06.2007 by Bochkanov Sergey
2936 *************************************************************************/
2938 {
2939  alglib_impl::ae_state _alglib_env_state;
2940  ae_int_t n;
2941  if( (x.length()!=y.length()) || (x.length()!=d.length()))
2942  throw ap_error("Error while calling 'spline1dbuildhermite': looks like one of arguments has wrong size");
2943  n = x.length();
2944  alglib_impl::ae_state_init(&_alglib_env_state);
2945  try
2946  {
2947  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);
2948 
2949  alglib_impl::ae_state_clear(&_alglib_env_state);
2950  return;
2951  }
2953  {
2954  throw ap_error(_alglib_env_state.error_msg);
2955  }
2956 }
2957 
2958 /*************************************************************************
2959 This subroutine builds Akima spline interpolant
2960 
2961 INPUT PARAMETERS:
2962  X - spline nodes, array[0..N-1]
2963  Y - function values, array[0..N-1]
2964  N - points count (optional):
2965  * N>=2
2966  * if given, only first N points are used to build spline
2967  * if not given, automatically detected from X/Y sizes
2968  (len(X) must be equal to len(Y))
2969 
2970 OUTPUT PARAMETERS:
2971  C - spline interpolant
2972 
2973 
2974 ORDER OF POINTS
2975 
2976 Subroutine automatically sorts points, so caller may pass unsorted array.
2977 
2978  -- ALGLIB PROJECT --
2979  Copyright 24.06.2007 by Bochkanov Sergey
2980 *************************************************************************/
2982 {
2983  alglib_impl::ae_state _alglib_env_state;
2984  alglib_impl::ae_state_init(&_alglib_env_state);
2985  try
2986  {
2987  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);
2988  alglib_impl::ae_state_clear(&_alglib_env_state);
2989  return;
2990  }
2992  {
2993  throw ap_error(_alglib_env_state.error_msg);
2994  }
2995 }
2996 
2997 /*************************************************************************
2998 This subroutine builds Akima spline interpolant
2999 
3000 INPUT PARAMETERS:
3001  X - spline nodes, array[0..N-1]
3002  Y - function values, array[0..N-1]
3003  N - points count (optional):
3004  * N>=2
3005  * if given, only first N points are used to build spline
3006  * if not given, automatically detected from X/Y sizes
3007  (len(X) must be equal to len(Y))
3008 
3009 OUTPUT PARAMETERS:
3010  C - spline interpolant
3011 
3012 
3013 ORDER OF POINTS
3014 
3015 Subroutine automatically sorts points, so caller may pass unsorted array.
3016 
3017  -- ALGLIB PROJECT --
3018  Copyright 24.06.2007 by Bochkanov Sergey
3019 *************************************************************************/
3021 {
3022  alglib_impl::ae_state _alglib_env_state;
3023  ae_int_t n;
3024  if( (x.length()!=y.length()))
3025  throw ap_error("Error while calling 'spline1dbuildakima': looks like one of arguments has wrong size");
3026  n = x.length();
3027  alglib_impl::ae_state_init(&_alglib_env_state);
3028  try
3029  {
3030  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);
3031 
3032  alglib_impl::ae_state_clear(&_alglib_env_state);
3033  return;
3034  }
3036  {
3037  throw ap_error(_alglib_env_state.error_msg);
3038  }
3039 }
3040 
3041 /*************************************************************************
3042 This subroutine calculates the value of the spline at the given point X.
3043 
3044 INPUT PARAMETERS:
3045  C - spline interpolant
3046  X - point
3047 
3048 Result:
3049  S(x)
3050 
3051  -- ALGLIB PROJECT --
3052  Copyright 23.06.2007 by Bochkanov Sergey
3053 *************************************************************************/
3054 double spline1dcalc(const spline1dinterpolant &c, const double x)
3055 {
3056  alglib_impl::ae_state _alglib_env_state;
3057  alglib_impl::ae_state_init(&_alglib_env_state);
3058  try
3059  {
3060  double result = alglib_impl::spline1dcalc(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), x, &_alglib_env_state);
3061  alglib_impl::ae_state_clear(&_alglib_env_state);
3062  return *(reinterpret_cast<double*>(&result));
3063  }
3065  {
3066  throw ap_error(_alglib_env_state.error_msg);
3067  }
3068 }
3069 
3070 /*************************************************************************
3071 This subroutine differentiates the spline.
3072 
3073 INPUT PARAMETERS:
3074  C - spline interpolant.
3075  X - point
3076 
3077 Result:
3078  S - S(x)
3079  DS - S'(x)
3080  D2S - S''(x)
3081 
3082  -- ALGLIB PROJECT --
3083  Copyright 24.06.2007 by Bochkanov Sergey
3084 *************************************************************************/
3085 void spline1ddiff(const spline1dinterpolant &c, const double x, double &s, double &ds, double &d2s)
3086 {
3087  alglib_impl::ae_state _alglib_env_state;
3088  alglib_impl::ae_state_init(&_alglib_env_state);
3089  try
3090  {
3091  alglib_impl::spline1ddiff(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), x, &s, &ds, &d2s, &_alglib_env_state);
3092  alglib_impl::ae_state_clear(&_alglib_env_state);
3093  return;
3094  }
3096  {
3097  throw ap_error(_alglib_env_state.error_msg);
3098  }
3099 }
3100 
3101 /*************************************************************************
3102 This subroutine unpacks the spline into the coefficients table.
3103 
3104 INPUT PARAMETERS:
3105  C - spline interpolant.
3106  X - point
3107 
3108 OUTPUT PARAMETERS:
3109  Tbl - coefficients table, unpacked format, array[0..N-2, 0..5].
3110  For I = 0...N-2:
3111  Tbl[I,0] = X[i]
3112  Tbl[I,1] = X[i+1]
3113  Tbl[I,2] = C0
3114  Tbl[I,3] = C1
3115  Tbl[I,4] = C2
3116  Tbl[I,5] = C3
3117  On [x[i], x[i+1]] spline is equals to:
3118  S(x) = C0 + C1*t + C2*t^2 + C3*t^3
3119  t = x-x[i]
3120 
3121 NOTE:
3122  You can rebuild spline with Spline1DBuildHermite() function, which
3123  accepts as inputs function values and derivatives at nodes, which are
3124  easy to calculate when you have coefficients.
3125 
3126  -- ALGLIB PROJECT --
3127  Copyright 29.06.2007 by Bochkanov Sergey
3128 *************************************************************************/
3130 {
3131  alglib_impl::ae_state _alglib_env_state;
3132  alglib_impl::ae_state_init(&_alglib_env_state);
3133  try
3134  {
3135  alglib_impl::spline1dunpack(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), &n, const_cast<alglib_impl::ae_matrix*>(tbl.c_ptr()), &_alglib_env_state);
3136  alglib_impl::ae_state_clear(&_alglib_env_state);
3137  return;
3138  }
3140  {
3141  throw ap_error(_alglib_env_state.error_msg);
3142  }
3143 }
3144 
3145 /*************************************************************************
3146 This subroutine performs linear transformation of the spline argument.
3147 
3148 INPUT PARAMETERS:
3149  C - spline interpolant.
3150  A, B- transformation coefficients: x = A*t + B
3151 Result:
3152  C - transformed spline
3153 
3154  -- ALGLIB PROJECT --
3155  Copyright 30.06.2007 by Bochkanov Sergey
3156 *************************************************************************/
3157 void spline1dlintransx(const spline1dinterpolant &c, const double a, const double b)
3158 {
3159  alglib_impl::ae_state _alglib_env_state;
3160  alglib_impl::ae_state_init(&_alglib_env_state);
3161  try
3162  {
3163  alglib_impl::spline1dlintransx(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
3164  alglib_impl::ae_state_clear(&_alglib_env_state);
3165  return;
3166  }
3168  {
3169  throw ap_error(_alglib_env_state.error_msg);
3170  }
3171 }
3172 
3173 /*************************************************************************
3174 This subroutine performs linear transformation of the spline.
3175 
3176 INPUT PARAMETERS:
3177  C - spline interpolant.
3178  A, B- transformation coefficients: S2(x) = A*S(x) + B
3179 Result:
3180  C - transformed spline
3181 
3182  -- ALGLIB PROJECT --
3183  Copyright 30.06.2007 by Bochkanov Sergey
3184 *************************************************************************/
3185 void spline1dlintransy(const spline1dinterpolant &c, const double a, const double b)
3186 {
3187  alglib_impl::ae_state _alglib_env_state;
3188  alglib_impl::ae_state_init(&_alglib_env_state);
3189  try
3190  {
3191  alglib_impl::spline1dlintransy(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
3192  alglib_impl::ae_state_clear(&_alglib_env_state);
3193  return;
3194  }
3196  {
3197  throw ap_error(_alglib_env_state.error_msg);
3198  }
3199 }
3200 
3201 /*************************************************************************
3202 This subroutine integrates the spline.
3203 
3204 INPUT PARAMETERS:
3205  C - spline interpolant.
3206  X - right bound of the integration interval [a, x],
3207  here 'a' denotes min(x[])
3208 Result:
3209  integral(S(t)dt,a,x)
3210 
3211  -- ALGLIB PROJECT --
3212  Copyright 23.06.2007 by Bochkanov Sergey
3213 *************************************************************************/
3214 double spline1dintegrate(const spline1dinterpolant &c, const double x)
3215 {
3216  alglib_impl::ae_state _alglib_env_state;
3217  alglib_impl::ae_state_init(&_alglib_env_state);
3218  try
3219  {
3220  double result = alglib_impl::spline1dintegrate(const_cast<alglib_impl::spline1dinterpolant*>(c.c_ptr()), x, &_alglib_env_state);
3221  alglib_impl::ae_state_clear(&_alglib_env_state);
3222  return *(reinterpret_cast<double*>(&result));
3223  }
3225  {
3226  throw ap_error(_alglib_env_state.error_msg);
3227  }
3228 }
3229 
3230 /*************************************************************************
3231 This function builds monotone cubic Hermite interpolant. This interpolant
3232 is monotonic in [x(0),x(n-1)] and is constant outside of this interval.
3233 
3234 In case y[] form non-monotonic sequence, interpolant is piecewise
3235 monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will
3236 monotonically grow at [0..2] and monotonically decrease at [2..4].
3237 
3238 INPUT PARAMETERS:
3239  X - spline nodes, array[0..N-1]. Subroutine automatically
3240  sorts points, so caller may pass unsorted array.
3241  Y - function values, array[0..N-1]
3242  N - the number of points(N>=2).
3243 
3244 OUTPUT PARAMETERS:
3245  C - spline interpolant.
3246 
3247  -- ALGLIB PROJECT --
3248  Copyright 21.06.2012 by Bochkanov Sergey
3249 *************************************************************************/
3251 {
3252  alglib_impl::ae_state _alglib_env_state;
3253  alglib_impl::ae_state_init(&_alglib_env_state);
3254  try
3255  {
3256  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);
3257  alglib_impl::ae_state_clear(&_alglib_env_state);
3258  return;
3259  }
3261  {
3262  throw ap_error(_alglib_env_state.error_msg);
3263  }
3264 }
3265 
3266 /*************************************************************************
3267 This function builds monotone cubic Hermite interpolant. This interpolant
3268 is monotonic in [x(0),x(n-1)] and is constant outside of this interval.
3269 
3270 In case y[] form non-monotonic sequence, interpolant is piecewise
3271 monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will
3272 monotonically grow at [0..2] and monotonically decrease at [2..4].
3273 
3274 INPUT PARAMETERS:
3275  X - spline nodes, array[0..N-1]. Subroutine automatically
3276  sorts points, so caller may pass unsorted array.
3277  Y - function values, array[0..N-1]
3278  N - the number of points(N>=2).
3279 
3280 OUTPUT PARAMETERS:
3281  C - spline interpolant.
3282 
3283  -- ALGLIB PROJECT --
3284  Copyright 21.06.2012 by Bochkanov Sergey
3285 *************************************************************************/
3287 {
3288  alglib_impl::ae_state _alglib_env_state;
3289  ae_int_t n;
3290  if( (x.length()!=y.length()))
3291  throw ap_error("Error while calling 'spline1dbuildmonotone': looks like one of arguments has wrong size");
3292  n = x.length();
3293  alglib_impl::ae_state_init(&_alglib_env_state);
3294  try
3295  {
3296  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);
3297 
3298  alglib_impl::ae_state_clear(&_alglib_env_state);
3299  return;
3300  }
3302  {
3303  throw ap_error(_alglib_env_state.error_msg);
3304  }
3305 }
3306 
3307 /*************************************************************************
3308 Polynomial fitting report:
3309  TaskRCond reciprocal of task's condition number
3310  RMSError RMS error
3311  AvgError average error
3312  AvgRelError average relative error (for non-zero Y[I])
3313  MaxError maximum error
3314 *************************************************************************/
3316 {
3318  if( p_struct==NULL )
3319  throw ap_error("ALGLIB: malloc error");
3321  throw ap_error("ALGLIB: malloc error");
3322 }
3323 
3325 {
3327  if( p_struct==NULL )
3328  throw ap_error("ALGLIB: malloc error");
3329  if( !alglib_impl::_polynomialfitreport_init_copy(p_struct, const_cast<alglib_impl::polynomialfitreport*>(rhs.p_struct), NULL, ae_false) )
3330  throw ap_error("ALGLIB: malloc error");
3331 }
3332 
3334 {
3335  if( this==&rhs )
3336  return *this;
3338  if( !alglib_impl::_polynomialfitreport_init_copy(p_struct, const_cast<alglib_impl::polynomialfitreport*>(rhs.p_struct), NULL, ae_false) )
3339  throw ap_error("ALGLIB: malloc error");
3340  return *this;
3341 }
3342 
3344 {
3346  ae_free(p_struct);
3347 }
3348 
3350 {
3351  return p_struct;
3352 }
3353 
3355 {
3356  return const_cast<alglib_impl::polynomialfitreport*>(p_struct);
3357 }
3358 polynomialfitreport::polynomialfitreport() : _polynomialfitreport_owner() ,taskrcond(p_struct->taskrcond),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),maxerror(p_struct->maxerror)
3359 {
3360 }
3361 
3363 {
3364 }
3365 
3367 {
3368  if( this==&rhs )
3369  return *this;
3371  return *this;
3372 }
3373 
3375 {
3376 }
3377 
3378 
3379 /*************************************************************************
3380 Barycentric fitting report:
3381  RMSError RMS error
3382  AvgError average error
3383  AvgRelError average relative error (for non-zero Y[I])
3384  MaxError maximum error
3385  TaskRCond reciprocal of task's condition number
3386 *************************************************************************/
3388 {
3390  if( p_struct==NULL )
3391  throw ap_error("ALGLIB: malloc error");
3393  throw ap_error("ALGLIB: malloc error");
3394 }
3395 
3397 {
3399  if( p_struct==NULL )
3400  throw ap_error("ALGLIB: malloc error");
3401  if( !alglib_impl::_barycentricfitreport_init_copy(p_struct, const_cast<alglib_impl::barycentricfitreport*>(rhs.p_struct), NULL, ae_false) )
3402  throw ap_error("ALGLIB: malloc error");
3403 }
3404 
3406 {
3407  if( this==&rhs )
3408  return *this;
3410  if( !alglib_impl::_barycentricfitreport_init_copy(p_struct, const_cast<alglib_impl::barycentricfitreport*>(rhs.p_struct), NULL, ae_false) )
3411  throw ap_error("ALGLIB: malloc error");
3412  return *this;
3413 }
3414 
3416 {
3418  ae_free(p_struct);
3419 }
3420 
3422 {
3423  return p_struct;
3424 }
3425 
3427 {
3428  return const_cast<alglib_impl::barycentricfitreport*>(p_struct);
3429 }
3431 {
3432 }
3433 
3435 {
3436 }
3437 
3439 {
3440  if( this==&rhs )
3441  return *this;
3443  return *this;
3444 }
3445 
3447 {
3448 }
3449 
3450 
3451 /*************************************************************************
3452 Spline fitting report:
3453  RMSError RMS error
3454  AvgError average error
3455  AvgRelError average relative error (for non-zero Y[I])
3456  MaxError maximum error
3457 
3458 Fields below are filled by obsolete functions (Spline1DFitCubic,
3459 Spline1DFitHermite). Modern fitting functions do NOT fill these fields:
3460  TaskRCond reciprocal of task's condition number
3461 *************************************************************************/
3463 {
3465  if( p_struct==NULL )
3466  throw ap_error("ALGLIB: malloc error");
3468  throw ap_error("ALGLIB: malloc error");
3469 }
3470 
3472 {
3474  if( p_struct==NULL )
3475  throw ap_error("ALGLIB: malloc error");
3476  if( !alglib_impl::_spline1dfitreport_init_copy(p_struct, const_cast<alglib_impl::spline1dfitreport*>(rhs.p_struct), NULL, ae_false) )
3477  throw ap_error("ALGLIB: malloc error");
3478 }
3479 
3481 {
3482  if( this==&rhs )
3483  return *this;
3485  if( !alglib_impl::_spline1dfitreport_init_copy(p_struct, const_cast<alglib_impl::spline1dfitreport*>(rhs.p_struct), NULL, ae_false) )
3486  throw ap_error("ALGLIB: malloc error");
3487  return *this;
3488 }
3489 
3491 {
3493  ae_free(p_struct);
3494 }
3495 
3497 {
3498  return p_struct;
3499 }
3500 
3502 {
3503  return const_cast<alglib_impl::spline1dfitreport*>(p_struct);
3504 }
3506 {
3507 }
3508 
3510 {
3511 }
3512 
3514 {
3515  if( this==&rhs )
3516  return *this;
3518  return *this;
3519 }
3520 
3522 {
3523 }
3524 
3525 
3526 /*************************************************************************
3527 Least squares fitting report. This structure contains informational fields
3528 which are set by fitting functions provided by this unit.
3529 
3530 Different functions initialize different sets of fields, so you should
3531 read documentation on specific function you used in order to know which
3532 fields are initialized.
3533 
3534  TaskRCond reciprocal of task's condition number
3535  IterationsCount number of internal iterations
3536 
3537  VarIdx if user-supplied gradient contains errors which were
3538  detected by nonlinear fitter, this field is set to
3539  index of the first component of gradient which is
3540  suspected to be spoiled by bugs.
3541 
3542  RMSError RMS error
3543  AvgError average error
3544  AvgRelError average relative error (for non-zero Y[I])
3545  MaxError maximum error
3546 
3547  WRMSError weighted RMS error
3548 
3549  CovPar covariance matrix for parameters, filled by some solvers
3550  ErrPar vector of errors in parameters, filled by some solvers
3551  ErrCurve vector of fit errors - variability of the best-fit
3552  curve, filled by some solvers.
3553  Noise vector of per-point noise estimates, filled by
3554  some solvers.
3555  R2 coefficient of determination (non-weighted, non-adjusted),
3556  filled by some solvers.
3557 *************************************************************************/
3559 {
3561  if( p_struct==NULL )
3562  throw ap_error("ALGLIB: malloc error");
3564  throw ap_error("ALGLIB: malloc error");
3565 }
3566 
3568 {
3570  if( p_struct==NULL )
3571  throw ap_error("ALGLIB: malloc error");
3572  if( !alglib_impl::_lsfitreport_init_copy(p_struct, const_cast<alglib_impl::lsfitreport*>(rhs.p_struct), NULL, ae_false) )
3573  throw ap_error("ALGLIB: malloc error");
3574 }
3575 
3577 {
3578  if( this==&rhs )
3579  return *this;
3581  if( !alglib_impl::_lsfitreport_init_copy(p_struct, const_cast<alglib_impl::lsfitreport*>(rhs.p_struct), NULL, ae_false) )
3582  throw ap_error("ALGLIB: malloc error");
3583  return *this;
3584 }
3585 
3587 {
3589  ae_free(p_struct);
3590 }
3591 
3593 {
3594  return p_struct;
3595 }
3596 
3598 {
3599  return const_cast<alglib_impl::lsfitreport*>(p_struct);
3600 }
3601 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)
3602 {
3603 }
3604 
3606 {
3607 }
3608 
3610 {
3611  if( this==&rhs )
3612  return *this;
3614  return *this;
3615 }
3616 
3618 {
3619 }
3620 
3621 
3622 /*************************************************************************
3623 Nonlinear fitter.
3624 
3625 You should use ALGLIB functions to work with fitter.
3626 Never try to access its fields directly!
3627 *************************************************************************/
3629 {
3631  if( p_struct==NULL )
3632  throw ap_error("ALGLIB: malloc error");
3634  throw ap_error("ALGLIB: malloc error");
3635 }
3636 
3638 {
3640  if( p_struct==NULL )
3641  throw ap_error("ALGLIB: malloc error");
3642  if( !alglib_impl::_lsfitstate_init_copy(p_struct, const_cast<alglib_impl::lsfitstate*>(rhs.p_struct), NULL, ae_false) )
3643  throw ap_error("ALGLIB: malloc error");
3644 }
3645 
3647 {
3648  if( this==&rhs )
3649  return *this;
3651  if( !alglib_impl::_lsfitstate_init_copy(p_struct, const_cast<alglib_impl::lsfitstate*>(rhs.p_struct), NULL, ae_false) )
3652  throw ap_error("ALGLIB: malloc error");
3653  return *this;
3654 }
3655 
3657 {
3659  ae_free(p_struct);
3660 }
3661 
3663 {
3664  return p_struct;
3665 }
3666 
3668 {
3669  return const_cast<alglib_impl::lsfitstate*>(p_struct);
3670 }
3671 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)
3672 {
3673 }
3674 
3676 {
3677 }
3678 
3680 {
3681  if( this==&rhs )
3682  return *this;
3684  return *this;
3685 }
3686 
3688 {
3689 }
3690 
3691 /*************************************************************************
3692 Fitting by polynomials in barycentric form. This function provides simple
3693 unterface for unconstrained unweighted fitting. See PolynomialFitWC() if
3694 you need constrained fitting.
3695 
3696 Task is linear, so linear least squares solver is used. Complexity of this
3697 computational scheme is O(N*M^2), mostly dominated by least squares solver
3698 
3699 SEE ALSO:
3700  PolynomialFitWC()
3701 
3702 INPUT PARAMETERS:
3703  X - points, array[0..N-1].
3704  Y - function values, array[0..N-1].
3705  N - number of points, N>0
3706  * if given, only leading N elements of X/Y are used
3707  * if not given, automatically determined from sizes of X/Y
3708  M - number of basis functions (= polynomial_degree + 1), M>=1
3709 
3710 OUTPUT PARAMETERS:
3711  Info- same format as in LSFitLinearW() subroutine:
3712  * Info>0 task is solved
3713  * Info<=0 an error occurred:
3714  -4 means inconvergence of internal SVD
3715  P - interpolant in barycentric form.
3716  Rep - report, same format as in LSFitLinearW() subroutine.
3717  Following fields are set:
3718  * RMSError rms error on the (X,Y).
3719  * AvgError average error on the (X,Y).
3720  * AvgRelError average relative error on the non-zero Y
3721  * MaxError maximum error
3722  NON-WEIGHTED ERRORS ARE CALCULATED
3723 
3724 NOTES:
3725  you can convert P from barycentric form to the power or Chebyshev
3726  basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
3727  POLINT subpackage.
3728 
3729  -- ALGLIB PROJECT --
3730  Copyright 10.12.2009 by Bochkanov Sergey
3731 *************************************************************************/
3733 {
3734  alglib_impl::ae_state _alglib_env_state;
3735  alglib_impl::ae_state_init(&_alglib_env_state);
3736  try
3737  {
3738  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);
3739  alglib_impl::ae_state_clear(&_alglib_env_state);
3740  return;
3741  }
3743  {
3744  throw ap_error(_alglib_env_state.error_msg);
3745  }
3746 }
3747 
3748 /*************************************************************************
3749 Fitting by polynomials in barycentric form. This function provides simple
3750 unterface for unconstrained unweighted fitting. See PolynomialFitWC() if
3751 you need constrained fitting.
3752 
3753 Task is linear, so linear least squares solver is used. Complexity of this
3754 computational scheme is O(N*M^2), mostly dominated by least squares solver
3755 
3756 SEE ALSO:
3757  PolynomialFitWC()
3758 
3759 INPUT PARAMETERS:
3760  X - points, array[0..N-1].
3761  Y - function values, array[0..N-1].
3762  N - number of points, N>0
3763  * if given, only leading N elements of X/Y are used
3764  * if not given, automatically determined from sizes of X/Y
3765  M - number of basis functions (= polynomial_degree + 1), M>=1
3766 
3767 OUTPUT PARAMETERS:
3768  Info- same format as in LSFitLinearW() subroutine:
3769  * Info>0 task is solved
3770  * Info<=0 an error occurred:
3771  -4 means inconvergence of internal SVD
3772  P - interpolant in barycentric form.
3773  Rep - report, same format as in LSFitLinearW() subroutine.
3774  Following fields are set:
3775  * RMSError rms error on the (X,Y).
3776  * AvgError average error on the (X,Y).
3777  * AvgRelError average relative error on the non-zero Y
3778  * MaxError maximum error
3779  NON-WEIGHTED ERRORS ARE CALCULATED
3780 
3781 NOTES:
3782  you can convert P from barycentric form to the power or Chebyshev
3783  basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
3784  POLINT subpackage.
3785 
3786  -- ALGLIB PROJECT --
3787  Copyright 10.12.2009 by Bochkanov Sergey
3788 *************************************************************************/
3790 {
3791  alglib_impl::ae_state _alglib_env_state;
3792  ae_int_t n;
3793  if( (x.length()!=y.length()))
3794  throw ap_error("Error while calling 'polynomialfit': looks like one of arguments has wrong size");
3795  n = x.length();
3796  alglib_impl::ae_state_init(&_alglib_env_state);
3797  try
3798  {
3799  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);
3800 
3801  alglib_impl::ae_state_clear(&_alglib_env_state);
3802  return;
3803  }
3805  {
3806  throw ap_error(_alglib_env_state.error_msg);
3807  }
3808 }
3809 
3810 /*************************************************************************
3811 Weighted fitting by polynomials in barycentric form, with constraints on
3812 function values or first derivatives.
3813 
3814 Small regularizing term is used when solving constrained tasks (to improve
3815 stability).
3816 
3817 Task is linear, so linear least squares solver is used. Complexity of this
3818 computational scheme is O(N*M^2), mostly dominated by least squares solver
3819 
3820 SEE ALSO:
3821  PolynomialFit()
3822 
3823 INPUT PARAMETERS:
3824  X - points, array[0..N-1].
3825  Y - function values, array[0..N-1].
3826  W - weights, array[0..N-1]
3827  Each summand in square sum of approximation deviations from
3828  given values is multiplied by the square of corresponding
3829  weight. Fill it by 1's if you don't want to solve weighted
3830  task.
3831  N - number of points, N>0.
3832  * if given, only leading N elements of X/Y/W are used
3833  * if not given, automatically determined from sizes of X/Y/W
3834  XC - points where polynomial values/derivatives are constrained,
3835  array[0..K-1].
3836  YC - values of constraints, array[0..K-1]
3837  DC - array[0..K-1], types of constraints:
3838  * DC[i]=0 means that P(XC[i])=YC[i]
3839  * DC[i]=1 means that P'(XC[i])=YC[i]
3840  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
3841  K - number of constraints, 0<=K<M.
3842  K=0 means no constraints (XC/YC/DC are not used in such cases)
3843  M - number of basis functions (= polynomial_degree + 1), M>=1
3844 
3845 OUTPUT PARAMETERS:
3846  Info- same format as in LSFitLinearW() subroutine:
3847  * Info>0 task is solved
3848  * Info<=0 an error occurred:
3849  -4 means inconvergence of internal SVD
3850  -3 means inconsistent constraints
3851  P - interpolant in barycentric form.
3852  Rep - report, same format as in LSFitLinearW() subroutine.
3853  Following fields are set:
3854  * RMSError rms error on the (X,Y).
3855  * AvgError average error on the (X,Y).
3856  * AvgRelError average relative error on the non-zero Y
3857  * MaxError maximum error
3858  NON-WEIGHTED ERRORS ARE CALCULATED
3859 
3860 IMPORTANT:
3861  this subroitine doesn't calculate task's condition number for K<>0.
3862 
3863 NOTES:
3864  you can convert P from barycentric form to the power or Chebyshev
3865  basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
3866  POLINT subpackage.
3867 
3868 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
3869 
3870 Setting constraints can lead to undesired results, like ill-conditioned
3871 behavior, or inconsistency being detected. From the other side, it allows
3872 us to improve quality of the fit. Here we summarize our experience with
3873 constrained regression splines:
3874 * even simple constraints can be inconsistent, see Wikipedia article on
3875  this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
3876 * the greater is M (given fixed constraints), the more chances that
3877  constraints will be consistent
3878 * in the general case, consistency of constraints is NOT GUARANTEED.
3879 * in the one special cases, however, we can guarantee consistency. This
3880  case is: M>1 and constraints on the function values (NOT DERIVATIVES)
3881 
3882 Our final recommendation is to use constraints WHEN AND ONLY when you
3883 can't solve your task without them. Anything beyond special cases given
3884 above is not guaranteed and may result in inconsistency.
3885 
3886  -- ALGLIB PROJECT --
3887  Copyright 10.12.2009 by Bochkanov Sergey
3888 *************************************************************************/
3890 {
3891  alglib_impl::ae_state _alglib_env_state;
3892  alglib_impl::ae_state_init(&_alglib_env_state);
3893  try
3894  {
3895  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);
3896  alglib_impl::ae_state_clear(&_alglib_env_state);
3897  return;
3898  }
3900  {
3901  throw ap_error(_alglib_env_state.error_msg);
3902  }
3903 }
3904 
3905 /*************************************************************************
3906 Weighted fitting by polynomials in barycentric form, with constraints on
3907 function values or first derivatives.
3908 
3909 Small regularizing term is used when solving constrained tasks (to improve
3910 stability).
3911 
3912 Task is linear, so linear least squares solver is used. Complexity of this
3913 computational scheme is O(N*M^2), mostly dominated by least squares solver
3914 
3915 SEE ALSO:
3916  PolynomialFit()
3917 
3918 INPUT PARAMETERS:
3919  X - points, array[0..N-1].
3920  Y - function values, array[0..N-1].
3921  W - weights, array[0..N-1]
3922  Each summand in square sum of approximation deviations from
3923  given values is multiplied by the square of corresponding
3924  weight. Fill it by 1's if you don't want to solve weighted
3925  task.
3926  N - number of points, N>0.
3927  * if given, only leading N elements of X/Y/W are used
3928  * if not given, automatically determined from sizes of X/Y/W
3929  XC - points where polynomial values/derivatives are constrained,
3930  array[0..K-1].
3931  YC - values of constraints, array[0..K-1]
3932  DC - array[0..K-1], types of constraints:
3933  * DC[i]=0 means that P(XC[i])=YC[i]
3934  * DC[i]=1 means that P'(XC[i])=YC[i]
3935  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
3936  K - number of constraints, 0<=K<M.
3937  K=0 means no constraints (XC/YC/DC are not used in such cases)
3938  M - number of basis functions (= polynomial_degree + 1), M>=1
3939 
3940 OUTPUT PARAMETERS:
3941  Info- same format as in LSFitLinearW() subroutine:
3942  * Info>0 task is solved
3943  * Info<=0 an error occurred:
3944  -4 means inconvergence of internal SVD
3945  -3 means inconsistent constraints
3946  P - interpolant in barycentric form.
3947  Rep - report, same format as in LSFitLinearW() subroutine.
3948  Following fields are set:
3949  * RMSError rms error on the (X,Y).
3950  * AvgError average error on the (X,Y).
3951  * AvgRelError average relative error on the non-zero Y
3952  * MaxError maximum error
3953  NON-WEIGHTED ERRORS ARE CALCULATED
3954 
3955 IMPORTANT:
3956  this subroitine doesn't calculate task's condition number for K<>0.
3957 
3958 NOTES:
3959  you can convert P from barycentric form to the power or Chebyshev
3960  basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
3961  POLINT subpackage.
3962 
3963 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
3964 
3965 Setting constraints can lead to undesired results, like ill-conditioned
3966 behavior, or inconsistency being detected. From the other side, it allows
3967 us to improve quality of the fit. Here we summarize our experience with
3968 constrained regression splines:
3969 * even simple constraints can be inconsistent, see Wikipedia article on
3970  this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
3971 * the greater is M (given fixed constraints), the more chances that
3972  constraints will be consistent
3973 * in the general case, consistency of constraints is NOT GUARANTEED.
3974 * in the one special cases, however, we can guarantee consistency. This
3975  case is: M>1 and constraints on the function values (NOT DERIVATIVES)
3976 
3977 Our final recommendation is to use constraints WHEN AND ONLY when you
3978 can't solve your task without them. Anything beyond special cases given
3979 above is not guaranteed and may result in inconsistency.
3980 
3981  -- ALGLIB PROJECT --
3982  Copyright 10.12.2009 by Bochkanov Sergey
3983 *************************************************************************/
3985 {
3986  alglib_impl::ae_state _alglib_env_state;
3987  ae_int_t n;
3988  ae_int_t k;
3989  if( (x.length()!=y.length()) || (x.length()!=w.length()))
3990  throw ap_error("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
3991  if( (xc.length()!=yc.length()) || (xc.length()!=dc.length()))
3992  throw ap_error("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
3993  n = x.length();
3994  k = xc.length();
3995  alglib_impl::ae_state_init(&_alglib_env_state);
3996  try
3997  {
3998  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);
3999 
4000  alglib_impl::ae_state_clear(&_alglib_env_state);
4001  return;
4002  }
4004  {
4005  throw ap_error(_alglib_env_state.error_msg);
4006  }
4007 }
4008 
4009 /*************************************************************************
4010 Weghted rational least squares fitting using Floater-Hormann rational
4011 functions with optimal D chosen from [0,9], with constraints and
4012 individual weights.
4013 
4014 Equidistant grid with M node on [min(x),max(x)] is used to build basis
4015 functions. Different values of D are tried, optimal D (least WEIGHTED root
4016 mean square error) is chosen. Task is linear, so linear least squares
4017 solver is used. Complexity of this computational scheme is O(N*M^2)
4018 (mostly dominated by the least squares solver).
4019 
4020 SEE ALSO
4021 * BarycentricFitFloaterHormann(), "lightweight" fitting without invididual
4022  weights and constraints.
4023 
4024 INPUT PARAMETERS:
4025  X - points, array[0..N-1].
4026  Y - function values, array[0..N-1].
4027  W - weights, array[0..N-1]
4028  Each summand in square sum of approximation deviations from
4029  given values is multiplied by the square of corresponding
4030  weight. Fill it by 1's if you don't want to solve weighted
4031  task.
4032  N - number of points, N>0.
4033  XC - points where function values/derivatives are constrained,
4034  array[0..K-1].
4035  YC - values of constraints, array[0..K-1]
4036  DC - array[0..K-1], types of constraints:
4037  * DC[i]=0 means that S(XC[i])=YC[i]
4038  * DC[i]=1 means that S'(XC[i])=YC[i]
4039  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
4040  K - number of constraints, 0<=K<M.
4041  K=0 means no constraints (XC/YC/DC are not used in such cases)
4042  M - number of basis functions ( = number_of_nodes), M>=2.
4043 
4044 OUTPUT PARAMETERS:
4045  Info- same format as in LSFitLinearWC() subroutine.
4046  * Info>0 task is solved
4047  * Info<=0 an error occurred:
4048  -4 means inconvergence of internal SVD
4049  -3 means inconsistent constraints
4050  -1 means another errors in parameters passed
4051  (N<=0, for example)
4052  B - barycentric interpolant.
4053  Rep - report, same format as in LSFitLinearWC() subroutine.
4054  Following fields are set:
4055  * DBest best value of the D parameter
4056  * RMSError rms error on the (X,Y).
4057  * AvgError average error on the (X,Y).
4058  * AvgRelError average relative error on the non-zero Y
4059  * MaxError maximum error
4060  NON-WEIGHTED ERRORS ARE CALCULATED
4061 
4062 IMPORTANT:
4063  this subroutine doesn't calculate task's condition number for K<>0.
4064 
4065 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
4066 
4067 Setting constraints can lead to undesired results, like ill-conditioned
4068 behavior, or inconsistency being detected. From the other side, it allows
4069 us to improve quality of the fit. Here we summarize our experience with
4070 constrained barycentric interpolants:
4071 * excessive constraints can be inconsistent. Floater-Hormann basis
4072  functions aren't as flexible as splines (although they are very smooth).
4073 * the more evenly constraints are spread across [min(x),max(x)], the more
4074  chances that they will be consistent
4075 * the greater is M (given fixed constraints), the more chances that
4076  constraints will be consistent
4077 * in the general case, consistency of constraints IS NOT GUARANTEED.
4078 * in the several special cases, however, we CAN guarantee consistency.
4079 * one of this cases is constraints on the function VALUES at the interval
4080  boundaries. Note that consustency of the constraints on the function
4081  DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines
4082  which are more flexible).
4083 * another special case is ONE constraint on the function value (OR, but
4084  not AND, derivative) anywhere in the interval
4085 
4086 Our final recommendation is to use constraints WHEN AND ONLY WHEN you
4087 can't solve your task without them. Anything beyond special cases given
4088 above is not guaranteed and may result in inconsistency.
4089 
4090  -- ALGLIB PROJECT --
4091  Copyright 18.08.2009 by Bochkanov Sergey
4092 *************************************************************************/
4094 {
4095  alglib_impl::ae_state _alglib_env_state;
4096  alglib_impl::ae_state_init(&_alglib_env_state);
4097  try
4098  {
4099  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);
4100  alglib_impl::ae_state_clear(&_alglib_env_state);
4101  return;
4102  }
4104  {
4105  throw ap_error(_alglib_env_state.error_msg);
4106  }
4107 }
4108 
4109 /*************************************************************************
4110 Rational least squares fitting using Floater-Hormann rational functions
4111 with optimal D chosen from [0,9].
4112 
4113 Equidistant grid with M node on [min(x),max(x)] is used to build basis
4114 functions. Different values of D are tried, optimal D (least root mean
4115 square error) is chosen. Task is linear, so linear least squares solver
4116 is used. Complexity of this computational scheme is O(N*M^2) (mostly
4117 dominated by the least squares solver).
4118 
4119 INPUT PARAMETERS:
4120  X - points, array[0..N-1].
4121  Y - function values, array[0..N-1].
4122  N - number of points, N>0.
4123  M - number of basis functions ( = number_of_nodes), M>=2.
4124 
4125 OUTPUT PARAMETERS:
4126  Info- same format as in LSFitLinearWC() subroutine.
4127  * Info>0 task is solved
4128  * Info<=0 an error occurred:
4129  -4 means inconvergence of internal SVD
4130  -3 means inconsistent constraints
4131  B - barycentric interpolant.
4132  Rep - report, same format as in LSFitLinearWC() subroutine.
4133  Following fields are set:
4134  * DBest best value of the D parameter
4135  * RMSError rms error on the (X,Y).
4136  * AvgError average error on the (X,Y).
4137  * AvgRelError average relative error on the non-zero Y
4138  * MaxError maximum error
4139  NON-WEIGHTED ERRORS ARE CALCULATED
4140 
4141  -- ALGLIB PROJECT --
4142  Copyright 18.08.2009 by Bochkanov Sergey
4143 *************************************************************************/
4145 {
4146  alglib_impl::ae_state _alglib_env_state;
4147  alglib_impl::ae_state_init(&_alglib_env_state);
4148  try
4149  {
4150  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);
4151  alglib_impl::ae_state_clear(&_alglib_env_state);
4152  return;
4153  }
4155  {
4156  throw ap_error(_alglib_env_state.error_msg);
4157  }
4158 }
4159 
4160 /*************************************************************************
4161 Rational least squares fitting using Floater-Hormann rational functions
4162 with optimal D chosen from [0,9].
4163 
4164 Equidistant grid with M node on [min(x),max(x)] is used to build basis
4165 functions. Different values of D are tried, optimal D (least root mean
4166 square error) is chosen. Task is linear, so linear least squares solver
4167 is used. Complexity of this computational scheme is O(N*M^2) (mostly
4168 dominated by the least squares solver).
4169 
4170 INPUT PARAMETERS:
4171  X - points, array[0..N-1].
4172  Y - function values, array[0..N-1].
4173  N - number of points, N>0.
4174  M - number of basis functions ( = number_of_nodes), M>=2.
4175 
4176 OUTPUT PARAMETERS:
4177  Info- same format as in LSFitLinearWC() subroutine.
4178  * Info>0 task is solved
4179  * Info<=0 an error occurred:
4180  -4 means inconvergence of internal SVD
4181  -3 means inconsistent constraints
4182  B - barycentric interpolant.
4183  Rep - report, same format as in LSFitLinearWC() subroutine.
4184  Following fields are set:
4185  * DBest best value of the D parameter
4186  * RMSError rms error on the (X,Y).
4187  * AvgError average error on the (X,Y).
4188  * AvgRelError average relative error on the non-zero Y
4189  * MaxError maximum error
4190  NON-WEIGHTED ERRORS ARE CALCULATED
4191 
4192  -- ALGLIB PROJECT --
4193  Copyright 18.08.2009 by Bochkanov Sergey
4194 *************************************************************************/
4195 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)
4196 {
4197  alglib_impl::ae_state _alglib_env_state;
4198  alglib_impl::ae_state_init(&_alglib_env_state);
4199  try
4200  {
4201  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);
4202  alglib_impl::ae_state_clear(&_alglib_env_state);
4203  return;
4204  }
4206  {
4207  throw ap_error(_alglib_env_state.error_msg);
4208  }
4209 }
4210 
4211 /*************************************************************************
4212 Rational least squares fitting using Floater-Hormann rational functions
4213 with optimal D chosen from [0,9].
4214 
4215 Equidistant grid with M node on [min(x),max(x)] is used to build basis
4216 functions. Different values of D are tried, optimal D (least root mean
4217 square error) is chosen. Task is linear, so linear least squares solver
4218 is used. Complexity of this computational scheme is O(N*M^2) (mostly
4219 dominated by the least squares solver).
4220 
4221 INPUT PARAMETERS:
4222  X - points, array[0..N-1].
4223  Y - function values, array[0..N-1].
4224  N - number of points, N>0.
4225  M - number of basis functions ( = number_of_nodes), M>=2.
4226 
4227 OUTPUT PARAMETERS:
4228  Info- same format as in LSFitLinearWC() subroutine.
4229  * Info>0 task is solved
4230  * Info<=0 an error occurred:
4231  -4 means inconvergence of internal SVD
4232  -3 means inconsistent constraints
4233  B - barycentric interpolant.
4234  Rep - report, same format as in LSFitLinearWC() subroutine.
4235  Following fields are set:
4236  * DBest best value of the D parameter
4237  * RMSError rms error on the (X,Y).
4238  * AvgError average error on the (X,Y).
4239  * AvgRelError average relative error on the non-zero Y
4240  * MaxError maximum error
4241  NON-WEIGHTED ERRORS ARE CALCULATED
4242 
4243  -- ALGLIB PROJECT --
4244  Copyright 18.08.2009 by Bochkanov Sergey
4245 *************************************************************************/
4247 {
4248  alglib_impl::ae_state _alglib_env_state;
4249  ae_int_t n;
4250  if( (x.length()!=y.length()))
4251  throw ap_error("Error while calling 'spline1dfitpenalized': looks like one of arguments has wrong size");
4252  n = x.length();
4253  alglib_impl::ae_state_init(&_alglib_env_state);
4254  try
4255  {
4256  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);
4257 
4258  alglib_impl::ae_state_clear(&_alglib_env_state);
4259  return;
4260  }
4262  {
4263  throw ap_error(_alglib_env_state.error_msg);
4264  }
4265 }
4266 
4267 /*************************************************************************
4268 Weighted fitting by penalized cubic spline.
4269 
4270 Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
4271 basis functions. Basis functions are cubic splines with natural boundary
4272 conditions. Problem is regularized by adding non-linearity penalty to the
4273 usual least squares penalty function:
4274 
4275  S(x) = arg min { LS + P }, where
4276  LS = SUM { w[i]^2*(y[i] - S(x[i]))^2 } - least squares penalty
4277  P = C*10^rho*integral{ S''(x)^2*dx } - non-linearity penalty
4278  rho - tunable constant given by user
4279  C - automatically determined scale parameter,
4280  makes penalty invariant with respect to scaling of X, Y, W.
4281 
4282 INPUT PARAMETERS:
4283  X - points, array[0..N-1].
4284  Y - function values, array[0..N-1].
4285  W - weights, array[0..N-1]
4286  Each summand in square sum of approximation deviations from
4287  given values is multiplied by the square of corresponding
4288  weight. Fill it by 1's if you don't want to solve weighted
4289  problem.
4290  N - number of points (optional):
4291  * N>0
4292  * if given, only first N elements of X/Y/W are processed
4293  * if not given, automatically determined from X/Y/W sizes
4294  M - number of basis functions ( = number_of_nodes), M>=4.
4295  Rho - regularization constant passed by user. It penalizes
4296  nonlinearity in the regression spline. It is logarithmically
4297  scaled, i.e. actual value of regularization constant is
4298  calculated as 10^Rho. It is automatically scaled so that:
4299  * Rho=2.0 corresponds to moderate amount of nonlinearity
4300  * generally, it should be somewhere in the [-8.0,+8.0]
4301  If you do not want to penalize nonlineary,
4302  pass small Rho. Values as low as -15 should work.
4303 
4304 OUTPUT PARAMETERS:
4305  Info- same format as in LSFitLinearWC() subroutine.
4306  * Info>0 task is solved
4307  * Info<=0 an error occurred:
4308  -4 means inconvergence of internal SVD or
4309  Cholesky decomposition; problem may be
4310  too ill-conditioned (very rare)
4311  S - spline interpolant.
4312  Rep - Following fields are set:
4313  * RMSError rms error on the (X,Y).
4314  * AvgError average error on the (X,Y).
4315  * AvgRelError average relative error on the non-zero Y
4316  * MaxError maximum error
4317  NON-WEIGHTED ERRORS ARE CALCULATED
4318 
4319 IMPORTANT:
4320  this subroitine doesn't calculate task's condition number for K<>0.
4321 
4322 NOTE 1: additional nodes are added to the spline outside of the fitting
4323 interval to force linearity when x<min(x,xc) or x>max(x,xc). It is done
4324 for consistency - we penalize non-linearity at [min(x,xc),max(x,xc)], so
4325 it is natural to force linearity outside of this interval.
4326 
4327 NOTE 2: function automatically sorts points, so caller may pass unsorted
4328 array.
4329 
4330  -- ALGLIB PROJECT --
4331  Copyright 19.10.2010 by Bochkanov Sergey
4332 *************************************************************************/
4333 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)
4334 {
4335  alglib_impl::ae_state _alglib_env_state;
4336  alglib_impl::ae_state_init(&_alglib_env_state);
4337  try
4338  {
4339  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);
4340  alglib_impl::ae_state_clear(&_alglib_env_state);
4341  return;
4342  }
4344  {
4345  throw ap_error(_alglib_env_state.error_msg);
4346  }
4347 }
4348 
4349 /*************************************************************************
4350 Weighted fitting by penalized cubic spline.
4351 
4352 Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
4353 basis functions. Basis functions are cubic splines with natural boundary
4354 conditions. Problem is regularized by adding non-linearity penalty to the
4355 usual least squares penalty function:
4356 
4357  S(x) = arg min { LS + P }, where
4358  LS = SUM { w[i]^2*(y[i] - S(x[i]))^2 } - least squares penalty
4359  P = C*10^rho*integral{ S''(x)^2*dx } - non-linearity penalty
4360  rho - tunable constant given by user
4361  C - automatically determined scale parameter,
4362  makes penalty invariant with respect to scaling of X, Y, W.
4363 
4364 INPUT PARAMETERS:
4365  X - points, array[0..N-1].
4366  Y - function values, array[0..N-1].
4367  W - weights, array[0..N-1]
4368  Each summand in square sum of approximation deviations from
4369  given values is multiplied by the square of corresponding
4370  weight. Fill it by 1's if you don't want to solve weighted
4371  problem.
4372  N - number of points (optional):
4373  * N>0
4374  * if given, only first N elements of X/Y/W are processed
4375  * if not given, automatically determined from X/Y/W sizes
4376  M - number of basis functions ( = number_of_nodes), M>=4.
4377  Rho - regularization constant passed by user. It penalizes
4378  nonlinearity in the regression spline. It is logarithmically
4379  scaled, i.e. actual value of regularization constant is
4380  calculated as 10^Rho. It is automatically scaled so that:
4381  * Rho=2.0 corresponds to moderate amount of nonlinearity
4382  * generally, it should be somewhere in the [-8.0,+8.0]
4383  If you do not want to penalize nonlineary,
4384  pass small Rho. Values as low as -15 should work.
4385 
4386 OUTPUT PARAMETERS:
4387  Info- same format as in LSFitLinearWC() subroutine.
4388  * Info>0 task is solved
4389  * Info<=0 an error occurred:
4390  -4 means inconvergence of internal SVD or
4391  Cholesky decomposition; problem may be
4392  too ill-conditioned (very rare)
4393  S - spline interpolant.
4394  Rep - Following fields are set:
4395  * RMSError rms error on the (X,Y).
4396  * AvgError average error on the (X,Y).
4397  * AvgRelError average relative error on the non-zero Y
4398  * MaxError maximum error
4399  NON-WEIGHTED ERRORS ARE CALCULATED
4400 
4401 IMPORTANT:
4402  this subroitine doesn't calculate task's condition number for K<>0.
4403 
4404 NOTE 1: additional nodes are added to the spline outside of the fitting
4405 interval to force linearity when x<min(x,xc) or x>max(x,xc). It is done
4406 for consistency - we penalize non-linearity at [min(x,xc),max(x,xc)], so
4407 it is natural to force linearity outside of this interval.
4408 
4409 NOTE 2: function automatically sorts points, so caller may pass unsorted
4410 array.
4411 
4412  -- ALGLIB PROJECT --
4413  Copyright 19.10.2010 by Bochkanov Sergey
4414 *************************************************************************/
4416 {
4417  alglib_impl::ae_state _alglib_env_state;
4418  ae_int_t n;
4419  if( (x.length()!=y.length()) || (x.length()!=w.length()))
4420  throw ap_error("Error while calling 'spline1dfitpenalizedw': looks like one of arguments has wrong size");
4421  n = x.length();
4422  alglib_impl::ae_state_init(&_alglib_env_state);
4423  try
4424  {
4425  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);
4426 
4427  alglib_impl::ae_state_clear(&_alglib_env_state);
4428  return;
4429  }
4431  {
4432  throw ap_error(_alglib_env_state.error_msg);
4433  }
4434 }
4435 
4436 /*************************************************************************
4437 Weighted fitting by cubic spline, with constraints on function values or
4438 derivatives.
4439 
4440 Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build
4441 basis functions. Basis functions are cubic splines with continuous second
4442 derivatives and non-fixed first derivatives at interval ends. Small
4443 regularizing term is used when solving constrained tasks (to improve
4444 stability).
4445 
4446 Task is linear, so linear least squares solver is used. Complexity of this
4447 computational scheme is O(N*M^2), mostly dominated by least squares solver
4448 
4449 SEE ALSO
4450  Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible,
4451  less smooth)
4452  Spline1DFitCubic() - "lightweight" fitting by cubic splines,
4453  without invididual weights and constraints
4454 
4455 INPUT PARAMETERS:
4456  X - points, array[0..N-1].
4457  Y - function values, array[0..N-1].
4458  W - weights, array[0..N-1]
4459  Each summand in square sum of approximation deviations from
4460  given values is multiplied by the square of corresponding
4461  weight. Fill it by 1's if you don't want to solve weighted
4462  task.
4463  N - number of points (optional):
4464  * N>0
4465  * if given, only first N elements of X/Y/W are processed
4466  * if not given, automatically determined from X/Y/W sizes
4467  XC - points where spline values/derivatives are constrained,
4468  array[0..K-1].
4469  YC - values of constraints, array[0..K-1]
4470  DC - array[0..K-1], types of constraints:
4471  * DC[i]=0 means that S(XC[i])=YC[i]
4472  * DC[i]=1 means that S'(XC[i])=YC[i]
4473  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
4474  K - number of constraints (optional):
4475  * 0<=K<M.
4476  * K=0 means no constraints (XC/YC/DC are not used)
4477  * if given, only first K elements of XC/YC/DC are used
4478  * if not given, automatically determined from XC/YC/DC
4479  M - number of basis functions ( = number_of_nodes+2), M>=4.
4480 
4481 OUTPUT PARAMETERS:
4482  Info- same format as in LSFitLinearWC() subroutine.
4483  * Info>0 task is solved
4484  * Info<=0 an error occurred:
4485  -4 means inconvergence of internal SVD
4486  -3 means inconsistent constraints
4487  S - spline interpolant.
4488  Rep - report, same format as in LSFitLinearWC() subroutine.
4489  Following fields are set:
4490  * RMSError rms error on the (X,Y).
4491  * AvgError average error on the (X,Y).
4492  * AvgRelError average relative error on the non-zero Y
4493  * MaxError maximum error
4494  NON-WEIGHTED ERRORS ARE CALCULATED
4495 
4496 IMPORTANT:
4497  this subroitine doesn't calculate task's condition number for K<>0.
4498 
4499 
4500 ORDER OF POINTS
4501 
4502 Subroutine automatically sorts points, so caller may pass unsorted array.
4503 
4504 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
4505 
4506 Setting constraints can lead to undesired results, like ill-conditioned
4507 behavior, or inconsistency being detected. From the other side, it allows
4508 us to improve quality of the fit. Here we summarize our experience with
4509 constrained regression splines:
4510 * excessive constraints can be inconsistent. Splines are piecewise cubic
4511  functions, and it is easy to create an example, where large number of
4512  constraints concentrated in small area will result in inconsistency.
4513  Just because spline is not flexible enough to satisfy all of them. And
4514  same constraints spread across the [min(x),max(x)] will be perfectly
4515  consistent.
4516 * the more evenly constraints are spread across [min(x),max(x)], the more
4517  chances that they will be consistent
4518 * the greater is M (given fixed constraints), the more chances that
4519  constraints will be consistent
4520 * in the general case, consistency of constraints IS NOT GUARANTEED.
4521 * in the several special cases, however, we CAN guarantee consistency.
4522 * one of this cases is constraints on the function values AND/OR its
4523  derivatives at the interval boundaries.
4524 * another special case is ONE constraint on the function value (OR, but
4525  not AND, derivative) anywhere in the interval
4526 
4527 Our final recommendation is to use constraints WHEN AND ONLY WHEN you
4528 can't solve your task without them. Anything beyond special cases given
4529 above is not guaranteed and may result in inconsistency.
4530 
4531 
4532  -- ALGLIB PROJECT --
4533  Copyright 18.08.2009 by Bochkanov Sergey
4534 *************************************************************************/
4536 {
4537  alglib_impl::ae_state _alglib_env_state;
4538  alglib_impl::ae_state_init(&_alglib_env_state);
4539  try
4540  {
4541  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);
4542  alglib_impl::ae_state_clear(&_alglib_env_state);
4543  return;
4544  }
4546  {
4547  throw ap_error(_alglib_env_state.error_msg);
4548  }
4549 }
4550 
4551 /*************************************************************************
4552 Weighted fitting by cubic spline, with constraints on function values or
4553 derivatives.
4554 
4555 Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build
4556 basis functions. Basis functions are cubic splines with continuous second
4557 derivatives and non-fixed first derivatives at interval ends. Small
4558 regularizing term is used when solving constrained tasks (to improve
4559 stability).
4560 
4561 Task is linear, so linear least squares solver is used. Complexity of this
4562 computational scheme is O(N*M^2), mostly dominated by least squares solver
4563 
4564 SEE ALSO
4565  Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible,
4566  less smooth)
4567  Spline1DFitCubic() - "lightweight" fitting by cubic splines,
4568  without invididual weights and constraints
4569 
4570 INPUT PARAMETERS:
4571  X - points, array[0..N-1].
4572  Y - function values, array[0..N-1].
4573  W - weights, array[0..N-1]
4574  Each summand in square sum of approximation deviations from
4575  given values is multiplied by the square of corresponding
4576  weight. Fill it by 1's if you don't want to solve weighted
4577  task.
4578  N - number of points (optional):
4579  * N>0
4580  * if given, only first N elements of X/Y/W are processed
4581  * if not given, automatically determined from X/Y/W sizes
4582  XC - points where spline values/derivatives are constrained,
4583  array[0..K-1].
4584  YC - values of constraints, array[0..K-1]
4585  DC - array[0..K-1], types of constraints:
4586  * DC[i]=0 means that S(XC[i])=YC[i]
4587  * DC[i]=1 means that S'(XC[i])=YC[i]
4588  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
4589  K - number of constraints (optional):
4590  * 0<=K<M.
4591  * K=0 means no constraints (XC/YC/DC are not used)
4592  * if given, only first K elements of XC/YC/DC are used
4593  * if not given, automatically determined from XC/YC/DC
4594  M - number of basis functions ( = number_of_nodes+2), M>=4.
4595 
4596 OUTPUT PARAMETERS:
4597  Info- same format as in LSFitLinearWC() subroutine.
4598  * Info>0 task is solved
4599  * Info<=0 an error occurred:
4600  -4 means inconvergence of internal SVD
4601  -3 means inconsistent constraints
4602  S - spline interpolant.
4603  Rep - report, same format as in LSFitLinearWC() subroutine.
4604  Following fields are set:
4605  * RMSError rms error on the (X,Y).
4606  * AvgError average error on the (X,Y).
4607  * AvgRelError average relative error on the non-zero Y
4608  * MaxError maximum error
4609  NON-WEIGHTED ERRORS ARE CALCULATED
4610 
4611 IMPORTANT:
4612  this subroitine doesn't calculate task's condition number for K<>0.
4613 
4614 
4615 ORDER OF POINTS
4616 
4617 Subroutine automatically sorts points, so caller may pass unsorted array.
4618 
4619 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
4620 
4621 Setting constraints can lead to undesired results, like ill-conditioned
4622 behavior, or inconsistency being detected. From the other side, it allows
4623 us to improve quality of the fit. Here we summarize our experience with
4624 constrained regression splines:
4625 * excessive constraints can be inconsistent. Splines are piecewise cubic
4626  functions, and it is easy to create an example, where large number of
4627  constraints concentrated in small area will result in inconsistency.
4628  Just because spline is not flexible enough to satisfy all of them. And
4629  same constraints spread across the [min(x),max(x)] will be perfectly
4630  consistent.
4631 * the more evenly constraints are spread across [min(x),max(x)], the more
4632  chances that they will be consistent
4633 * the greater is M (given fixed constraints), the more chances that
4634  constraints will be consistent
4635 * in the general case, consistency of constraints IS NOT GUARANTEED.
4636 * in the several special cases, however, we CAN guarantee consistency.
4637 * one of this cases is constraints on the function values AND/OR its
4638  derivatives at the interval boundaries.
4639 * another special case is ONE constraint on the function value (OR, but
4640  not AND, derivative) anywhere in the interval
4641 
4642 Our final recommendation is to use constraints WHEN AND ONLY WHEN you
4643 can't solve your task without them. Anything beyond special cases given
4644 above is not guaranteed and may result in inconsistency.
4645 
4646 
4647  -- ALGLIB PROJECT --
4648  Copyright 18.08.2009 by Bochkanov Sergey
4649 *************************************************************************/
4651 {
4652  alglib_impl::ae_state _alglib_env_state;
4653  ae_int_t n;
4654  ae_int_t k;
4655  if( (x.length()!=y.length()) || (x.length()!=w.length()))
4656  throw ap_error("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size");
4657  if( (xc.length()!=yc.length()) || (xc.length()!=dc.length()))
4658  throw ap_error("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size");
4659  n = x.length();
4660  k = xc.length();
4661  alglib_impl::ae_state_init(&_alglib_env_state);
4662  try
4663  {
4664  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);
4665 
4666  alglib_impl::ae_state_clear(&_alglib_env_state);
4667  return;
4668  }
4670  {
4671  throw ap_error(_alglib_env_state.error_msg);
4672  }
4673 }
4674 
4675 /*************************************************************************
4676 Weighted fitting by Hermite spline, with constraints on function values
4677 or first derivatives.
4678 
4679 Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
4680 basis functions. Basis functions are Hermite splines. Small regularizing
4681 term is used when solving constrained tasks (to improve stability).
4682 
4683 Task is linear, so linear least squares solver is used. Complexity of this
4684 computational scheme is O(N*M^2), mostly dominated by least squares solver
4685 
4686 SEE ALSO
4687  Spline1DFitCubicWC() - fitting by Cubic splines (less flexible,
4688  more smooth)
4689  Spline1DFitHermite() - "lightweight" Hermite fitting, without
4690  invididual weights and constraints
4691 
4692 INPUT PARAMETERS:
4693  X - points, array[0..N-1].
4694  Y - function values, array[0..N-1].
4695  W - weights, array[0..N-1]
4696  Each summand in square sum of approximation deviations from
4697  given values is multiplied by the square of corresponding
4698  weight. Fill it by 1's if you don't want to solve weighted
4699  task.
4700  N - number of points (optional):
4701  * N>0
4702  * if given, only first N elements of X/Y/W are processed
4703  * if not given, automatically determined from X/Y/W sizes
4704  XC - points where spline values/derivatives are constrained,
4705  array[0..K-1].
4706  YC - values of constraints, array[0..K-1]
4707  DC - array[0..K-1], types of constraints:
4708  * DC[i]=0 means that S(XC[i])=YC[i]
4709  * DC[i]=1 means that S'(XC[i])=YC[i]
4710  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
4711  K - number of constraints (optional):
4712  * 0<=K<M.
4713  * K=0 means no constraints (XC/YC/DC are not used)
4714  * if given, only first K elements of XC/YC/DC are used
4715  * if not given, automatically determined from XC/YC/DC
4716  M - number of basis functions (= 2 * number of nodes),
4717  M>=4,
4718  M IS EVEN!
4719 
4720 OUTPUT PARAMETERS:
4721  Info- same format as in LSFitLinearW() subroutine:
4722  * Info>0 task is solved
4723  * Info<=0 an error occurred:
4724  -4 means inconvergence of internal SVD
4725  -3 means inconsistent constraints
4726  -2 means odd M was passed (which is not supported)
4727  -1 means another errors in parameters passed
4728  (N<=0, for example)
4729  S - spline interpolant.
4730  Rep - report, same format as in LSFitLinearW() subroutine.
4731  Following fields are set:
4732  * RMSError rms error on the (X,Y).
4733  * AvgError average error on the (X,Y).
4734  * AvgRelError average relative error on the non-zero Y
4735  * MaxError maximum error
4736  NON-WEIGHTED ERRORS ARE CALCULATED
4737 
4738 IMPORTANT:
4739  this subroitine doesn't calculate task's condition number for K<>0.
4740 
4741 IMPORTANT:
4742  this subroitine supports only even M's
4743 
4744 
4745 ORDER OF POINTS
4746 
4747 Subroutine automatically sorts points, so caller may pass unsorted array.
4748 
4749 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
4750 
4751 Setting constraints can lead to undesired results, like ill-conditioned
4752 behavior, or inconsistency being detected. From the other side, it allows
4753 us to improve quality of the fit. Here we summarize our experience with
4754 constrained regression splines:
4755 * excessive constraints can be inconsistent. Splines are piecewise cubic
4756  functions, and it is easy to create an example, where large number of
4757  constraints concentrated in small area will result in inconsistency.
4758  Just because spline is not flexible enough to satisfy all of them. And
4759  same constraints spread across the [min(x),max(x)] will be perfectly
4760  consistent.
4761 * the more evenly constraints are spread across [min(x),max(x)], the more
4762  chances that they will be consistent
4763 * the greater is M (given fixed constraints), the more chances that
4764  constraints will be consistent
4765 * in the general case, consistency of constraints is NOT GUARANTEED.
4766 * in the several special cases, however, we can guarantee consistency.
4767 * one of this cases is M>=4 and constraints on the function value
4768  (AND/OR its derivative) at the interval boundaries.
4769 * another special case is M>=4 and ONE constraint on the function value
4770  (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]
4771 
4772 Our final recommendation is to use constraints WHEN AND ONLY when you
4773 can't solve your task without them. Anything beyond special cases given
4774 above is not guaranteed and may result in inconsistency.
4775 
4776  -- ALGLIB PROJECT --
4777  Copyright 18.08.2009 by Bochkanov Sergey
4778 *************************************************************************/
4780 {
4781  alglib_impl::ae_state _alglib_env_state;
4782  alglib_impl::ae_state_init(&_alglib_env_state);
4783  try
4784  {
4785  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);
4786  alglib_impl::ae_state_clear(&_alglib_env_state);
4787  return;
4788  }
4790  {
4791  throw ap_error(_alglib_env_state.error_msg);
4792  }
4793 }
4794 
4795 /*************************************************************************
4796 Weighted fitting by Hermite spline, with constraints on function values
4797 or first derivatives.
4798 
4799 Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
4800 basis functions. Basis functions are Hermite splines. Small regularizing
4801 term is used when solving constrained tasks (to improve stability).
4802 
4803 Task is linear, so linear least squares solver is used. Complexity of this
4804 computational scheme is O(N*M^2), mostly dominated by least squares solver
4805 
4806 SEE ALSO
4807  Spline1DFitCubicWC() - fitting by Cubic splines (less flexible,
4808  more smooth)
4809  Spline1DFitHermite() - "lightweight" Hermite fitting, without
4810  invididual weights and constraints
4811 
4812 INPUT PARAMETERS:
4813  X - points, array[0..N-1].
4814  Y - function values, array[0..N-1].
4815  W - weights, array[0..N-1]
4816  Each summand in square sum of approximation deviations from
4817  given values is multiplied by the square of corresponding
4818  weight. Fill it by 1's if you don't want to solve weighted
4819  task.
4820  N - number of points (optional):
4821  * N>0
4822  * if given, only first N elements of X/Y/W are processed
4823  * if not given, automatically determined from X/Y/W sizes
4824  XC - points where spline values/derivatives are constrained,
4825  array[0..K-1].
4826  YC - values of constraints, array[0..K-1]
4827  DC - array[0..K-1], types of constraints:
4828  * DC[i]=0 means that S(XC[i])=YC[i]
4829  * DC[i]=1 means that S'(XC[i])=YC[i]
4830  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
4831  K - number of constraints (optional):
4832  * 0<=K<M.
4833  * K=0 means no constraints (XC/YC/DC are not used)
4834  * if given, only first K elements of XC/YC/DC are used
4835  * if not given, automatically determined from XC/YC/DC
4836  M - number of basis functions (= 2 * number of nodes),
4837  M>=4,
4838  M IS EVEN!
4839 
4840 OUTPUT PARAMETERS:
4841  Info- same format as in LSFitLinearW() subroutine:
4842  * Info>0 task is solved
4843  * Info<=0 an error occurred:
4844  -4 means inconvergence of internal SVD
4845  -3 means inconsistent constraints
4846  -2 means odd M was passed (which is not supported)
4847  -1 means another errors in parameters passed
4848  (N<=0, for example)
4849  S - spline interpolant.
4850  Rep - report, same format as in LSFitLinearW() subroutine.
4851  Following fields are set:
4852  * RMSError rms error on the (X,Y).
4853  * AvgError average error on the (X,Y).
4854  * AvgRelError average relative error on the non-zero Y
4855  * MaxError maximum error
4856  NON-WEIGHTED ERRORS ARE CALCULATED
4857 
4858 IMPORTANT:
4859  this subroitine doesn't calculate task's condition number for K<>0.
4860 
4861 IMPORTANT:
4862  this subroitine supports only even M's
4863 
4864 
4865 ORDER OF POINTS
4866 
4867 Subroutine automatically sorts points, so caller may pass unsorted array.
4868 
4869 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
4870 
4871 Setting constraints can lead to undesired results, like ill-conditioned
4872 behavior, or inconsistency being detected. From the other side, it allows
4873 us to improve quality of the fit. Here we summarize our experience with
4874 constrained regression splines:
4875 * excessive constraints can be inconsistent. Splines are piecewise cubic
4876  functions, and it is easy to create an example, where large number of
4877  constraints concentrated in small area will result in inconsistency.
4878  Just because spline is not flexible enough to satisfy all of them. And
4879  same constraints spread across the [min(x),max(x)] will be perfectly
4880  consistent.
4881 * the more evenly constraints are spread across [min(x),max(x)], the more
4882  chances that they will be consistent
4883 * the greater is M (given fixed constraints), the more chances that
4884  constraints will be consistent
4885 * in the general case, consistency of constraints is NOT GUARANTEED.
4886 * in the several special cases, however, we can guarantee consistency.
4887 * one of this cases is M>=4 and constraints on the function value
4888  (AND/OR its derivative) at the interval boundaries.
4889 * another special case is M>=4 and ONE constraint on the function value
4890  (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]
4891 
4892 Our final recommendation is to use constraints WHEN AND ONLY when you
4893 can't solve your task without them. Anything beyond special cases given
4894 above is not guaranteed and may result in inconsistency.
4895 
4896  -- ALGLIB PROJECT --
4897  Copyright 18.08.2009 by Bochkanov Sergey
4898 *************************************************************************/
4900 {
4901  alglib_impl::ae_state _alglib_env_state;
4902  ae_int_t n;
4903  ae_int_t k;
4904  if( (x.length()!=y.length()) || (x.length()!=w.length()))
4905  throw ap_error("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
4906  if( (xc.length()!=yc.length()) || (xc.length()!=dc.length()))
4907  throw ap_error("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
4908  n = x.length();
4909  k = xc.length();
4910  alglib_impl::ae_state_init(&_alglib_env_state);
4911  try
4912  {
4913  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);
4914 
4915  alglib_impl::ae_state_clear(&_alglib_env_state);
4916  return;
4917  }
4919  {
4920  throw ap_error(_alglib_env_state.error_msg);
4921  }
4922 }
4923 
4924 /*************************************************************************
4925 Least squares fitting by cubic spline.
4926 
4927 This subroutine is "lightweight" alternative for more complex and feature-
4928 rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information
4929 about subroutine parameters (we don't duplicate it here because of length)
4930 
4931  -- ALGLIB PROJECT --
4932  Copyright 18.08.2009 by Bochkanov Sergey
4933 *************************************************************************/
4935 {
4936  alglib_impl::ae_state _alglib_env_state;
4937  alglib_impl::ae_state_init(&_alglib_env_state);
4938  try
4939  {
4940  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);
4941  alglib_impl::ae_state_clear(&_alglib_env_state);
4942  return;
4943  }
4945  {
4946  throw ap_error(_alglib_env_state.error_msg);
4947  }
4948 }
4949 
4950 /*************************************************************************
4951 Least squares fitting by cubic spline.
4952 
4953 This subroutine is "lightweight" alternative for more complex and feature-
4954 rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information
4955 about subroutine parameters (we don't duplicate it here because of length)
4956 
4957  -- ALGLIB PROJECT --
4958  Copyright 18.08.2009 by Bochkanov Sergey
4959 *************************************************************************/
4961 {
4962  alglib_impl::ae_state _alglib_env_state;
4963  ae_int_t n;
4964  if( (x.length()!=y.length()))
4965  throw ap_error("Error while calling 'spline1dfitcubic': looks like one of arguments has wrong size");
4966  n = x.length();
4967  alglib_impl::ae_state_init(&_alglib_env_state);
4968  try
4969  {
4970  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);
4971 
4972  alglib_impl::ae_state_clear(&_alglib_env_state);
4973  return;
4974  }
4976  {
4977  throw ap_error(_alglib_env_state.error_msg);
4978  }
4979 }
4980 
4981 /*************************************************************************
4982 Least squares fitting by Hermite spline.
4983 
4984 This subroutine is "lightweight" alternative for more complex and feature-
4985 rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for
4986 more information about subroutine parameters (we don't duplicate it here
4987 because of length).
4988 
4989  -- ALGLIB PROJECT --
4990  Copyright 18.08.2009 by Bochkanov Sergey
4991 *************************************************************************/
4993 {
4994  alglib_impl::ae_state _alglib_env_state;
4995  alglib_impl::ae_state_init(&_alglib_env_state);
4996  try
4997  {
4998  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);
4999  alglib_impl::ae_state_clear(&_alglib_env_state);
5000  return;
5001  }
5003  {
5004  throw ap_error(_alglib_env_state.error_msg);
5005  }
5006 }
5007 
5008 /*************************************************************************
5009 Least squares fitting by Hermite spline.
5010 
5011 This subroutine is "lightweight" alternative for more complex and feature-
5012 rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for
5013 more information about subroutine parameters (we don't duplicate it here
5014 because of length).
5015 
5016  -- ALGLIB PROJECT --
5017  Copyright 18.08.2009 by Bochkanov Sergey
5018 *************************************************************************/
5020 {
5021  alglib_impl::ae_state _alglib_env_state;
5022  ae_int_t n;
5023  if( (x.length()!=y.length()))
5024  throw ap_error("Error while calling 'spline1dfithermite': looks like one of arguments has wrong size");
5025  n = x.length();
5026  alglib_impl::ae_state_init(&_alglib_env_state);
5027  try
5028  {
5029  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);
5030 
5031  alglib_impl::ae_state_clear(&_alglib_env_state);
5032  return;
5033  }
5035  {
5036  throw ap_error(_alglib_env_state.error_msg);
5037  }
5038 }
5039 
5040 /*************************************************************************
5041 Weighted linear least squares fitting.
5042 
5043 QR decomposition is used to reduce task to MxM, then triangular solver or
5044 SVD-based solver is used depending on condition number of the system. It
5045 allows to maximize speed and retain decent accuracy.
5046 
5047 IMPORTANT: if you want to perform polynomial fitting, it may be more
5048  convenient to use PolynomialFit() function. This function gives
5049  best results on polynomial problems and solves numerical
5050  stability issues which arise when you fit high-degree
5051  polynomials to your data.
5052 
5053 INPUT PARAMETERS:
5054  Y - array[0..N-1] Function values in N points.
5055  W - array[0..N-1] Weights corresponding to function values.
5056  Each summand in square sum of approximation deviations
5057  from given values is multiplied by the square of
5058  corresponding weight.
5059  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5060  FMatrix[I, J] - value of J-th basis function in I-th point.
5061  N - number of points used. N>=1.
5062  M - number of basis functions, M>=1.
5063 
5064 OUTPUT PARAMETERS:
5065  Info - error code:
5066  * -4 internal SVD decomposition subroutine failed (very
5067  rare and for degenerate systems only)
5068  * -1 incorrect N/M were specified
5069  * 1 task is solved
5070  C - decomposition coefficients, array[0..M-1]
5071  Rep - fitting report. Following fields are set:
5072  * Rep.TaskRCond reciprocal of condition number
5073  * R2 non-adjusted coefficient of determination
5074  (non-weighted)
5075  * RMSError rms error on the (X,Y).
5076  * AvgError average error on the (X,Y).
5077  * AvgRelError average relative error on the non-zero Y
5078  * MaxError maximum error
5079  NON-WEIGHTED ERRORS ARE CALCULATED
5080 
5081 ERRORS IN PARAMETERS
5082 
5083 This solver also calculates different kinds of errors in parameters and
5084 fills corresponding fields of report:
5085 * Rep.CovPar covariance matrix for parameters, array[K,K].
5086 * Rep.ErrPar errors in parameters, array[K],
5087  errpar = sqrt(diag(CovPar))
5088 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5089  best-fit curve from "ideal" best-fit curve built with
5090  infinite number of samples, array[N].
5091  errcurve = sqrt(diag(F*CovPar*F')),
5092  where F is functions matrix.
5093 * Rep.Noise vector of per-point estimates of noise, array[N]
5094 
5095 NOTE: noise in the data is estimated as follows:
5096  * for fitting without user-supplied weights all points are
5097  assumed to have same level of noise, which is estimated from
5098  the data
5099  * for fitting with user-supplied weights we assume that noise
5100  level in I-th point is inversely proportional to Ith weight.
5101  Coefficient of proportionality is estimated from the data.
5102 
5103 NOTE: we apply small amount of regularization when we invert squared
5104  Jacobian and calculate covariance matrix. It guarantees that
5105  algorithm won't divide by zero during inversion, but skews
5106  error estimates a bit (fractional error is about 10^-9).
5107 
5108  However, we believe that this difference is insignificant for
5109  all practical purposes except for the situation when you want
5110  to compare ALGLIB results with "reference" implementation up
5111  to the last significant digit.
5112 
5113 NOTE: covariance matrix is estimated using correction for degrees
5114  of freedom (covariances are divided by N-M instead of dividing
5115  by N).
5116 
5117  -- ALGLIB --
5118  Copyright 17.08.2009 by Bochkanov Sergey
5119 *************************************************************************/
5120 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)
5121 {
5122  alglib_impl::ae_state _alglib_env_state;
5123  alglib_impl::ae_state_init(&_alglib_env_state);
5124  try
5125  {
5126  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);
5127  alglib_impl::ae_state_clear(&_alglib_env_state);
5128  return;
5129  }
5131  {
5132  throw ap_error(_alglib_env_state.error_msg);
5133  }
5134 }
5135 
5136 /*************************************************************************
5137 Weighted linear least squares fitting.
5138 
5139 QR decomposition is used to reduce task to MxM, then triangular solver or
5140 SVD-based solver is used depending on condition number of the system. It
5141 allows to maximize speed and retain decent accuracy.
5142 
5143 IMPORTANT: if you want to perform polynomial fitting, it may be more
5144  convenient to use PolynomialFit() function. This function gives
5145  best results on polynomial problems and solves numerical
5146  stability issues which arise when you fit high-degree
5147  polynomials to your data.
5148 
5149 INPUT PARAMETERS:
5150  Y - array[0..N-1] Function values in N points.
5151  W - array[0..N-1] Weights corresponding to function values.
5152  Each summand in square sum of approximation deviations
5153  from given values is multiplied by the square of
5154  corresponding weight.
5155  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5156  FMatrix[I, J] - value of J-th basis function in I-th point.
5157  N - number of points used. N>=1.
5158  M - number of basis functions, M>=1.
5159 
5160 OUTPUT PARAMETERS:
5161  Info - error code:
5162  * -4 internal SVD decomposition subroutine failed (very
5163  rare and for degenerate systems only)
5164  * -1 incorrect N/M were specified
5165  * 1 task is solved
5166  C - decomposition coefficients, array[0..M-1]
5167  Rep - fitting report. Following fields are set:
5168  * Rep.TaskRCond reciprocal of condition number
5169  * R2 non-adjusted coefficient of determination
5170  (non-weighted)
5171  * RMSError rms error on the (X,Y).
5172  * AvgError average error on the (X,Y).
5173  * AvgRelError average relative error on the non-zero Y
5174  * MaxError maximum error
5175  NON-WEIGHTED ERRORS ARE CALCULATED
5176 
5177 ERRORS IN PARAMETERS
5178 
5179 This solver also calculates different kinds of errors in parameters and
5180 fills corresponding fields of report:
5181 * Rep.CovPar covariance matrix for parameters, array[K,K].
5182 * Rep.ErrPar errors in parameters, array[K],
5183  errpar = sqrt(diag(CovPar))
5184 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5185  best-fit curve from "ideal" best-fit curve built with
5186  infinite number of samples, array[N].
5187  errcurve = sqrt(diag(F*CovPar*F')),
5188  where F is functions matrix.
5189 * Rep.Noise vector of per-point estimates of noise, array[N]
5190 
5191 NOTE: noise in the data is estimated as follows:
5192  * for fitting without user-supplied weights all points are
5193  assumed to have same level of noise, which is estimated from
5194  the data
5195  * for fitting with user-supplied weights we assume that noise
5196  level in I-th point is inversely proportional to Ith weight.
5197  Coefficient of proportionality is estimated from the data.
5198 
5199 NOTE: we apply small amount of regularization when we invert squared
5200  Jacobian and calculate covariance matrix. It guarantees that
5201  algorithm won't divide by zero during inversion, but skews
5202  error estimates a bit (fractional error is about 10^-9).
5203 
5204  However, we believe that this difference is insignificant for
5205  all practical purposes except for the situation when you want
5206  to compare ALGLIB results with "reference" implementation up
5207  to the last significant digit.
5208 
5209 NOTE: covariance matrix is estimated using correction for degrees
5210  of freedom (covariances are divided by N-M instead of dividing
5211  by N).
5212 
5213  -- ALGLIB --
5214  Copyright 17.08.2009 by Bochkanov Sergey
5215 *************************************************************************/
5216 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)
5217 {
5218  alglib_impl::ae_state _alglib_env_state;
5219  ae_int_t n;
5220  ae_int_t m;
5221  if( (y.length()!=w.length()) || (y.length()!=fmatrix.rows()))
5222  throw ap_error("Error while calling 'lsfitlinearw': looks like one of arguments has wrong size");
5223  n = y.length();
5224  m = fmatrix.cols();
5225  alglib_impl::ae_state_init(&_alglib_env_state);
5226  try
5227  {
5228  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);
5229 
5230  alglib_impl::ae_state_clear(&_alglib_env_state);
5231  return;
5232  }
5234  {
5235  throw ap_error(_alglib_env_state.error_msg);
5236  }
5237 }
5238 
5239 /*************************************************************************
5240 Weighted constained linear least squares fitting.
5241 
5242 This is variation of LSFitLinearW(), which searchs for min|A*x=b| given
5243 that K additional constraints C*x=bc are satisfied. It reduces original
5244 task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW()
5245 is called.
5246 
5247 IMPORTANT: if you want to perform polynomial fitting, it may be more
5248  convenient to use PolynomialFit() function. This function gives
5249  best results on polynomial problems and solves numerical
5250  stability issues which arise when you fit high-degree
5251  polynomials to your data.
5252 
5253 INPUT PARAMETERS:
5254  Y - array[0..N-1] Function values in N points.
5255  W - array[0..N-1] Weights corresponding to function values.
5256  Each summand in square sum of approximation deviations
5257  from given values is multiplied by the square of
5258  corresponding weight.
5259  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5260  FMatrix[I,J] - value of J-th basis function in I-th point.
5261  CMatrix - a table of constraints, array[0..K-1,0..M].
5262  I-th row of CMatrix corresponds to I-th linear constraint:
5263  CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
5264  N - number of points used. N>=1.
5265  M - number of basis functions, M>=1.
5266  K - number of constraints, 0 <= K < M
5267  K=0 corresponds to absence of constraints.
5268 
5269 OUTPUT PARAMETERS:
5270  Info - error code:
5271  * -4 internal SVD decomposition subroutine failed (very
5272  rare and for degenerate systems only)
5273  * -3 either too many constraints (M or more),
5274  degenerate constraints (some constraints are
5275  repetead twice) or inconsistent constraints were
5276  specified.
5277  * 1 task is solved
5278  C - decomposition coefficients, array[0..M-1]
5279  Rep - fitting report. Following fields are set:
5280  * R2 non-adjusted coefficient of determination
5281  (non-weighted)
5282  * RMSError rms error on the (X,Y).
5283  * AvgError average error on the (X,Y).
5284  * AvgRelError average relative error on the non-zero Y
5285  * MaxError maximum error
5286  NON-WEIGHTED ERRORS ARE CALCULATED
5287 
5288 IMPORTANT:
5289  this subroitine doesn't calculate task's condition number for K<>0.
5290 
5291 ERRORS IN PARAMETERS
5292 
5293 This solver also calculates different kinds of errors in parameters and
5294 fills corresponding fields of report:
5295 * Rep.CovPar covariance matrix for parameters, array[K,K].
5296 * Rep.ErrPar errors in parameters, array[K],
5297  errpar = sqrt(diag(CovPar))
5298 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5299  best-fit curve from "ideal" best-fit curve built with
5300  infinite number of samples, array[N].
5301  errcurve = sqrt(diag(F*CovPar*F')),
5302  where F is functions matrix.
5303 * Rep.Noise vector of per-point estimates of noise, array[N]
5304 
5305 IMPORTANT: errors in parameters are calculated without taking into
5306  account boundary/linear constraints! Presence of constraints
5307  changes distribution of errors, but there is no easy way to
5308  account for constraints when you calculate covariance matrix.
5309 
5310 NOTE: noise in the data is estimated as follows:
5311  * for fitting without user-supplied weights all points are
5312  assumed to have same level of noise, which is estimated from
5313  the data
5314  * for fitting with user-supplied weights we assume that noise
5315  level in I-th point is inversely proportional to Ith weight.
5316  Coefficient of proportionality is estimated from the data.
5317 
5318 NOTE: we apply small amount of regularization when we invert squared
5319  Jacobian and calculate covariance matrix. It guarantees that
5320  algorithm won't divide by zero during inversion, but skews
5321  error estimates a bit (fractional error is about 10^-9).
5322 
5323  However, we believe that this difference is insignificant for
5324  all practical purposes except for the situation when you want
5325  to compare ALGLIB results with "reference" implementation up
5326  to the last significant digit.
5327 
5328 NOTE: covariance matrix is estimated using correction for degrees
5329  of freedom (covariances are divided by N-M instead of dividing
5330  by N).
5331 
5332  -- ALGLIB --
5333  Copyright 07.09.2009 by Bochkanov Sergey
5334 *************************************************************************/
5335 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)
5336 {
5337  alglib_impl::ae_state _alglib_env_state;
5338  alglib_impl::ae_state_init(&_alglib_env_state);
5339  try
5340  {
5341  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);
5342  alglib_impl::ae_state_clear(&_alglib_env_state);
5343  return;
5344  }
5346  {
5347  throw ap_error(_alglib_env_state.error_msg);
5348  }
5349 }
5350 
5351 /*************************************************************************
5352 Weighted constained linear least squares fitting.
5353 
5354 This is variation of LSFitLinearW(), which searchs for min|A*x=b| given
5355 that K additional constraints C*x=bc are satisfied. It reduces original
5356 task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW()
5357 is called.
5358 
5359 IMPORTANT: if you want to perform polynomial fitting, it may be more
5360  convenient to use PolynomialFit() function. This function gives
5361  best results on polynomial problems and solves numerical
5362  stability issues which arise when you fit high-degree
5363  polynomials to your data.
5364 
5365 INPUT PARAMETERS:
5366  Y - array[0..N-1] Function values in N points.
5367  W - array[0..N-1] Weights corresponding to function values.
5368  Each summand in square sum of approximation deviations
5369  from given values is multiplied by the square of
5370  corresponding weight.
5371  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5372  FMatrix[I,J] - value of J-th basis function in I-th point.
5373  CMatrix - a table of constraints, array[0..K-1,0..M].
5374  I-th row of CMatrix corresponds to I-th linear constraint:
5375  CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
5376  N - number of points used. N>=1.
5377  M - number of basis functions, M>=1.
5378  K - number of constraints, 0 <= K < M
5379  K=0 corresponds to absence of constraints.
5380 
5381 OUTPUT PARAMETERS:
5382  Info - error code:
5383  * -4 internal SVD decomposition subroutine failed (very
5384  rare and for degenerate systems only)
5385  * -3 either too many constraints (M or more),
5386  degenerate constraints (some constraints are
5387  repetead twice) or inconsistent constraints were
5388  specified.
5389  * 1 task is solved
5390  C - decomposition coefficients, array[0..M-1]
5391  Rep - fitting report. Following fields are set:
5392  * R2 non-adjusted coefficient of determination
5393  (non-weighted)
5394  * RMSError rms error on the (X,Y).
5395  * AvgError average error on the (X,Y).
5396  * AvgRelError average relative error on the non-zero Y
5397  * MaxError maximum error
5398  NON-WEIGHTED ERRORS ARE CALCULATED
5399 
5400 IMPORTANT:
5401  this subroitine doesn't calculate task's condition number for K<>0.
5402 
5403 ERRORS IN PARAMETERS
5404 
5405 This solver also calculates different kinds of errors in parameters and
5406 fills corresponding fields of report:
5407 * Rep.CovPar covariance matrix for parameters, array[K,K].
5408 * Rep.ErrPar errors in parameters, array[K],
5409  errpar = sqrt(diag(CovPar))
5410 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5411  best-fit curve from "ideal" best-fit curve built with
5412  infinite number of samples, array[N].
5413  errcurve = sqrt(diag(F*CovPar*F')),
5414  where F is functions matrix.
5415 * Rep.Noise vector of per-point estimates of noise, array[N]
5416 
5417 IMPORTANT: errors in parameters are calculated without taking into
5418  account boundary/linear constraints! Presence of constraints
5419  changes distribution of errors, but there is no easy way to
5420  account for constraints when you calculate covariance matrix.
5421 
5422 NOTE: noise in the data is estimated as follows:
5423  * for fitting without user-supplied weights all points are
5424  assumed to have same level of noise, which is estimated from
5425  the data
5426  * for fitting with user-supplied weights we assume that noise
5427  level in I-th point is inversely proportional to Ith weight.
5428  Coefficient of proportionality is estimated from the data.
5429 
5430 NOTE: we apply small amount of regularization when we invert squared
5431  Jacobian and calculate covariance matrix. It guarantees that
5432  algorithm won't divide by zero during inversion, but skews
5433  error estimates a bit (fractional error is about 10^-9).
5434 
5435  However, we believe that this difference is insignificant for
5436  all practical purposes except for the situation when you want
5437  to compare ALGLIB results with "reference" implementation up
5438  to the last significant digit.
5439 
5440 NOTE: covariance matrix is estimated using correction for degrees
5441  of freedom (covariances are divided by N-M instead of dividing
5442  by N).
5443 
5444  -- ALGLIB --
5445  Copyright 07.09.2009 by Bochkanov Sergey
5446 *************************************************************************/
5447 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)
5448 {
5449  alglib_impl::ae_state _alglib_env_state;
5450  ae_int_t n;
5451  ae_int_t m;
5452  ae_int_t k;
5453  if( (y.length()!=w.length()) || (y.length()!=fmatrix.rows()))
5454  throw ap_error("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size");
5455  if( (fmatrix.cols()!=cmatrix.cols()-1))
5456  throw ap_error("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size");
5457  n = y.length();
5458  m = fmatrix.cols();
5459  k = cmatrix.rows();
5460  alglib_impl::ae_state_init(&_alglib_env_state);
5461  try
5462  {
5463  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);
5464 
5465  alglib_impl::ae_state_clear(&_alglib_env_state);
5466  return;
5467  }
5469  {
5470  throw ap_error(_alglib_env_state.error_msg);
5471  }
5472 }
5473 
5474 /*************************************************************************
5475 Linear least squares fitting.
5476 
5477 QR decomposition is used to reduce task to MxM, then triangular solver or
5478 SVD-based solver is used depending on condition number of the system. It
5479 allows to maximize speed and retain decent accuracy.
5480 
5481 IMPORTANT: if you want to perform polynomial fitting, it may be more
5482  convenient to use PolynomialFit() function. This function gives
5483  best results on polynomial problems and solves numerical
5484  stability issues which arise when you fit high-degree
5485  polynomials to your data.
5486 
5487 INPUT PARAMETERS:
5488  Y - array[0..N-1] Function values in N points.
5489  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5490  FMatrix[I, J] - value of J-th basis function in I-th point.
5491  N - number of points used. N>=1.
5492  M - number of basis functions, M>=1.
5493 
5494 OUTPUT PARAMETERS:
5495  Info - error code:
5496  * -4 internal SVD decomposition subroutine failed (very
5497  rare and for degenerate systems only)
5498  * 1 task is solved
5499  C - decomposition coefficients, array[0..M-1]
5500  Rep - fitting report. Following fields are set:
5501  * Rep.TaskRCond reciprocal of condition number
5502  * R2 non-adjusted coefficient of determination
5503  (non-weighted)
5504  * RMSError rms error on the (X,Y).
5505  * AvgError average error on the (X,Y).
5506  * AvgRelError average relative error on the non-zero Y
5507  * MaxError maximum error
5508  NON-WEIGHTED ERRORS ARE CALCULATED
5509 
5510 ERRORS IN PARAMETERS
5511 
5512 This solver also calculates different kinds of errors in parameters and
5513 fills corresponding fields of report:
5514 * Rep.CovPar covariance matrix for parameters, array[K,K].
5515 * Rep.ErrPar errors in parameters, array[K],
5516  errpar = sqrt(diag(CovPar))
5517 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5518  best-fit curve from "ideal" best-fit curve built with
5519  infinite number of samples, array[N].
5520  errcurve = sqrt(diag(F*CovPar*F')),
5521  where F is functions matrix.
5522 * Rep.Noise vector of per-point estimates of noise, array[N]
5523 
5524 NOTE: noise in the data is estimated as follows:
5525  * for fitting without user-supplied weights all points are
5526  assumed to have same level of noise, which is estimated from
5527  the data
5528  * for fitting with user-supplied weights we assume that noise
5529  level in I-th point is inversely proportional to Ith weight.
5530  Coefficient of proportionality is estimated from the data.
5531 
5532 NOTE: we apply small amount of regularization when we invert squared
5533  Jacobian and calculate covariance matrix. It guarantees that
5534  algorithm won't divide by zero during inversion, but skews
5535  error estimates a bit (fractional error is about 10^-9).
5536 
5537  However, we believe that this difference is insignificant for
5538  all practical purposes except for the situation when you want
5539  to compare ALGLIB results with "reference" implementation up
5540  to the last significant digit.
5541 
5542 NOTE: covariance matrix is estimated using correction for degrees
5543  of freedom (covariances are divided by N-M instead of dividing
5544  by N).
5545 
5546  -- ALGLIB --
5547  Copyright 17.08.2009 by Bochkanov Sergey
5548 *************************************************************************/
5549 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)
5550 {
5551  alglib_impl::ae_state _alglib_env_state;
5552  alglib_impl::ae_state_init(&_alglib_env_state);
5553  try
5554  {
5555  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);
5556  alglib_impl::ae_state_clear(&_alglib_env_state);
5557  return;
5558  }
5560  {
5561  throw ap_error(_alglib_env_state.error_msg);
5562  }
5563 }
5564 
5565 /*************************************************************************
5566 Linear least squares fitting.
5567 
5568 QR decomposition is used to reduce task to MxM, then triangular solver or
5569 SVD-based solver is used depending on condition number of the system. It
5570 allows to maximize speed and retain decent accuracy.
5571 
5572 IMPORTANT: if you want to perform polynomial fitting, it may be more
5573  convenient to use PolynomialFit() function. This function gives
5574  best results on polynomial problems and solves numerical
5575  stability issues which arise when you fit high-degree
5576  polynomials to your data.
5577 
5578 INPUT PARAMETERS:
5579  Y - array[0..N-1] Function values in N points.
5580  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5581  FMatrix[I, J] - value of J-th basis function in I-th point.
5582  N - number of points used. N>=1.
5583  M - number of basis functions, M>=1.
5584 
5585 OUTPUT PARAMETERS:
5586  Info - error code:
5587  * -4 internal SVD decomposition subroutine failed (very
5588  rare and for degenerate systems only)
5589  * 1 task is solved
5590  C - decomposition coefficients, array[0..M-1]
5591  Rep - fitting report. Following fields are set:
5592  * Rep.TaskRCond reciprocal of condition number
5593  * R2 non-adjusted coefficient of determination
5594  (non-weighted)
5595  * RMSError rms error on the (X,Y).
5596  * AvgError average error on the (X,Y).
5597  * AvgRelError average relative error on the non-zero Y
5598  * MaxError maximum error
5599  NON-WEIGHTED ERRORS ARE CALCULATED
5600 
5601 ERRORS IN PARAMETERS
5602 
5603 This solver also calculates different kinds of errors in parameters and
5604 fills corresponding fields of report:
5605 * Rep.CovPar covariance matrix for parameters, array[K,K].
5606 * Rep.ErrPar errors in parameters, array[K],
5607  errpar = sqrt(diag(CovPar))
5608 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5609  best-fit curve from "ideal" best-fit curve built with
5610  infinite number of samples, array[N].
5611  errcurve = sqrt(diag(F*CovPar*F')),
5612  where F is functions matrix.
5613 * Rep.Noise vector of per-point estimates of noise, array[N]
5614 
5615 NOTE: noise in the data is estimated as follows:
5616  * for fitting without user-supplied weights all points are
5617  assumed to have same level of noise, which is estimated from
5618  the data
5619  * for fitting with user-supplied weights we assume that noise
5620  level in I-th point is inversely proportional to Ith weight.
5621  Coefficient of proportionality is estimated from the data.
5622 
5623 NOTE: we apply small amount of regularization when we invert squared
5624  Jacobian and calculate covariance matrix. It guarantees that
5625  algorithm won't divide by zero during inversion, but skews
5626  error estimates a bit (fractional error is about 10^-9).
5627 
5628  However, we believe that this difference is insignificant for
5629  all practical purposes except for the situation when you want
5630  to compare ALGLIB results with "reference" implementation up
5631  to the last significant digit.
5632 
5633 NOTE: covariance matrix is estimated using correction for degrees
5634  of freedom (covariances are divided by N-M instead of dividing
5635  by N).
5636 
5637  -- ALGLIB --
5638  Copyright 17.08.2009 by Bochkanov Sergey
5639 *************************************************************************/
5640 void lsfitlinear(const real_1d_array &y, const real_2d_array &fmatrix, ae_int_t &info, real_1d_array &c, lsfitreport &rep)
5641 {
5642  alglib_impl::ae_state _alglib_env_state;
5643  ae_int_t n;
5644  ae_int_t m;
5645  if( (y.length()!=fmatrix.rows()))
5646  throw ap_error("Error while calling 'lsfitlinear': looks like one of arguments has wrong size");
5647  n = y.length();
5648  m = fmatrix.cols();
5649  alglib_impl::ae_state_init(&_alglib_env_state);
5650  try
5651  {
5652  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);
5653 
5654  alglib_impl::ae_state_clear(&_alglib_env_state);
5655  return;
5656  }
5658  {
5659  throw ap_error(_alglib_env_state.error_msg);
5660  }
5661 }
5662 
5663 /*************************************************************************
5664 Constained linear least squares fitting.
5665 
5666 This is variation of LSFitLinear(), which searchs for min|A*x=b| given
5667 that K additional constraints C*x=bc are satisfied. It reduces original
5668 task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear()
5669 is called.
5670 
5671 IMPORTANT: if you want to perform polynomial fitting, it may be more
5672  convenient to use PolynomialFit() function. This function gives
5673  best results on polynomial problems and solves numerical
5674  stability issues which arise when you fit high-degree
5675  polynomials to your data.
5676 
5677 INPUT PARAMETERS:
5678  Y - array[0..N-1] Function values in N points.
5679  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5680  FMatrix[I,J] - value of J-th basis function in I-th point.
5681  CMatrix - a table of constraints, array[0..K-1,0..M].
5682  I-th row of CMatrix corresponds to I-th linear constraint:
5683  CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
5684  N - number of points used. N>=1.
5685  M - number of basis functions, M>=1.
5686  K - number of constraints, 0 <= K < M
5687  K=0 corresponds to absence of constraints.
5688 
5689 OUTPUT PARAMETERS:
5690  Info - error code:
5691  * -4 internal SVD decomposition subroutine failed (very
5692  rare and for degenerate systems only)
5693  * -3 either too many constraints (M or more),
5694  degenerate constraints (some constraints are
5695  repetead twice) or inconsistent constraints were
5696  specified.
5697  * 1 task is solved
5698  C - decomposition coefficients, array[0..M-1]
5699  Rep - fitting report. Following fields are set:
5700  * R2 non-adjusted coefficient of determination
5701  (non-weighted)
5702  * RMSError rms error on the (X,Y).
5703  * AvgError average error on the (X,Y).
5704  * AvgRelError average relative error on the non-zero Y
5705  * MaxError maximum error
5706  NON-WEIGHTED ERRORS ARE CALCULATED
5707 
5708 IMPORTANT:
5709  this subroitine doesn't calculate task's condition number for K<>0.
5710 
5711 ERRORS IN PARAMETERS
5712 
5713 This solver also calculates different kinds of errors in parameters and
5714 fills corresponding fields of report:
5715 * Rep.CovPar covariance matrix for parameters, array[K,K].
5716 * Rep.ErrPar errors in parameters, array[K],
5717  errpar = sqrt(diag(CovPar))
5718 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5719  best-fit curve from "ideal" best-fit curve built with
5720  infinite number of samples, array[N].
5721  errcurve = sqrt(diag(F*CovPar*F')),
5722  where F is functions matrix.
5723 * Rep.Noise vector of per-point estimates of noise, array[N]
5724 
5725 IMPORTANT: errors in parameters are calculated without taking into
5726  account boundary/linear constraints! Presence of constraints
5727  changes distribution of errors, but there is no easy way to
5728  account for constraints when you calculate covariance matrix.
5729 
5730 NOTE: noise in the data is estimated as follows:
5731  * for fitting without user-supplied weights all points are
5732  assumed to have same level of noise, which is estimated from
5733  the data
5734  * for fitting with user-supplied weights we assume that noise
5735  level in I-th point is inversely proportional to Ith weight.
5736  Coefficient of proportionality is estimated from the data.
5737 
5738 NOTE: we apply small amount of regularization when we invert squared
5739  Jacobian and calculate covariance matrix. It guarantees that
5740  algorithm won't divide by zero during inversion, but skews
5741  error estimates a bit (fractional error is about 10^-9).
5742 
5743  However, we believe that this difference is insignificant for
5744  all practical purposes except for the situation when you want
5745  to compare ALGLIB results with "reference" implementation up
5746  to the last significant digit.
5747 
5748 NOTE: covariance matrix is estimated using correction for degrees
5749  of freedom (covariances are divided by N-M instead of dividing
5750  by N).
5751 
5752  -- ALGLIB --
5753  Copyright 07.09.2009 by Bochkanov Sergey
5754 *************************************************************************/
5755 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)
5756 {
5757  alglib_impl::ae_state _alglib_env_state;
5758  alglib_impl::ae_state_init(&_alglib_env_state);
5759  try
5760  {
5761  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);
5762  alglib_impl::ae_state_clear(&_alglib_env_state);
5763  return;
5764  }
5766  {
5767  throw ap_error(_alglib_env_state.error_msg);
5768  }
5769 }
5770 
5771 /*************************************************************************
5772 Constained linear least squares fitting.
5773 
5774 This is variation of LSFitLinear(), which searchs for min|A*x=b| given
5775 that K additional constraints C*x=bc are satisfied. It reduces original
5776 task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear()
5777 is called.
5778 
5779 IMPORTANT: if you want to perform polynomial fitting, it may be more
5780  convenient to use PolynomialFit() function. This function gives
5781  best results on polynomial problems and solves numerical
5782  stability issues which arise when you fit high-degree
5783  polynomials to your data.
5784 
5785 INPUT PARAMETERS:
5786  Y - array[0..N-1] Function values in N points.
5787  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
5788  FMatrix[I,J] - value of J-th basis function in I-th point.
5789  CMatrix - a table of constraints, array[0..K-1,0..M].
5790  I-th row of CMatrix corresponds to I-th linear constraint:
5791  CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
5792  N - number of points used. N>=1.
5793  M - number of basis functions, M>=1.
5794  K - number of constraints, 0 <= K < M
5795  K=0 corresponds to absence of constraints.
5796 
5797 OUTPUT PARAMETERS:
5798  Info - error code:
5799  * -4 internal SVD decomposition subroutine failed (very
5800  rare and for degenerate systems only)
5801  * -3 either too many constraints (M or more),
5802  degenerate constraints (some constraints are
5803  repetead twice) or inconsistent constraints were
5804  specified.
5805  * 1 task is solved
5806  C - decomposition coefficients, array[0..M-1]
5807  Rep - fitting report. Following fields are set:
5808  * R2 non-adjusted coefficient of determination
5809  (non-weighted)
5810  * RMSError rms error on the (X,Y).
5811  * AvgError average error on the (X,Y).
5812  * AvgRelError average relative error on the non-zero Y
5813  * MaxError maximum error
5814  NON-WEIGHTED ERRORS ARE CALCULATED
5815 
5816 IMPORTANT:
5817  this subroitine doesn't calculate task's condition number for K<>0.
5818 
5819 ERRORS IN PARAMETERS
5820 
5821 This solver also calculates different kinds of errors in parameters and
5822 fills corresponding fields of report:
5823 * Rep.CovPar covariance matrix for parameters, array[K,K].
5824 * Rep.ErrPar errors in parameters, array[K],
5825  errpar = sqrt(diag(CovPar))
5826 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
5827  best-fit curve from "ideal" best-fit curve built with
5828  infinite number of samples, array[N].
5829  errcurve = sqrt(diag(F*CovPar*F')),
5830  where F is functions matrix.
5831 * Rep.Noise vector of per-point estimates of noise, array[N]
5832 
5833 IMPORTANT: errors in parameters are calculated without taking into
5834  account boundary/linear constraints! Presence of constraints
5835  changes distribution of errors, but there is no easy way to
5836  account for constraints when you calculate covariance matrix.
5837 
5838 NOTE: noise in the data is estimated as follows:
5839  * for fitting without user-supplied weights all points are
5840  assumed to have same level of noise, which is estimated from
5841  the data
5842  * for fitting with user-supplied weights we assume that noise
5843  level in I-th point is inversely proportional to Ith weight.
5844  Coefficient of proportionality is estimated from the data.
5845 
5846 NOTE: we apply small amount of regularization when we invert squared
5847  Jacobian and calculate covariance matrix. It guarantees that
5848  algorithm won't divide by zero during inversion, but skews
5849  error estimates a bit (fractional error is about 10^-9).
5850 
5851  However, we believe that this difference is insignificant for
5852  all practical purposes except for the situation when you want
5853  to compare ALGLIB results with "reference" implementation up
5854  to the last significant digit.
5855 
5856 NOTE: covariance matrix is estimated using correction for degrees
5857  of freedom (covariances are divided by N-M instead of dividing
5858  by N).
5859 
5860  -- ALGLIB --
5861  Copyright 07.09.2009 by Bochkanov Sergey
5862 *************************************************************************/
5863 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)
5864 {
5865  alglib_impl::ae_state _alglib_env_state;
5866  ae_int_t n;
5867  ae_int_t m;
5868  ae_int_t k;
5869  if( (y.length()!=fmatrix.rows()))
5870  throw ap_error("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size");
5871  if( (fmatrix.cols()!=cmatrix.cols()-1))
5872  throw ap_error("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size");
5873  n = y.length();
5874  m = fmatrix.cols();
5875  k = cmatrix.rows();
5876  alglib_impl::ae_state_init(&_alglib_env_state);
5877  try
5878  {
5879  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);
5880 
5881  alglib_impl::ae_state_clear(&_alglib_env_state);
5882  return;
5883  }
5885  {
5886  throw ap_error(_alglib_env_state.error_msg);
5887  }
5888 }
5889 
5890 /*************************************************************************
5891 Weighted nonlinear least squares fitting using function values only.
5892 
5893 Combination of numerical differentiation and secant updates is used to
5894 obtain function Jacobian.
5895 
5896 Nonlinear task min(F(c)) is solved, where
5897 
5898  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
5899 
5900  * N is a number of points,
5901  * M is a dimension of a space points belong to,
5902  * K is a dimension of a space of parameters being fitted,
5903  * w is an N-dimensional vector of weight coefficients,
5904  * x is a set of N points, each of them is an M-dimensional vector,
5905  * c is a K-dimensional vector of parameters being fitted
5906 
5907 This subroutine uses only f(c,x[i]).
5908 
5909 INPUT PARAMETERS:
5910  X - array[0..N-1,0..M-1], points (one row = one point)
5911  Y - array[0..N-1], function values.
5912  W - weights, array[0..N-1]
5913  C - array[0..K-1], initial approximation to the solution,
5914  N - number of points, N>1
5915  M - dimension of space
5916  K - number of parameters being fitted
5917  DiffStep- numerical differentiation step;
5918  should not be very small or large;
5919  large = loss of accuracy
5920  small = growth of round-off errors
5921 
5922 OUTPUT PARAMETERS:
5923  State - structure which stores algorithm state
5924 
5925  -- ALGLIB --
5926  Copyright 18.10.2008 by Bochkanov Sergey
5927 *************************************************************************/
5928 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)
5929 {
5930  alglib_impl::ae_state _alglib_env_state;
5931  alglib_impl::ae_state_init(&_alglib_env_state);
5932  try
5933  {
5934  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);
5935  alglib_impl::ae_state_clear(&_alglib_env_state);
5936  return;
5937  }
5939  {
5940  throw ap_error(_alglib_env_state.error_msg);
5941  }
5942 }
5943 
5944 /*************************************************************************
5945 Weighted nonlinear least squares fitting using function values only.
5946 
5947 Combination of numerical differentiation and secant updates is used to
5948 obtain function Jacobian.
5949 
5950 Nonlinear task min(F(c)) is solved, where
5951 
5952  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
5953 
5954  * N is a number of points,
5955  * M is a dimension of a space points belong to,
5956  * K is a dimension of a space of parameters being fitted,
5957  * w is an N-dimensional vector of weight coefficients,
5958  * x is a set of N points, each of them is an M-dimensional vector,
5959  * c is a K-dimensional vector of parameters being fitted
5960 
5961 This subroutine uses only f(c,x[i]).
5962 
5963 INPUT PARAMETERS:
5964  X - array[0..N-1,0..M-1], points (one row = one point)
5965  Y - array[0..N-1], function values.
5966  W - weights, array[0..N-1]
5967  C - array[0..K-1], initial approximation to the solution,
5968  N - number of points, N>1
5969  M - dimension of space
5970  K - number of parameters being fitted
5971  DiffStep- numerical differentiation step;
5972  should not be very small or large;
5973  large = loss of accuracy
5974  small = growth of round-off errors
5975 
5976 OUTPUT PARAMETERS:
5977  State - structure which stores algorithm state
5978 
5979  -- ALGLIB --
5980  Copyright 18.10.2008 by Bochkanov Sergey
5981 *************************************************************************/
5982 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)
5983 {
5984  alglib_impl::ae_state _alglib_env_state;
5985  ae_int_t n;
5986  ae_int_t m;
5987  ae_int_t k;
5988  if( (x.rows()!=y.length()) || (x.rows()!=w.length()))
5989  throw ap_error("Error while calling 'lsfitcreatewf': looks like one of arguments has wrong size");
5990  n = x.rows();
5991  m = x.cols();
5992  k = c.length();
5993  alglib_impl::ae_state_init(&_alglib_env_state);
5994  try
5995  {
5996  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);
5997 
5998  alglib_impl::ae_state_clear(&_alglib_env_state);
5999  return;
6000  }
6002  {
6003  throw ap_error(_alglib_env_state.error_msg);
6004  }
6005 }
6006 
6007 /*************************************************************************
6008 Nonlinear least squares fitting using function values only.
6009 
6010 Combination of numerical differentiation and secant updates is used to
6011 obtain function Jacobian.
6012 
6013 Nonlinear task min(F(c)) is solved, where
6014 
6015  F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2,
6016 
6017  * N is a number of points,
6018  * M is a dimension of a space points belong to,
6019  * K is a dimension of a space of parameters being fitted,
6020  * w is an N-dimensional vector of weight coefficients,
6021  * x is a set of N points, each of them is an M-dimensional vector,
6022  * c is a K-dimensional vector of parameters being fitted
6023 
6024 This subroutine uses only f(c,x[i]).
6025 
6026 INPUT PARAMETERS:
6027  X - array[0..N-1,0..M-1], points (one row = one point)
6028  Y - array[0..N-1], function values.
6029  C - array[0..K-1], initial approximation to the solution,
6030  N - number of points, N>1
6031  M - dimension of space
6032  K - number of parameters being fitted
6033  DiffStep- numerical differentiation step;
6034  should not be very small or large;
6035  large = loss of accuracy
6036  small = growth of round-off errors
6037 
6038 OUTPUT PARAMETERS:
6039  State - structure which stores algorithm state
6040 
6041  -- ALGLIB --
6042  Copyright 18.10.2008 by Bochkanov Sergey
6043 *************************************************************************/
6044 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)
6045 {
6046  alglib_impl::ae_state _alglib_env_state;
6047  alglib_impl::ae_state_init(&_alglib_env_state);
6048  try
6049  {
6050  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);
6051  alglib_impl::ae_state_clear(&_alglib_env_state);
6052  return;
6053  }
6055  {
6056  throw ap_error(_alglib_env_state.error_msg);
6057  }
6058 }
6059 
6060 /*************************************************************************
6061 Nonlinear least squares fitting using function values only.
6062 
6063 Combination of numerical differentiation and secant updates is used to
6064 obtain function Jacobian.
6065 
6066 Nonlinear task min(F(c)) is solved, where
6067 
6068  F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2,
6069 
6070  * N is a number of points,
6071  * M is a dimension of a space points belong to,
6072  * K is a dimension of a space of parameters being fitted,
6073  * w is an N-dimensional vector of weight coefficients,
6074  * x is a set of N points, each of them is an M-dimensional vector,
6075  * c is a K-dimensional vector of parameters being fitted
6076 
6077 This subroutine uses only f(c,x[i]).
6078 
6079 INPUT PARAMETERS:
6080  X - array[0..N-1,0..M-1], points (one row = one point)
6081  Y - array[0..N-1], function values.
6082  C - array[0..K-1], initial approximation to the solution,
6083  N - number of points, N>1
6084  M - dimension of space
6085  K - number of parameters being fitted
6086  DiffStep- numerical differentiation step;
6087  should not be very small or large;
6088  large = loss of accuracy
6089  small = growth of round-off errors
6090 
6091 OUTPUT PARAMETERS:
6092  State - structure which stores algorithm state
6093 
6094  -- ALGLIB --
6095  Copyright 18.10.2008 by Bochkanov Sergey
6096 *************************************************************************/
6097 void lsfitcreatef(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const double diffstep, lsfitstate &state)
6098 {
6099  alglib_impl::ae_state _alglib_env_state;
6100  ae_int_t n;
6101  ae_int_t m;
6102  ae_int_t k;
6103  if( (x.rows()!=y.length()))
6104  throw ap_error("Error while calling 'lsfitcreatef': looks like one of arguments has wrong size");
6105  n = x.rows();
6106  m = x.cols();
6107  k = c.length();
6108  alglib_impl::ae_state_init(&_alglib_env_state);
6109  try
6110  {
6111  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);
6112 
6113  alglib_impl::ae_state_clear(&_alglib_env_state);
6114  return;
6115  }
6117  {
6118  throw ap_error(_alglib_env_state.error_msg);
6119  }
6120 }
6121 
6122 /*************************************************************************
6123 Weighted nonlinear least squares fitting using gradient only.
6124 
6125 Nonlinear task min(F(c)) is solved, where
6126 
6127  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
6128 
6129  * N is a number of points,
6130  * M is a dimension of a space points belong to,
6131  * K is a dimension of a space of parameters being fitted,
6132  * w is an N-dimensional vector of weight coefficients,
6133  * x is a set of N points, each of them is an M-dimensional vector,
6134  * c is a K-dimensional vector of parameters being fitted
6135 
6136 This subroutine uses only f(c,x[i]) and its gradient.
6137 
6138 INPUT PARAMETERS:
6139  X - array[0..N-1,0..M-1], points (one row = one point)
6140  Y - array[0..N-1], function values.
6141  W - weights, array[0..N-1]
6142  C - array[0..K-1], initial approximation to the solution,
6143  N - number of points, N>1
6144  M - dimension of space
6145  K - number of parameters being fitted
6146  CheapFG - boolean flag, which is:
6147  * True if both function and gradient calculation complexity
6148  are less than O(M^2). An improved algorithm can
6149  be used which corresponds to FGJ scheme from
6150  MINLM unit.
6151  * False otherwise.
6152  Standard Jacibian-bases Levenberg-Marquardt algo
6153  will be used (FJ scheme).
6154 
6155 OUTPUT PARAMETERS:
6156  State - structure which stores algorithm state
6157 
6158 See also:
6159  LSFitResults
6160  LSFitCreateFG (fitting without weights)
6161  LSFitCreateWFGH (fitting using Hessian)
6162  LSFitCreateFGH (fitting using Hessian, without weights)
6163 
6164  -- ALGLIB --
6165  Copyright 17.08.2009 by Bochkanov Sergey
6166 *************************************************************************/
6167 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)
6168 {
6169  alglib_impl::ae_state _alglib_env_state;
6170  alglib_impl::ae_state_init(&_alglib_env_state);
6171  try
6172  {
6173  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);
6174  alglib_impl::ae_state_clear(&_alglib_env_state);
6175  return;
6176  }
6178  {
6179  throw ap_error(_alglib_env_state.error_msg);
6180  }
6181 }
6182 
6183 /*************************************************************************
6184 Weighted nonlinear least squares fitting using gradient only.
6185 
6186 Nonlinear task min(F(c)) is solved, where
6187 
6188  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
6189 
6190  * N is a number of points,
6191  * M is a dimension of a space points belong to,
6192  * K is a dimension of a space of parameters being fitted,
6193  * w is an N-dimensional vector of weight coefficients,
6194  * x is a set of N points, each of them is an M-dimensional vector,
6195  * c is a K-dimensional vector of parameters being fitted
6196 
6197 This subroutine uses only f(c,x[i]) and its gradient.
6198 
6199 INPUT PARAMETERS:
6200  X - array[0..N-1,0..M-1], points (one row = one point)
6201  Y - array[0..N-1], function values.
6202  W - weights, array[0..N-1]
6203  C - array[0..K-1], initial approximation to the solution,
6204  N - number of points, N>1
6205  M - dimension of space
6206  K - number of parameters being fitted
6207  CheapFG - boolean flag, which is:
6208  * True if both function and gradient calculation complexity
6209  are less than O(M^2). An improved algorithm can
6210  be used which corresponds to FGJ scheme from
6211  MINLM unit.
6212  * False otherwise.
6213  Standard Jacibian-bases Levenberg-Marquardt algo
6214  will be used (FJ scheme).
6215 
6216 OUTPUT PARAMETERS:
6217  State - structure which stores algorithm state
6218 
6219 See also:
6220  LSFitResults
6221  LSFitCreateFG (fitting without weights)
6222  LSFitCreateWFGH (fitting using Hessian)
6223  LSFitCreateFGH (fitting using Hessian, without weights)
6224 
6225  -- ALGLIB --
6226  Copyright 17.08.2009 by Bochkanov Sergey
6227 *************************************************************************/
6228 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)
6229 {
6230  alglib_impl::ae_state _alglib_env_state;
6231  ae_int_t n;
6232  ae_int_t m;
6233  ae_int_t k;
6234  if( (x.rows()!=y.length()) || (x.rows()!=w.length()))
6235  throw ap_error("Error while calling 'lsfitcreatewfg': looks like one of arguments has wrong size");
6236  n = x.rows();
6237  m = x.cols();
6238  k = c.length();
6239  alglib_impl::ae_state_init(&_alglib_env_state);
6240  try
6241  {
6242  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);
6243 
6244  alglib_impl::ae_state_clear(&_alglib_env_state);
6245  return;
6246  }
6248  {
6249  throw ap_error(_alglib_env_state.error_msg);
6250  }
6251 }
6252 
6253 /*************************************************************************
6254 Nonlinear least squares fitting using gradient only, without individual
6255 weights.
6256 
6257 Nonlinear task min(F(c)) is solved, where
6258 
6259  F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
6260 
6261  * N is a number of points,
6262  * M is a dimension of a space points belong to,
6263  * K is a dimension of a space of parameters being fitted,
6264  * x is a set of N points, each of them is an M-dimensional vector,
6265  * c is a K-dimensional vector of parameters being fitted
6266 
6267 This subroutine uses only f(c,x[i]) and its gradient.
6268 
6269 INPUT PARAMETERS:
6270  X - array[0..N-1,0..M-1], points (one row = one point)
6271  Y - array[0..N-1], function values.
6272  C - array[0..K-1], initial approximation to the solution,
6273  N - number of points, N>1
6274  M - dimension of space
6275  K - number of parameters being fitted
6276  CheapFG - boolean flag, which is:
6277  * True if both function and gradient calculation complexity
6278  are less than O(M^2). An improved algorithm can
6279  be used which corresponds to FGJ scheme from
6280  MINLM unit.
6281  * False otherwise.
6282  Standard Jacibian-bases Levenberg-Marquardt algo
6283  will be used (FJ scheme).
6284 
6285 OUTPUT PARAMETERS:
6286  State - structure which stores algorithm state
6287 
6288  -- ALGLIB --
6289  Copyright 17.08.2009 by Bochkanov Sergey
6290 *************************************************************************/
6291 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)
6292 {
6293  alglib_impl::ae_state _alglib_env_state;
6294  alglib_impl::ae_state_init(&_alglib_env_state);
6295  try
6296  {
6297  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);
6298  alglib_impl::ae_state_clear(&_alglib_env_state);
6299  return;
6300  }
6302  {
6303  throw ap_error(_alglib_env_state.error_msg);
6304  }
6305 }
6306 
6307 /*************************************************************************
6308 Nonlinear least squares fitting using gradient only, without individual
6309 weights.
6310 
6311 Nonlinear task min(F(c)) is solved, where
6312 
6313  F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
6314 
6315  * N is a number of points,
6316  * M is a dimension of a space points belong to,
6317  * K is a dimension of a space of parameters being fitted,
6318  * x is a set of N points, each of them is an M-dimensional vector,
6319  * c is a K-dimensional vector of parameters being fitted
6320 
6321 This subroutine uses only f(c,x[i]) and its gradient.
6322 
6323 INPUT PARAMETERS:
6324  X - array[0..N-1,0..M-1], points (one row = one point)
6325  Y - array[0..N-1], function values.
6326  C - array[0..K-1], initial approximation to the solution,
6327  N - number of points, N>1
6328  M - dimension of space
6329  K - number of parameters being fitted
6330  CheapFG - boolean flag, which is:
6331  * True if both function and gradient calculation complexity
6332  are less than O(M^2). An improved algorithm can
6333  be used which corresponds to FGJ scheme from
6334  MINLM unit.
6335  * False otherwise.
6336  Standard Jacibian-bases Levenberg-Marquardt algo
6337  will be used (FJ scheme).
6338 
6339 OUTPUT PARAMETERS:
6340  State - structure which stores algorithm state
6341 
6342  -- ALGLIB --
6343  Copyright 17.08.2009 by Bochkanov Sergey
6344 *************************************************************************/
6345 void lsfitcreatefg(const real_2d_array &x, const real_1d_array &y, const real_1d_array &c, const bool cheapfg, lsfitstate &state)
6346 {
6347  alglib_impl::ae_state _alglib_env_state;
6348  ae_int_t n;
6349  ae_int_t m;
6350  ae_int_t k;
6351  if( (x.rows()!=y.length()))
6352  throw ap_error("Error while calling 'lsfitcreatefg': looks like one of arguments has wrong size");
6353  n = x.rows();
6354  m = x.cols();
6355  k = c.length();
6356  alglib_impl::ae_state_init(&_alglib_env_state);
6357  try
6358  {
6359  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);
6360 
6361  alglib_impl::ae_state_clear(&_alglib_env_state);
6362  return;
6363  }
6365  {
6366  throw ap_error(_alglib_env_state.error_msg);
6367  }
6368 }
6369 
6370 /*************************************************************************
6371 Weighted nonlinear least squares fitting using gradient/Hessian.
6372 
6373 Nonlinear task min(F(c)) is solved, where
6374 
6375  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
6376 
6377  * N is a number of points,
6378  * M is a dimension of a space points belong to,
6379  * K is a dimension of a space of parameters being fitted,
6380  * w is an N-dimensional vector of weight coefficients,
6381  * x is a set of N points, each of them is an M-dimensional vector,
6382  * c is a K-dimensional vector of parameters being fitted
6383 
6384 This subroutine uses f(c,x[i]), its gradient and its Hessian.
6385 
6386 INPUT PARAMETERS:
6387  X - array[0..N-1,0..M-1], points (one row = one point)
6388  Y - array[0..N-1], function values.
6389  W - weights, array[0..N-1]
6390  C - array[0..K-1], initial approximation to the solution,
6391  N - number of points, N>1
6392  M - dimension of space
6393  K - number of parameters being fitted
6394 
6395 OUTPUT PARAMETERS:
6396  State - structure which stores algorithm state
6397 
6398  -- ALGLIB --
6399  Copyright 17.08.2009 by Bochkanov Sergey
6400 *************************************************************************/
6401 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)
6402 {
6403  alglib_impl::ae_state _alglib_env_state;
6404  alglib_impl::ae_state_init(&_alglib_env_state);
6405  try
6406  {
6407  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);
6408  alglib_impl::ae_state_clear(&_alglib_env_state);
6409  return;
6410  }
6412  {
6413  throw ap_error(_alglib_env_state.error_msg);
6414  }
6415 }
6416 
6417 /*************************************************************************
6418 Weighted nonlinear least squares fitting using gradient/Hessian.
6419 
6420 Nonlinear task min(F(c)) is solved, where
6421 
6422  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
6423 
6424  * N is a number of points,
6425  * M is a dimension of a space points belong to,
6426  * K is a dimension of a space of parameters being fitted,
6427  * w is an N-dimensional vector of weight coefficients,
6428  * x is a set of N points, each of them is an M-dimensional vector,
6429  * c is a K-dimensional vector of parameters being fitted
6430 
6431 This subroutine uses f(c,x[i]), its gradient and its Hessian.
6432 
6433 INPUT PARAMETERS:
6434  X - array[0..N-1,0..M-1], points (one row = one point)
6435  Y - array[0..N-1], function values.
6436  W - weights, array[0..N-1]
6437  C - array[0..K-1], initial approximation to the solution,
6438  N - number of points, N>1
6439  M - dimension of space
6440  K - number of parameters being fitted
6441 
6442 OUTPUT PARAMETERS:
6443  State - structure which stores algorithm state
6444 
6445  -- ALGLIB --
6446  Copyright 17.08.2009 by Bochkanov Sergey
6447 *************************************************************************/
6449 {
6450  alglib_impl::ae_state _alglib_env_state;
6451  ae_int_t n;
6452  ae_int_t m;
6453  ae_int_t k;
6454  if( (x.rows()!=y.length()) || (x.rows()!=w.length()))
6455  throw ap_error("Error while calling 'lsfitcreatewfgh': looks like one of arguments has wrong size");
6456  n = x.rows();
6457  m = x.cols();
6458  k = c.length();
6459  alglib_impl::ae_state_init(&_alglib_env_state);
6460  try
6461  {
6462  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);
6463 
6464  alglib_impl::ae_state_clear(&_alglib_env_state);
6465  return;
6466  }
6468  {
6469  throw ap_error(_alglib_env_state.error_msg);
6470  }
6471 }
6472 
6473 /*************************************************************************
6474 Nonlinear least squares fitting using gradient/Hessian, without individial
6475 weights.
6476 
6477 Nonlinear task min(F(c)) is solved, where
6478 
6479  F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
6480 
6481  * N is a number of points,
6482  * M is a dimension of a space points belong to,
6483  * K is a dimension of a space of parameters being fitted,
6484  * x is a set of N points, each of them is an M-dimensional vector,
6485  * c is a K-dimensional vector of parameters being fitted
6486 
6487 This subroutine uses f(c,x[i]), its gradient and its Hessian.
6488 
6489 INPUT PARAMETERS:
6490  X - array[0..N-1,0..M-1], points (one row = one point)
6491  Y - array[0..N-1], function values.
6492  C - array[0..K-1], initial approximation to the solution,
6493  N - number of points, N>1
6494  M - dimension of space
6495  K - number of parameters being fitted
6496 
6497 OUTPUT PARAMETERS:
6498  State - structure which stores algorithm state
6499 
6500 
6501  -- ALGLIB --
6502  Copyright 17.08.2009 by Bochkanov Sergey
6503 *************************************************************************/
6504 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)
6505 {
6506  alglib_impl::ae_state _alglib_env_state;
6507  alglib_impl::ae_state_init(&_alglib_env_state);
6508  try
6509  {
6510  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);
6511  alglib_impl::ae_state_clear(&_alglib_env_state);
6512  return;
6513  }
6515  {
6516  throw ap_error(_alglib_env_state.error_msg);
6517  }
6518 }
6519 
6520 /*************************************************************************
6521 Nonlinear least squares fitting using gradient/Hessian, without individial
6522 weights.
6523 
6524 Nonlinear task min(F(c)) is solved, where
6525 
6526  F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
6527 
6528  * N is a number of points,
6529  * M is a dimension of a space points belong to,
6530  * K is a dimension of a space of parameters being fitted,
6531  * x is a set of N points, each of them is an M-dimensional vector,
6532  * c is a K-dimensional vector of parameters being fitted
6533 
6534 This subroutine uses f(c,x[i]), its gradient and its Hessian.
6535 
6536 INPUT PARAMETERS:
6537  X - array[0..N-1,0..M-1], points (one row = one point)
6538  Y - array[0..N-1], function values.
6539  C - array[0..K-1], initial approximation to the solution,
6540  N - number of points, N>1
6541  M - dimension of space
6542  K - number of parameters being fitted
6543 
6544 OUTPUT PARAMETERS:
6545  State - structure which stores algorithm state
6546 
6547 
6548  -- ALGLIB --
6549  Copyright 17.08.2009 by Bochkanov Sergey
6550 *************************************************************************/
6552 {
6553  alglib_impl::ae_state _alglib_env_state;
6554  ae_int_t n;
6555  ae_int_t m;
6556  ae_int_t k;
6557  if( (x.rows()!=y.length()))
6558  throw ap_error("Error while calling 'lsfitcreatefgh': looks like one of arguments has wrong size");
6559  n = x.rows();
6560  m = x.cols();
6561  k = c.length();
6562  alglib_impl::ae_state_init(&_alglib_env_state);
6563  try
6564  {
6565  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);
6566 
6567  alglib_impl::ae_state_clear(&_alglib_env_state);
6568  return;
6569  }
6571  {
6572  throw ap_error(_alglib_env_state.error_msg);
6573  }
6574 }
6575 
6576 /*************************************************************************
6577 Stopping conditions for nonlinear least squares fitting.
6578 
6579 INPUT PARAMETERS:
6580  State - structure which stores algorithm state
6581  EpsF - stopping criterion. Algorithm stops if
6582  |F(k+1)-F(k)| <= EpsF*max{|F(k)|, |F(k+1)|, 1}
6583  EpsX - >=0
6584  The subroutine finishes its work if on k+1-th iteration
6585  the condition |v|<=EpsX is fulfilled, where:
6586  * |.| means Euclidian norm
6587  * v - scaled step vector, v[i]=dx[i]/s[i]
6588  * dx - ste pvector, dx=X(k+1)-X(k)
6589  * s - scaling coefficients set by LSFitSetScale()
6590  MaxIts - maximum number of iterations. If MaxIts=0, the number of
6591  iterations is unlimited. Only Levenberg-Marquardt
6592  iterations are counted (L-BFGS/CG iterations are NOT
6593  counted because their cost is very low compared to that of
6594  LM).
6595 
6596 NOTE
6597 
6598 Passing EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
6599 stopping criterion selection (according to the scheme used by MINLM unit).
6600 
6601 
6602  -- ALGLIB --
6603  Copyright 17.08.2009 by Bochkanov Sergey
6604 *************************************************************************/
6605 void lsfitsetcond(const lsfitstate &state, const double epsf, const double epsx, const ae_int_t maxits)
6606 {
6607  alglib_impl::ae_state _alglib_env_state;
6608  alglib_impl::ae_state_init(&_alglib_env_state);
6609  try
6610  {
6611  alglib_impl::lsfitsetcond(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), epsf, epsx, maxits, &_alglib_env_state);
6612  alglib_impl::ae_state_clear(&_alglib_env_state);
6613  return;
6614  }
6616  {
6617  throw ap_error(_alglib_env_state.error_msg);
6618  }
6619 }
6620 
6621 /*************************************************************************
6622 This function sets maximum step length
6623 
6624 INPUT PARAMETERS:
6625  State - structure which stores algorithm state
6626  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
6627  want to limit step length.
6628 
6629 Use this subroutine when you optimize target function which contains exp()
6630 or other fast growing functions, and optimization algorithm makes too
6631 large steps which leads to overflow. This function allows us to reject
6632 steps that are too large (and therefore expose us to the possible
6633 overflow) without actually calculating function value at the x+stp*d.
6634 
6635 NOTE: non-zero StpMax leads to moderate performance degradation because
6636 intermediate step of preconditioned L-BFGS optimization is incompatible
6637 with limits on step size.
6638 
6639  -- ALGLIB --
6640  Copyright 02.04.2010 by Bochkanov Sergey
6641 *************************************************************************/
6642 void lsfitsetstpmax(const lsfitstate &state, const double stpmax)
6643 {
6644  alglib_impl::ae_state _alglib_env_state;
6645  alglib_impl::ae_state_init(&_alglib_env_state);
6646  try
6647  {
6648  alglib_impl::lsfitsetstpmax(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
6649  alglib_impl::ae_state_clear(&_alglib_env_state);
6650  return;
6651  }
6653  {
6654  throw ap_error(_alglib_env_state.error_msg);
6655  }
6656 }
6657 
6658 /*************************************************************************
6659 This function turns on/off reporting.
6660 
6661 INPUT PARAMETERS:
6662  State - structure which stores algorithm state
6663  NeedXRep- whether iteration reports are needed or not
6664 
6665 When reports are needed, State.C (current parameters) and State.F (current
6666 value of fitting function) are reported.
6667 
6668 
6669  -- ALGLIB --
6670  Copyright 15.08.2010 by Bochkanov Sergey
6671 *************************************************************************/
6672 void lsfitsetxrep(const lsfitstate &state, const bool needxrep)
6673 {
6674  alglib_impl::ae_state _alglib_env_state;
6675  alglib_impl::ae_state_init(&_alglib_env_state);
6676  try
6677  {
6678  alglib_impl::lsfitsetxrep(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
6679  alglib_impl::ae_state_clear(&_alglib_env_state);
6680  return;
6681  }
6683  {
6684  throw ap_error(_alglib_env_state.error_msg);
6685  }
6686 }
6687 
6688 /*************************************************************************
6689 This function sets scaling coefficients for underlying optimizer.
6690 
6691 ALGLIB optimizers use scaling matrices to test stopping conditions (step
6692 size and gradient are scaled before comparison with tolerances). Scale of
6693 the I-th variable is a translation invariant measure of:
6694 a) "how large" the variable is
6695 b) how large the step should be to make significant changes in the function
6696 
6697 Generally, scale is NOT considered to be a form of preconditioner. But LM
6698 optimizer is unique in that it uses scaling matrix both in the stopping
6699 condition tests and as Marquardt damping factor.
6700 
6701 Proper scaling is very important for the algorithm performance. It is less
6702 important for the quality of results, but still has some influence (it is
6703 easier to converge when variables are properly scaled, so premature
6704 stopping is possible when very badly scalled variables are combined with
6705 relaxed stopping conditions).
6706 
6707 INPUT PARAMETERS:
6708  State - structure stores algorithm state
6709  S - array[N], non-zero scaling coefficients
6710  S[i] may be negative, sign doesn't matter.
6711 
6712  -- ALGLIB --
6713  Copyright 14.01.2011 by Bochkanov Sergey
6714 *************************************************************************/
6715 void lsfitsetscale(const lsfitstate &state, const real_1d_array &s)
6716 {
6717  alglib_impl::ae_state _alglib_env_state;
6718  alglib_impl::ae_state_init(&_alglib_env_state);
6719  try
6720  {
6721  alglib_impl::lsfitsetscale(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
6722  alglib_impl::ae_state_clear(&_alglib_env_state);
6723  return;
6724  }
6726  {
6727  throw ap_error(_alglib_env_state.error_msg);
6728  }
6729 }
6730 
6731 /*************************************************************************
6732 This function sets boundary constraints for underlying optimizer
6733 
6734 Boundary constraints are inactive by default (after initial creation).
6735 They are preserved until explicitly turned off with another SetBC() call.
6736 
6737 INPUT PARAMETERS:
6738  State - structure stores algorithm state
6739  BndL - lower bounds, array[K].
6740  If some (all) variables are unbounded, you may specify
6741  very small number or -INF (latter is recommended because
6742  it will allow solver to use better algorithm).
6743  BndU - upper bounds, array[K].
6744  If some (all) variables are unbounded, you may specify
6745  very large number or +INF (latter is recommended because
6746  it will allow solver to use better algorithm).
6747 
6748 NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
6749 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
6750 
6751 NOTE 2: unlike other constrained optimization algorithms, this solver has
6752 following useful properties:
6753 * bound constraints are always satisfied exactly
6754 * function is evaluated only INSIDE area specified by bound constraints
6755 
6756  -- ALGLIB --
6757  Copyright 14.01.2011 by Bochkanov Sergey
6758 *************************************************************************/
6759 void lsfitsetbc(const lsfitstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
6760 {
6761  alglib_impl::ae_state _alglib_env_state;
6762  alglib_impl::ae_state_init(&_alglib_env_state);
6763  try
6764  {
6765  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);
6766  alglib_impl::ae_state_clear(&_alglib_env_state);
6767  return;
6768  }
6770  {
6771  throw ap_error(_alglib_env_state.error_msg);
6772  }
6773 }
6774 
6775 /*************************************************************************
6776 This function provides reverse communication interface
6777 Reverse communication interface is not documented or recommended to use.
6778 See below for functions which provide better documented API
6779 *************************************************************************/
6780 bool lsfititeration(const lsfitstate &state)
6781 {
6782  alglib_impl::ae_state _alglib_env_state;
6783  alglib_impl::ae_state_init(&_alglib_env_state);
6784  try
6785  {
6786  ae_bool result = alglib_impl::lsfititeration(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), &_alglib_env_state);
6787  alglib_impl::ae_state_clear(&_alglib_env_state);
6788  return *(reinterpret_cast<bool*>(&result));
6789  }
6791  {
6792  throw ap_error(_alglib_env_state.error_msg);
6793  }
6794 }
6795 
6796 
6797 void lsfitfit(lsfitstate &state,
6798  void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr),
6799  void (*rep)(const real_1d_array &c, double func, void *ptr),
6800  void *ptr)
6801 {
6802  alglib_impl::ae_state _alglib_env_state;
6803  if( func==NULL )
6804  throw ap_error("ALGLIB: error in 'lsfitfit()' (func is NULL)");
6805  alglib_impl::ae_state_init(&_alglib_env_state);
6806  try
6807  {
6808  while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) )
6809  {
6810  if( state.needf )
6811  {
6812  func(state.c, state.x, state.f, ptr);
6813  continue;
6814  }
6815  if( state.xupdated )
6816  {
6817  if( rep!=NULL )
6818  rep(state.c, state.f, ptr);
6819  continue;
6820  }
6821  throw ap_error("ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)");
6822  }
6823  alglib_impl::ae_state_clear(&_alglib_env_state);
6824  }
6826  {
6827  throw ap_error(_alglib_env_state.error_msg);
6828  }
6829 }
6830 
6831 
6832 void lsfitfit(lsfitstate &state,
6833  void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr),
6834  void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
6835  void (*rep)(const real_1d_array &c, double func, void *ptr),
6836  void *ptr)
6837 {
6838  alglib_impl::ae_state _alglib_env_state;
6839  if( func==NULL )
6840  throw ap_error("ALGLIB: error in 'lsfitfit()' (func is NULL)");
6841  if( grad==NULL )
6842  throw ap_error("ALGLIB: error in 'lsfitfit()' (grad is NULL)");
6843  alglib_impl::ae_state_init(&_alglib_env_state);
6844  try
6845  {
6846  while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) )
6847  {
6848  if( state.needf )
6849  {
6850  func(state.c, state.x, state.f, ptr);
6851  continue;
6852  }
6853  if( state.needfg )
6854  {
6855  grad(state.c, state.x, state.f, state.g, ptr);
6856  continue;
6857  }
6858  if( state.xupdated )
6859  {
6860  if( rep!=NULL )
6861  rep(state.c, state.f, ptr);
6862  continue;
6863  }
6864  throw ap_error("ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)");
6865  }
6866  alglib_impl::ae_state_clear(&_alglib_env_state);
6867  }
6869  {
6870  throw ap_error(_alglib_env_state.error_msg);
6871  }
6872 }
6873 
6874 
6875 void lsfitfit(lsfitstate &state,
6876  void (*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr),
6877  void (*grad)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
6878  void (*hess)(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr),
6879  void (*rep)(const real_1d_array &c, double func, void *ptr),
6880  void *ptr)
6881 {
6882  alglib_impl::ae_state _alglib_env_state;
6883  if( func==NULL )
6884  throw ap_error("ALGLIB: error in 'lsfitfit()' (func is NULL)");
6885  if( grad==NULL )
6886  throw ap_error("ALGLIB: error in 'lsfitfit()' (grad is NULL)");
6887  if( hess==NULL )
6888  throw ap_error("ALGLIB: error in 'lsfitfit()' (hess is NULL)");
6889  alglib_impl::ae_state_init(&_alglib_env_state);
6890  try
6891  {
6892  while( alglib_impl::lsfititeration(state.c_ptr(), &_alglib_env_state) )
6893  {
6894  if( state.needf )
6895  {
6896  func(state.c, state.x, state.f, ptr);
6897  continue;
6898  }
6899  if( state.needfg )
6900  {
6901  grad(state.c, state.x, state.f, state.g, ptr);
6902  continue;
6903  }
6904  if( state.needfgh )
6905  {
6906  hess(state.c, state.x, state.f, state.g, state.h, ptr);
6907  continue;
6908  }
6909  if( state.xupdated )
6910  {
6911  if( rep!=NULL )
6912  rep(state.c, state.f, ptr);
6913  continue;
6914  }
6915  throw ap_error("ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)");
6916  }
6917  alglib_impl::ae_state_clear(&_alglib_env_state);
6918  }
6920  {
6921  throw ap_error(_alglib_env_state.error_msg);
6922  }
6923 }
6924 
6925 
6926 
6927 /*************************************************************************
6928 Nonlinear least squares fitting results.
6929 
6930 Called after return from LSFitFit().
6931 
6932 INPUT PARAMETERS:
6933  State - algorithm state
6934 
6935 OUTPUT PARAMETERS:
6936  Info - completion code:
6937  * -7 gradient verification failed.
6938  See LSFitSetGradientCheck() for more information.
6939  * 1 relative function improvement is no more than
6940  EpsF.
6941  * 2 relative step is no more than EpsX.
6942  * 4 gradient norm is no more than EpsG
6943  * 5 MaxIts steps was taken
6944  * 7 stopping conditions are too stringent,
6945  further improvement is impossible
6946  C - array[0..K-1], solution
6947  Rep - optimization report. On success following fields are set:
6948  * R2 non-adjusted coefficient of determination
6949  (non-weighted)
6950  * RMSError rms error on the (X,Y).
6951  * AvgError average error on the (X,Y).
6952  * AvgRelError average relative error on the non-zero Y
6953  * MaxError maximum error
6954  NON-WEIGHTED ERRORS ARE CALCULATED
6955  * WRMSError weighted rms error on the (X,Y).
6956 
6957 ERRORS IN PARAMETERS
6958 
6959 This solver also calculates different kinds of errors in parameters and
6960 fills corresponding fields of report:
6961 * Rep.CovPar covariance matrix for parameters, array[K,K].
6962 * Rep.ErrPar errors in parameters, array[K],
6963  errpar = sqrt(diag(CovPar))
6964 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
6965  best-fit curve from "ideal" best-fit curve built with
6966  infinite number of samples, array[N].
6967  errcurve = sqrt(diag(J*CovPar*J')),
6968  where J is Jacobian matrix.
6969 * Rep.Noise vector of per-point estimates of noise, array[N]
6970 
6971 IMPORTANT: errors in parameters are calculated without taking into
6972  account boundary/linear constraints! Presence of constraints
6973  changes distribution of errors, but there is no easy way to
6974  account for constraints when you calculate covariance matrix.
6975 
6976 NOTE: noise in the data is estimated as follows:
6977  * for fitting without user-supplied weights all points are
6978  assumed to have same level of noise, which is estimated from
6979  the data
6980  * for fitting with user-supplied weights we assume that noise
6981  level in I-th point is inversely proportional to Ith weight.
6982  Coefficient of proportionality is estimated from the data.
6983 
6984 NOTE: we apply small amount of regularization when we invert squared
6985  Jacobian and calculate covariance matrix. It guarantees that
6986  algorithm won't divide by zero during inversion, but skews
6987  error estimates a bit (fractional error is about 10^-9).
6988 
6989  However, we believe that this difference is insignificant for
6990  all practical purposes except for the situation when you want
6991  to compare ALGLIB results with "reference" implementation up
6992  to the last significant digit.
6993 
6994 NOTE: covariance matrix is estimated using correction for degrees
6995  of freedom (covariances are divided by N-M instead of dividing
6996  by N).
6997 
6998  -- ALGLIB --
6999  Copyright 17.08.2009 by Bochkanov Sergey
7000 *************************************************************************/
7001 void lsfitresults(const lsfitstate &state, ae_int_t &info, real_1d_array &c, lsfitreport &rep)
7002 {
7003  alglib_impl::ae_state _alglib_env_state;
7004  alglib_impl::ae_state_init(&_alglib_env_state);
7005  try
7006  {
7007  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);
7008  alglib_impl::ae_state_clear(&_alglib_env_state);
7009  return;
7010  }
7012  {
7013  throw ap_error(_alglib_env_state.error_msg);
7014  }
7015 }
7016 
7017 /*************************************************************************
7018 This subroutine turns on verification of the user-supplied analytic
7019 gradient:
7020 * user calls this subroutine before fitting begins
7021 * LSFitFit() is called
7022 * prior to actual fitting, for each point in data set X_i and each
7023  component of parameters being fited C_j algorithm performs following
7024  steps:
7025  * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j],
7026  where C_j is j-th parameter and S[j] is a scale of j-th parameter
7027  * if needed, steps are bounded with respect to constraints on C[]
7028  * F(X_i|C) is evaluated at these trial points
7029  * we perform one more evaluation in the middle point of the interval
7030  * we build cubic model using function values and derivatives at trial
7031  points and we compare its prediction with actual value in the middle
7032  point
7033  * in case difference between prediction and actual value is higher than
7034  some predetermined threshold, algorithm stops with completion code -7;
7035  Rep.VarIdx is set to index of the parameter with incorrect derivative.
7036 * after verification is over, algorithm proceeds to the actual optimization.
7037 
7038 NOTE 1: verification needs N*K (points count * parameters count) gradient
7039  evaluations. It is very costly and you should use it only for low
7040  dimensional problems, when you want to be sure that you've
7041  correctly calculated analytic derivatives. You should not use it
7042  in the production code (unless you want to check derivatives
7043  provided by some third party).
7044 
7045 NOTE 2: you should carefully choose TestStep. Value which is too large
7046  (so large that function behaviour is significantly non-cubic) will
7047  lead to false alarms. You may use different step for different
7048  parameters by means of setting scale with LSFitSetScale().
7049 
7050 NOTE 3: this function may lead to false positives. In case it reports that
7051  I-th derivative was calculated incorrectly, you may decrease test
7052  step and try one more time - maybe your function changes too
7053  sharply and your step is too large for such rapidly chanding
7054  function.
7055 
7056 NOTE 4: this function works only for optimizers created with LSFitCreateWFG()
7057  or LSFitCreateFG() constructors.
7058 
7059 INPUT PARAMETERS:
7060  State - structure used to store algorithm state
7061  TestStep - verification step:
7062  * TestStep=0 turns verification off
7063  * TestStep>0 activates verification
7064 
7065  -- ALGLIB --
7066  Copyright 15.06.2012 by Bochkanov Sergey
7067 *************************************************************************/
7068 void lsfitsetgradientcheck(const lsfitstate &state, const double teststep)
7069 {
7070  alglib_impl::ae_state _alglib_env_state;
7071  alglib_impl::ae_state_init(&_alglib_env_state);
7072  try
7073  {
7074  alglib_impl::lsfitsetgradientcheck(const_cast<alglib_impl::lsfitstate*>(state.c_ptr()), teststep, &_alglib_env_state);
7075  alglib_impl::ae_state_clear(&_alglib_env_state);
7076  return;
7077  }
7079  {
7080  throw ap_error(_alglib_env_state.error_msg);
7081  }
7082 }
7083 
7084 /*************************************************************************
7085 Parametric spline inteprolant: 2-dimensional curve.
7086 
7087 You should not try to access its members directly - use PSpline2XXXXXXXX()
7088 functions instead.
7089 *************************************************************************/
7091 {
7093  if( p_struct==NULL )
7094  throw ap_error("ALGLIB: malloc error");
7096  throw ap_error("ALGLIB: malloc error");
7097 }
7098 
7100 {
7102  if( p_struct==NULL )
7103  throw ap_error("ALGLIB: malloc error");
7104  if( !alglib_impl::_pspline2interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline2interpolant*>(rhs.p_struct), NULL, ae_false) )
7105  throw ap_error("ALGLIB: malloc error");
7106 }
7107 
7109 {
7110  if( this==&rhs )
7111  return *this;
7113  if( !alglib_impl::_pspline2interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline2interpolant*>(rhs.p_struct), NULL, ae_false) )
7114  throw ap_error("ALGLIB: malloc error");
7115  return *this;
7116 }
7117 
7119 {
7121  ae_free(p_struct);
7122 }
7123 
7125 {
7126  return p_struct;
7127 }
7128 
7130 {
7131  return const_cast<alglib_impl::pspline2interpolant*>(p_struct);
7132 }
7134 {
7135 }
7136 
7138 {
7139 }
7140 
7142 {
7143  if( this==&rhs )
7144  return *this;
7146  return *this;
7147 }
7148 
7150 {
7151 }
7152 
7153 
7154 /*************************************************************************
7155 Parametric spline inteprolant: 3-dimensional curve.
7156 
7157 You should not try to access its members directly - use PSpline3XXXXXXXX()
7158 functions instead.
7159 *************************************************************************/
7161 {
7163  if( p_struct==NULL )
7164  throw ap_error("ALGLIB: malloc error");
7166  throw ap_error("ALGLIB: malloc error");
7167 }
7168 
7170 {
7172  if( p_struct==NULL )
7173  throw ap_error("ALGLIB: malloc error");
7174  if( !alglib_impl::_pspline3interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline3interpolant*>(rhs.p_struct), NULL, ae_false) )
7175  throw ap_error("ALGLIB: malloc error");
7176 }
7177 
7179 {
7180  if( this==&rhs )
7181  return *this;
7183  if( !alglib_impl::_pspline3interpolant_init_copy(p_struct, const_cast<alglib_impl::pspline3interpolant*>(rhs.p_struct), NULL, ae_false) )
7184  throw ap_error("ALGLIB: malloc error");
7185  return *this;
7186 }
7187 
7189 {
7191  ae_free(p_struct);
7192 }
7193 
7195 {
7196  return p_struct;
7197 }
7198 
7200 {
7201  return const_cast<alglib_impl::pspline3interpolant*>(p_struct);
7202 }
7204 {
7205 }
7206 
7208 {
7209 }
7210 
7212 {
7213  if( this==&rhs )
7214  return *this;
7216  return *this;
7217 }
7218 
7220 {
7221 }
7222 
7223 /*************************************************************************
7224 This function builds non-periodic 2-dimensional parametric spline which
7225 starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]).
7226 
7227 INPUT PARAMETERS:
7228  XY - points, array[0..N-1,0..1].
7229  XY[I,0:1] corresponds to the Ith point.
7230  Order of points is important!
7231  N - points count, N>=5 for Akima splines, N>=2 for other types of
7232  splines.
7233  ST - spline type:
7234  * 0 Akima spline
7235  * 1 parabolically terminated Catmull-Rom spline (Tension=0)
7236  * 2 parabolically terminated cubic spline
7237  PT - parameterization type:
7238  * 0 uniform
7239  * 1 chord length
7240  * 2 centripetal
7241 
7242 OUTPUT PARAMETERS:
7243  P - parametric spline interpolant
7244 
7245 
7246 NOTES:
7247 * this function assumes that there all consequent points are distinct.
7248  I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
7249  However, non-consequent points may coincide, i.e. we can have (x0,y0)=
7250  =(x2,y2).
7251 
7252  -- ALGLIB PROJECT --
7253  Copyright 28.05.2010 by Bochkanov Sergey
7254 *************************************************************************/
7255 void pspline2build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p)
7256 {
7257  alglib_impl::ae_state _alglib_env_state;
7258  alglib_impl::ae_state_init(&_alglib_env_state);
7259  try
7260  {
7261  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);
7262  alglib_impl::ae_state_clear(&_alglib_env_state);
7263  return;
7264  }
7266  {
7267  throw ap_error(_alglib_env_state.error_msg);
7268  }
7269 }
7270 
7271 /*************************************************************************
7272 This function builds non-periodic 3-dimensional parametric spline which
7273 starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]).
7274 
7275 Same as PSpline2Build() function, but for 3D, so we won't duplicate its
7276 description here.
7277 
7278  -- ALGLIB PROJECT --
7279  Copyright 28.05.2010 by Bochkanov Sergey
7280 *************************************************************************/
7281 void pspline3build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p)
7282 {
7283  alglib_impl::ae_state _alglib_env_state;
7284  alglib_impl::ae_state_init(&_alglib_env_state);
7285  try
7286  {
7287  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);
7288  alglib_impl::ae_state_clear(&_alglib_env_state);
7289  return;
7290  }
7292  {
7293  throw ap_error(_alglib_env_state.error_msg);
7294  }
7295 }
7296 
7297 /*************************************************************************
7298 This function builds periodic 2-dimensional parametric spline which
7299 starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then
7300 back to (X[0],Y[0]).
7301 
7302 INPUT PARAMETERS:
7303  XY - points, array[0..N-1,0..1].
7304  XY[I,0:1] corresponds to the Ith point.
7305  XY[N-1,0:1] must be different from XY[0,0:1].
7306  Order of points is important!
7307  N - points count, N>=3 for other types of splines.
7308  ST - spline type:
7309  * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions
7310  * 2 cubic spline with cyclic boundary conditions
7311  PT - parameterization type:
7312  * 0 uniform
7313  * 1 chord length
7314  * 2 centripetal
7315 
7316 OUTPUT PARAMETERS:
7317  P - parametric spline interpolant
7318 
7319 
7320 NOTES:
7321 * this function assumes that there all consequent points are distinct.
7322  I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
7323  However, non-consequent points may coincide, i.e. we can have (x0,y0)=
7324  =(x2,y2).
7325 * last point of sequence is NOT equal to the first point. You shouldn't
7326  make curve "explicitly periodic" by making them equal.
7327 
7328  -- ALGLIB PROJECT --
7329  Copyright 28.05.2010 by Bochkanov Sergey
7330 *************************************************************************/
7332 {
7333  alglib_impl::ae_state _alglib_env_state;
7334  alglib_impl::ae_state_init(&_alglib_env_state);
7335  try
7336  {
7337  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);
7338  alglib_impl::ae_state_clear(&_alglib_env_state);
7339  return;
7340  }
7342  {
7343  throw ap_error(_alglib_env_state.error_msg);
7344  }
7345 }
7346 
7347 /*************************************************************************
7348 This function builds periodic 3-dimensional parametric spline which
7349 starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1])
7350 and then back to (X[0],Y[0],Z[0]).
7351 
7352 Same as PSpline2Build() function, but for 3D, so we won't duplicate its
7353 description here.
7354 
7355  -- ALGLIB PROJECT --
7356  Copyright 28.05.2010 by Bochkanov Sergey
7357 *************************************************************************/
7359 {
7360  alglib_impl::ae_state _alglib_env_state;
7361  alglib_impl::ae_state_init(&_alglib_env_state);
7362  try
7363  {
7364  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);
7365  alglib_impl::ae_state_clear(&_alglib_env_state);
7366  return;
7367  }
7369  {
7370  throw ap_error(_alglib_env_state.error_msg);
7371  }
7372 }
7373 
7374 /*************************************************************************
7375 This function returns vector of parameter values correspoding to points.
7376 
7377 I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we
7378 have
7379  (X[0],Y[0]) = PSpline2Calc(P,U[0]),
7380  (X[1],Y[1]) = PSpline2Calc(P,U[1]),
7381  (X[2],Y[2]) = PSpline2Calc(P,U[2]),
7382  ...
7383 
7384 INPUT PARAMETERS:
7385  P - parametric spline interpolant
7386 
7387 OUTPUT PARAMETERS:
7388  N - array size
7389  T - array[0..N-1]
7390 
7391 
7392 NOTES:
7393 * for non-periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]=1
7394 * for periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]<1
7395 
7396  -- ALGLIB PROJECT --
7397  Copyright 28.05.2010 by Bochkanov Sergey
7398 *************************************************************************/
7400 {
7401  alglib_impl::ae_state _alglib_env_state;
7402  alglib_impl::ae_state_init(&_alglib_env_state);
7403  try
7404  {
7405  alglib_impl::pspline2parametervalues(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), &n, const_cast<alglib_impl::ae_vector*>(t.c_ptr()), &_alglib_env_state);
7406  alglib_impl::ae_state_clear(&_alglib_env_state);
7407  return;
7408  }
7410  {
7411  throw ap_error(_alglib_env_state.error_msg);
7412  }
7413 }
7414 
7415 /*************************************************************************
7416 This function returns vector of parameter values correspoding to points.
7417 
7418 Same as PSpline2ParameterValues(), but for 3D.
7419 
7420  -- ALGLIB PROJECT --
7421  Copyright 28.05.2010 by Bochkanov Sergey
7422 *************************************************************************/
7424 {
7425  alglib_impl::ae_state _alglib_env_state;
7426  alglib_impl::ae_state_init(&_alglib_env_state);
7427  try
7428  {
7429  alglib_impl::pspline3parametervalues(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), &n, const_cast<alglib_impl::ae_vector*>(t.c_ptr()), &_alglib_env_state);
7430  alglib_impl::ae_state_clear(&_alglib_env_state);
7431  return;
7432  }
7434  {
7435  throw ap_error(_alglib_env_state.error_msg);
7436  }
7437 }
7438 
7439 /*************************************************************************
7440 This function calculates the value of the parametric spline for a given
7441 value of parameter T
7442 
7443 INPUT PARAMETERS:
7444  P - parametric spline interpolant
7445  T - point:
7446  * T in [0,1] corresponds to interval spanned by points
7447  * for non-periodic splines T<0 (or T>1) correspond to parts of
7448  the curve before the first (after the last) point
7449  * for periodic splines T<0 (or T>1) are projected into [0,1]
7450  by making T=T-floor(T).
7451 
7452 OUTPUT PARAMETERS:
7453  X - X-position
7454  Y - Y-position
7455 
7456 
7457  -- ALGLIB PROJECT --
7458  Copyright 28.05.2010 by Bochkanov Sergey
7459 *************************************************************************/
7460 void pspline2calc(const pspline2interpolant &p, const double t, double &x, double &y)
7461 {
7462  alglib_impl::ae_state _alglib_env_state;
7463  alglib_impl::ae_state_init(&_alglib_env_state);
7464  try
7465  {
7466  alglib_impl::pspline2calc(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &y, &_alglib_env_state);
7467  alglib_impl::ae_state_clear(&_alglib_env_state);
7468  return;
7469  }
7471  {
7472  throw ap_error(_alglib_env_state.error_msg);
7473  }
7474 }
7475 
7476 /*************************************************************************
7477 This function calculates the value of the parametric spline for a given
7478 value of parameter T.
7479 
7480 INPUT PARAMETERS:
7481  P - parametric spline interpolant
7482  T - point:
7483  * T in [0,1] corresponds to interval spanned by points
7484  * for non-periodic splines T<0 (or T>1) correspond to parts of
7485  the curve before the first (after the last) point
7486  * for periodic splines T<0 (or T>1) are projected into [0,1]
7487  by making T=T-floor(T).
7488 
7489 OUTPUT PARAMETERS:
7490  X - X-position
7491  Y - Y-position
7492  Z - Z-position
7493 
7494 
7495  -- ALGLIB PROJECT --
7496  Copyright 28.05.2010 by Bochkanov Sergey
7497 *************************************************************************/
7498 void pspline3calc(const pspline3interpolant &p, const double t, double &x, double &y, double &z)
7499 {
7500  alglib_impl::ae_state _alglib_env_state;
7501  alglib_impl::ae_state_init(&_alglib_env_state);
7502  try
7503  {
7504  alglib_impl::pspline3calc(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &y, &z, &_alglib_env_state);
7505  alglib_impl::ae_state_clear(&_alglib_env_state);
7506  return;
7507  }
7509  {
7510  throw ap_error(_alglib_env_state.error_msg);
7511  }
7512 }
7513 
7514 /*************************************************************************
7515 This function calculates tangent vector for a given value of parameter T
7516 
7517 INPUT PARAMETERS:
7518  P - parametric spline interpolant
7519  T - point:
7520  * T in [0,1] corresponds to interval spanned by points
7521  * for non-periodic splines T<0 (or T>1) correspond to parts of
7522  the curve before the first (after the last) point
7523  * for periodic splines T<0 (or T>1) are projected into [0,1]
7524  by making T=T-floor(T).
7525 
7526 OUTPUT PARAMETERS:
7527  X - X-component of tangent vector (normalized)
7528  Y - Y-component of tangent vector (normalized)
7529 
7530 NOTE:
7531  X^2+Y^2 is either 1 (for non-zero tangent vector) or 0.
7532 
7533 
7534  -- ALGLIB PROJECT --
7535  Copyright 28.05.2010 by Bochkanov Sergey
7536 *************************************************************************/
7537 void pspline2tangent(const pspline2interpolant &p, const double t, double &x, double &y)
7538 {
7539  alglib_impl::ae_state _alglib_env_state;
7540  alglib_impl::ae_state_init(&_alglib_env_state);
7541  try
7542  {
7543  alglib_impl::pspline2tangent(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &y, &_alglib_env_state);
7544  alglib_impl::ae_state_clear(&_alglib_env_state);
7545  return;
7546  }
7548  {
7549  throw ap_error(_alglib_env_state.error_msg);
7550  }
7551 }
7552 
7553 /*************************************************************************
7554 This function calculates tangent vector for a given value of parameter T
7555 
7556 INPUT PARAMETERS:
7557  P - parametric spline interpolant
7558  T - point:
7559  * T in [0,1] corresponds to interval spanned by points
7560  * for non-periodic splines T<0 (or T>1) correspond to parts of
7561  the curve before the first (after the last) point
7562  * for periodic splines T<0 (or T>1) are projected into [0,1]
7563  by making T=T-floor(T).
7564 
7565 OUTPUT PARAMETERS:
7566  X - X-component of tangent vector (normalized)
7567  Y - Y-component of tangent vector (normalized)
7568  Z - Z-component of tangent vector (normalized)
7569 
7570 NOTE:
7571  X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0.
7572 
7573 
7574  -- ALGLIB PROJECT --
7575  Copyright 28.05.2010 by Bochkanov Sergey
7576 *************************************************************************/
7577 void pspline3tangent(const pspline3interpolant &p, const double t, double &x, double &y, double &z)
7578 {
7579  alglib_impl::ae_state _alglib_env_state;
7580  alglib_impl::ae_state_init(&_alglib_env_state);
7581  try
7582  {
7583  alglib_impl::pspline3tangent(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &y, &z, &_alglib_env_state);
7584  alglib_impl::ae_state_clear(&_alglib_env_state);
7585  return;
7586  }
7588  {
7589  throw ap_error(_alglib_env_state.error_msg);
7590  }
7591 }
7592 
7593 /*************************************************************************
7594 This function calculates derivative, i.e. it returns (dX/dT,dY/dT).
7595 
7596 INPUT PARAMETERS:
7597  P - parametric spline interpolant
7598  T - point:
7599  * T in [0,1] corresponds to interval spanned by points
7600  * for non-periodic splines T<0 (or T>1) correspond to parts of
7601  the curve before the first (after the last) point
7602  * for periodic splines T<0 (or T>1) are projected into [0,1]
7603  by making T=T-floor(T).
7604 
7605 OUTPUT PARAMETERS:
7606  X - X-value
7607  DX - X-derivative
7608  Y - Y-value
7609  DY - Y-derivative
7610 
7611 
7612  -- ALGLIB PROJECT --
7613  Copyright 28.05.2010 by Bochkanov Sergey
7614 *************************************************************************/
7615 void pspline2diff(const pspline2interpolant &p, const double t, double &x, double &dx, double &y, double &dy)
7616 {
7617  alglib_impl::ae_state _alglib_env_state;
7618  alglib_impl::ae_state_init(&_alglib_env_state);
7619  try
7620  {
7621  alglib_impl::pspline2diff(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &dx, &y, &dy, &_alglib_env_state);
7622  alglib_impl::ae_state_clear(&_alglib_env_state);
7623  return;
7624  }
7626  {
7627  throw ap_error(_alglib_env_state.error_msg);
7628  }
7629 }
7630 
7631 /*************************************************************************
7632 This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT).
7633 
7634 INPUT PARAMETERS:
7635  P - parametric spline interpolant
7636  T - point:
7637  * T in [0,1] corresponds to interval spanned by points
7638  * for non-periodic splines T<0 (or T>1) correspond to parts of
7639  the curve before the first (after the last) point
7640  * for periodic splines T<0 (or T>1) are projected into [0,1]
7641  by making T=T-floor(T).
7642 
7643 OUTPUT PARAMETERS:
7644  X - X-value
7645  DX - X-derivative
7646  Y - Y-value
7647  DY - Y-derivative
7648  Z - Z-value
7649  DZ - Z-derivative
7650 
7651 
7652  -- ALGLIB PROJECT --
7653  Copyright 28.05.2010 by Bochkanov Sergey
7654 *************************************************************************/
7655 void pspline3diff(const pspline3interpolant &p, const double t, double &x, double &dx, double &y, double &dy, double &z, double &dz)
7656 {
7657  alglib_impl::ae_state _alglib_env_state;
7658  alglib_impl::ae_state_init(&_alglib_env_state);
7659  try
7660  {
7661  alglib_impl::pspline3diff(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &dx, &y, &dy, &z, &dz, &_alglib_env_state);
7662  alglib_impl::ae_state_clear(&_alglib_env_state);
7663  return;
7664  }
7666  {
7667  throw ap_error(_alglib_env_state.error_msg);
7668  }
7669 }
7670 
7671 /*************************************************************************
7672 This function calculates first and second derivative with respect to T.
7673 
7674 INPUT PARAMETERS:
7675  P - parametric spline interpolant
7676  T - point:
7677  * T in [0,1] corresponds to interval spanned by points
7678  * for non-periodic splines T<0 (or T>1) correspond to parts of
7679  the curve before the first (after the last) point
7680  * for periodic splines T<0 (or T>1) are projected into [0,1]
7681  by making T=T-floor(T).
7682 
7683 OUTPUT PARAMETERS:
7684  X - X-value
7685  DX - derivative
7686  D2X - second derivative
7687  Y - Y-value
7688  DY - derivative
7689  D2Y - second derivative
7690 
7691 
7692  -- ALGLIB PROJECT --
7693  Copyright 28.05.2010 by Bochkanov Sergey
7694 *************************************************************************/
7695 void pspline2diff2(const pspline2interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y)
7696 {
7697  alglib_impl::ae_state _alglib_env_state;
7698  alglib_impl::ae_state_init(&_alglib_env_state);
7699  try
7700  {
7701  alglib_impl::pspline2diff2(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), t, &x, &dx, &d2x, &y, &dy, &d2y, &_alglib_env_state);
7702  alglib_impl::ae_state_clear(&_alglib_env_state);
7703  return;
7704  }
7706  {
7707  throw ap_error(_alglib_env_state.error_msg);
7708  }
7709 }
7710 
7711 /*************************************************************************
7712 This function calculates first and second derivative with respect to T.
7713 
7714 INPUT PARAMETERS:
7715  P - parametric spline interpolant
7716  T - point:
7717  * T in [0,1] corresponds to interval spanned by points
7718  * for non-periodic splines T<0 (or T>1) correspond to parts of
7719  the curve before the first (after the last) point
7720  * for periodic splines T<0 (or T>1) are projected into [0,1]
7721  by making T=T-floor(T).
7722 
7723 OUTPUT PARAMETERS:
7724  X - X-value
7725  DX - derivative
7726  D2X - second derivative
7727  Y - Y-value
7728  DY - derivative
7729  D2Y - second derivative
7730  Z - Z-value
7731  DZ - derivative
7732  D2Z - second derivative
7733 
7734 
7735  -- ALGLIB PROJECT --
7736  Copyright 28.05.2010 by Bochkanov Sergey
7737 *************************************************************************/
7738 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)
7739 {
7740  alglib_impl::ae_state _alglib_env_state;
7741  alglib_impl::ae_state_init(&_alglib_env_state);
7742  try
7743  {
7744  alglib_impl::pspline3diff2(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), t, &x, &dx, &d2x, &y, &dy, &d2y, &z, &dz, &d2z, &_alglib_env_state);
7745  alglib_impl::ae_state_clear(&_alglib_env_state);
7746  return;
7747  }
7749  {
7750  throw ap_error(_alglib_env_state.error_msg);
7751  }
7752 }
7753 
7754 /*************************************************************************
7755 This function calculates arc length, i.e. length of curve between t=a
7756 and t=b.
7757 
7758 INPUT PARAMETERS:
7759  P - parametric spline interpolant
7760  A,B - parameter values corresponding to arc ends:
7761  * B>A will result in positive length returned
7762  * B<A will result in negative length returned
7763 
7764 RESULT:
7765  length of arc starting at T=A and ending at T=B.
7766 
7767 
7768  -- ALGLIB PROJECT --
7769  Copyright 30.05.2010 by Bochkanov Sergey
7770 *************************************************************************/
7771 double pspline2arclength(const pspline2interpolant &p, const double a, const double b)
7772 {
7773  alglib_impl::ae_state _alglib_env_state;
7774  alglib_impl::ae_state_init(&_alglib_env_state);
7775  try
7776  {
7777  double result = alglib_impl::pspline2arclength(const_cast<alglib_impl::pspline2interpolant*>(p.c_ptr()), a, b, &_alglib_env_state);
7778  alglib_impl::ae_state_clear(&_alglib_env_state);
7779  return *(reinterpret_cast<double*>(&result));
7780  }
7782  {
7783  throw ap_error(_alglib_env_state.error_msg);
7784  }
7785 }
7786 
7787 /*************************************************************************
7788 This function calculates arc length, i.e. length of curve between t=a
7789 and t=b.
7790 
7791 INPUT PARAMETERS:
7792  P - parametric spline interpolant
7793  A,B - parameter values corresponding to arc ends:
7794  * B>A will result in positive length returned
7795  * B<A will result in negative length returned
7796 
7797 RESULT:
7798  length of arc starting at T=A and ending at T=B.
7799 
7800 
7801  -- ALGLIB PROJECT --
7802  Copyright 30.05.2010 by Bochkanov Sergey
7803 *************************************************************************/
7804 double pspline3arclength(const pspline3interpolant &p, const double a, const double b)
7805 {
7806  alglib_impl::ae_state _alglib_env_state;
7807  alglib_impl::ae_state_init(&_alglib_env_state);
7808  try
7809  {
7810  double result = alglib_impl::pspline3arclength(const_cast<alglib_impl::pspline3interpolant*>(p.c_ptr()), a, b, &_alglib_env_state);
7811  alglib_impl::ae_state_clear(&_alglib_env_state);
7812  return *(reinterpret_cast<double*>(&result));
7813  }
7815  {
7816  throw ap_error(_alglib_env_state.error_msg);
7817  }
7818 }
7819 
7820 /*************************************************************************
7821 RBF model.
7822 
7823 Never try to directly work with fields of this object - always use ALGLIB
7824 functions to use this object.
7825 *************************************************************************/
7827 {
7829  if( p_struct==NULL )
7830  throw ap_error("ALGLIB: malloc error");
7832  throw ap_error("ALGLIB: malloc error");
7833 }
7834 
7836 {
7838  if( p_struct==NULL )
7839  throw ap_error("ALGLIB: malloc error");
7840  if( !alglib_impl::_rbfmodel_init_copy(p_struct, const_cast<alglib_impl::rbfmodel*>(rhs.p_struct), NULL, ae_false) )
7841  throw ap_error("ALGLIB: malloc error");
7842 }
7843 
7845 {
7846  if( this==&rhs )
7847  return *this;
7849  if( !alglib_impl::_rbfmodel_init_copy(p_struct, const_cast<alglib_impl::rbfmodel*>(rhs.p_struct), NULL, ae_false) )
7850  throw ap_error("ALGLIB: malloc error");
7851  return *this;
7852 }
7853 
7855 {
7857  ae_free(p_struct);
7858 }
7859 
7861 {
7862  return p_struct;
7863 }
7864 
7866 {
7867  return const_cast<alglib_impl::rbfmodel*>(p_struct);
7868 }
7870 {
7871 }
7872 
7874 {
7875 }
7876 
7878 {
7879  if( this==&rhs )
7880  return *this;
7882  return *this;
7883 }
7884 
7886 {
7887 }
7888 
7889 
7890 /*************************************************************************
7891 RBF solution report:
7892 * TerminationType - termination type, positive values - success,
7893  non-positive - failure.
7894 *************************************************************************/
7896 {
7898  if( p_struct==NULL )
7899  throw ap_error("ALGLIB: malloc error");
7901  throw ap_error("ALGLIB: malloc error");
7902 }
7903 
7905 {
7907  if( p_struct==NULL )
7908  throw ap_error("ALGLIB: malloc error");
7909  if( !alglib_impl::_rbfreport_init_copy(p_struct, const_cast<alglib_impl::rbfreport*>(rhs.p_struct), NULL, ae_false) )
7910  throw ap_error("ALGLIB: malloc error");
7911 }
7912 
7914 {
7915  if( this==&rhs )
7916  return *this;
7918  if( !alglib_impl::_rbfreport_init_copy(p_struct, const_cast<alglib_impl::rbfreport*>(rhs.p_struct), NULL, ae_false) )
7919  throw ap_error("ALGLIB: malloc error");
7920  return *this;
7921 }
7922 
7924 {
7926  ae_free(p_struct);
7927 }
7928 
7930 {
7931  return p_struct;
7932 }
7933 
7935 {
7936  return const_cast<alglib_impl::rbfreport*>(p_struct);
7937 }
7938 rbfreport::rbfreport() : _rbfreport_owner() ,arows(p_struct->arows),acols(p_struct->acols),annz(p_struct->annz),iterationscount(p_struct->iterationscount),nmv(p_struct->nmv),terminationtype(p_struct->terminationtype)
7939 {
7940 }
7941 
7943 {
7944 }
7945 
7947 {
7948  if( this==&rhs )
7949  return *this;
7951  return *this;
7952 }
7953 
7955 {
7956 }
7957 
7958 
7959 /*************************************************************************
7960 This function serializes data structure to string.
7961 
7962 Important properties of s_out:
7963 * it contains alphanumeric characters, dots, underscores, minus signs
7964 * these symbols are grouped into words, which are separated by spaces
7965  and Windows-style (CR+LF) newlines
7966 * although serializer uses spaces and CR+LF as separators, you can
7967  replace any separator character by arbitrary combination of spaces,
7968  tabs, Windows or Unix newlines. It allows flexible reformatting of
7969  the string in case you want to include it into text or XML file.
7970  But you should not insert separators into the middle of the "words"
7971  nor you should change case of letters.
7972 * s_out can be freely moved between 32-bit and 64-bit systems, little
7973  and big endian machines, and so on. You can serialize structure on
7974  32-bit machine and unserialize it on 64-bit one (or vice versa), or
7975  serialize it on SPARC and unserialize on x86. You can also
7976  serialize it in C++ version of ALGLIB and unserialize in C# one,
7977  and vice versa.
7978 *************************************************************************/
7979 void rbfserialize(rbfmodel &obj, std::string &s_out)
7980 {
7981  alglib_impl::ae_state state;
7982  alglib_impl::ae_serializer serializer;
7983  alglib_impl::ae_int_t ssize;
7984 
7986  try
7987  {
7988  alglib_impl::ae_serializer_init(&serializer);
7990  alglib_impl::rbfalloc(&serializer, obj.c_ptr(), &state);
7991  ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer);
7992  s_out.clear();
7993  s_out.reserve((size_t)(ssize+1));
7994  alglib_impl::ae_serializer_sstart_str(&serializer, &s_out);
7995  alglib_impl::rbfserialize(&serializer, obj.c_ptr(), &state);
7996  alglib_impl::ae_serializer_stop(&serializer);
7997  if( s_out.length()>(size_t)ssize )
7998  throw ap_error("ALGLIB: serialization integrity error");
7999  alglib_impl::ae_serializer_clear(&serializer);
8001  }
8003  {
8004  throw ap_error(state.error_msg);
8005  }
8006 }
8007 /*************************************************************************
8008 This function unserializes data structure from string.
8009 *************************************************************************/
8010 void rbfunserialize(std::string &s_in, rbfmodel &obj)
8011 {
8012  alglib_impl::ae_state state;
8013  alglib_impl::ae_serializer serializer;
8014 
8016  try
8017  {
8018  alglib_impl::ae_serializer_init(&serializer);
8019  alglib_impl::ae_serializer_ustart_str(&serializer, &s_in);
8020  alglib_impl::rbfunserialize(&serializer, obj.c_ptr(), &state);
8021  alglib_impl::ae_serializer_stop(&serializer);
8022  alglib_impl::ae_serializer_clear(&serializer);
8024  }
8026  {
8027  throw ap_error(state.error_msg);
8028  }
8029 }
8030 
8031 /*************************************************************************
8032 This function creates RBF model for a scalar (NY=1) or vector (NY>1)
8033 function in a NX-dimensional space (NX=2 or NX=3).
8034 
8035 Newly created model is empty. It can be used for interpolation right after
8036 creation, but it just returns zeros. You have to add points to the model,
8037 tune interpolation settings, and then call model construction function
8038 RBFBuildModel() which will update model according to your specification.
8039 
8040 USAGE:
8041 1. User creates model with RBFCreate()
8042 2. User adds dataset with RBFSetPoints() (points do NOT have to be on a
8043  regular grid)
8044 3. (OPTIONAL) User chooses polynomial term by calling:
8045  * RBFLinTerm() to set linear term
8046  * RBFConstTerm() to set constant term
8047  * RBFZeroTerm() to set zero term
8048  By default, linear term is used.
8049 4. User chooses specific RBF algorithm to use: either QNN (RBFSetAlgoQNN)
8050  or ML (RBFSetAlgoMultiLayer).
8051 5. User calls RBFBuildModel() function which rebuilds model according to
8052  the specification
8053 6. User may call RBFCalc() to calculate model value at the specified point,
8054  RBFGridCalc() to calculate model values at the points of the regular
8055  grid. User may extract model coefficients with RBFUnpack() call.
8056 
8057 INPUT PARAMETERS:
8058  NX - dimension of the space, NX=2 or NX=3
8059  NY - function dimension, NY>=1
8060 
8061 OUTPUT PARAMETERS:
8062  S - RBF model (initially equals to zero)
8063 
8064 NOTE 1: memory requirements. RBF models require amount of memory which is
8065  proportional to the number of data points. Memory is allocated
8066  during model construction, but most of this memory is freed after
8067  model coefficients are calculated.
8068 
8069  Some approximate estimates for N centers with default settings are
8070  given below:
8071  * about 250*N*(sizeof(double)+2*sizeof(int)) bytes of memory is
8072  needed during model construction stage.
8073  * about 15*N*sizeof(double) bytes is needed after model is built.
8074  For example, for N=100000 we may need 0.6 GB of memory to build
8075  model, but just about 0.012 GB to store it.
8076 
8077  -- ALGLIB --
8078  Copyright 13.12.2011 by Bochkanov Sergey
8079 *************************************************************************/
8080 void rbfcreate(const ae_int_t nx, const ae_int_t ny, rbfmodel &s)
8081 {
8082  alglib_impl::ae_state _alglib_env_state;
8083  alglib_impl::ae_state_init(&_alglib_env_state);
8084  try
8085  {
8086  alglib_impl::rbfcreate(nx, ny, const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
8087  alglib_impl::ae_state_clear(&_alglib_env_state);
8088  return;
8089  }
8091  {
8092  throw ap_error(_alglib_env_state.error_msg);
8093  }
8094 }
8095 
8096 /*************************************************************************
8097 This function adds dataset.
8098 
8099 This function overrides results of the previous calls, i.e. multiple calls
8100 of this function will result in only the last set being added.
8101 
8102 INPUT PARAMETERS:
8103  S - RBF model, initialized by RBFCreate() call.
8104  XY - points, array[N,NX+NY]. One row corresponds to one point
8105  in the dataset. First NX elements are coordinates, next
8106  NY elements are function values. Array may be larger than
8107  specific, in this case only leading [N,NX+NY] elements
8108  will be used.
8109  N - number of points in the dataset
8110 
8111 After you've added dataset and (optionally) tuned algorithm settings you
8112 should call RBFBuildModel() in order to build a model for you.
8113 
8114 NOTE: this function has some serialization-related subtleties. We
8115  recommend you to study serialization examples from ALGLIB Reference
8116  Manual if you want to perform serialization of your models.
8117 
8118 
8119  -- ALGLIB --
8120  Copyright 13.12.2011 by Bochkanov Sergey
8121 *************************************************************************/
8122 void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const ae_int_t n)
8123 {
8124  alglib_impl::ae_state _alglib_env_state;
8125  alglib_impl::ae_state_init(&_alglib_env_state);
8126  try
8127  {
8128  alglib_impl::rbfsetpoints(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, &_alglib_env_state);
8129  alglib_impl::ae_state_clear(&_alglib_env_state);
8130  return;
8131  }
8133  {
8134  throw ap_error(_alglib_env_state.error_msg);
8135  }
8136 }
8137 
8138 /*************************************************************************
8139 This function adds dataset.
8140 
8141 This function overrides results of the previous calls, i.e. multiple calls
8142 of this function will result in only the last set being added.
8143 
8144 INPUT PARAMETERS:
8145  S - RBF model, initialized by RBFCreate() call.
8146  XY - points, array[N,NX+NY]. One row corresponds to one point
8147  in the dataset. First NX elements are coordinates, next
8148  NY elements are function values. Array may be larger than
8149  specific, in this case only leading [N,NX+NY] elements
8150  will be used.
8151  N - number of points in the dataset
8152 
8153 After you've added dataset and (optionally) tuned algorithm settings you
8154 should call RBFBuildModel() in order to build a model for you.
8155 
8156 NOTE: this function has some serialization-related subtleties. We
8157  recommend you to study serialization examples from ALGLIB Reference
8158  Manual if you want to perform serialization of your models.
8159 
8160 
8161  -- ALGLIB --
8162  Copyright 13.12.2011 by Bochkanov Sergey
8163 *************************************************************************/
8164 void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy)
8165 {
8166  alglib_impl::ae_state _alglib_env_state;
8167  ae_int_t n;
8168 
8169  n = xy.rows();
8170  alglib_impl::ae_state_init(&_alglib_env_state);
8171  try
8172  {
8173  alglib_impl::rbfsetpoints(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), n, &_alglib_env_state);
8174 
8175  alglib_impl::ae_state_clear(&_alglib_env_state);
8176  return;
8177  }
8179  {
8180  throw ap_error(_alglib_env_state.error_msg);
8181  }
8182 }
8183 
8184 /*************************************************************************
8185 This function sets RBF interpolation algorithm. ALGLIB supports several
8186 RBF algorithms with different properties.
8187 
8188 This algorithm is called RBF-QNN and it is good for point sets with
8189 following properties:
8190 a) all points are distinct
8191 b) all points are well separated.
8192 c) points distribution is approximately uniform. There is no "contour
8193  lines", clusters of points, or other small-scale structures.
8194 
8195 Algorithm description:
8196 1) interpolation centers are allocated to data points
8197 2) interpolation radii are calculated as distances to the nearest centers
8198  times Q coefficient (where Q is a value from [0.75,1.50]).
8199 3) after performing (2) radii are transformed in order to avoid situation
8200  when single outlier has very large radius and influences many points
8201  across all dataset. Transformation has following form:
8202  new_r[i] = min(r[i],Z*median(r[]))
8203  where r[i] is I-th radius, median() is a median radius across entire
8204  dataset, Z is user-specified value which controls amount of deviation
8205  from median radius.
8206 
8207 When (a) is violated, we will be unable to build RBF model. When (b) or
8208 (c) are violated, model will be built, but interpolation quality will be
8209 low. See http://www.alglib.net/interpolation/ for more information on this
8210 subject.
8211 
8212 This algorithm is used by default.
8213 
8214 Additional Q parameter controls smoothness properties of the RBF basis:
8215 * Q<0.75 will give perfectly conditioned basis, but terrible smoothness
8216  properties (RBF interpolant will have sharp peaks around function values)
8217 * Q around 1.0 gives good balance between smoothness and condition number
8218 * Q>1.5 will lead to badly conditioned systems and slow convergence of the
8219  underlying linear solver (although smoothness will be very good)
8220 * Q>2.0 will effectively make optimizer useless because it won't converge
8221  within reasonable amount of iterations. It is possible to set such large
8222  Q, but it is advised not to do so.
8223 
8224 INPUT PARAMETERS:
8225  S - RBF model, initialized by RBFCreate() call
8226  Q - Q parameter, Q>0, recommended value - 1.0
8227  Z - Z parameter, Z>0, recommended value - 5.0
8228 
8229 NOTE: this function has some serialization-related subtleties. We
8230  recommend you to study serialization examples from ALGLIB Reference
8231  Manual if you want to perform serialization of your models.
8232 
8233 
8234  -- ALGLIB --
8235  Copyright 13.12.2011 by Bochkanov Sergey
8236 *************************************************************************/
8237 void rbfsetalgoqnn(const rbfmodel &s, const double q, const double z)
8238 {
8239  alglib_impl::ae_state _alglib_env_state;
8240  alglib_impl::ae_state_init(&_alglib_env_state);
8241  try
8242  {
8243  alglib_impl::rbfsetalgoqnn(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), q, z, &_alglib_env_state);
8244  alglib_impl::ae_state_clear(&_alglib_env_state);
8245  return;
8246  }
8248  {
8249  throw ap_error(_alglib_env_state.error_msg);
8250  }
8251 }
8252 
8253 /*************************************************************************
8254 This function sets RBF interpolation algorithm. ALGLIB supports several
8255 RBF algorithms with different properties.
8256 
8257 This algorithm is called RBF-QNN and it is good for point sets with
8258 following properties:
8259 a) all points are distinct
8260 b) all points are well separated.
8261 c) points distribution is approximately uniform. There is no "contour
8262  lines", clusters of points, or other small-scale structures.
8263 
8264 Algorithm description:
8265 1) interpolation centers are allocated to data points
8266 2) interpolation radii are calculated as distances to the nearest centers
8267  times Q coefficient (where Q is a value from [0.75,1.50]).
8268 3) after performing (2) radii are transformed in order to avoid situation
8269  when single outlier has very large radius and influences many points
8270  across all dataset. Transformation has following form:
8271  new_r[i] = min(r[i],Z*median(r[]))
8272  where r[i] is I-th radius, median() is a median radius across entire
8273  dataset, Z is user-specified value which controls amount of deviation
8274  from median radius.
8275 
8276 When (a) is violated, we will be unable to build RBF model. When (b) or
8277 (c) are violated, model will be built, but interpolation quality will be
8278 low. See http://www.alglib.net/interpolation/ for more information on this
8279 subject.
8280 
8281 This algorithm is used by default.
8282 
8283 Additional Q parameter controls smoothness properties of the RBF basis:
8284 * Q<0.75 will give perfectly conditioned basis, but terrible smoothness
8285  properties (RBF interpolant will have sharp peaks around function values)
8286 * Q around 1.0 gives good balance between smoothness and condition number
8287 * Q>1.5 will lead to badly conditioned systems and slow convergence of the
8288  underlying linear solver (although smoothness will be very good)
8289 * Q>2.0 will effectively make optimizer useless because it won't converge
8290  within reasonable amount of iterations. It is possible to set such large
8291  Q, but it is advised not to do so.
8292 
8293 INPUT PARAMETERS:
8294  S - RBF model, initialized by RBFCreate() call
8295  Q - Q parameter, Q>0, recommended value - 1.0
8296  Z - Z parameter, Z>0, recommended value - 5.0
8297 
8298 NOTE: this function has some serialization-related subtleties. We
8299  recommend you to study serialization examples from ALGLIB Reference
8300  Manual if you want to perform serialization of your models.
8301 
8302 
8303  -- ALGLIB --
8304  Copyright 13.12.2011 by Bochkanov Sergey
8305 *************************************************************************/
8306 void rbfsetalgoqnn(const rbfmodel &s)
8307 {
8308  alglib_impl::ae_state _alglib_env_state;
8309  double q;
8310  double z;
8311 
8312  q = 1.0;
8313  z = 5.0;
8314  alglib_impl::ae_state_init(&_alglib_env_state);
8315  try
8316  {
8317  alglib_impl::rbfsetalgoqnn(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), q, z, &_alglib_env_state);
8318 
8319  alglib_impl::ae_state_clear(&_alglib_env_state);
8320  return;
8321  }
8323  {
8324  throw ap_error(_alglib_env_state.error_msg);
8325  }
8326 }
8327 
8328 /*************************************************************************
8329 This function sets RBF interpolation algorithm. ALGLIB supports several
8330 RBF algorithms with different properties.
8331 
8332 This algorithm is called RBF-ML. It builds multilayer RBF model, i.e.
8333 model with subsequently decreasing radii, which allows us to combine
8334 smoothness (due to large radii of the first layers) with exactness (due
8335 to small radii of the last layers) and fast convergence.
8336 
8337 Internally RBF-ML uses many different means of acceleration, from sparse
8338 matrices to KD-trees, which results in algorithm whose working time is
8339 roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a
8340 number of points, Density is an average density if points per unit of the
8341 interpolation space, RBase is an initial radius, NLayers is a number of
8342 layers.
8343 
8344 RBF-ML is good for following kinds of interpolation problems:
8345 1. "exact" problems (perfect fit) with well separated points
8346 2. least squares problems with arbitrary distribution of points (algorithm
8347  gives perfect fit where it is possible, and resorts to least squares
8348  fit in the hard areas).
8349 3. noisy problems where we want to apply some controlled amount of
8350  smoothing.
8351 
8352 INPUT PARAMETERS:
8353  S - RBF model, initialized by RBFCreate() call
8354  RBase - RBase parameter, RBase>0
8355  NLayers - NLayers parameter, NLayers>0, recommended value to start
8356  with - about 5.
8357  LambdaV - regularization value, can be useful when solving problem
8358  in the least squares sense. Optimal lambda is problem-
8359  dependent and require trial and error. In our experience,
8360  good lambda can be as large as 0.1, and you can use 0.001
8361  as initial guess.
8362  Default value - 0.01, which is used when LambdaV is not
8363  given. You can specify zero value, but it is not
8364  recommended to do so.
8365 
8366 TUNING ALGORITHM
8367 
8368 In order to use this algorithm you have to choose three parameters:
8369 * initial radius RBase
8370 * number of layers in the model NLayers
8371 * regularization coefficient LambdaV
8372 
8373 Initial radius is easy to choose - you can pick any number several times
8374 larger than the average distance between points. Algorithm won't break
8375 down if you choose radius which is too large (model construction time will
8376 increase, but model will be built correctly).
8377 
8378 Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
8379 by the last layer) will be smaller than the typical distance between
8380 points. In case model error is too large, you can increase number of
8381 layers. Having more layers will make model construction and evaluation
8382 proportionally slower, but it will allow you to have model which precisely
8383 fits your data. From the other side, if you want to suppress noise, you
8384 can DECREASE number of layers to make your model less flexible.
8385 
8386 Regularization coefficient LambdaV controls smoothness of the individual
8387 models built for each layer. We recommend you to use default value in case
8388 you don't want to tune this parameter, because having non-zero LambdaV
8389 accelerates and stabilizes internal iterative algorithm. In case you want
8390 to suppress noise you can use LambdaV as additional parameter (larger
8391 value = more smoothness) to tune.
8392 
8393 TYPICAL ERRORS
8394 
8395 1. Using initial radius which is too large. Memory requirements of the
8396  RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is
8397  an average density of points per unit of the interpolation space). In
8398  the extreme case of the very large RBase we will need O(N^2) units of
8399  memory - and many layers in order to decrease radius to some reasonably
8400  small value.
8401 
8402 2. Using too small number of layers - RBF models with large radius are not
8403  flexible enough to reproduce small variations in the target function.
8404  You need many layers with different radii, from large to small, in
8405  order to have good model.
8406 
8407 3. Using initial radius which is too small. You will get model with
8408  "holes" in the areas which are too far away from interpolation centers.
8409  However, algorithm will work correctly (and quickly) in this case.
8410 
8411 4. Using too many layers - you will get too large and too slow model. This
8412  model will perfectly reproduce your function, but maybe you will be
8413  able to achieve similar results with less layers (and less memory).
8414 
8415  -- ALGLIB --
8416  Copyright 02.03.2012 by Bochkanov Sergey
8417 *************************************************************************/
8418 void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdav)
8419 {
8420  alglib_impl::ae_state _alglib_env_state;
8421  alglib_impl::ae_state_init(&_alglib_env_state);
8422  try
8423  {
8424  alglib_impl::rbfsetalgomultilayer(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), rbase, nlayers, lambdav, &_alglib_env_state);
8425  alglib_impl::ae_state_clear(&_alglib_env_state);
8426  return;
8427  }
8429  {
8430  throw ap_error(_alglib_env_state.error_msg);
8431  }
8432 }
8433 
8434 /*************************************************************************
8435 This function sets RBF interpolation algorithm. ALGLIB supports several
8436 RBF algorithms with different properties.
8437 
8438 This algorithm is called RBF-ML. It builds multilayer RBF model, i.e.
8439 model with subsequently decreasing radii, which allows us to combine
8440 smoothness (due to large radii of the first layers) with exactness (due
8441 to small radii of the last layers) and fast convergence.
8442 
8443 Internally RBF-ML uses many different means of acceleration, from sparse
8444 matrices to KD-trees, which results in algorithm whose working time is
8445 roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a
8446 number of points, Density is an average density if points per unit of the
8447 interpolation space, RBase is an initial radius, NLayers is a number of
8448 layers.
8449 
8450 RBF-ML is good for following kinds of interpolation problems:
8451 1. "exact" problems (perfect fit) with well separated points
8452 2. least squares problems with arbitrary distribution of points (algorithm
8453  gives perfect fit where it is possible, and resorts to least squares
8454  fit in the hard areas).
8455 3. noisy problems where we want to apply some controlled amount of
8456  smoothing.
8457 
8458 INPUT PARAMETERS:
8459  S - RBF model, initialized by RBFCreate() call
8460  RBase - RBase parameter, RBase>0
8461  NLayers - NLayers parameter, NLayers>0, recommended value to start
8462  with - about 5.
8463  LambdaV - regularization value, can be useful when solving problem
8464  in the least squares sense. Optimal lambda is problem-
8465  dependent and require trial and error. In our experience,
8466  good lambda can be as large as 0.1, and you can use 0.001
8467  as initial guess.
8468  Default value - 0.01, which is used when LambdaV is not
8469  given. You can specify zero value, but it is not
8470  recommended to do so.
8471 
8472 TUNING ALGORITHM
8473 
8474 In order to use this algorithm you have to choose three parameters:
8475 * initial radius RBase
8476 * number of layers in the model NLayers
8477 * regularization coefficient LambdaV
8478 
8479 Initial radius is easy to choose - you can pick any number several times
8480 larger than the average distance between points. Algorithm won't break
8481 down if you choose radius which is too large (model construction time will
8482 increase, but model will be built correctly).
8483 
8484 Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
8485 by the last layer) will be smaller than the typical distance between
8486 points. In case model error is too large, you can increase number of
8487 layers. Having more layers will make model construction and evaluation
8488 proportionally slower, but it will allow you to have model which precisely
8489 fits your data. From the other side, if you want to suppress noise, you
8490 can DECREASE number of layers to make your model less flexible.
8491 
8492 Regularization coefficient LambdaV controls smoothness of the individual
8493 models built for each layer. We recommend you to use default value in case
8494 you don't want to tune this parameter, because having non-zero LambdaV
8495 accelerates and stabilizes internal iterative algorithm. In case you want
8496 to suppress noise you can use LambdaV as additional parameter (larger
8497 value = more smoothness) to tune.
8498 
8499 TYPICAL ERRORS
8500 
8501 1. Using initial radius which is too large. Memory requirements of the
8502  RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is
8503  an average density of points per unit of the interpolation space). In
8504  the extreme case of the very large RBase we will need O(N^2) units of
8505  memory - and many layers in order to decrease radius to some reasonably
8506  small value.
8507 
8508 2. Using too small number of layers - RBF models with large radius are not
8509  flexible enough to reproduce small variations in the target function.
8510  You need many layers with different radii, from large to small, in
8511  order to have good model.
8512 
8513 3. Using initial radius which is too small. You will get model with
8514  "holes" in the areas which are too far away from interpolation centers.
8515  However, algorithm will work correctly (and quickly) in this case.
8516 
8517 4. Using too many layers - you will get too large and too slow model. This
8518  model will perfectly reproduce your function, but maybe you will be
8519  able to achieve similar results with less layers (and less memory).
8520 
8521  -- ALGLIB --
8522  Copyright 02.03.2012 by Bochkanov Sergey
8523 *************************************************************************/
8524 void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers)
8525 {
8526  alglib_impl::ae_state _alglib_env_state;
8527  double lambdav;
8528 
8529  lambdav = 0.01;
8530  alglib_impl::ae_state_init(&_alglib_env_state);
8531  try
8532  {
8533  alglib_impl::rbfsetalgomultilayer(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), rbase, nlayers, lambdav, &_alglib_env_state);
8534 
8535  alglib_impl::ae_state_clear(&_alglib_env_state);
8536  return;
8537  }
8539  {
8540  throw ap_error(_alglib_env_state.error_msg);
8541  }
8542 }
8543 
8544 /*************************************************************************
8545 This function sets linear term (model is a sum of radial basis functions
8546 plus linear polynomial). This function won't have effect until next call
8547 to RBFBuildModel().
8548 
8549 INPUT PARAMETERS:
8550  S - RBF model, initialized by RBFCreate() call
8551 
8552 NOTE: this function has some serialization-related subtleties. We
8553  recommend you to study serialization examples from ALGLIB Reference
8554  Manual if you want to perform serialization of your models.
8555 
8556  -- ALGLIB --
8557  Copyright 13.12.2011 by Bochkanov Sergey
8558 *************************************************************************/
8559 void rbfsetlinterm(const rbfmodel &s)
8560 {
8561  alglib_impl::ae_state _alglib_env_state;
8562  alglib_impl::ae_state_init(&_alglib_env_state);
8563  try
8564  {
8565  alglib_impl::rbfsetlinterm(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
8566  alglib_impl::ae_state_clear(&_alglib_env_state);
8567  return;
8568  }
8570  {
8571  throw ap_error(_alglib_env_state.error_msg);
8572  }
8573 }
8574 
8575 /*************************************************************************
8576 This function sets constant term (model is a sum of radial basis functions
8577 plus constant). This function won't have effect until next call to
8578 RBFBuildModel().
8579 
8580 INPUT PARAMETERS:
8581  S - RBF model, initialized by RBFCreate() call
8582 
8583 NOTE: this function has some serialization-related subtleties. We
8584  recommend you to study serialization examples from ALGLIB Reference
8585  Manual if you want to perform serialization of your models.
8586 
8587  -- ALGLIB --
8588  Copyright 13.12.2011 by Bochkanov Sergey
8589 *************************************************************************/
8591 {
8592  alglib_impl::ae_state _alglib_env_state;
8593  alglib_impl::ae_state_init(&_alglib_env_state);
8594  try
8595  {
8596  alglib_impl::rbfsetconstterm(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
8597  alglib_impl::ae_state_clear(&_alglib_env_state);
8598  return;
8599  }
8601  {
8602  throw ap_error(_alglib_env_state.error_msg);
8603  }
8604 }
8605 
8606 /*************************************************************************
8607 This function sets zero term (model is a sum of radial basis functions
8608 without polynomial term). This function won't have effect until next call
8609 to RBFBuildModel().
8610 
8611 INPUT PARAMETERS:
8612  S - RBF model, initialized by RBFCreate() call
8613 
8614 NOTE: this function has some serialization-related subtleties. We
8615  recommend you to study serialization examples from ALGLIB Reference
8616  Manual if you want to perform serialization of your models.
8617 
8618  -- ALGLIB --
8619  Copyright 13.12.2011 by Bochkanov Sergey
8620 *************************************************************************/
8621 void rbfsetzeroterm(const rbfmodel &s)
8622 {
8623  alglib_impl::ae_state _alglib_env_state;
8624  alglib_impl::ae_state_init(&_alglib_env_state);
8625  try
8626  {
8627  alglib_impl::rbfsetzeroterm(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), &_alglib_env_state);
8628  alglib_impl::ae_state_clear(&_alglib_env_state);
8629  return;
8630  }
8632  {
8633  throw ap_error(_alglib_env_state.error_msg);
8634  }
8635 }
8636 
8637 /*************************************************************************
8638 This function builds RBF model and returns report (contains some
8639 information which can be used for evaluation of the algorithm properties).
8640 
8641 Call to this function modifies RBF model by calculating its centers/radii/
8642 weights and saving them into RBFModel structure. Initially RBFModel
8643 contain zero coefficients, but after call to this function we will have
8644 coefficients which were calculated in order to fit our dataset.
8645 
8646 After you called this function you can call RBFCalc(), RBFGridCalc() and
8647 other model calculation functions.
8648 
8649 INPUT PARAMETERS:
8650  S - RBF model, initialized by RBFCreate() call
8651  Rep - report:
8652  * Rep.TerminationType:
8653  * -5 - non-distinct basis function centers were detected,
8654  interpolation aborted
8655  * -4 - nonconvergence of the internal SVD solver
8656  * 1 - successful termination
8657  Fields are used for debugging purposes:
8658  * Rep.IterationsCount - iterations count of the LSQR solver
8659  * Rep.NMV - number of matrix-vector products
8660  * Rep.ARows - rows count for the system matrix
8661  * Rep.ACols - columns count for the system matrix
8662  * Rep.ANNZ - number of significantly non-zero elements
8663  (elements above some algorithm-determined threshold)
8664 
8665 NOTE: failure to build model will leave current state of the structure
8666 unchanged.
8667 
8668  -- ALGLIB --
8669  Copyright 13.12.2011 by Bochkanov Sergey
8670 *************************************************************************/
8671 void rbfbuildmodel(const rbfmodel &s, rbfreport &rep)
8672 {
8673  alglib_impl::ae_state _alglib_env_state;
8674  alglib_impl::ae_state_init(&_alglib_env_state);
8675  try
8676  {
8677  alglib_impl::rbfbuildmodel(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), const_cast<alglib_impl::rbfreport*>(rep.c_ptr()), &_alglib_env_state);
8678  alglib_impl::ae_state_clear(&_alglib_env_state);
8679  return;
8680  }
8682  {
8683  throw ap_error(_alglib_env_state.error_msg);
8684  }
8685 }
8686 
8687 /*************************************************************************
8688 This function calculates values of the RBF model in the given point.
8689 
8690 This function should be used when we have NY=1 (scalar function) and NX=2
8691 (2-dimensional space). If you have 3-dimensional space, use RBFCalc3(). If
8692 you have general situation (NX-dimensional space, NY-dimensional function)
8693 you should use general, less efficient implementation RBFCalc().
8694 
8695 If you want to calculate function values many times, consider using
8696 RBFGridCalc2(), which is far more efficient than many subsequent calls to
8697 RBFCalc2().
8698 
8699 This function returns 0.0 when:
8700 * model is not initialized
8701 * NX<>2
8702  *NY<>1
8703 
8704 INPUT PARAMETERS:
8705  S - RBF model
8706  X0 - first coordinate, finite number
8707  X1 - second coordinate, finite number
8708 
8709 RESULT:
8710  value of the model or 0.0 (as defined above)
8711 
8712  -- ALGLIB --
8713  Copyright 13.12.2011 by Bochkanov Sergey
8714 *************************************************************************/
8715 double rbfcalc2(const rbfmodel &s, const double x0, const double x1)
8716 {
8717  alglib_impl::ae_state _alglib_env_state;
8718  alglib_impl::ae_state_init(&_alglib_env_state);
8719  try
8720  {
8721  double result = alglib_impl::rbfcalc2(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), x0, x1, &_alglib_env_state);
8722  alglib_impl::ae_state_clear(&_alglib_env_state);
8723  return *(reinterpret_cast<double*>(&result));
8724  }
8726  {
8727  throw ap_error(_alglib_env_state.error_msg);
8728  }
8729 }
8730 
8731 /*************************************************************************
8732 This function calculates values of the RBF model in the given point.
8733 
8734 This function should be used when we have NY=1 (scalar function) and NX=3
8735 (3-dimensional space). If you have 2-dimensional space, use RBFCalc2(). If
8736 you have general situation (NX-dimensional space, NY-dimensional function)
8737 you should use general, less efficient implementation RBFCalc().
8738 
8739 This function returns 0.0 when:
8740 * model is not initialized
8741 * NX<>3
8742  *NY<>1
8743 
8744 INPUT PARAMETERS:
8745  S - RBF model
8746  X0 - first coordinate, finite number
8747  X1 - second coordinate, finite number
8748  X2 - third coordinate, finite number
8749 
8750 RESULT:
8751  value of the model or 0.0 (as defined above)
8752 
8753  -- ALGLIB --
8754  Copyright 13.12.2011 by Bochkanov Sergey
8755 *************************************************************************/
8756 double rbfcalc3(const rbfmodel &s, const double x0, const double x1, const double x2)
8757 {
8758  alglib_impl::ae_state _alglib_env_state;
8759  alglib_impl::ae_state_init(&_alglib_env_state);
8760  try
8761  {
8762  double result = alglib_impl::rbfcalc3(const_cast<alglib_impl::rbfmodel*>(s.c_ptr()), x0, x1, x2, &_alglib_env_state);
8763  alglib_impl::ae_state_clear(&_alglib_env_state);
8764  return *(reinterpret_cast<double*>(&result));
8765  }
8767  {
8768  throw ap_error(_alglib_env_state.error_msg);
8769  }
8770 }
8771 
8772 /*************************************************************************
8773 This function calculates values of the RBF model at the given point.
8774 
8775 This is general function which can be used for arbitrary NX (dimension of
8776 the space of arguments) and NY (dimension of the function itself). However
8777 when you have NY=1 you may find more convenient to use RBFCalc2() or
8778 RBFCalc3().
8779 
8780 This function returns 0.0 when model is not initialized.
8781 
8782 INPUT PARAMETERS:
8783  S - RBF model
8784  X - coordinates, array[NX].
8785  X may have more than NX elements, in this case only
8786  leading NX will be used.
8787 
8788 OUTPUT PARAMETERS:
8789  Y - function value, array[NY]. Y is out-parameter and
8790  reallocated after call to this function. In case you want
8791  to reuse previously allocated Y, you may use RBFCalcBuf(),
8792  which reallocates Y only when it is too small.
8793 
8794  -- ALGLIB --
8795  Copyright 13.12.2011 by Bochkanov Sergey
8796 *************************************************************************/
8797 void rbfcalc(const rbfmodel &s, const real_1d_array &x, real_1d_array &y)
8798 {
8799  alglib_impl::ae_state _alglib_env_state;
8800  alglib_impl::ae_state_init(&_alglib_env_state);
8801  try
8802  {
8803  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);
8804  alglib_impl::ae_state_clear(&_alglib_env_state);
8805  return;
8806  }
8808  {
8809  throw ap_error(_alglib_env_state.error_msg);
8810  }
8811 }
8812 
8813 /*************************************************************************
8814 This function calculates values of the RBF model at the given point.
8815 
8816 Same as RBFCalc(), but does not reallocate Y when in is large enough to
8817 store function values.
8818 
8819 INPUT PARAMETERS:
8820  S - RBF model
8821  X - coordinates, array[NX].
8822  X may have more than NX elements, in this case only
8823  leading NX will be used.
8824  Y - possibly preallocated array
8825 
8826 OUTPUT PARAMETERS:
8827  Y - function value, array[NY]. Y is not reallocated when it
8828  is larger than NY.
8829 
8830  -- ALGLIB --
8831  Copyright 13.12.2011 by Bochkanov Sergey
8832 *************************************************************************/
8834 {
8835  alglib_impl::ae_state _alglib_env_state;
8836  alglib_impl::ae_state_init(&_alglib_env_state);
8837  try
8838  {
8839  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);
8840  alglib_impl::ae_state_clear(&_alglib_env_state);
8841  return;
8842  }
8844  {
8845  throw ap_error(_alglib_env_state.error_msg);
8846  }
8847 }
8848 
8849 /*************************************************************************
8850 This function calculates values of the RBF model at the regular grid.
8851 
8852 Grid have N0*N1 points, with Point[I,J] = (X0[I], X1[J])
8853 
8854 This function returns 0.0 when:
8855 * model is not initialized
8856 * NX<>2
8857  *NY<>1
8858 
8859 INPUT PARAMETERS:
8860  S - RBF model
8861  X0 - array of grid nodes, first coordinates, array[N0]
8862  N0 - grid size (number of nodes) in the first dimension
8863  X1 - array of grid nodes, second coordinates, array[N1]
8864  N1 - grid size (number of nodes) in the second dimension
8865 
8866 OUTPUT PARAMETERS:
8867  Y - function values, array[N0,N1]. Y is out-variable and
8868  is reallocated by this function.
8869 
8870  -- ALGLIB --
8871  Copyright 13.12.2011 by Bochkanov Sergey
8872 *************************************************************************/
8873 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)
8874 {
8875  alglib_impl::ae_state _alglib_env_state;
8876  alglib_impl::ae_state_init(&_alglib_env_state);
8877  try
8878  {
8879  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);
8880  alglib_impl::ae_state_clear(&_alglib_env_state);
8881  return;
8882  }
8884  {
8885  throw ap_error(_alglib_env_state.error_msg);
8886  }
8887 }
8888 
8889 /*************************************************************************
8890 This function "unpacks" RBF model by extracting its coefficients.
8891 
8892 INPUT PARAMETERS:
8893  S - RBF model
8894 
8895 OUTPUT PARAMETERS:
8896  NX - dimensionality of argument
8897  NY - dimensionality of the target function
8898  XWR - model information, array[NC,NX+NY+1].
8899  One row of the array corresponds to one basis function:
8900  * first NX columns - coordinates of the center
8901  * next NY columns - weights, one per dimension of the
8902  function being modelled
8903  * last column - radius, same for all dimensions of
8904  the function being modelled
8905  NC - number of the centers
8906  V - polynomial term , array[NY,NX+1]. One row per one
8907  dimension of the function being modelled. First NX
8908  elements are linear coefficients, V[NX] is equal to the
8909  constant part.
8910 
8911  -- ALGLIB --
8912  Copyright 13.12.2011 by Bochkanov Sergey
8913 *************************************************************************/
8914 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)
8915 {
8916  alglib_impl::ae_state _alglib_env_state;
8917  alglib_impl::ae_state_init(&_alglib_env_state);
8918  try
8919  {
8920  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()), &_alglib_env_state);
8921  alglib_impl::ae_state_clear(&_alglib_env_state);
8922  return;
8923  }
8925  {
8926  throw ap_error(_alglib_env_state.error_msg);
8927  }
8928 }
8929 
8930 /*************************************************************************
8931 2-dimensional spline inteprolant
8932 *************************************************************************/
8934 {
8936  if( p_struct==NULL )
8937  throw ap_error("ALGLIB: malloc error");
8939  throw ap_error("ALGLIB: malloc error");
8940 }
8941 
8943 {
8945  if( p_struct==NULL )
8946  throw ap_error("ALGLIB: malloc error");
8947  if( !alglib_impl::_spline2dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline2dinterpolant*>(rhs.p_struct), NULL, ae_false) )
8948  throw ap_error("ALGLIB: malloc error");
8949 }
8950 
8952 {
8953  if( this==&rhs )
8954  return *this;
8956  if( !alglib_impl::_spline2dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline2dinterpolant*>(rhs.p_struct), NULL, ae_false) )
8957  throw ap_error("ALGLIB: malloc error");
8958  return *this;
8959 }
8960 
8962 {
8964  ae_free(p_struct);
8965 }
8966 
8968 {
8969  return p_struct;
8970 }
8971 
8973 {
8974  return const_cast<alglib_impl::spline2dinterpolant*>(p_struct);
8975 }
8977 {
8978 }
8979 
8981 {
8982 }
8983 
8985 {
8986  if( this==&rhs )
8987  return *this;
8989  return *this;
8990 }
8991 
8993 {
8994 }
8995 
8996 /*************************************************************************
8997 This subroutine calculates the value of the bilinear or bicubic spline at
8998 the given point X.
8999 
9000 Input parameters:
9001  C - coefficients table.
9002  Built by BuildBilinearSpline or BuildBicubicSpline.
9003  X, Y- point
9004 
9005 Result:
9006  S(x,y)
9007 
9008  -- ALGLIB PROJECT --
9009  Copyright 05.07.2007 by Bochkanov Sergey
9010 *************************************************************************/
9011 double spline2dcalc(const spline2dinterpolant &c, const double x, const double y)
9012 {
9013  alglib_impl::ae_state _alglib_env_state;
9014  alglib_impl::ae_state_init(&_alglib_env_state);
9015  try
9016  {
9017  double result = alglib_impl::spline2dcalc(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, &_alglib_env_state);
9018  alglib_impl::ae_state_clear(&_alglib_env_state);
9019  return *(reinterpret_cast<double*>(&result));
9020  }
9022  {
9023  throw ap_error(_alglib_env_state.error_msg);
9024  }
9025 }
9026 
9027 /*************************************************************************
9028 This subroutine calculates the value of the bilinear or bicubic spline at
9029 the given point X and its derivatives.
9030 
9031 Input parameters:
9032  C - spline interpolant.
9033  X, Y- point
9034 
9035 Output parameters:
9036  F - S(x,y)
9037  FX - dS(x,y)/dX
9038  FY - dS(x,y)/dY
9039  FXY - d2S(x,y)/dXdY
9040 
9041  -- ALGLIB PROJECT --
9042  Copyright 05.07.2007 by Bochkanov Sergey
9043 *************************************************************************/
9044 void spline2ddiff(const spline2dinterpolant &c, const double x, const double y, double &f, double &fx, double &fy, double &fxy)
9045 {
9046  alglib_impl::ae_state _alglib_env_state;
9047  alglib_impl::ae_state_init(&_alglib_env_state);
9048  try
9049  {
9050  alglib_impl::spline2ddiff(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), x, y, &f, &fx, &fy, &fxy, &_alglib_env_state);
9051  alglib_impl::ae_state_clear(&_alglib_env_state);
9052  return;
9053  }
9055  {
9056  throw ap_error(_alglib_env_state.error_msg);
9057  }
9058 }
9059 
9060 /*************************************************************************
9061 This subroutine performs linear transformation of the spline argument.
9062 
9063 Input parameters:
9064  C - spline interpolant
9065  AX, BX - transformation coefficients: x = A*t + B
9066  AY, BY - transformation coefficients: y = A*u + B
9067 Result:
9068  C - transformed spline
9069 
9070  -- ALGLIB PROJECT --
9071  Copyright 30.06.2007 by Bochkanov Sergey
9072 *************************************************************************/
9073 void spline2dlintransxy(const spline2dinterpolant &c, const double ax, const double bx, const double ay, const double by)
9074 {
9075  alglib_impl::ae_state _alglib_env_state;
9076  alglib_impl::ae_state_init(&_alglib_env_state);
9077  try
9078  {
9079  alglib_impl::spline2dlintransxy(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), ax, bx, ay, by, &_alglib_env_state);
9080  alglib_impl::ae_state_clear(&_alglib_env_state);
9081  return;
9082  }
9084  {
9085  throw ap_error(_alglib_env_state.error_msg);
9086  }
9087 }
9088 
9089 /*************************************************************************
9090 This subroutine performs linear transformation of the spline.
9091 
9092 Input parameters:
9093  C - spline interpolant.
9094  A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B
9095 
9096 Output parameters:
9097  C - transformed spline
9098 
9099  -- ALGLIB PROJECT --
9100  Copyright 30.06.2007 by Bochkanov Sergey
9101 *************************************************************************/
9102 void spline2dlintransf(const spline2dinterpolant &c, const double a, const double b)
9103 {
9104  alglib_impl::ae_state _alglib_env_state;
9105  alglib_impl::ae_state_init(&_alglib_env_state);
9106  try
9107  {
9108  alglib_impl::spline2dlintransf(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
9109  alglib_impl::ae_state_clear(&_alglib_env_state);
9110  return;
9111  }
9113  {
9114  throw ap_error(_alglib_env_state.error_msg);
9115  }
9116 }
9117 
9118 /*************************************************************************
9119 This subroutine makes the copy of the spline model.
9120 
9121 Input parameters:
9122  C - spline interpolant
9123 
9124 Output parameters:
9125  CC - spline copy
9126 
9127  -- ALGLIB PROJECT --
9128  Copyright 29.06.2007 by Bochkanov Sergey
9129 *************************************************************************/
9131 {
9132  alglib_impl::ae_state _alglib_env_state;
9133  alglib_impl::ae_state_init(&_alglib_env_state);
9134  try
9135  {
9136  alglib_impl::spline2dcopy(const_cast<alglib_impl::spline2dinterpolant*>(c.c_ptr()), const_cast<alglib_impl::spline2dinterpolant*>(cc.c_ptr()), &_alglib_env_state);
9137  alglib_impl::ae_state_clear(&_alglib_env_state);
9138  return;
9139  }
9141  {
9142  throw ap_error(_alglib_env_state.error_msg);
9143  }
9144 }
9145 
9146 /*************************************************************************
9147 Bicubic spline resampling
9148 
9149 Input parameters:
9150  A - function values at the old grid,
9151  array[0..OldHeight-1, 0..OldWidth-1]
9152  OldHeight - old grid height, OldHeight>1
9153  OldWidth - old grid width, OldWidth>1
9154  NewHeight - new grid height, NewHeight>1
9155  NewWidth - new grid width, NewWidth>1
9156 
9157 Output parameters:
9158  B - function values at the new grid,
9159  array[0..NewHeight-1, 0..NewWidth-1]
9160 
9161  -- ALGLIB routine --
9162  15 May, 2007
9163  Copyright by Bochkanov Sergey
9164 *************************************************************************/
9165 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)
9166 {
9167  alglib_impl::ae_state _alglib_env_state;
9168  alglib_impl::ae_state_init(&_alglib_env_state);
9169  try
9170  {
9171  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);
9172  alglib_impl::ae_state_clear(&_alglib_env_state);
9173  return;
9174  }
9176  {
9177  throw ap_error(_alglib_env_state.error_msg);
9178  }
9179 }
9180 
9181 /*************************************************************************
9182 Bilinear spline resampling
9183 
9184 Input parameters:
9185  A - function values at the old grid,
9186  array[0..OldHeight-1, 0..OldWidth-1]
9187  OldHeight - old grid height, OldHeight>1
9188  OldWidth - old grid width, OldWidth>1
9189  NewHeight - new grid height, NewHeight>1
9190  NewWidth - new grid width, NewWidth>1
9191 
9192 Output parameters:
9193  B - function values at the new grid,
9194  array[0..NewHeight-1, 0..NewWidth-1]
9195 
9196  -- ALGLIB routine --
9197  09.07.2007
9198  Copyright by Bochkanov Sergey
9199 *************************************************************************/
9200 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)
9201 {
9202  alglib_impl::ae_state _alglib_env_state;
9203  alglib_impl::ae_state_init(&_alglib_env_state);
9204  try
9205  {
9206  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);
9207  alglib_impl::ae_state_clear(&_alglib_env_state);
9208  return;
9209  }
9211  {
9212  throw ap_error(_alglib_env_state.error_msg);
9213  }
9214 }
9215 
9216 /*************************************************************************
9217 This subroutine builds bilinear vector-valued spline.
9218 
9219 Input parameters:
9220  X - spline abscissas, array[0..N-1]
9221  Y - spline ordinates, array[0..M-1]
9222  F - function values, array[0..M*N*D-1]:
9223  * first D elements store D values at (X[0],Y[0])
9224  * next D elements store D values at (X[1],Y[0])
9225  * general form - D function values at (X[i],Y[j]) are stored
9226  at F[D*(J*N+I)...D*(J*N+I)+D-1].
9227  M,N - grid size, M>=2, N>=2
9228  D - vector dimension, D>=1
9229 
9230 Output parameters:
9231  C - spline interpolant
9232 
9233  -- ALGLIB PROJECT --
9234  Copyright 16.04.2012 by Bochkanov Sergey
9235 *************************************************************************/
9237 {
9238  alglib_impl::ae_state _alglib_env_state;
9239  alglib_impl::ae_state_init(&_alglib_env_state);
9240  try
9241  {
9242  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);
9243  alglib_impl::ae_state_clear(&_alglib_env_state);
9244  return;
9245  }
9247  {
9248  throw ap_error(_alglib_env_state.error_msg);
9249  }
9250 }
9251 
9252 /*************************************************************************
9253 This subroutine builds bicubic vector-valued spline.
9254 
9255 Input parameters:
9256  X - spline abscissas, array[0..N-1]
9257  Y - spline ordinates, array[0..M-1]
9258  F - function values, array[0..M*N*D-1]:
9259  * first D elements store D values at (X[0],Y[0])
9260  * next D elements store D values at (X[1],Y[0])
9261  * general form - D function values at (X[i],Y[j]) are stored
9262  at F[D*(J*N+I)...D*(J*N+I)+D-1].
9263  M,N - grid size, M>=2, N>=2
9264  D - vector dimension, D>=1
9265 
9266 Output parameters:
9267  C - spline interpolant
9268 
9269  -- ALGLIB PROJECT --
9270  Copyright 16.04.2012 by Bochkanov Sergey
9271 *************************************************************************/
9273 {
9274  alglib_impl::ae_state _alglib_env_state;
9275  alglib_impl::ae_state_init(&_alglib_env_state);
9276  try
9277  {
9278  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);
9279  alglib_impl::ae_state_clear(&_alglib_env_state);
9280  return;
9281  }
9283  {
9284  throw ap_error(_alglib_env_state.error_msg);
9285  }
9286 }
9287 
9288 /*************************************************************************
9289 This subroutine calculates bilinear or bicubic vector-valued spline at the
9290 given point (X,Y).
9291 
9292 INPUT PARAMETERS:
9293  C - spline interpolant.
9294  X, Y- point
9295  F - output buffer, possibly preallocated array. In case array size
9296  is large enough to store result, it is not reallocated. Array
9297  which is too short will be reallocated
9298 
9299 OUTPUT PARAMETERS:
9300  F - array[D] (or larger) which stores function values
9301 
9302  -- ALGLIB PROJECT --
9303  Copyright 16.04.2012 by Bochkanov Sergey
9304 *************************************************************************/
9305 void spline2dcalcvbuf(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f)
9306 {
9307  alglib_impl::ae_state _alglib_env_state;
9308  alglib_impl::ae_state_init(&_alglib_env_state);
9309  try
9310  {
9311  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);
9312  alglib_impl::ae_state_clear(&_alglib_env_state);
9313  return;
9314  }
9316  {
9317  throw ap_error(_alglib_env_state.error_msg);
9318  }
9319 }
9320 
9321 /*************************************************************************
9322 This subroutine calculates bilinear or bicubic vector-valued spline at the
9323 given point (X,Y).
9324 
9325 INPUT PARAMETERS:
9326  C - spline interpolant.
9327  X, Y- point
9328 
9329 OUTPUT PARAMETERS:
9330  F - array[D] which stores function values. F is out-parameter and
9331  it is reallocated after call to this function. In case you
9332  want to reuse previously allocated F, you may use
9333  Spline2DCalcVBuf(), which reallocates F only when it is too
9334  small.
9335 
9336  -- ALGLIB PROJECT --
9337  Copyright 16.04.2012 by Bochkanov Sergey
9338 *************************************************************************/
9339 void spline2dcalcv(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f)
9340 {
9341  alglib_impl::ae_state _alglib_env_state;
9342  alglib_impl::ae_state_init(&_alglib_env_state);
9343  try
9344  {
9345  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);
9346  alglib_impl::ae_state_clear(&_alglib_env_state);
9347  return;
9348  }
9350  {
9351  throw ap_error(_alglib_env_state.error_msg);
9352  }
9353 }
9354 
9355 /*************************************************************************
9356 This subroutine unpacks two-dimensional spline into the coefficients table
9357 
9358 Input parameters:
9359  C - spline interpolant.
9360 
9361 Result:
9362  M, N- grid size (x-axis and y-axis)
9363  D - number of components
9364  Tbl - coefficients table, unpacked format,
9365  D - components: [0..(N-1)*(M-1)*D-1, 0..19].
9366  For T=0..D-1 (component index), I = 0...N-2 (x index),
9367  J=0..M-2 (y index):
9368  K := T + I*D + J*D*(N-1)
9369 
9370  K-th row stores decomposition for T-th component of the
9371  vector-valued function
9372 
9373  Tbl[K,0] = X[i]
9374  Tbl[K,1] = X[i+1]
9375  Tbl[K,2] = Y[j]
9376  Tbl[K,3] = Y[j+1]
9377  Tbl[K,4] = C00
9378  Tbl[K,5] = C01
9379  Tbl[K,6] = C02
9380  Tbl[K,7] = C03
9381  Tbl[K,8] = C10
9382  Tbl[K,9] = C11
9383  ...
9384  Tbl[K,19] = C33
9385  On each grid square spline is equals to:
9386  S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3)
9387  t = x-x[j]
9388  u = y-y[i]
9389 
9390  -- ALGLIB PROJECT --
9391  Copyright 16.04.2012 by Bochkanov Sergey
9392 *************************************************************************/
9394 {
9395  alglib_impl::ae_state _alglib_env_state;
9396  alglib_impl::ae_state_init(&_alglib_env_state);
9397  try
9398  {
9399  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);
9400  alglib_impl::ae_state_clear(&_alglib_env_state);
9401  return;
9402  }
9404  {
9405  throw ap_error(_alglib_env_state.error_msg);
9406  }
9407 }
9408 
9409 /*************************************************************************
9410 This subroutine was deprecated in ALGLIB 3.6.0
9411 
9412 We recommend you to switch to Spline2DBuildBilinearV(), which is more
9413 flexible and accepts its arguments in more convenient order.
9414 
9415  -- ALGLIB PROJECT --
9416  Copyright 05.07.2007 by Bochkanov Sergey
9417 *************************************************************************/
9419 {
9420  alglib_impl::ae_state _alglib_env_state;
9421  alglib_impl::ae_state_init(&_alglib_env_state);
9422  try
9423  {
9424  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);
9425  alglib_impl::ae_state_clear(&_alglib_env_state);
9426  return;
9427  }
9429  {
9430  throw ap_error(_alglib_env_state.error_msg);
9431  }
9432 }
9433 
9434 /*************************************************************************
9435 This subroutine was deprecated in ALGLIB 3.6.0
9436 
9437 We recommend you to switch to Spline2DBuildBicubicV(), which is more
9438 flexible and accepts its arguments in more convenient order.
9439 
9440  -- ALGLIB PROJECT --
9441  Copyright 05.07.2007 by Bochkanov Sergey
9442 *************************************************************************/
9444 {
9445  alglib_impl::ae_state _alglib_env_state;
9446  alglib_impl::ae_state_init(&_alglib_env_state);
9447  try
9448  {
9449  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);
9450  alglib_impl::ae_state_clear(&_alglib_env_state);
9451  return;
9452  }
9454  {
9455  throw ap_error(_alglib_env_state.error_msg);
9456  }
9457 }
9458 
9459 /*************************************************************************
9460 This subroutine was deprecated in ALGLIB 3.6.0
9461 
9462 We recommend you to switch to Spline2DUnpackV(), which is more flexible
9463 and accepts its arguments in more convenient order.
9464 
9465  -- ALGLIB PROJECT --
9466  Copyright 29.06.2007 by Bochkanov Sergey
9467 *************************************************************************/
9469 {
9470  alglib_impl::ae_state _alglib_env_state;
9471  alglib_impl::ae_state_init(&_alglib_env_state);
9472  try
9473  {
9474  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);
9475  alglib_impl::ae_state_clear(&_alglib_env_state);
9476  return;
9477  }
9479  {
9480  throw ap_error(_alglib_env_state.error_msg);
9481  }
9482 }
9483 
9484 /*************************************************************************
9485 3-dimensional spline inteprolant
9486 *************************************************************************/
9488 {
9490  if( p_struct==NULL )
9491  throw ap_error("ALGLIB: malloc error");
9493  throw ap_error("ALGLIB: malloc error");
9494 }
9495 
9497 {
9499  if( p_struct==NULL )
9500  throw ap_error("ALGLIB: malloc error");
9501  if( !alglib_impl::_spline3dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline3dinterpolant*>(rhs.p_struct), NULL, ae_false) )
9502  throw ap_error("ALGLIB: malloc error");
9503 }
9504 
9506 {
9507  if( this==&rhs )
9508  return *this;
9510  if( !alglib_impl::_spline3dinterpolant_init_copy(p_struct, const_cast<alglib_impl::spline3dinterpolant*>(rhs.p_struct), NULL, ae_false) )
9511  throw ap_error("ALGLIB: malloc error");
9512  return *this;
9513 }
9514 
9516 {
9518  ae_free(p_struct);
9519 }
9520 
9522 {
9523  return p_struct;
9524 }
9525 
9527 {
9528  return const_cast<alglib_impl::spline3dinterpolant*>(p_struct);
9529 }
9531 {
9532 }
9533 
9535 {
9536 }
9537 
9539 {
9540  if( this==&rhs )
9541  return *this;
9543  return *this;
9544 }
9545 
9547 {
9548 }
9549 
9550 /*************************************************************************
9551 This subroutine calculates the value of the trilinear or tricubic spline at
9552 the given point (X,Y,Z).
9553 
9554 INPUT PARAMETERS:
9555  C - coefficients table.
9556  Built by BuildBilinearSpline or BuildBicubicSpline.
9557  X, Y,
9558  Z - point
9559 
9560 Result:
9561  S(x,y,z)
9562 
9563  -- ALGLIB PROJECT --
9564  Copyright 26.04.2012 by Bochkanov Sergey
9565 *************************************************************************/
9566 double spline3dcalc(const spline3dinterpolant &c, const double x, const double y, const double z)
9567 {
9568  alglib_impl::ae_state _alglib_env_state;
9569  alglib_impl::ae_state_init(&_alglib_env_state);
9570  try
9571  {
9572  double result = alglib_impl::spline3dcalc(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), x, y, z, &_alglib_env_state);
9573  alglib_impl::ae_state_clear(&_alglib_env_state);
9574  return *(reinterpret_cast<double*>(&result));
9575  }
9577  {
9578  throw ap_error(_alglib_env_state.error_msg);
9579  }
9580 }
9581 
9582 /*************************************************************************
9583 This subroutine performs linear transformation of the spline argument.
9584 
9585 INPUT PARAMETERS:
9586  C - spline interpolant
9587  AX, BX - transformation coefficients: x = A*u + B
9588  AY, BY - transformation coefficients: y = A*v + B
9589  AZ, BZ - transformation coefficients: z = A*w + B
9590 
9591 OUTPUT PARAMETERS:
9592  C - transformed spline
9593 
9594  -- ALGLIB PROJECT --
9595  Copyright 26.04.2012 by Bochkanov Sergey
9596 *************************************************************************/
9597 void spline3dlintransxyz(const spline3dinterpolant &c, const double ax, const double bx, const double ay, const double by, const double az, const double bz)
9598 {
9599  alglib_impl::ae_state _alglib_env_state;
9600  alglib_impl::ae_state_init(&_alglib_env_state);
9601  try
9602  {
9603  alglib_impl::spline3dlintransxyz(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), ax, bx, ay, by, az, bz, &_alglib_env_state);
9604  alglib_impl::ae_state_clear(&_alglib_env_state);
9605  return;
9606  }
9608  {
9609  throw ap_error(_alglib_env_state.error_msg);
9610  }
9611 }
9612 
9613 /*************************************************************************
9614 This subroutine performs linear transformation of the spline.
9615 
9616 INPUT PARAMETERS:
9617  C - spline interpolant.
9618  A, B- transformation coefficients: S2(x,y) = A*S(x,y,z) + B
9619 
9620 OUTPUT PARAMETERS:
9621  C - transformed spline
9622 
9623  -- ALGLIB PROJECT --
9624  Copyright 26.04.2012 by Bochkanov Sergey
9625 *************************************************************************/
9626 void spline3dlintransf(const spline3dinterpolant &c, const double a, const double b)
9627 {
9628  alglib_impl::ae_state _alglib_env_state;
9629  alglib_impl::ae_state_init(&_alglib_env_state);
9630  try
9631  {
9632  alglib_impl::spline3dlintransf(const_cast<alglib_impl::spline3dinterpolant*>(c.c_ptr()), a, b, &_alglib_env_state);
9633  alglib_impl::ae_state_clear(&_alglib_env_state);
9634  return;
9635  }
9637  {
9638  throw ap_error(_alglib_env_state.error_msg);
9639  }
9640 }
9641 
9642 /*************************************************************************
9643 Trilinear spline resampling
9644 
9645 INPUT PARAMETERS:
9646  A - array[0..OldXCount*OldYCount*OldZCount-1], function
9647  values at the old grid, :
9648  A[0] x=0,y=0,z=0
9649  A[1] x=1,y=0,z=0
9650  A[..] ...
9651  A[..] x=oldxcount-1,y=0,z=0
9652  A[..] x=0,y=1,z=0
9653  A[..] ...
9654  ...
9655  OldZCount - old Z-count, OldZCount>1
9656  OldYCount - old Y-count, OldYCount>1
9657  OldXCount - old X-count, OldXCount>1
9658  NewZCount - new Z-count, NewZCount>1
9659  NewYCount - new Y-count, NewYCount>1
9660  NewXCount - new X-count, NewXCount>1
9661 
9662 OUTPUT PARAMETERS:
9663  B - array[0..NewXCount*NewYCount*NewZCount-1], function
9664  values at the new grid:
9665  B[0] x=0,y=0,z=0
9666  B[1] x=1,y=0,z=0
9667  B[..] ...
9668  B[..] x=newxcount-1,y=0,z=0
9669  B[..] x=0,y=1,z=0
9670  B[..] ...
9671  ...
9672 
9673  -- ALGLIB routine --
9674  26.04.2012
9675  Copyright by Bochkanov Sergey
9676 *************************************************************************/
9677 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)
9678 {
9679  alglib_impl::ae_state _alglib_env_state;
9680  alglib_impl::ae_state_init(&_alglib_env_state);
9681  try
9682  {
9683  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);
9684  alglib_impl::ae_state_clear(&_alglib_env_state);
9685  return;
9686  }
9688  {
9689  throw ap_error(_alglib_env_state.error_msg);
9690  }
9691 }
9692 
9693 /*************************************************************************
9694 This subroutine builds trilinear vector-valued spline.
9695 
9696 INPUT PARAMETERS:
9697  X - spline abscissas, array[0..N-1]
9698  Y - spline ordinates, array[0..M-1]
9699  Z - spline applicates, array[0..L-1]
9700  F - function values, array[0..M*N*L*D-1]:
9701  * first D elements store D values at (X[0],Y[0],Z[0])
9702  * next D elements store D values at (X[1],Y[0],Z[0])
9703  * next D elements store D values at (X[2],Y[0],Z[0])
9704  * ...
9705  * next D elements store D values at (X[0],Y[1],Z[0])
9706  * next D elements store D values at (X[1],Y[1],Z[0])
9707  * next D elements store D values at (X[2],Y[1],Z[0])
9708  * ...
9709  * next D elements store D values at (X[0],Y[0],Z[1])
9710  * next D elements store D values at (X[1],Y[0],Z[1])
9711  * next D elements store D values at (X[2],Y[0],Z[1])
9712  * ...
9713  * general form - D function values at (X[i],Y[j]) are stored
9714  at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1].
9715  M,N,
9716  L - grid size, M>=2, N>=2, L>=2
9717  D - vector dimension, D>=1
9718 
9719 OUTPUT PARAMETERS:
9720  C - spline interpolant
9721 
9722  -- ALGLIB PROJECT --
9723  Copyright 26.04.2012 by Bochkanov Sergey
9724 *************************************************************************/
9726 {
9727  alglib_impl::ae_state _alglib_env_state;
9728  alglib_impl::ae_state_init(&_alglib_env_state);
9729  try
9730  {
9731  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);
9732  alglib_impl::ae_state_clear(&_alglib_env_state);
9733  return;
9734  }
9736  {
9737  throw ap_error(_alglib_env_state.error_msg);
9738  }
9739 }
9740 
9741 /*************************************************************************
9742 This subroutine calculates bilinear or bicubic vector-valued spline at the
9743 given point (X,Y,Z).
9744 
9745 INPUT PARAMETERS:
9746  C - spline interpolant.
9747  X, Y,
9748  Z - point
9749  F - output buffer, possibly preallocated array. In case array size
9750  is large enough to store result, it is not reallocated. Array
9751  which is too short will be reallocated
9752 
9753 OUTPUT PARAMETERS:
9754  F - array[D] (or larger) which stores function values
9755 
9756  -- ALGLIB PROJECT --
9757  Copyright 26.04.2012 by Bochkanov Sergey
9758 *************************************************************************/
9759 void spline3dcalcvbuf(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f)
9760 {
9761  alglib_impl::ae_state _alglib_env_state;
9762  alglib_impl::ae_state_init(&_alglib_env_state);
9763  try
9764  {
9765  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);
9766  alglib_impl::ae_state_clear(&_alglib_env_state);
9767  return;
9768  }
9770  {
9771  throw ap_error(_alglib_env_state.error_msg);
9772  }
9773 }
9774 
9775 /*************************************************************************
9776 This subroutine calculates trilinear or tricubic vector-valued spline at the
9777 given point (X,Y,Z).
9778 
9779 INPUT PARAMETERS:
9780  C - spline interpolant.
9781  X, Y,
9782  Z - point
9783 
9784 OUTPUT PARAMETERS:
9785  F - array[D] which stores function values. F is out-parameter and
9786  it is reallocated after call to this function. In case you
9787  want to reuse previously allocated F, you may use
9788  Spline2DCalcVBuf(), which reallocates F only when it is too
9789  small.
9790 
9791  -- ALGLIB PROJECT --
9792  Copyright 26.04.2012 by Bochkanov Sergey
9793 *************************************************************************/
9794 void spline3dcalcv(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f)
9795 {
9796  alglib_impl::ae_state _alglib_env_state;
9797  alglib_impl::ae_state_init(&_alglib_env_state);
9798  try
9799  {
9800  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);
9801  alglib_impl::ae_state_clear(&_alglib_env_state);
9802  return;
9803  }
9805  {
9806  throw ap_error(_alglib_env_state.error_msg);
9807  }
9808 }
9809 
9810 /*************************************************************************
9811 This subroutine unpacks tri-dimensional spline into the coefficients table
9812 
9813 INPUT PARAMETERS:
9814  C - spline interpolant.
9815 
9816 Result:
9817  N - grid size (X)
9818  M - grid size (Y)
9819  L - grid size (Z)
9820  D - number of components
9821  SType- spline type. Currently, only one spline type is supported:
9822  trilinear spline, as indicated by SType=1.
9823  Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13].
9824  For T=0..D-1 (component index), I = 0...N-2 (x index),
9825  J=0..M-2 (y index), K=0..L-2 (z index):
9826  Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1),
9827 
9828  Q-th row stores decomposition for T-th component of the
9829  vector-valued function
9830 
9831  Tbl[Q,0] = X[i]
9832  Tbl[Q,1] = X[i+1]
9833  Tbl[Q,2] = Y[j]
9834  Tbl[Q,3] = Y[j+1]
9835  Tbl[Q,4] = Z[k]
9836  Tbl[Q,5] = Z[k+1]
9837 
9838  Tbl[Q,6] = C000
9839  Tbl[Q,7] = C100
9840  Tbl[Q,8] = C010
9841  Tbl[Q,9] = C110
9842  Tbl[Q,10]= C001
9843  Tbl[Q,11]= C101
9844  Tbl[Q,12]= C011
9845  Tbl[Q,13]= C111
9846  On each grid square spline is equals to:
9847  S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1)
9848  t = x-x[j]
9849  u = y-y[i]
9850  v = z-z[k]
9851 
9852  NOTE: format of Tbl is given for SType=1. Future versions of
9853  ALGLIB can use different formats for different values of
9854  SType.
9855 
9856  -- ALGLIB PROJECT --
9857  Copyright 26.04.2012 by Bochkanov Sergey
9858 *************************************************************************/
9860 {
9861  alglib_impl::ae_state _alglib_env_state;
9862  alglib_impl::ae_state_init(&_alglib_env_state);
9863  try
9864  {
9865  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);
9866  alglib_impl::ae_state_clear(&_alglib_env_state);
9867  return;
9868  }
9870  {
9871  throw ap_error(_alglib_env_state.error_msg);
9872  }
9873 }
9874 }
9875 
9877 //
9878 // THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
9879 //
9881 namespace alglib_impl
9882 {
9883 static double idwint_idwqfactor = 1.5;
9884 static ae_int_t idwint_idwkmin = 5;
9885 static double idwint_idwcalcq(idwinterpolant* z,
9886  /* Real */ ae_vector* x,
9887  ae_int_t k,
9888  ae_state *_state);
9889 static void idwint_idwinit1(ae_int_t n,
9890  ae_int_t nx,
9891  ae_int_t d,
9892  ae_int_t nq,
9893  ae_int_t nw,
9894  idwinterpolant* z,
9895  ae_state *_state);
9896 static void idwint_idwinternalsolver(/* Real */ ae_vector* y,
9897  /* Real */ ae_vector* w,
9898  /* Real */ ae_matrix* fmatrix,
9899  /* Real */ ae_vector* temp,
9900  ae_int_t n,
9901  ae_int_t m,
9902  ae_int_t* info,
9903  /* Real */ ae_vector* x,
9904  double* taskrcond,
9905  ae_state *_state);
9906 
9907 
9908 static void ratint_barycentricnormalize(barycentricinterpolant* b,
9909  ae_state *_state);
9910 
9911 
9912 
9913 
9914 static void spline1d_spline1dgriddiffcubicinternal(/* Real */ ae_vector* x,
9915  /* Real */ ae_vector* y,
9916  ae_int_t n,
9917  ae_int_t boundltype,
9918  double boundl,
9919  ae_int_t boundrtype,
9920  double boundr,
9921  /* Real */ ae_vector* d,
9922  /* Real */ ae_vector* a1,
9923  /* Real */ ae_vector* a2,
9924  /* Real */ ae_vector* a3,
9925  /* Real */ ae_vector* b,
9926  /* Real */ ae_vector* dt,
9927  ae_state *_state);
9928 static void spline1d_heapsortpoints(/* Real */ ae_vector* x,
9929  /* Real */ ae_vector* y,
9930  ae_int_t n,
9931  ae_state *_state);
9932 static void spline1d_heapsortppoints(/* Real */ ae_vector* x,
9933  /* Real */ ae_vector* y,
9934  /* Integer */ ae_vector* p,
9935  ae_int_t n,
9936  ae_state *_state);
9937 static void spline1d_solvetridiagonal(/* Real */ ae_vector* a,
9938  /* Real */ ae_vector* b,
9939  /* Real */ ae_vector* c,
9940  /* Real */ ae_vector* d,
9941  ae_int_t n,
9942  /* Real */ ae_vector* x,
9943  ae_state *_state);
9944 static void spline1d_solvecyclictridiagonal(/* Real */ ae_vector* a,
9945  /* Real */ ae_vector* b,
9946  /* Real */ ae_vector* c,
9947  /* Real */ ae_vector* d,
9948  ae_int_t n,
9949  /* Real */ ae_vector* x,
9950  ae_state *_state);
9951 static double spline1d_diffthreepoint(double t,
9952  double x0,
9953  double f0,
9954  double x1,
9955  double f1,
9956  double x2,
9957  double f2,
9958  ae_state *_state);
9959 static void spline1d_hermitecalc(double p0,
9960  double m0,
9961  double p1,
9962  double m1,
9963  double t,
9964  double* s,
9965  double* ds,
9966  ae_state *_state);
9967 static double spline1d_rescaleval(double a0,
9968  double b0,
9969  double a1,
9970  double b1,
9971  double t,
9972  ae_state *_state);
9973 
9974 
9975 static void lsfit_spline1dfitinternal(ae_int_t st,
9976  /* Real */ ae_vector* x,
9977  /* Real */ ae_vector* y,
9978  /* Real */ ae_vector* w,
9979  ae_int_t n,
9980  /* Real */ ae_vector* xc,
9981  /* Real */ ae_vector* yc,
9982  /* Integer */ ae_vector* dc,
9983  ae_int_t k,
9984  ae_int_t m,
9985  ae_int_t* info,
9987  spline1dfitreport* rep,
9988  ae_state *_state);
9989 static void lsfit_lsfitlinearinternal(/* Real */ ae_vector* y,
9990  /* Real */ ae_vector* w,
9991  /* Real */ ae_matrix* fmatrix,
9992  ae_int_t n,
9993  ae_int_t m,
9994  ae_int_t* info,
9995  /* Real */ ae_vector* c,
9996  lsfitreport* rep,
9997  ae_state *_state);
9998 static void lsfit_lsfitclearrequestfields(lsfitstate* state,
9999  ae_state *_state);
10000 static void lsfit_barycentriccalcbasis(barycentricinterpolant* b,
10001  double t,
10002  /* Real */ ae_vector* y,
10003  ae_state *_state);
10004 static void lsfit_internalchebyshevfit(/* Real */ ae_vector* x,
10005  /* Real */ ae_vector* y,
10006  /* Real */ ae_vector* w,
10007  ae_int_t n,
10008  /* Real */ ae_vector* xc,
10009  /* Real */ ae_vector* yc,
10010  /* Integer */ ae_vector* dc,
10011  ae_int_t k,
10012  ae_int_t m,
10013  ae_int_t* info,
10014  /* Real */ ae_vector* c,
10015  lsfitreport* rep,
10016  ae_state *_state);
10017 static void lsfit_barycentricfitwcfixedd(/* Real */ ae_vector* x,
10018  /* Real */ ae_vector* y,
10019  /* Real */ ae_vector* w,
10020  ae_int_t n,
10021  /* Real */ ae_vector* xc,
10022  /* Real */ ae_vector* yc,
10023  /* Integer */ ae_vector* dc,
10024  ae_int_t k,
10025  ae_int_t m,
10026  ae_int_t d,
10027  ae_int_t* info,
10029  barycentricfitreport* rep,
10030  ae_state *_state);
10031 static void lsfit_clearreport(lsfitreport* rep, ae_state *_state);
10032 static void lsfit_estimateerrors(/* Real */ ae_matrix* f1,
10033  /* Real */ ae_vector* f0,
10034  /* Real */ ae_vector* y,
10035  /* Real */ ae_vector* w,
10036  /* Real */ ae_vector* x,
10037  /* Real */ ae_vector* s,
10038  ae_int_t n,
10039  ae_int_t k,
10040  lsfitreport* rep,
10041  /* Real */ ae_matrix* z,
10042  ae_int_t zkind,
10043  ae_state *_state);
10044 
10045 
10046 static void pspline_pspline2par(/* Real */ ae_matrix* xy,
10047  ae_int_t n,
10048  ae_int_t pt,
10049  /* Real */ ae_vector* p,
10050  ae_state *_state);
10051 static void pspline_pspline3par(/* Real */ ae_matrix* xy,
10052  ae_int_t n,
10053  ae_int_t pt,
10054  /* Real */ ae_vector* p,
10055  ae_state *_state);
10056 
10057 
10058 static double rbf_eps = 1.0E-6;
10059 static ae_int_t rbf_mxnx = 3;
10060 static double rbf_rbffarradius = 6;
10061 static double rbf_rbfnearradius = 2.1;
10062 static double rbf_rbfmlradius = 3;
10063 static ae_int_t rbf_rbffirstversion = 0;
10064 static void rbf_rbfgridpoints(rbfmodel* s, ae_state *_state);
10065 static void rbf_rbfradnn(rbfmodel* s,
10066  double q,
10067  double z,
10068  ae_state *_state);
10069 static ae_bool rbf_buildlinearmodel(/* Real */ ae_matrix* x,
10070  /* Real */ ae_matrix* y,
10071  ae_int_t n,
10072  ae_int_t ny,
10073  ae_int_t modeltype,
10074  /* Real */ ae_matrix* v,
10075  ae_state *_state);
10076 static void rbf_buildrbfmodellsqr(/* Real */ ae_matrix* x,
10077  /* Real */ ae_matrix* y,
10078  /* Real */ ae_matrix* xc,
10079  /* Real */ ae_vector* r,
10080  ae_int_t n,
10081  ae_int_t nc,
10082  ae_int_t ny,
10083  kdtree* pointstree,
10084  kdtree* centerstree,
10085  double epsort,
10086  double epserr,
10087  ae_int_t maxits,
10088  ae_int_t* gnnz,
10089  ae_int_t* snnz,
10090  /* Real */ ae_matrix* w,
10091  ae_int_t* info,
10092  ae_int_t* iterationscount,
10093  ae_int_t* nmv,
10094  ae_state *_state);
10095 static void rbf_buildrbfmlayersmodellsqr(/* Real */ ae_matrix* x,
10096  /* Real */ ae_matrix* y,
10097  /* Real */ ae_matrix* xc,
10098  double rval,
10099  /* Real */ ae_vector* r,
10100  ae_int_t n,
10101  ae_int_t* nc,
10102  ae_int_t ny,
10103  ae_int_t nlayers,
10104  kdtree* centerstree,
10105  double epsort,
10106  double epserr,
10107  ae_int_t maxits,
10108  double lambdav,
10109  ae_int_t* annz,
10110  /* Real */ ae_matrix* w,
10111  ae_int_t* info,
10112  ae_int_t* iterationscount,
10113  ae_int_t* nmv,
10114  ae_state *_state);
10115 
10116 
10117 static void spline2d_bicubiccalcderivatives(/* Real */ ae_matrix* a,
10118  /* Real */ ae_vector* x,
10119  /* Real */ ae_vector* y,
10120  ae_int_t m,
10121  ae_int_t n,
10122  /* Real */ ae_matrix* dx,
10123  /* Real */ ae_matrix* dy,
10124  /* Real */ ae_matrix* dxy,
10125  ae_state *_state);
10126 
10127 
10128 static void spline3d_spline3ddiff(spline3dinterpolant* c,
10129  double x,
10130  double y,
10131  double z,
10132  double* f,
10133  double* fx,
10134  double* fy,
10135  double* fxy,
10136  ae_state *_state);
10137 
10138 
10139 
10140 
10141 
10142 /*************************************************************************
10143 IDW interpolation
10144 
10145 INPUT PARAMETERS:
10146  Z - IDW interpolant built with one of model building
10147  subroutines.
10148  X - array[0..NX-1], interpolation point
10149 
10150 Result:
10151  IDW interpolant Z(X)
10152 
10153  -- ALGLIB --
10154  Copyright 02.03.2010 by Bochkanov Sergey
10155 *************************************************************************/
10157  /* Real */ ae_vector* x,
10158  ae_state *_state)
10159 {
10160  ae_int_t i;
10161  ae_int_t k;
10162  double r;
10163  double s;
10164  double w;
10165  double v1;
10166  double v2;
10167  double d0;
10168  double di;
10169  double result;
10170 
10171 
10172 
10173  /*
10174  * these initializers are not really necessary,
10175  * but without them compiler complains about uninitialized locals
10176  */
10177  k = 0;
10178 
10179  /*
10180  * Query
10181  */
10182  if( z->modeltype==0 )
10183  {
10184 
10185  /*
10186  * NQ/NW-based model
10187  */
10188  k = kdtreequeryknn(&z->tree, x, z->nw, ae_true, _state);
10189  kdtreequeryresultsdistances(&z->tree, &z->rbuf, _state);
10190  kdtreequeryresultstags(&z->tree, &z->tbuf, _state);
10191  }
10192  if( z->modeltype==1 )
10193  {
10194 
10195  /*
10196  * R-based model
10197  */
10198  k = kdtreequeryrnn(&z->tree, x, z->r, ae_true, _state);
10199  kdtreequeryresultsdistances(&z->tree, &z->rbuf, _state);
10200  kdtreequeryresultstags(&z->tree, &z->tbuf, _state);
10201  if( k<idwint_idwkmin )
10202  {
10203 
10204  /*
10205  * we need at least IDWKMin points
10206  */
10207  k = kdtreequeryknn(&z->tree, x, idwint_idwkmin, ae_true, _state);
10208  kdtreequeryresultsdistances(&z->tree, &z->rbuf, _state);
10209  kdtreequeryresultstags(&z->tree, &z->tbuf, _state);
10210  }
10211  }
10212 
10213  /*
10214  * initialize weights for linear/quadratic members calculation.
10215  *
10216  * NOTE 1: weights are calculated using NORMALIZED modified
10217  * Shepard's formula. Original formula gives w(i) = sqr((R-di)/(R*di)),
10218  * where di is i-th distance, R is max(di). Modified formula have
10219  * following form:
10220  * w_mod(i) = 1, if di=d0
10221  * w_mod(i) = w(i)/w(0), if di<>d0
10222  *
10223  * NOTE 2: self-match is USED for this query
10224  *
10225  * NOTE 3: last point almost always gain zero weight, but it MUST
10226  * be used for fitting because sometimes it will gain NON-ZERO
10227  * weight - for example, when all distances are equal.
10228  */
10229  r = z->rbuf.ptr.p_double[k-1];
10230  d0 = z->rbuf.ptr.p_double[0];
10231  result = 0;
10232  s = 0;
10233  for(i=0; i<=k-1; i++)
10234  {
10235  di = z->rbuf.ptr.p_double[i];
10236  if( ae_fp_eq(di,d0) )
10237  {
10238 
10239  /*
10240  * distance is equal to shortest, set it 1.0
10241  * without explicitly calculating (which would give
10242  * us same result, but 'll expose us to the risk of
10243  * division by zero).
10244  */
10245  w = 1;
10246  }
10247  else
10248  {
10249 
10250  /*
10251  * use normalized formula
10252  */
10253  v1 = (r-di)/(r-d0);
10254  v2 = d0/di;
10255  w = ae_sqr(v1*v2, _state);
10256  }
10257  result = result+w*idwint_idwcalcq(z, x, z->tbuf.ptr.p_int[i], _state);
10258  s = s+w;
10259  }
10260  result = result/s;
10261  return result;
10262 }
10263 
10264 
10265 /*************************************************************************
10266 IDW interpolant using modified Shepard method for uniform point
10267 distributions.
10268 
10269 INPUT PARAMETERS:
10270  XY - X and Y values, array[0..N-1,0..NX].
10271  First NX columns contain X-values, last column contain
10272  Y-values.
10273  N - number of nodes, N>0.
10274  NX - space dimension, NX>=1.
10275  D - nodal function type, either:
10276  * 0 constant model. Just for demonstration only, worst
10277  model ever.
10278  * 1 linear model, least squares fitting. Simpe model for
10279  datasets too small for quadratic models
10280  * 2 quadratic model, least squares fitting. Best model
10281  available (if your dataset is large enough).
10282  * -1 "fast" linear model, use with caution!!! It is
10283  significantly faster than linear/quadratic and better
10284  than constant model. But it is less robust (especially
10285  in the presence of noise).
10286  NQ - number of points used to calculate nodal functions (ignored
10287  for constant models). NQ should be LARGER than:
10288  * max(1.5*(1+NX),2^NX+1) for linear model,
10289  * max(3/4*(NX+2)*(NX+1),2^NX+1) for quadratic model.
10290  Values less than this threshold will be silently increased.
10291  NW - number of points used to calculate weights and to interpolate.
10292  Required: >=2^NX+1, values less than this threshold will be
10293  silently increased.
10294  Recommended value: about 2*NQ
10295 
10296 OUTPUT PARAMETERS:
10297  Z - IDW interpolant.
10298 
10299 NOTES:
10300  * best results are obtained with quadratic models, worst - with constant
10301  models
10302  * when N is large, NQ and NW must be significantly smaller than N both
10303  to obtain optimal performance and to obtain optimal accuracy. In 2 or
10304  3-dimensional tasks NQ=15 and NW=25 are good values to start with.
10305  * NQ and NW may be greater than N. In such cases they will be
10306  automatically decreased.
10307  * this subroutine is always succeeds (as long as correct parameters are
10308  passed).
10309  * see 'Multivariate Interpolation of Large Sets of Scattered Data' by
10310  Robert J. Renka for more information on this algorithm.
10311  * this subroutine assumes that point distribution is uniform at the small
10312  scales. If it isn't - for example, points are concentrated along
10313  "lines", but "lines" distribution is uniform at the larger scale - then
10314  you should use IDWBuildModifiedShepardR()
10315 
10316 
10317  -- ALGLIB PROJECT --
10318  Copyright 02.03.2010 by Bochkanov Sergey
10319 *************************************************************************/
10321  ae_int_t n,
10322  ae_int_t nx,
10323  ae_int_t d,
10324  ae_int_t nq,
10325  ae_int_t nw,
10326  idwinterpolant* z,
10327  ae_state *_state)
10328 {
10329  ae_frame _frame_block;
10330  ae_int_t i;
10331  ae_int_t j;
10332  ae_int_t k;
10333  ae_int_t j2;
10334  ae_int_t j3;
10335  double v;
10336  double r;
10337  double s;
10338  double d0;
10339  double di;
10340  double v1;
10341  double v2;
10342  ae_int_t nc;
10343  ae_int_t offs;
10344  ae_vector x;
10345  ae_vector qrbuf;
10346  ae_matrix qxybuf;
10347  ae_vector y;
10348  ae_matrix fmatrix;
10349  ae_vector w;
10350  ae_vector qsol;
10351  ae_vector temp;
10352  ae_vector tags;
10353  ae_int_t info;
10354  double taskrcond;
10355 
10356  ae_frame_make(_state, &_frame_block);
10358  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
10359  ae_vector_init(&qrbuf, 0, DT_REAL, _state, ae_true);
10360  ae_matrix_init(&qxybuf, 0, 0, DT_REAL, _state, ae_true);
10361  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
10362  ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
10363  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
10364  ae_vector_init(&qsol, 0, DT_REAL, _state, ae_true);
10365  ae_vector_init(&temp, 0, DT_REAL, _state, ae_true);
10366  ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
10367 
10368 
10369  /*
10370  * these initializers are not really necessary,
10371  * but without them compiler complains about uninitialized locals
10372  */
10373  nc = 0;
10374 
10375  /*
10376  * assertions
10377  */
10378  ae_assert(n>0, "IDWBuildModifiedShepard: N<=0!", _state);
10379  ae_assert(nx>=1, "IDWBuildModifiedShepard: NX<1!", _state);
10380  ae_assert(d>=-1&&d<=2, "IDWBuildModifiedShepard: D<>-1 and D<>0 and D<>1 and D<>2!", _state);
10381 
10382  /*
10383  * Correct parameters if needed
10384  */
10385  if( d==1 )
10386  {
10387  nq = ae_maxint(nq, ae_iceil(idwint_idwqfactor*(1+nx), _state)+1, _state);
10388  nq = ae_maxint(nq, ae_round(ae_pow(2, nx, _state), _state)+1, _state);
10389  }
10390  if( d==2 )
10391  {
10392  nq = ae_maxint(nq, ae_iceil(idwint_idwqfactor*(nx+2)*(nx+1)/2, _state)+1, _state);
10393  nq = ae_maxint(nq, ae_round(ae_pow(2, nx, _state), _state)+1, _state);
10394  }
10395  nw = ae_maxint(nw, ae_round(ae_pow(2, nx, _state), _state)+1, _state);
10396  nq = ae_minint(nq, n, _state);
10397  nw = ae_minint(nw, n, _state);
10398 
10399  /*
10400  * primary initialization of Z
10401  */
10402  idwint_idwinit1(n, nx, d, nq, nw, z, _state);
10403  z->modeltype = 0;
10404 
10405  /*
10406  * Create KD-tree
10407  */
10408  ae_vector_set_length(&tags, n, _state);
10409  for(i=0; i<=n-1; i++)
10410  {
10411  tags.ptr.p_int[i] = i;
10412  }
10413  kdtreebuildtagged(xy, &tags, n, nx, 1, 2, &z->tree, _state);
10414 
10415  /*
10416  * build nodal functions
10417  */
10418  ae_vector_set_length(&temp, nq+1, _state);
10419  ae_vector_set_length(&x, nx, _state);
10420  ae_vector_set_length(&qrbuf, nq, _state);
10421  ae_matrix_set_length(&qxybuf, nq, nx+1, _state);
10422  if( d==-1 )
10423  {
10424  ae_vector_set_length(&w, nq, _state);
10425  }
10426  if( d==1 )
10427  {
10428  ae_vector_set_length(&y, nq, _state);
10429  ae_vector_set_length(&w, nq, _state);
10430  ae_vector_set_length(&qsol, nx, _state);
10431 
10432  /*
10433  * NX for linear members,
10434  * 1 for temporary storage
10435  */
10436  ae_matrix_set_length(&fmatrix, nq, nx+1, _state);
10437  }
10438  if( d==2 )
10439  {
10440  ae_vector_set_length(&y, nq, _state);
10441  ae_vector_set_length(&w, nq, _state);
10442  ae_vector_set_length(&qsol, nx+ae_round(nx*(nx+1)*0.5, _state), _state);
10443 
10444  /*
10445  * NX for linear members,
10446  * Round(NX*(NX+1)*0.5) for quadratic model,
10447  * 1 for temporary storage
10448  */
10449  ae_matrix_set_length(&fmatrix, nq, nx+ae_round(nx*(nx+1)*0.5, _state)+1, _state);
10450  }
10451  for(i=0; i<=n-1; i++)
10452  {
10453 
10454  /*
10455  * Initialize center and function value.
10456  * If D=0 it is all what we need
10457  */
10458  ae_v_move(&z->q.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx));
10459  if( d==0 )
10460  {
10461  continue;
10462  }
10463 
10464  /*
10465  * calculate weights for linear/quadratic members calculation.
10466  *
10467  * NOTE 1: weights are calculated using NORMALIZED modified
10468  * Shepard's formula. Original formula is w(i) = sqr((R-di)/(R*di)),
10469  * where di is i-th distance, R is max(di). Modified formula have
10470  * following form:
10471  * w_mod(i) = 1, if di=d0
10472  * w_mod(i) = w(i)/w(0), if di<>d0
10473  *
10474  * NOTE 2: self-match is NOT used for this query
10475  *
10476  * NOTE 3: last point almost always gain zero weight, but it MUST
10477  * be used for fitting because sometimes it will gain NON-ZERO
10478  * weight - for example, when all distances are equal.
10479  */
10480  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
10481  k = kdtreequeryknn(&z->tree, &x, nq, ae_false, _state);
10482  kdtreequeryresultsxy(&z->tree, &qxybuf, _state);
10483  kdtreequeryresultsdistances(&z->tree, &qrbuf, _state);
10484  r = qrbuf.ptr.p_double[k-1];
10485  d0 = qrbuf.ptr.p_double[0];
10486  for(j=0; j<=k-1; j++)
10487  {
10488  di = qrbuf.ptr.p_double[j];
10489  if( ae_fp_eq(di,d0) )
10490  {
10491 
10492  /*
10493  * distance is equal to shortest, set it 1.0
10494  * without explicitly calculating (which would give
10495  * us same result, but 'll expose us to the risk of
10496  * division by zero).
10497  */
10498  w.ptr.p_double[j] = 1;
10499  }
10500  else
10501  {
10502 
10503  /*
10504  * use normalized formula
10505  */
10506  v1 = (r-di)/(r-d0);
10507  v2 = d0/di;
10508  w.ptr.p_double[j] = ae_sqr(v1*v2, _state);
10509  }
10510  }
10511 
10512  /*
10513  * calculate linear/quadratic members
10514  */
10515  if( d==-1 )
10516  {
10517 
10518  /*
10519  * "Fast" linear nodal function calculated using
10520  * inverse distance weighting
10521  */
10522  for(j=0; j<=nx-1; j++)
10523  {
10524  x.ptr.p_double[j] = 0;
10525  }
10526  s = 0;
10527  for(j=0; j<=k-1; j++)
10528  {
10529 
10530  /*
10531  * calculate J-th inverse distance weighted gradient:
10532  * grad_k = (y_j-y_k)*(x_j-x_k)/sqr(norm(x_j-x_k))
10533  * grad = sum(wk*grad_k)/sum(w_k)
10534  */
10535  v = 0;
10536  for(j2=0; j2<=nx-1; j2++)
10537  {
10538  v = v+ae_sqr(qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2], _state);
10539  }
10540 
10541  /*
10542  * Although x_j<>x_k, sqr(norm(x_j-x_k)) may be zero due to
10543  * underflow. If it is, we assume than J-th gradient is zero
10544  * (i.e. don't add anything)
10545  */
10546  if( ae_fp_neq(v,0) )
10547  {
10548  for(j2=0; j2<=nx-1; j2++)
10549  {
10550  x.ptr.p_double[j2] = x.ptr.p_double[j2]+w.ptr.p_double[j]*(qxybuf.ptr.pp_double[j][nx]-xy->ptr.pp_double[i][nx])*(qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2])/v;
10551  }
10552  }
10553  s = s+w.ptr.p_double[j];
10554  }
10555  for(j=0; j<=nx-1; j++)
10556  {
10557  z->q.ptr.pp_double[i][nx+1+j] = x.ptr.p_double[j]/s;
10558  }
10559  }
10560  else
10561  {
10562 
10563  /*
10564  * Least squares models: build
10565  */
10566  if( d==1 )
10567  {
10568 
10569  /*
10570  * Linear nodal function calculated using
10571  * least squares fitting to its neighbors
10572  */
10573  for(j=0; j<=k-1; j++)
10574  {
10575  for(j2=0; j2<=nx-1; j2++)
10576  {
10577  fmatrix.ptr.pp_double[j][j2] = qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2];
10578  }
10579  y.ptr.p_double[j] = qxybuf.ptr.pp_double[j][nx]-xy->ptr.pp_double[i][nx];
10580  }
10581  nc = nx;
10582  }
10583  if( d==2 )
10584  {
10585 
10586  /*
10587  * Quadratic nodal function calculated using
10588  * least squares fitting to its neighbors
10589  */
10590  for(j=0; j<=k-1; j++)
10591  {
10592  offs = 0;
10593  for(j2=0; j2<=nx-1; j2++)
10594  {
10595  fmatrix.ptr.pp_double[j][offs] = qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2];
10596  offs = offs+1;
10597  }
10598  for(j2=0; j2<=nx-1; j2++)
10599  {
10600  for(j3=j2; j3<=nx-1; j3++)
10601  {
10602  fmatrix.ptr.pp_double[j][offs] = (qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2])*(qxybuf.ptr.pp_double[j][j3]-xy->ptr.pp_double[i][j3]);
10603  offs = offs+1;
10604  }
10605  }
10606  y.ptr.p_double[j] = qxybuf.ptr.pp_double[j][nx]-xy->ptr.pp_double[i][nx];
10607  }
10608  nc = nx+ae_round(nx*(nx+1)*0.5, _state);
10609  }
10610  idwint_idwinternalsolver(&y, &w, &fmatrix, &temp, k, nc, &info, &qsol, &taskrcond, _state);
10611 
10612  /*
10613  * Least squares models: copy results
10614  */
10615  if( info>0 )
10616  {
10617 
10618  /*
10619  * LLS task is solved, copy results
10620  */
10621  z->debugworstrcond = ae_minreal(z->debugworstrcond, taskrcond, _state);
10622  z->debugbestrcond = ae_maxreal(z->debugbestrcond, taskrcond, _state);
10623  for(j=0; j<=nc-1; j++)
10624  {
10625  z->q.ptr.pp_double[i][nx+1+j] = qsol.ptr.p_double[j];
10626  }
10627  }
10628  else
10629  {
10630 
10631  /*
10632  * Solver failure, very strange, but we will use
10633  * zero values to handle it.
10634  */
10636  for(j=0; j<=nc-1; j++)
10637  {
10638  z->q.ptr.pp_double[i][nx+1+j] = 0;
10639  }
10640  }
10641  }
10642  }
10643  ae_frame_leave(_state);
10644 }
10645 
10646 
10647 /*************************************************************************
10648 IDW interpolant using modified Shepard method for non-uniform datasets.
10649 
10650 This type of model uses constant nodal functions and interpolates using
10651 all nodes which are closer than user-specified radius R. It may be used
10652 when points distribution is non-uniform at the small scale, but it is at
10653 the distances as large as R.
10654 
10655 INPUT PARAMETERS:
10656  XY - X and Y values, array[0..N-1,0..NX].
10657  First NX columns contain X-values, last column contain
10658  Y-values.
10659  N - number of nodes, N>0.
10660  NX - space dimension, NX>=1.
10661  R - radius, R>0
10662 
10663 OUTPUT PARAMETERS:
10664  Z - IDW interpolant.
10665 
10666 NOTES:
10667 * if there is less than IDWKMin points within R-ball, algorithm selects
10668  IDWKMin closest ones, so that continuity properties of interpolant are
10669  preserved even far from points.
10670 
10671  -- ALGLIB PROJECT --
10672  Copyright 11.04.2010 by Bochkanov Sergey
10673 *************************************************************************/
10675  ae_int_t n,
10676  ae_int_t nx,
10677  double r,
10678  idwinterpolant* z,
10679  ae_state *_state)
10680 {
10681  ae_frame _frame_block;
10682  ae_int_t i;
10683  ae_vector tags;
10684 
10685  ae_frame_make(_state, &_frame_block);
10687  ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
10688 
10689 
10690  /*
10691  * assertions
10692  */
10693  ae_assert(n>0, "IDWBuildModifiedShepardR: N<=0!", _state);
10694  ae_assert(nx>=1, "IDWBuildModifiedShepardR: NX<1!", _state);
10695  ae_assert(ae_fp_greater(r,0), "IDWBuildModifiedShepardR: R<=0!", _state);
10696 
10697  /*
10698  * primary initialization of Z
10699  */
10700  idwint_idwinit1(n, nx, 0, 0, n, z, _state);
10701  z->modeltype = 1;
10702  z->r = r;
10703 
10704  /*
10705  * Create KD-tree
10706  */
10707  ae_vector_set_length(&tags, n, _state);
10708  for(i=0; i<=n-1; i++)
10709  {
10710  tags.ptr.p_int[i] = i;
10711  }
10712  kdtreebuildtagged(xy, &tags, n, nx, 1, 2, &z->tree, _state);
10713 
10714  /*
10715  * build nodal functions
10716  */
10717  for(i=0; i<=n-1; i++)
10718  {
10719  ae_v_move(&z->q.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx));
10720  }
10721  ae_frame_leave(_state);
10722 }
10723 
10724 
10725 /*************************************************************************
10726 IDW model for noisy data.
10727 
10728 This subroutine may be used to handle noisy data, i.e. data with noise in
10729 OUTPUT values. It differs from IDWBuildModifiedShepard() in the following
10730 aspects:
10731 * nodal functions are not constrained to pass through nodes: Qi(xi)<>yi,
10732  i.e. we have fitting instead of interpolation.
10733 * weights which are used during least squares fitting stage are all equal
10734  to 1.0 (independently of distance)
10735 * "fast"-linear or constant nodal functions are not supported (either not
10736  robust enough or too rigid)
10737 
10738 This problem require far more complex tuning than interpolation problems.
10739 Below you can find some recommendations regarding this problem:
10740 * focus on tuning NQ; it controls noise reduction. As for NW, you can just
10741  make it equal to 2*NQ.
10742 * you can use cross-validation to determine optimal NQ.
10743 * optimal NQ is a result of complex tradeoff between noise level (more
10744  noise = larger NQ required) and underlying function complexity (given
10745  fixed N, larger NQ means smoothing of compex features in the data). For
10746  example, NQ=N will reduce noise to the minimum level possible, but you
10747  will end up with just constant/linear/quadratic (depending on D) least
10748  squares model for the whole dataset.
10749 
10750 INPUT PARAMETERS:
10751  XY - X and Y values, array[0..N-1,0..NX].
10752  First NX columns contain X-values, last column contain
10753  Y-values.
10754  N - number of nodes, N>0.
10755  NX - space dimension, NX>=1.
10756  D - nodal function degree, either:
10757  * 1 linear model, least squares fitting. Simpe model for
10758  datasets too small for quadratic models (or for very
10759  noisy problems).
10760  * 2 quadratic model, least squares fitting. Best model
10761  available (if your dataset is large enough).
10762  NQ - number of points used to calculate nodal functions. NQ should
10763  be significantly larger than 1.5 times the number of
10764  coefficients in a nodal function to overcome effects of noise:
10765  * larger than 1.5*(1+NX) for linear model,
10766  * larger than 3/4*(NX+2)*(NX+1) for quadratic model.
10767  Values less than this threshold will be silently increased.
10768  NW - number of points used to calculate weights and to interpolate.
10769  Required: >=2^NX+1, values less than this threshold will be
10770  silently increased.
10771  Recommended value: about 2*NQ or larger
10772 
10773 OUTPUT PARAMETERS:
10774  Z - IDW interpolant.
10775 
10776 NOTES:
10777  * best results are obtained with quadratic models, linear models are not
10778  recommended to use unless you are pretty sure that it is what you want
10779  * this subroutine is always succeeds (as long as correct parameters are
10780  passed).
10781  * see 'Multivariate Interpolation of Large Sets of Scattered Data' by
10782  Robert J. Renka for more information on this algorithm.
10783 
10784 
10785  -- ALGLIB PROJECT --
10786  Copyright 02.03.2010 by Bochkanov Sergey
10787 *************************************************************************/
10788 void idwbuildnoisy(/* Real */ ae_matrix* xy,
10789  ae_int_t n,
10790  ae_int_t nx,
10791  ae_int_t d,
10792  ae_int_t nq,
10793  ae_int_t nw,
10794  idwinterpolant* z,
10795  ae_state *_state)
10796 {
10797  ae_frame _frame_block;
10798  ae_int_t i;
10799  ae_int_t j;
10800  ae_int_t k;
10801  ae_int_t j2;
10802  ae_int_t j3;
10803  double v;
10804  ae_int_t nc;
10805  ae_int_t offs;
10806  double taskrcond;
10807  ae_vector x;
10808  ae_vector qrbuf;
10809  ae_matrix qxybuf;
10810  ae_vector y;
10811  ae_vector w;
10812  ae_matrix fmatrix;
10813  ae_vector qsol;
10814  ae_vector tags;
10815  ae_vector temp;
10816  ae_int_t info;
10817 
10818  ae_frame_make(_state, &_frame_block);
10820  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
10821  ae_vector_init(&qrbuf, 0, DT_REAL, _state, ae_true);
10822  ae_matrix_init(&qxybuf, 0, 0, DT_REAL, _state, ae_true);
10823  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
10824  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
10825  ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
10826  ae_vector_init(&qsol, 0, DT_REAL, _state, ae_true);
10827  ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
10828  ae_vector_init(&temp, 0, DT_REAL, _state, ae_true);
10829 
10830 
10831  /*
10832  * these initializers are not really necessary,
10833  * but without them compiler complains about uninitialized locals
10834  */
10835  nc = 0;
10836 
10837  /*
10838  * assertions
10839  */
10840  ae_assert(n>0, "IDWBuildNoisy: N<=0!", _state);
10841  ae_assert(nx>=1, "IDWBuildNoisy: NX<1!", _state);
10842  ae_assert(d>=1&&d<=2, "IDWBuildNoisy: D<>1 and D<>2!", _state);
10843 
10844  /*
10845  * Correct parameters if needed
10846  */
10847  if( d==1 )
10848  {
10849  nq = ae_maxint(nq, ae_iceil(idwint_idwqfactor*(1+nx), _state)+1, _state);
10850  }
10851  if( d==2 )
10852  {
10853  nq = ae_maxint(nq, ae_iceil(idwint_idwqfactor*(nx+2)*(nx+1)/2, _state)+1, _state);
10854  }
10855  nw = ae_maxint(nw, ae_round(ae_pow(2, nx, _state), _state)+1, _state);
10856  nq = ae_minint(nq, n, _state);
10857  nw = ae_minint(nw, n, _state);
10858 
10859  /*
10860  * primary initialization of Z
10861  */
10862  idwint_idwinit1(n, nx, d, nq, nw, z, _state);
10863  z->modeltype = 0;
10864 
10865  /*
10866  * Create KD-tree
10867  */
10868  ae_vector_set_length(&tags, n, _state);
10869  for(i=0; i<=n-1; i++)
10870  {
10871  tags.ptr.p_int[i] = i;
10872  }
10873  kdtreebuildtagged(xy, &tags, n, nx, 1, 2, &z->tree, _state);
10874 
10875  /*
10876  * build nodal functions
10877  * (special algorithm for noisy data is used)
10878  */
10879  ae_vector_set_length(&temp, nq+1, _state);
10880  ae_vector_set_length(&x, nx, _state);
10881  ae_vector_set_length(&qrbuf, nq, _state);
10882  ae_matrix_set_length(&qxybuf, nq, nx+1, _state);
10883  if( d==1 )
10884  {
10885  ae_vector_set_length(&y, nq, _state);
10886  ae_vector_set_length(&w, nq, _state);
10887  ae_vector_set_length(&qsol, 1+nx, _state);
10888 
10889  /*
10890  * 1 for constant member,
10891  * NX for linear members,
10892  * 1 for temporary storage
10893  */
10894  ae_matrix_set_length(&fmatrix, nq, 1+nx+1, _state);
10895  }
10896  if( d==2 )
10897  {
10898  ae_vector_set_length(&y, nq, _state);
10899  ae_vector_set_length(&w, nq, _state);
10900  ae_vector_set_length(&qsol, 1+nx+ae_round(nx*(nx+1)*0.5, _state), _state);
10901 
10902  /*
10903  * 1 for constant member,
10904  * NX for linear members,
10905  * Round(NX*(NX+1)*0.5) for quadratic model,
10906  * 1 for temporary storage
10907  */
10908  ae_matrix_set_length(&fmatrix, nq, 1+nx+ae_round(nx*(nx+1)*0.5, _state)+1, _state);
10909  }
10910  for(i=0; i<=n-1; i++)
10911  {
10912 
10913  /*
10914  * Initialize center.
10915  */
10916  ae_v_move(&z->q.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
10917 
10918  /*
10919  * Calculate linear/quadratic members
10920  * using least squares fit
10921  * NOTE 1: all weight are equal to 1.0
10922  * NOTE 2: self-match is USED for this query
10923  */
10924  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
10925  k = kdtreequeryknn(&z->tree, &x, nq, ae_true, _state);
10926  kdtreequeryresultsxy(&z->tree, &qxybuf, _state);
10927  kdtreequeryresultsdistances(&z->tree, &qrbuf, _state);
10928  if( d==1 )
10929  {
10930 
10931  /*
10932  * Linear nodal function calculated using
10933  * least squares fitting to its neighbors
10934  */
10935  for(j=0; j<=k-1; j++)
10936  {
10937  fmatrix.ptr.pp_double[j][0] = 1.0;
10938  for(j2=0; j2<=nx-1; j2++)
10939  {
10940  fmatrix.ptr.pp_double[j][1+j2] = qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2];
10941  }
10942  y.ptr.p_double[j] = qxybuf.ptr.pp_double[j][nx];
10943  w.ptr.p_double[j] = 1;
10944  }
10945  nc = 1+nx;
10946  }
10947  if( d==2 )
10948  {
10949 
10950  /*
10951  * Quadratic nodal function calculated using
10952  * least squares fitting to its neighbors
10953  */
10954  for(j=0; j<=k-1; j++)
10955  {
10956  fmatrix.ptr.pp_double[j][0] = 1;
10957  offs = 1;
10958  for(j2=0; j2<=nx-1; j2++)
10959  {
10960  fmatrix.ptr.pp_double[j][offs] = qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2];
10961  offs = offs+1;
10962  }
10963  for(j2=0; j2<=nx-1; j2++)
10964  {
10965  for(j3=j2; j3<=nx-1; j3++)
10966  {
10967  fmatrix.ptr.pp_double[j][offs] = (qxybuf.ptr.pp_double[j][j2]-xy->ptr.pp_double[i][j2])*(qxybuf.ptr.pp_double[j][j3]-xy->ptr.pp_double[i][j3]);
10968  offs = offs+1;
10969  }
10970  }
10971  y.ptr.p_double[j] = qxybuf.ptr.pp_double[j][nx];
10972  w.ptr.p_double[j] = 1;
10973  }
10974  nc = 1+nx+ae_round(nx*(nx+1)*0.5, _state);
10975  }
10976  idwint_idwinternalsolver(&y, &w, &fmatrix, &temp, k, nc, &info, &qsol, &taskrcond, _state);
10977 
10978  /*
10979  * Least squares models: copy results
10980  */
10981  if( info>0 )
10982  {
10983 
10984  /*
10985  * LLS task is solved, copy results
10986  */
10987  z->debugworstrcond = ae_minreal(z->debugworstrcond, taskrcond, _state);
10988  z->debugbestrcond = ae_maxreal(z->debugbestrcond, taskrcond, _state);
10989  for(j=0; j<=nc-1; j++)
10990  {
10991  z->q.ptr.pp_double[i][nx+j] = qsol.ptr.p_double[j];
10992  }
10993  }
10994  else
10995  {
10996 
10997  /*
10998  * Solver failure, very strange, but we will use
10999  * zero values to handle it.
11000  */
11002  v = 0;
11003  for(j=0; j<=k-1; j++)
11004  {
11005  v = v+qxybuf.ptr.pp_double[j][nx];
11006  }
11007  z->q.ptr.pp_double[i][nx] = v/k;
11008  for(j=0; j<=nc-2; j++)
11009  {
11010  z->q.ptr.pp_double[i][nx+1+j] = 0;
11011  }
11012  }
11013  }
11014  ae_frame_leave(_state);
11015 }
11016 
11017 
11018 /*************************************************************************
11019 Internal subroutine: K-th nodal function calculation
11020 
11021  -- ALGLIB --
11022  Copyright 02.03.2010 by Bochkanov Sergey
11023 *************************************************************************/
11024 static double idwint_idwcalcq(idwinterpolant* z,
11025  /* Real */ ae_vector* x,
11026  ae_int_t k,
11027  ae_state *_state)
11028 {
11029  ae_int_t nx;
11030  ae_int_t i;
11031  ae_int_t j;
11032  ae_int_t offs;
11033  double result;
11034 
11035 
11036  nx = z->nx;
11037 
11038  /*
11039  * constant member
11040  */
11041  result = z->q.ptr.pp_double[k][nx];
11042 
11043  /*
11044  * linear members
11045  */
11046  if( z->d>=1 )
11047  {
11048  for(i=0; i<=nx-1; i++)
11049  {
11050  result = result+z->q.ptr.pp_double[k][nx+1+i]*(x->ptr.p_double[i]-z->q.ptr.pp_double[k][i]);
11051  }
11052  }
11053 
11054  /*
11055  * quadratic members
11056  */
11057  if( z->d>=2 )
11058  {
11059  offs = nx+1+nx;
11060  for(i=0; i<=nx-1; i++)
11061  {
11062  for(j=i; j<=nx-1; j++)
11063  {
11064  result = result+z->q.ptr.pp_double[k][offs]*(x->ptr.p_double[i]-z->q.ptr.pp_double[k][i])*(x->ptr.p_double[j]-z->q.ptr.pp_double[k][j]);
11065  offs = offs+1;
11066  }
11067  }
11068  }
11069  return result;
11070 }
11071 
11072 
11073 /*************************************************************************
11074 Initialization of internal structures.
11075 
11076 It assumes correctness of all parameters.
11077 
11078  -- ALGLIB --
11079  Copyright 02.03.2010 by Bochkanov Sergey
11080 *************************************************************************/
11081 static void idwint_idwinit1(ae_int_t n,
11082  ae_int_t nx,
11083  ae_int_t d,
11084  ae_int_t nq,
11085  ae_int_t nw,
11086  idwinterpolant* z,
11087  ae_state *_state)
11088 {
11089 
11090 
11091  z->debugsolverfailures = 0;
11092  z->debugworstrcond = 1.0;
11093  z->debugbestrcond = 0;
11094  z->n = n;
11095  z->nx = nx;
11096  z->d = 0;
11097  if( d==1 )
11098  {
11099  z->d = 1;
11100  }
11101  if( d==2 )
11102  {
11103  z->d = 2;
11104  }
11105  if( d==-1 )
11106  {
11107  z->d = 1;
11108  }
11109  z->nw = nw;
11110  if( d==-1 )
11111  {
11112  ae_matrix_set_length(&z->q, n, nx+1+nx, _state);
11113  }
11114  if( d==0 )
11115  {
11116  ae_matrix_set_length(&z->q, n, nx+1, _state);
11117  }
11118  if( d==1 )
11119  {
11120  ae_matrix_set_length(&z->q, n, nx+1+nx, _state);
11121  }
11122  if( d==2 )
11123  {
11124  ae_matrix_set_length(&z->q, n, nx+1+nx+ae_round(nx*(nx+1)*0.5, _state), _state);
11125  }
11126  ae_vector_set_length(&z->tbuf, nw, _state);
11127  ae_vector_set_length(&z->rbuf, nw, _state);
11128  ae_matrix_set_length(&z->xybuf, nw, nx+1, _state);
11129  ae_vector_set_length(&z->xbuf, nx, _state);
11130 }
11131 
11132 
11133 /*************************************************************************
11134 Linear least squares solver for small tasks.
11135 
11136 Works faster than standard ALGLIB solver in non-degenerate cases (due to
11137 absence of internal allocations and optimized row/colums). In degenerate
11138 cases it calls standard solver, which results in small performance penalty
11139 associated with preliminary steps.
11140 
11141 INPUT PARAMETERS:
11142  Y array[0..N-1]
11143  W array[0..N-1]
11144  FMatrix array[0..N-1,0..M], have additional column for temporary
11145  values
11146  Temp array[0..N]
11147 *************************************************************************/
11148 static void idwint_idwinternalsolver(/* Real */ ae_vector* y,
11149  /* Real */ ae_vector* w,
11150  /* Real */ ae_matrix* fmatrix,
11151  /* Real */ ae_vector* temp,
11152  ae_int_t n,
11153  ae_int_t m,
11154  ae_int_t* info,
11155  /* Real */ ae_vector* x,
11156  double* taskrcond,
11157  ae_state *_state)
11158 {
11159  ae_frame _frame_block;
11160  ae_int_t i;
11161  ae_int_t j;
11162  double v;
11163  double tau;
11164  ae_vector b;
11165  densesolverlsreport srep;
11166 
11167  ae_frame_make(_state, &_frame_block);
11168  *info = 0;
11169  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
11170  _densesolverlsreport_init(&srep, _state, ae_true);
11171 
11172 
11173  /*
11174  * set up info
11175  */
11176  *info = 1;
11177 
11178  /*
11179  * prepare matrix
11180  */
11181  for(i=0; i<=n-1; i++)
11182  {
11183  fmatrix->ptr.pp_double[i][m] = y->ptr.p_double[i];
11184  v = w->ptr.p_double[i];
11185  ae_v_muld(&fmatrix->ptr.pp_double[i][0], 1, ae_v_len(0,m), v);
11186  }
11187 
11188  /*
11189  * use either fast algorithm or general algorithm
11190  */
11191  if( m<=n )
11192  {
11193 
11194  /*
11195  * QR decomposition
11196  * We assume that M<=N (we would have called LSFit() otherwise)
11197  */
11198  for(i=0; i<=m-1; i++)
11199  {
11200  if( i<n-1 )
11201  {
11202  ae_v_move(&temp->ptr.p_double[1], 1, &fmatrix->ptr.pp_double[i][i], fmatrix->stride, ae_v_len(1,n-i));
11203  generatereflection(temp, n-i, &tau, _state);
11204  fmatrix->ptr.pp_double[i][i] = temp->ptr.p_double[1];
11205  temp->ptr.p_double[1] = 1;
11206  for(j=i+1; j<=m; j++)
11207  {
11208  v = ae_v_dotproduct(&fmatrix->ptr.pp_double[i][j], fmatrix->stride, &temp->ptr.p_double[1], 1, ae_v_len(i,n-1));
11209  v = tau*v;
11210  ae_v_subd(&fmatrix->ptr.pp_double[i][j], fmatrix->stride, &temp->ptr.p_double[1], 1, ae_v_len(i,n-1), v);
11211  }
11212  }
11213  }
11214 
11215  /*
11216  * Check condition number
11217  */
11218  *taskrcond = rmatrixtrrcondinf(fmatrix, m, ae_true, ae_false, _state);
11219 
11220  /*
11221  * use either fast algorithm for non-degenerate cases
11222  * or slow algorithm for degenerate cases
11223  */
11224  if( ae_fp_greater(*taskrcond,10000*n*ae_machineepsilon) )
11225  {
11226 
11227  /*
11228  * solve triangular system R*x = FMatrix[0:M-1,M]
11229  * using fast algorithm, then exit
11230  */
11231  x->ptr.p_double[m-1] = fmatrix->ptr.pp_double[m-1][m]/fmatrix->ptr.pp_double[m-1][m-1];
11232  for(i=m-2; i>=0; i--)
11233  {
11234  v = ae_v_dotproduct(&fmatrix->ptr.pp_double[i][i+1], 1, &x->ptr.p_double[i+1], 1, ae_v_len(i+1,m-1));
11235  x->ptr.p_double[i] = (fmatrix->ptr.pp_double[i][m]-v)/fmatrix->ptr.pp_double[i][i];
11236  }
11237  }
11238  else
11239  {
11240 
11241  /*
11242  * use more general algorithm
11243  */
11244  ae_vector_set_length(&b, m, _state);
11245  for(i=0; i<=m-1; i++)
11246  {
11247  for(j=0; j<=i-1; j++)
11248  {
11249  fmatrix->ptr.pp_double[i][j] = 0.0;
11250  }
11251  b.ptr.p_double[i] = fmatrix->ptr.pp_double[i][m];
11252  }
11253  rmatrixsolvels(fmatrix, m, m, &b, 10000*ae_machineepsilon, info, &srep, x, _state);
11254  }
11255  }
11256  else
11257  {
11258 
11259  /*
11260  * use more general algorithm
11261  */
11262  ae_vector_set_length(&b, n, _state);
11263  for(i=0; i<=n-1; i++)
11264  {
11265  b.ptr.p_double[i] = fmatrix->ptr.pp_double[i][m];
11266  }
11267  rmatrixsolvels(fmatrix, n, m, &b, 10000*ae_machineepsilon, info, &srep, x, _state);
11268  *taskrcond = srep.r2;
11269  }
11270  ae_frame_leave(_state);
11271 }
11272 
11273 
11274 ae_bool _idwinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
11275 {
11276  idwinterpolant *p = (idwinterpolant*)_p;
11277  ae_touch_ptr((void*)p);
11278  if( !_kdtree_init(&p->tree, _state, make_automatic) )
11279  return ae_false;
11280  if( !ae_matrix_init(&p->q, 0, 0, DT_REAL, _state, make_automatic) )
11281  return ae_false;
11282  if( !ae_vector_init(&p->xbuf, 0, DT_REAL, _state, make_automatic) )
11283  return ae_false;
11284  if( !ae_vector_init(&p->tbuf, 0, DT_INT, _state, make_automatic) )
11285  return ae_false;
11286  if( !ae_vector_init(&p->rbuf, 0, DT_REAL, _state, make_automatic) )
11287  return ae_false;
11288  if( !ae_matrix_init(&p->xybuf, 0, 0, DT_REAL, _state, make_automatic) )
11289  return ae_false;
11290  return ae_true;
11291 }
11292 
11293 
11294 ae_bool _idwinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
11295 {
11296  idwinterpolant *dst = (idwinterpolant*)_dst;
11297  idwinterpolant *src = (idwinterpolant*)_src;
11298  dst->n = src->n;
11299  dst->nx = src->nx;
11300  dst->d = src->d;
11301  dst->r = src->r;
11302  dst->nw = src->nw;
11303  if( !_kdtree_init_copy(&dst->tree, &src->tree, _state, make_automatic) )
11304  return ae_false;
11305  dst->modeltype = src->modeltype;
11306  if( !ae_matrix_init_copy(&dst->q, &src->q, _state, make_automatic) )
11307  return ae_false;
11308  if( !ae_vector_init_copy(&dst->xbuf, &src->xbuf, _state, make_automatic) )
11309  return ae_false;
11310  if( !ae_vector_init_copy(&dst->tbuf, &src->tbuf, _state, make_automatic) )
11311  return ae_false;
11312  if( !ae_vector_init_copy(&dst->rbuf, &src->rbuf, _state, make_automatic) )
11313  return ae_false;
11314  if( !ae_matrix_init_copy(&dst->xybuf, &src->xybuf, _state, make_automatic) )
11315  return ae_false;
11317  dst->debugworstrcond = src->debugworstrcond;
11318  dst->debugbestrcond = src->debugbestrcond;
11319  return ae_true;
11320 }
11321 
11322 
11324 {
11325  idwinterpolant *p = (idwinterpolant*)_p;
11326  ae_touch_ptr((void*)p);
11327  _kdtree_clear(&p->tree);
11328  ae_matrix_clear(&p->q);
11329  ae_vector_clear(&p->xbuf);
11330  ae_vector_clear(&p->tbuf);
11331  ae_vector_clear(&p->rbuf);
11332  ae_matrix_clear(&p->xybuf);
11333 }
11334 
11335 
11337 {
11338  idwinterpolant *p = (idwinterpolant*)_p;
11339  ae_touch_ptr((void*)p);
11340  _kdtree_destroy(&p->tree);
11341  ae_matrix_destroy(&p->q);
11342  ae_vector_destroy(&p->xbuf);
11343  ae_vector_destroy(&p->tbuf);
11344  ae_vector_destroy(&p->rbuf);
11345  ae_matrix_destroy(&p->xybuf);
11346 }
11347 
11348 
11349 
11350 
11351 /*************************************************************************
11352 Rational interpolation using barycentric formula
11353 
11354 F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
11355 
11356 Input parameters:
11357  B - barycentric interpolant built with one of model building
11358  subroutines.
11359  T - interpolation point
11360 
11361 Result:
11362  barycentric interpolant F(t)
11363 
11364  -- ALGLIB --
11365  Copyright 17.08.2009 by Bochkanov Sergey
11366 *************************************************************************/
11368  double t,
11369  ae_state *_state)
11370 {
11371  double s1;
11372  double s2;
11373  double s;
11374  double v;
11375  ae_int_t i;
11376  double result;
11377 
11378 
11379  ae_assert(!ae_isinf(t, _state), "BarycentricCalc: infinite T!", _state);
11380 
11381  /*
11382  * special case: NaN
11383  */
11384  if( ae_isnan(t, _state) )
11385  {
11386  result = _state->v_nan;
11387  return result;
11388  }
11389 
11390  /*
11391  * special case: N=1
11392  */
11393  if( b->n==1 )
11394  {
11395  result = b->sy*b->y.ptr.p_double[0];
11396  return result;
11397  }
11398 
11399  /*
11400  * Here we assume that task is normalized, i.e.:
11401  * 1. abs(Y[i])<=1
11402  * 2. abs(W[i])<=1
11403  * 3. X[] is ordered
11404  */
11405  s = ae_fabs(t-b->x.ptr.p_double[0], _state);
11406  for(i=0; i<=b->n-1; i++)
11407  {
11408  v = b->x.ptr.p_double[i];
11409  if( ae_fp_eq(v,t) )
11410  {
11411  result = b->sy*b->y.ptr.p_double[i];
11412  return result;
11413  }
11414  v = ae_fabs(t-v, _state);
11415  if( ae_fp_less(v,s) )
11416  {
11417  s = v;
11418  }
11419  }
11420  s1 = 0;
11421  s2 = 0;
11422  for(i=0; i<=b->n-1; i++)
11423  {
11424  v = s/(t-b->x.ptr.p_double[i]);
11425  v = v*b->w.ptr.p_double[i];
11426  s1 = s1+v*b->y.ptr.p_double[i];
11427  s2 = s2+v;
11428  }
11429  result = b->sy*s1/s2;
11430  return result;
11431 }
11432 
11433 
11434 /*************************************************************************
11435 Differentiation of barycentric interpolant: first derivative.
11436 
11437 Algorithm used in this subroutine is very robust and should not fail until
11438 provided with values too close to MaxRealNumber (usually MaxRealNumber/N
11439 or greater will overflow).
11440 
11441 INPUT PARAMETERS:
11442  B - barycentric interpolant built with one of model building
11443  subroutines.
11444  T - interpolation point
11445 
11446 OUTPUT PARAMETERS:
11447  F - barycentric interpolant at T
11448  DF - first derivative
11449 
11450 NOTE
11451 
11452 
11453  -- ALGLIB --
11454  Copyright 17.08.2009 by Bochkanov Sergey
11455 *************************************************************************/
11457  double t,
11458  double* f,
11459  double* df,
11460  ae_state *_state)
11461 {
11462  double v;
11463  double vv;
11464  ae_int_t i;
11465  ae_int_t k;
11466  double n0;
11467  double n1;
11468  double d0;
11469  double d1;
11470  double s0;
11471  double s1;
11472  double xk;
11473  double xi;
11474  double xmin;
11475  double xmax;
11476  double xscale1;
11477  double xoffs1;
11478  double xscale2;
11479  double xoffs2;
11480  double xprev;
11481 
11482  *f = 0;
11483  *df = 0;
11484 
11485  ae_assert(!ae_isinf(t, _state), "BarycentricDiff1: infinite T!", _state);
11486 
11487  /*
11488  * special case: NaN
11489  */
11490  if( ae_isnan(t, _state) )
11491  {
11492  *f = _state->v_nan;
11493  *df = _state->v_nan;
11494  return;
11495  }
11496 
11497  /*
11498  * special case: N=1
11499  */
11500  if( b->n==1 )
11501  {
11502  *f = b->sy*b->y.ptr.p_double[0];
11503  *df = 0;
11504  return;
11505  }
11506  if( ae_fp_eq(b->sy,0) )
11507  {
11508  *f = 0;
11509  *df = 0;
11510  return;
11511  }
11512  ae_assert(ae_fp_greater(b->sy,0), "BarycentricDiff1: internal error", _state);
11513 
11514  /*
11515  * We assume than N>1 and B.SY>0. Find:
11516  * 1. pivot point (X[i] closest to T)
11517  * 2. width of interval containing X[i]
11518  */
11519  v = ae_fabs(b->x.ptr.p_double[0]-t, _state);
11520  k = 0;
11521  xmin = b->x.ptr.p_double[0];
11522  xmax = b->x.ptr.p_double[0];
11523  for(i=1; i<=b->n-1; i++)
11524  {
11525  vv = b->x.ptr.p_double[i];
11526  if( ae_fp_less(ae_fabs(vv-t, _state),v) )
11527  {
11528  v = ae_fabs(vv-t, _state);
11529  k = i;
11530  }
11531  xmin = ae_minreal(xmin, vv, _state);
11532  xmax = ae_maxreal(xmax, vv, _state);
11533  }
11534 
11535  /*
11536  * pivot point found, calculate dNumerator and dDenominator
11537  */
11538  xscale1 = 1/(xmax-xmin);
11539  xoffs1 = -xmin/(xmax-xmin)+1;
11540  xscale2 = 2;
11541  xoffs2 = -3;
11542  t = t*xscale1+xoffs1;
11543  t = t*xscale2+xoffs2;
11544  xk = b->x.ptr.p_double[k];
11545  xk = xk*xscale1+xoffs1;
11546  xk = xk*xscale2+xoffs2;
11547  v = t-xk;
11548  n0 = 0;
11549  n1 = 0;
11550  d0 = 0;
11551  d1 = 0;
11552  xprev = -2;
11553  for(i=0; i<=b->n-1; i++)
11554  {
11555  xi = b->x.ptr.p_double[i];
11556  xi = xi*xscale1+xoffs1;
11557  xi = xi*xscale2+xoffs2;
11558  ae_assert(ae_fp_greater(xi,xprev), "BarycentricDiff1: points are too close!", _state);
11559  xprev = xi;
11560  if( i!=k )
11561  {
11562  vv = ae_sqr(t-xi, _state);
11563  s0 = (t-xk)/(t-xi);
11564  s1 = (xk-xi)/vv;
11565  }
11566  else
11567  {
11568  s0 = 1;
11569  s1 = 0;
11570  }
11571  vv = b->w.ptr.p_double[i]*b->y.ptr.p_double[i];
11572  n0 = n0+s0*vv;
11573  n1 = n1+s1*vv;
11574  vv = b->w.ptr.p_double[i];
11575  d0 = d0+s0*vv;
11576  d1 = d1+s1*vv;
11577  }
11578  *f = b->sy*n0/d0;
11579  *df = (n1*d0-n0*d1)/ae_sqr(d0, _state);
11580  if( ae_fp_neq(*df,0) )
11581  {
11582  *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);
11583  }
11584 }
11585 
11586 
11587 /*************************************************************************
11588 Differentiation of barycentric interpolant: first/second derivatives.
11589 
11590 INPUT PARAMETERS:
11591  B - barycentric interpolant built with one of model building
11592  subroutines.
11593  T - interpolation point
11594 
11595 OUTPUT PARAMETERS:
11596  F - barycentric interpolant at T
11597  DF - first derivative
11598  D2F - second derivative
11599 
11600 NOTE: this algorithm may fail due to overflow/underflor if used on data
11601 whose values are close to MaxRealNumber or MinRealNumber. Use more robust
11602 BarycentricDiff1() subroutine in such cases.
11603 
11604 
11605  -- ALGLIB --
11606  Copyright 17.08.2009 by Bochkanov Sergey
11607 *************************************************************************/
11609  double t,
11610  double* f,
11611  double* df,
11612  double* d2f,
11613  ae_state *_state)
11614 {
11615  double v;
11616  double vv;
11617  ae_int_t i;
11618  ae_int_t k;
11619  double n0;
11620  double n1;
11621  double n2;
11622  double d0;
11623  double d1;
11624  double d2;
11625  double s0;
11626  double s1;
11627  double s2;
11628  double xk;
11629  double xi;
11630 
11631  *f = 0;
11632  *df = 0;
11633  *d2f = 0;
11634 
11635  ae_assert(!ae_isinf(t, _state), "BarycentricDiff1: infinite T!", _state);
11636 
11637  /*
11638  * special case: NaN
11639  */
11640  if( ae_isnan(t, _state) )
11641  {
11642  *f = _state->v_nan;
11643  *df = _state->v_nan;
11644  *d2f = _state->v_nan;
11645  return;
11646  }
11647 
11648  /*
11649  * special case: N=1
11650  */
11651  if( b->n==1 )
11652  {
11653  *f = b->sy*b->y.ptr.p_double[0];
11654  *df = 0;
11655  *d2f = 0;
11656  return;
11657  }
11658  if( ae_fp_eq(b->sy,0) )
11659  {
11660  *f = 0;
11661  *df = 0;
11662  *d2f = 0;
11663  return;
11664  }
11665 
11666  /*
11667  * We assume than N>1 and B.SY>0. Find:
11668  * 1. pivot point (X[i] closest to T)
11669  * 2. width of interval containing X[i]
11670  */
11671  ae_assert(ae_fp_greater(b->sy,0), "BarycentricDiff: internal error", _state);
11672  *f = 0;
11673  *df = 0;
11674  *d2f = 0;
11675  v = ae_fabs(b->x.ptr.p_double[0]-t, _state);
11676  k = 0;
11677  for(i=1; i<=b->n-1; i++)
11678  {
11679  vv = b->x.ptr.p_double[i];
11680  if( ae_fp_less(ae_fabs(vv-t, _state),v) )
11681  {
11682  v = ae_fabs(vv-t, _state);
11683  k = i;
11684  }
11685  }
11686 
11687  /*
11688  * pivot point found, calculate dNumerator and dDenominator
11689  */
11690  xk = b->x.ptr.p_double[k];
11691  v = t-xk;
11692  n0 = 0;
11693  n1 = 0;
11694  n2 = 0;
11695  d0 = 0;
11696  d1 = 0;
11697  d2 = 0;
11698  for(i=0; i<=b->n-1; i++)
11699  {
11700  if( i!=k )
11701  {
11702  xi = b->x.ptr.p_double[i];
11703  vv = ae_sqr(t-xi, _state);
11704  s0 = (t-xk)/(t-xi);
11705  s1 = (xk-xi)/vv;
11706  s2 = -2*(xk-xi)/(vv*(t-xi));
11707  }
11708  else
11709  {
11710  s0 = 1;
11711  s1 = 0;
11712  s2 = 0;
11713  }
11714  vv = b->w.ptr.p_double[i]*b->y.ptr.p_double[i];
11715  n0 = n0+s0*vv;
11716  n1 = n1+s1*vv;
11717  n2 = n2+s2*vv;
11718  vv = b->w.ptr.p_double[i];
11719  d0 = d0+s0*vv;
11720  d1 = d1+s1*vv;
11721  d2 = d2+s2*vv;
11722  }
11723  *f = b->sy*n0/d0;
11724  *df = b->sy*(n1*d0-n0*d1)/ae_sqr(d0, _state);
11725  *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);
11726 }
11727 
11728 
11729 /*************************************************************************
11730 This subroutine performs linear transformation of the argument.
11731 
11732 INPUT PARAMETERS:
11733  B - rational interpolant in barycentric form
11734  CA, CB - transformation coefficients: x = CA*t + CB
11735 
11736 OUTPUT PARAMETERS:
11737  B - transformed interpolant with X replaced by T
11738 
11739  -- ALGLIB PROJECT --
11740  Copyright 19.08.2009 by Bochkanov Sergey
11741 *************************************************************************/
11743  double ca,
11744  double cb,
11745  ae_state *_state)
11746 {
11747  ae_int_t i;
11748  ae_int_t j;
11749  double v;
11750 
11751 
11752 
11753  /*
11754  * special case, replace by constant F(CB)
11755  */
11756  if( ae_fp_eq(ca,0) )
11757  {
11758  b->sy = barycentriccalc(b, cb, _state);
11759  v = 1;
11760  for(i=0; i<=b->n-1; i++)
11761  {
11762  b->y.ptr.p_double[i] = 1;
11763  b->w.ptr.p_double[i] = v;
11764  v = -v;
11765  }
11766  return;
11767  }
11768 
11769  /*
11770  * general case: CA<>0
11771  */
11772  for(i=0; i<=b->n-1; i++)
11773  {
11774  b->x.ptr.p_double[i] = (b->x.ptr.p_double[i]-cb)/ca;
11775  }
11776  if( ae_fp_less(ca,0) )
11777  {
11778  for(i=0; i<=b->n-1; i++)
11779  {
11780  if( i<b->n-1-i )
11781  {
11782  j = b->n-1-i;
11783  v = b->x.ptr.p_double[i];
11784  b->x.ptr.p_double[i] = b->x.ptr.p_double[j];
11785  b->x.ptr.p_double[j] = v;
11786  v = b->y.ptr.p_double[i];
11787  b->y.ptr.p_double[i] = b->y.ptr.p_double[j];
11788  b->y.ptr.p_double[j] = v;
11789  v = b->w.ptr.p_double[i];
11790  b->w.ptr.p_double[i] = b->w.ptr.p_double[j];
11791  b->w.ptr.p_double[j] = v;
11792  }
11793  else
11794  {
11795  break;
11796  }
11797  }
11798  }
11799 }
11800 
11801 
11802 /*************************************************************************
11803 This subroutine performs linear transformation of the barycentric
11804 interpolant.
11805 
11806 INPUT PARAMETERS:
11807  B - rational interpolant in barycentric form
11808  CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB
11809 
11810 OUTPUT PARAMETERS:
11811  B - transformed interpolant
11812 
11813  -- ALGLIB PROJECT --
11814  Copyright 19.08.2009 by Bochkanov Sergey
11815 *************************************************************************/
11817  double ca,
11818  double cb,
11819  ae_state *_state)
11820 {
11821  ae_int_t i;
11822  double v;
11823 
11824 
11825  for(i=0; i<=b->n-1; i++)
11826  {
11827  b->y.ptr.p_double[i] = ca*b->sy*b->y.ptr.p_double[i]+cb;
11828  }
11829  b->sy = 0;
11830  for(i=0; i<=b->n-1; i++)
11831  {
11832  b->sy = ae_maxreal(b->sy, ae_fabs(b->y.ptr.p_double[i], _state), _state);
11833  }
11834  if( ae_fp_greater(b->sy,0) )
11835  {
11836  v = 1/b->sy;
11837  ae_v_muld(&b->y.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
11838  }
11839 }
11840 
11841 
11842 /*************************************************************************
11843 Extracts X/Y/W arrays from rational interpolant
11844 
11845 INPUT PARAMETERS:
11846  B - barycentric interpolant
11847 
11848 OUTPUT PARAMETERS:
11849  N - nodes count, N>0
11850  X - interpolation nodes, array[0..N-1]
11851  F - function values, array[0..N-1]
11852  W - barycentric weights, array[0..N-1]
11853 
11854  -- ALGLIB --
11855  Copyright 17.08.2009 by Bochkanov Sergey
11856 *************************************************************************/
11858  ae_int_t* n,
11859  /* Real */ ae_vector* x,
11860  /* Real */ ae_vector* y,
11861  /* Real */ ae_vector* w,
11862  ae_state *_state)
11863 {
11864  double v;
11865 
11866  *n = 0;
11867  ae_vector_clear(x);
11868  ae_vector_clear(y);
11869  ae_vector_clear(w);
11870 
11871  *n = b->n;
11872  ae_vector_set_length(x, *n, _state);
11873  ae_vector_set_length(y, *n, _state);
11874  ae_vector_set_length(w, *n, _state);
11875  v = b->sy;
11876  ae_v_move(&x->ptr.p_double[0], 1, &b->x.ptr.p_double[0], 1, ae_v_len(0,*n-1));
11877  ae_v_moved(&y->ptr.p_double[0], 1, &b->y.ptr.p_double[0], 1, ae_v_len(0,*n-1), v);
11878  ae_v_move(&w->ptr.p_double[0], 1, &b->w.ptr.p_double[0], 1, ae_v_len(0,*n-1));
11879 }
11880 
11881 
11882 /*************************************************************************
11883 Rational interpolant from X/Y/W arrays
11884 
11885 F(t) = SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))
11886 
11887 INPUT PARAMETERS:
11888  X - interpolation nodes, array[0..N-1]
11889  F - function values, array[0..N-1]
11890  W - barycentric weights, array[0..N-1]
11891  N - nodes count, N>0
11892 
11893 OUTPUT PARAMETERS:
11894  B - barycentric interpolant built from (X, Y, W)
11895 
11896  -- ALGLIB --
11897  Copyright 17.08.2009 by Bochkanov Sergey
11898 *************************************************************************/
11899 void barycentricbuildxyw(/* Real */ ae_vector* x,
11900  /* Real */ ae_vector* y,
11901  /* Real */ ae_vector* w,
11902  ae_int_t n,
11904  ae_state *_state)
11905 {
11906 
11908 
11909  ae_assert(n>0, "BarycentricBuildXYW: incorrect N!", _state);
11910 
11911  /*
11912  * fill X/Y/W
11913  */
11914  ae_vector_set_length(&b->x, n, _state);
11915  ae_vector_set_length(&b->y, n, _state);
11916  ae_vector_set_length(&b->w, n, _state);
11917  ae_v_move(&b->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
11918  ae_v_move(&b->y.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
11919  ae_v_move(&b->w.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
11920  b->n = n;
11921 
11922  /*
11923  * Normalize
11924  */
11925  ratint_barycentricnormalize(b, _state);
11926 }
11927 
11928 
11929 /*************************************************************************
11930 Rational interpolant without poles
11931 
11932 The subroutine constructs the rational interpolating function without real
11933 poles (see 'Barycentric rational interpolation with no poles and high
11934 rates of approximation', Michael S. Floater. and Kai Hormann, for more
11935 information on this subject).
11936 
11937 Input parameters:
11938  X - interpolation nodes, array[0..N-1].
11939  Y - function values, array[0..N-1].
11940  N - number of nodes, N>0.
11941  D - order of the interpolation scheme, 0 <= D <= N-1.
11942  D<0 will cause an error.
11943  D>=N it will be replaced with D=N-1.
11944  if you don't know what D to choose, use small value about 3-5.
11945 
11946 Output parameters:
11947  B - barycentric interpolant.
11948 
11949 Note:
11950  this algorithm always succeeds and calculates the weights with close
11951  to machine precision.
11952 
11953  -- ALGLIB PROJECT --
11954  Copyright 17.06.2007 by Bochkanov Sergey
11955 *************************************************************************/
11957  /* Real */ ae_vector* y,
11958  ae_int_t n,
11959  ae_int_t d,
11961  ae_state *_state)
11962 {
11963  ae_frame _frame_block;
11964  double s0;
11965  double s;
11966  double v;
11967  ae_int_t i;
11968  ae_int_t j;
11969  ae_int_t k;
11970  ae_vector perm;
11971  ae_vector wtemp;
11972  ae_vector sortrbuf;
11973  ae_vector sortrbuf2;
11974 
11975  ae_frame_make(_state, &_frame_block);
11977  ae_vector_init(&perm, 0, DT_INT, _state, ae_true);
11978  ae_vector_init(&wtemp, 0, DT_REAL, _state, ae_true);
11979  ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true);
11980  ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true);
11981 
11982  ae_assert(n>0, "BarycentricFloaterHormann: N<=0!", _state);
11983  ae_assert(d>=0, "BarycentricFloaterHormann: incorrect D!", _state);
11984 
11985  /*
11986  * Prepare
11987  */
11988  if( d>n-1 )
11989  {
11990  d = n-1;
11991  }
11992  b->n = n;
11993 
11994  /*
11995  * special case: N=1
11996  */
11997  if( n==1 )
11998  {
11999  ae_vector_set_length(&b->x, n, _state);
12000  ae_vector_set_length(&b->y, n, _state);
12001  ae_vector_set_length(&b->w, n, _state);
12002  b->x.ptr.p_double[0] = x->ptr.p_double[0];
12003  b->y.ptr.p_double[0] = y->ptr.p_double[0];
12004  b->w.ptr.p_double[0] = 1;
12005  ratint_barycentricnormalize(b, _state);
12006  ae_frame_leave(_state);
12007  return;
12008  }
12009 
12010  /*
12011  * Fill X/Y
12012  */
12013  ae_vector_set_length(&b->x, n, _state);
12014  ae_vector_set_length(&b->y, n, _state);
12015  ae_v_move(&b->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
12016  ae_v_move(&b->y.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
12017  tagsortfastr(&b->x, &b->y, &sortrbuf, &sortrbuf2, n, _state);
12018 
12019  /*
12020  * Calculate Wk
12021  */
12022  ae_vector_set_length(&b->w, n, _state);
12023  s0 = 1;
12024  for(k=1; k<=d; k++)
12025  {
12026  s0 = -s0;
12027  }
12028  for(k=0; k<=n-1; k++)
12029  {
12030 
12031  /*
12032  * Wk
12033  */
12034  s = 0;
12035  for(i=ae_maxint(k-d, 0, _state); i<=ae_minint(k, n-1-d, _state); i++)
12036  {
12037  v = 1;
12038  for(j=i; j<=i+d; j++)
12039  {
12040  if( j!=k )
12041  {
12042  v = v/ae_fabs(b->x.ptr.p_double[k]-b->x.ptr.p_double[j], _state);
12043  }
12044  }
12045  s = s+v;
12046  }
12047  b->w.ptr.p_double[k] = s0*s;
12048 
12049  /*
12050  * Next S0
12051  */
12052  s0 = -s0;
12053  }
12054 
12055  /*
12056  * Normalize
12057  */
12058  ratint_barycentricnormalize(b, _state);
12059  ae_frame_leave(_state);
12060 }
12061 
12062 
12063 /*************************************************************************
12064 Copying of the barycentric interpolant (for internal use only)
12065 
12066 INPUT PARAMETERS:
12067  B - barycentric interpolant
12068 
12069 OUTPUT PARAMETERS:
12070  B2 - copy(B1)
12071 
12072  -- ALGLIB --
12073  Copyright 17.08.2009 by Bochkanov Sergey
12074 *************************************************************************/
12077  ae_state *_state)
12078 {
12079 
12081 
12082  b2->n = b->n;
12083  b2->sy = b->sy;
12084  ae_vector_set_length(&b2->x, b2->n, _state);
12085  ae_vector_set_length(&b2->y, b2->n, _state);
12086  ae_vector_set_length(&b2->w, b2->n, _state);
12087  ae_v_move(&b2->x.ptr.p_double[0], 1, &b->x.ptr.p_double[0], 1, ae_v_len(0,b2->n-1));
12088  ae_v_move(&b2->y.ptr.p_double[0], 1, &b->y.ptr.p_double[0], 1, ae_v_len(0,b2->n-1));
12089  ae_v_move(&b2->w.ptr.p_double[0], 1, &b->w.ptr.p_double[0], 1, ae_v_len(0,b2->n-1));
12090 }
12091 
12092 
12093 /*************************************************************************
12094 Normalization of barycentric interpolant:
12095 * B.N, B.X, B.Y and B.W are initialized
12096 * B.SY is NOT initialized
12097 * Y[] is normalized, scaling coefficient is stored in B.SY
12098 * W[] is normalized, no scaling coefficient is stored
12099 * X[] is sorted
12100 
12101 Internal subroutine.
12102 *************************************************************************/
12103 static void ratint_barycentricnormalize(barycentricinterpolant* b,
12104  ae_state *_state)
12105 {
12106  ae_frame _frame_block;
12107  ae_vector p1;
12108  ae_vector p2;
12109  ae_int_t i;
12110  ae_int_t j;
12111  ae_int_t j2;
12112  double v;
12113 
12114  ae_frame_make(_state, &_frame_block);
12115  ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
12116  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
12117 
12118 
12119  /*
12120  * Normalize task: |Y|<=1, |W|<=1, sort X[]
12121  */
12122  b->sy = 0;
12123  for(i=0; i<=b->n-1; i++)
12124  {
12125  b->sy = ae_maxreal(b->sy, ae_fabs(b->y.ptr.p_double[i], _state), _state);
12126  }
12127  if( ae_fp_greater(b->sy,0)&&ae_fp_greater(ae_fabs(b->sy-1, _state),10*ae_machineepsilon) )
12128  {
12129  v = 1/b->sy;
12130  ae_v_muld(&b->y.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
12131  }
12132  v = 0;
12133  for(i=0; i<=b->n-1; i++)
12134  {
12135  v = ae_maxreal(v, ae_fabs(b->w.ptr.p_double[i], _state), _state);
12136  }
12137  if( ae_fp_greater(v,0)&&ae_fp_greater(ae_fabs(v-1, _state),10*ae_machineepsilon) )
12138  {
12139  v = 1/v;
12140  ae_v_muld(&b->w.ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
12141  }
12142  for(i=0; i<=b->n-2; i++)
12143  {
12144  if( ae_fp_less(b->x.ptr.p_double[i+1],b->x.ptr.p_double[i]) )
12145  {
12146  tagsort(&b->x, b->n, &p1, &p2, _state);
12147  for(j=0; j<=b->n-1; j++)
12148  {
12149  j2 = p2.ptr.p_int[j];
12150  v = b->y.ptr.p_double[j];
12151  b->y.ptr.p_double[j] = b->y.ptr.p_double[j2];
12152  b->y.ptr.p_double[j2] = v;
12153  v = b->w.ptr.p_double[j];
12154  b->w.ptr.p_double[j] = b->w.ptr.p_double[j2];
12155  b->w.ptr.p_double[j2] = v;
12156  }
12157  break;
12158  }
12159  }
12160  ae_frame_leave(_state);
12161 }
12162 
12163 
12164 ae_bool _barycentricinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
12165 {
12167  ae_touch_ptr((void*)p);
12168  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
12169  return ae_false;
12170  if( !ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic) )
12171  return ae_false;
12172  if( !ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic) )
12173  return ae_false;
12174  return ae_true;
12175 }
12176 
12177 
12178 ae_bool _barycentricinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
12179 {
12182  dst->n = src->n;
12183  dst->sy = src->sy;
12184  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
12185  return ae_false;
12186  if( !ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic) )
12187  return ae_false;
12188  if( !ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic) )
12189  return ae_false;
12190  return ae_true;
12191 }
12192 
12193 
12195 {
12197  ae_touch_ptr((void*)p);
12198  ae_vector_clear(&p->x);
12199  ae_vector_clear(&p->y);
12200  ae_vector_clear(&p->w);
12201 }
12202 
12203 
12205 {
12207  ae_touch_ptr((void*)p);
12208  ae_vector_destroy(&p->x);
12209  ae_vector_destroy(&p->y);
12210  ae_vector_destroy(&p->w);
12211 }
12212 
12213 
12214 
12215 
12216 /*************************************************************************
12217 Conversion from barycentric representation to Chebyshev basis.
12218 This function has O(N^2) complexity.
12219 
12220 INPUT PARAMETERS:
12221  P - polynomial in barycentric form
12222  A,B - base interval for Chebyshev polynomials (see below)
12223  A<>B
12224 
12225 OUTPUT PARAMETERS
12226  T - coefficients of Chebyshev representation;
12227  P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 },
12228  where Ti - I-th Chebyshev polynomial.
12229 
12230 NOTES:
12231  barycentric interpolant passed as P may be either polynomial obtained
12232  from polynomial interpolation/ fitting or rational function which is
12233  NOT polynomial. We can't distinguish between these two cases, and this
12234  algorithm just tries to work assuming that P IS a polynomial. If not,
12235  algorithm will return results, but they won't have any meaning.
12236 
12237  -- ALGLIB --
12238  Copyright 30.09.2010 by Bochkanov Sergey
12239 *************************************************************************/
12241  double a,
12242  double b,
12243  /* Real */ ae_vector* t,
12244  ae_state *_state)
12245 {
12246  ae_frame _frame_block;
12247  ae_int_t i;
12248  ae_int_t k;
12249  ae_vector vp;
12250  ae_vector vx;
12251  ae_vector tk;
12252  ae_vector tk1;
12253  double v;
12254 
12255  ae_frame_make(_state, &_frame_block);
12256  ae_vector_clear(t);
12257  ae_vector_init(&vp, 0, DT_REAL, _state, ae_true);
12258  ae_vector_init(&vx, 0, DT_REAL, _state, ae_true);
12259  ae_vector_init(&tk, 0, DT_REAL, _state, ae_true);
12260  ae_vector_init(&tk1, 0, DT_REAL, _state, ae_true);
12261 
12262  ae_assert(ae_isfinite(a, _state), "PolynomialBar2Cheb: A is not finite!", _state);
12263  ae_assert(ae_isfinite(b, _state), "PolynomialBar2Cheb: B is not finite!", _state);
12264  ae_assert(ae_fp_neq(a,b), "PolynomialBar2Cheb: A=B!", _state);
12265  ae_assert(p->n>0, "PolynomialBar2Cheb: P is not correctly initialized barycentric interpolant!", _state);
12266 
12267  /*
12268  * Calculate function values on a Chebyshev grid
12269  */
12270  ae_vector_set_length(&vp, p->n, _state);
12271  ae_vector_set_length(&vx, p->n, _state);
12272  for(i=0; i<=p->n-1; i++)
12273  {
12274  vx.ptr.p_double[i] = ae_cos(ae_pi*(i+0.5)/p->n, _state);
12275  vp.ptr.p_double[i] = barycentriccalc(p, 0.5*(vx.ptr.p_double[i]+1)*(b-a)+a, _state);
12276  }
12277 
12278  /*
12279  * T[0]
12280  */
12281  ae_vector_set_length(t, p->n, _state);
12282  v = 0;
12283  for(i=0; i<=p->n-1; i++)
12284  {
12285  v = v+vp.ptr.p_double[i];
12286  }
12287  t->ptr.p_double[0] = v/p->n;
12288 
12289  /*
12290  * other T's.
12291  *
12292  * NOTES:
12293  * 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX
12294  * 2. we can do same calculations with fast DCT, but it
12295  * * adds dependencies
12296  * * still leaves us with O(N^2) algorithm because
12297  * preparation of function values is O(N^2) process
12298  */
12299  if( p->n>1 )
12300  {
12301  ae_vector_set_length(&tk, p->n, _state);
12302  ae_vector_set_length(&tk1, p->n, _state);
12303  for(i=0; i<=p->n-1; i++)
12304  {
12305  tk.ptr.p_double[i] = vx.ptr.p_double[i];
12306  tk1.ptr.p_double[i] = 1;
12307  }
12308  for(k=1; k<=p->n-1; k++)
12309  {
12310 
12311  /*
12312  * calculate discrete product of function vector and TK
12313  */
12314  v = ae_v_dotproduct(&tk.ptr.p_double[0], 1, &vp.ptr.p_double[0], 1, ae_v_len(0,p->n-1));
12315  t->ptr.p_double[k] = v/(0.5*p->n);
12316 
12317  /*
12318  * Update TK and TK1
12319  */
12320  for(i=0; i<=p->n-1; i++)
12321  {
12322  v = 2*vx.ptr.p_double[i]*tk.ptr.p_double[i]-tk1.ptr.p_double[i];
12323  tk1.ptr.p_double[i] = tk.ptr.p_double[i];
12324  tk.ptr.p_double[i] = v;
12325  }
12326  }
12327  }
12328  ae_frame_leave(_state);
12329 }
12330 
12331 
12332 /*************************************************************************
12333 Conversion from Chebyshev basis to barycentric representation.
12334 This function has O(N^2) complexity.
12335 
12336 INPUT PARAMETERS:
12337  T - coefficients of Chebyshev representation;
12338  P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N },
12339  where Ti - I-th Chebyshev polynomial.
12340  N - number of coefficients:
12341  * if given, only leading N elements of T are used
12342  * if not given, automatically determined from size of T
12343  A,B - base interval for Chebyshev polynomials (see above)
12344  A<B
12345 
12346 OUTPUT PARAMETERS
12347  P - polynomial in barycentric form
12348 
12349  -- ALGLIB --
12350  Copyright 30.09.2010 by Bochkanov Sergey
12351 *************************************************************************/
12352 void polynomialcheb2bar(/* Real */ ae_vector* t,
12353  ae_int_t n,
12354  double a,
12355  double b,
12357  ae_state *_state)
12358 {
12359  ae_frame _frame_block;
12360  ae_int_t i;
12361  ae_int_t k;
12362  ae_vector y;
12363  double tk;
12364  double tk1;
12365  double vx;
12366  double vy;
12367  double v;
12368 
12369  ae_frame_make(_state, &_frame_block);
12371  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
12372 
12373  ae_assert(ae_isfinite(a, _state), "PolynomialBar2Cheb: A is not finite!", _state);
12374  ae_assert(ae_isfinite(b, _state), "PolynomialBar2Cheb: B is not finite!", _state);
12375  ae_assert(ae_fp_neq(a,b), "PolynomialBar2Cheb: A=B!", _state);
12376  ae_assert(n>=1, "PolynomialBar2Cheb: N<1", _state);
12377  ae_assert(t->cnt>=n, "PolynomialBar2Cheb: Length(T)<N", _state);
12378  ae_assert(isfinitevector(t, n, _state), "PolynomialBar2Cheb: T[] contains INF or NAN", _state);
12379 
12380  /*
12381  * Calculate function values on a Chebyshev grid spanning [-1,+1]
12382  */
12383  ae_vector_set_length(&y, n, _state);
12384  for(i=0; i<=n-1; i++)
12385  {
12386 
12387  /*
12388  * Calculate value on a grid spanning [-1,+1]
12389  */
12390  vx = ae_cos(ae_pi*(i+0.5)/n, _state);
12391  vy = t->ptr.p_double[0];
12392  tk1 = 1;
12393  tk = vx;
12394  for(k=1; k<=n-1; k++)
12395  {
12396  vy = vy+t->ptr.p_double[k]*tk;
12397  v = 2*vx*tk-tk1;
12398  tk1 = tk;
12399  tk = v;
12400  }
12401  y.ptr.p_double[i] = vy;
12402  }
12403 
12404  /*
12405  * Build barycentric interpolant, map grid from [-1,+1] to [A,B]
12406  */
12407  polynomialbuildcheb1(a, b, &y, n, p, _state);
12408  ae_frame_leave(_state);
12409 }
12410 
12411 
12412 /*************************************************************************
12413 Conversion from barycentric representation to power basis.
12414 This function has O(N^2) complexity.
12415 
12416 INPUT PARAMETERS:
12417  P - polynomial in barycentric form
12418  C - offset (see below); 0.0 is used as default value.
12419  S - scale (see below); 1.0 is used as default value. S<>0.
12420 
12421 OUTPUT PARAMETERS
12422  A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
12423  N - number of coefficients (polynomial degree plus 1)
12424 
12425 NOTES:
12426 1. this function accepts offset and scale, which can be set to improve
12427  numerical properties of polynomial. For example, if P was obtained as
12428  result of interpolation on [-1,+1], you can set C=0 and S=1 and
12429  represent P as sum of 1, x, x^2, x^3 and so on. In most cases you it
12430  is exactly what you need.
12431 
12432  However, if your interpolation model was built on [999,1001], you will
12433  see significant growth of numerical errors when using {1, x, x^2, x^3}
12434  as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
12435  will be better option. Such representation can be obtained by using
12436  1000.0 as offset C and 1.0 as scale S.
12437 
12438 2. power basis is ill-conditioned and tricks described above can't solve
12439  this problem completely. This function will return coefficients in
12440  any case, but for N>8 they will become unreliable. However, N's
12441  less than 5 are pretty safe.
12442 
12443 3. barycentric interpolant passed as P may be either polynomial obtained
12444  from polynomial interpolation/ fitting or rational function which is
12445  NOT polynomial. We can't distinguish between these two cases, and this
12446  algorithm just tries to work assuming that P IS a polynomial. If not,
12447  algorithm will return results, but they won't have any meaning.
12448 
12449  -- ALGLIB --
12450  Copyright 30.09.2010 by Bochkanov Sergey
12451 *************************************************************************/
12453  double c,
12454  double s,
12455  /* Real */ ae_vector* a,
12456  ae_state *_state)
12457 {
12458  ae_frame _frame_block;
12459  ae_int_t i;
12460  ae_int_t k;
12461  double e;
12462  double d;
12463  ae_vector vp;
12464  ae_vector vx;
12465  ae_vector tk;
12466  ae_vector tk1;
12467  ae_vector t;
12468  double v;
12469 
12470  ae_frame_make(_state, &_frame_block);
12471  ae_vector_clear(a);
12472  ae_vector_init(&vp, 0, DT_REAL, _state, ae_true);
12473  ae_vector_init(&vx, 0, DT_REAL, _state, ae_true);
12474  ae_vector_init(&tk, 0, DT_REAL, _state, ae_true);
12475  ae_vector_init(&tk1, 0, DT_REAL, _state, ae_true);
12476  ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
12477 
12478  ae_assert(ae_isfinite(c, _state), "PolynomialBar2Pow: C is not finite!", _state);
12479  ae_assert(ae_isfinite(s, _state), "PolynomialBar2Pow: S is not finite!", _state);
12480  ae_assert(ae_fp_neq(s,0), "PolynomialBar2Pow: S=0!", _state);
12481  ae_assert(p->n>0, "PolynomialBar2Pow: P is not correctly initialized barycentric interpolant!", _state);
12482 
12483  /*
12484  * Calculate function values on a Chebyshev grid
12485  */
12486  ae_vector_set_length(&vp, p->n, _state);
12487  ae_vector_set_length(&vx, p->n, _state);
12488  for(i=0; i<=p->n-1; i++)
12489  {
12490  vx.ptr.p_double[i] = ae_cos(ae_pi*(i+0.5)/p->n, _state);
12491  vp.ptr.p_double[i] = barycentriccalc(p, s*vx.ptr.p_double[i]+c, _state);
12492  }
12493 
12494  /*
12495  * T[0]
12496  */
12497  ae_vector_set_length(&t, p->n, _state);
12498  v = 0;
12499  for(i=0; i<=p->n-1; i++)
12500  {
12501  v = v+vp.ptr.p_double[i];
12502  }
12503  t.ptr.p_double[0] = v/p->n;
12504 
12505  /*
12506  * other T's.
12507  *
12508  * NOTES:
12509  * 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX
12510  * 2. we can do same calculations with fast DCT, but it
12511  * * adds dependencies
12512  * * still leaves us with O(N^2) algorithm because
12513  * preparation of function values is O(N^2) process
12514  */
12515  if( p->n>1 )
12516  {
12517  ae_vector_set_length(&tk, p->n, _state);
12518  ae_vector_set_length(&tk1, p->n, _state);
12519  for(i=0; i<=p->n-1; i++)
12520  {
12521  tk.ptr.p_double[i] = vx.ptr.p_double[i];
12522  tk1.ptr.p_double[i] = 1;
12523  }
12524  for(k=1; k<=p->n-1; k++)
12525  {
12526 
12527  /*
12528  * calculate discrete product of function vector and TK
12529  */
12530  v = ae_v_dotproduct(&tk.ptr.p_double[0], 1, &vp.ptr.p_double[0], 1, ae_v_len(0,p->n-1));
12531  t.ptr.p_double[k] = v/(0.5*p->n);
12532 
12533  /*
12534  * Update TK and TK1
12535  */
12536  for(i=0; i<=p->n-1; i++)
12537  {
12538  v = 2*vx.ptr.p_double[i]*tk.ptr.p_double[i]-tk1.ptr.p_double[i];
12539  tk1.ptr.p_double[i] = tk.ptr.p_double[i];
12540  tk.ptr.p_double[i] = v;
12541  }
12542  }
12543  }
12544 
12545  /*
12546  * Convert from Chebyshev basis to power basis
12547  */
12548  ae_vector_set_length(a, p->n, _state);
12549  for(i=0; i<=p->n-1; i++)
12550  {
12551  a->ptr.p_double[i] = 0;
12552  }
12553  d = 0;
12554  for(i=0; i<=p->n-1; i++)
12555  {
12556  for(k=i; k<=p->n-1; k++)
12557  {
12558  e = a->ptr.p_double[k];
12559  a->ptr.p_double[k] = 0;
12560  if( i<=1&&k==i )
12561  {
12562  a->ptr.p_double[k] = 1;
12563  }
12564  else
12565  {
12566  if( i!=0 )
12567  {
12568  a->ptr.p_double[k] = 2*d;
12569  }
12570  if( k>i+1 )
12571  {
12572  a->ptr.p_double[k] = a->ptr.p_double[k]-a->ptr.p_double[k-2];
12573  }
12574  }
12575  d = e;
12576  }
12577  d = a->ptr.p_double[i];
12578  e = 0;
12579  k = i;
12580  while(k<=p->n-1)
12581  {
12582  e = e+a->ptr.p_double[k]*t.ptr.p_double[k];
12583  k = k+2;
12584  }
12585  a->ptr.p_double[i] = e;
12586  }
12587  ae_frame_leave(_state);
12588 }
12589 
12590 
12591 /*************************************************************************
12592 Conversion from power basis to barycentric representation.
12593 This function has O(N^2) complexity.
12594 
12595 INPUT PARAMETERS:
12596  A - coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
12597  N - number of coefficients (polynomial degree plus 1)
12598  * if given, only leading N elements of A are used
12599  * if not given, automatically determined from size of A
12600  C - offset (see below); 0.0 is used as default value.
12601  S - scale (see below); 1.0 is used as default value. S<>0.
12602 
12603 OUTPUT PARAMETERS
12604  P - polynomial in barycentric form
12605 
12606 
12607 NOTES:
12608 1. this function accepts offset and scale, which can be set to improve
12609  numerical properties of polynomial. For example, if you interpolate on
12610  [-1,+1], you can set C=0 and S=1 and convert from sum of 1, x, x^2,
12611  x^3 and so on. In most cases you it is exactly what you need.
12612 
12613  However, if your interpolation model was built on [999,1001], you will
12614  see significant growth of numerical errors when using {1, x, x^2, x^3}
12615  as input basis. Converting from sum of 1, (x-1000), (x-1000)^2,
12616  (x-1000)^3 will be better option (you have to specify 1000.0 as offset
12617  C and 1.0 as scale S).
12618 
12619 2. power basis is ill-conditioned and tricks described above can't solve
12620  this problem completely. This function will return barycentric model
12621  in any case, but for N>8 accuracy well degrade. However, N's less than
12622  5 are pretty safe.
12623 
12624  -- ALGLIB --
12625  Copyright 30.09.2010 by Bochkanov Sergey
12626 *************************************************************************/
12627 void polynomialpow2bar(/* Real */ ae_vector* a,
12628  ae_int_t n,
12629  double c,
12630  double s,
12632  ae_state *_state)
12633 {
12634  ae_frame _frame_block;
12635  ae_int_t i;
12636  ae_int_t k;
12637  ae_vector y;
12638  double vx;
12639  double vy;
12640  double px;
12641 
12642  ae_frame_make(_state, &_frame_block);
12644  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
12645 
12646  ae_assert(ae_isfinite(c, _state), "PolynomialPow2Bar: C is not finite!", _state);
12647  ae_assert(ae_isfinite(s, _state), "PolynomialPow2Bar: S is not finite!", _state);
12648  ae_assert(ae_fp_neq(s,0), "PolynomialPow2Bar: S is zero!", _state);
12649  ae_assert(n>=1, "PolynomialPow2Bar: N<1", _state);
12650  ae_assert(a->cnt>=n, "PolynomialPow2Bar: Length(A)<N", _state);
12651  ae_assert(isfinitevector(a, n, _state), "PolynomialPow2Bar: A[] contains INF or NAN", _state);
12652 
12653  /*
12654  * Calculate function values on a Chebyshev grid spanning [-1,+1]
12655  */
12656  ae_vector_set_length(&y, n, _state);
12657  for(i=0; i<=n-1; i++)
12658  {
12659 
12660  /*
12661  * Calculate value on a grid spanning [-1,+1]
12662  */
12663  vx = ae_cos(ae_pi*(i+0.5)/n, _state);
12664  vy = a->ptr.p_double[0];
12665  px = vx;
12666  for(k=1; k<=n-1; k++)
12667  {
12668  vy = vy+px*a->ptr.p_double[k];
12669  px = px*vx;
12670  }
12671  y.ptr.p_double[i] = vy;
12672  }
12673 
12674  /*
12675  * Build barycentric interpolant, map grid from [-1,+1] to [A,B]
12676  */
12677  polynomialbuildcheb1(c-s, c+s, &y, n, p, _state);
12678  ae_frame_leave(_state);
12679 }
12680 
12681 
12682 /*************************************************************************
12683 Lagrange intepolant: generation of the model on the general grid.
12684 This function has O(N^2) complexity.
12685 
12686 INPUT PARAMETERS:
12687  X - abscissas, array[0..N-1]
12688  Y - function values, array[0..N-1]
12689  N - number of points, N>=1
12690 
12691 OUTPUT PARAMETERS
12692  P - barycentric model which represents Lagrange interpolant
12693  (see ratint unit info and BarycentricCalc() description for
12694  more information).
12695 
12696  -- ALGLIB --
12697  Copyright 02.12.2009 by Bochkanov Sergey
12698 *************************************************************************/
12699 void polynomialbuild(/* Real */ ae_vector* x,
12700  /* Real */ ae_vector* y,
12701  ae_int_t n,
12703  ae_state *_state)
12704 {
12705  ae_frame _frame_block;
12706  ae_vector _x;
12707  ae_vector _y;
12708  ae_int_t j;
12709  ae_int_t k;
12710  ae_vector w;
12711  double b;
12712  double a;
12713  double v;
12714  double mx;
12715  ae_vector sortrbuf;
12716  ae_vector sortrbuf2;
12717 
12718  ae_frame_make(_state, &_frame_block);
12719  ae_vector_init_copy(&_x, x, _state, ae_true);
12720  x = &_x;
12721  ae_vector_init_copy(&_y, y, _state, ae_true);
12722  y = &_y;
12724  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
12725  ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true);
12726  ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true);
12727 
12728  ae_assert(n>0, "PolynomialBuild: N<=0!", _state);
12729  ae_assert(x->cnt>=n, "PolynomialBuild: Length(X)<N!", _state);
12730  ae_assert(y->cnt>=n, "PolynomialBuild: Length(Y)<N!", _state);
12731  ae_assert(isfinitevector(x, n, _state), "PolynomialBuild: X contains infinite or NaN values!", _state);
12732  ae_assert(isfinitevector(y, n, _state), "PolynomialBuild: Y contains infinite or NaN values!", _state);
12733  tagsortfastr(x, y, &sortrbuf, &sortrbuf2, n, _state);
12734  ae_assert(aredistinct(x, n, _state), "PolynomialBuild: at least two consequent points are too close!", _state);
12735 
12736  /*
12737  * calculate W[j]
12738  * multi-pass algorithm is used to avoid overflow
12739  */
12740  ae_vector_set_length(&w, n, _state);
12741  a = x->ptr.p_double[0];
12742  b = x->ptr.p_double[0];
12743  for(j=0; j<=n-1; j++)
12744  {
12745  w.ptr.p_double[j] = 1;
12746  a = ae_minreal(a, x->ptr.p_double[j], _state);
12747  b = ae_maxreal(b, x->ptr.p_double[j], _state);
12748  }
12749  for(k=0; k<=n-1; k++)
12750  {
12751 
12752  /*
12753  * W[K] is used instead of 0.0 because
12754  * cycle on J does not touch K-th element
12755  * and we MUST get maximum from ALL elements
12756  */
12757  mx = ae_fabs(w.ptr.p_double[k], _state);
12758  for(j=0; j<=n-1; j++)
12759  {
12760  if( j!=k )
12761  {
12762  v = (b-a)/(x->ptr.p_double[j]-x->ptr.p_double[k]);
12763  w.ptr.p_double[j] = w.ptr.p_double[j]*v;
12764  mx = ae_maxreal(mx, ae_fabs(w.ptr.p_double[j], _state), _state);
12765  }
12766  }
12767  if( k%5==0 )
12768  {
12769 
12770  /*
12771  * every 5-th run we renormalize W[]
12772  */
12773  v = 1/mx;
12774  ae_v_muld(&w.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
12775  }
12776  }
12777  barycentricbuildxyw(x, y, &w, n, p, _state);
12778  ae_frame_leave(_state);
12779 }
12780 
12781 
12782 /*************************************************************************
12783 Lagrange intepolant: generation of the model on equidistant grid.
12784 This function has O(N) complexity.
12785 
12786 INPUT PARAMETERS:
12787  A - left boundary of [A,B]
12788  B - right boundary of [A,B]
12789  Y - function values at the nodes, array[0..N-1]
12790  N - number of points, N>=1
12791  for N=1 a constant model is constructed.
12792 
12793 OUTPUT PARAMETERS
12794  P - barycentric model which represents Lagrange interpolant
12795  (see ratint unit info and BarycentricCalc() description for
12796  more information).
12797 
12798  -- ALGLIB --
12799  Copyright 03.12.2009 by Bochkanov Sergey
12800 *************************************************************************/
12802  double b,
12803  /* Real */ ae_vector* y,
12804  ae_int_t n,
12806  ae_state *_state)
12807 {
12808  ae_frame _frame_block;
12809  ae_int_t i;
12810  ae_vector w;
12811  ae_vector x;
12812  double v;
12813 
12814  ae_frame_make(_state, &_frame_block);
12816  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
12817  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
12818 
12819  ae_assert(n>0, "PolynomialBuildEqDist: N<=0!", _state);
12820  ae_assert(y->cnt>=n, "PolynomialBuildEqDist: Length(Y)<N!", _state);
12821  ae_assert(ae_isfinite(a, _state), "PolynomialBuildEqDist: A is infinite or NaN!", _state);
12822  ae_assert(ae_isfinite(b, _state), "PolynomialBuildEqDist: B is infinite or NaN!", _state);
12823  ae_assert(isfinitevector(y, n, _state), "PolynomialBuildEqDist: Y contains infinite or NaN values!", _state);
12824  ae_assert(ae_fp_neq(b,a), "PolynomialBuildEqDist: B=A!", _state);
12825  ae_assert(ae_fp_neq(a+(b-a)/n,a), "PolynomialBuildEqDist: B is too close to A!", _state);
12826 
12827  /*
12828  * Special case: N=1
12829  */
12830  if( n==1 )
12831  {
12832  ae_vector_set_length(&x, 1, _state);
12833  ae_vector_set_length(&w, 1, _state);
12834  x.ptr.p_double[0] = 0.5*(b+a);
12835  w.ptr.p_double[0] = 1;
12836  barycentricbuildxyw(&x, y, &w, 1, p, _state);
12837  ae_frame_leave(_state);
12838  return;
12839  }
12840 
12841  /*
12842  * general case
12843  */
12844  ae_vector_set_length(&x, n, _state);
12845  ae_vector_set_length(&w, n, _state);
12846  v = 1;
12847  for(i=0; i<=n-1; i++)
12848  {
12849  w.ptr.p_double[i] = v;
12850  x.ptr.p_double[i] = a+(b-a)*i/(n-1);
12851  v = -v*(n-1-i);
12852  v = v/(i+1);
12853  }
12854  barycentricbuildxyw(&x, y, &w, n, p, _state);
12855  ae_frame_leave(_state);
12856 }
12857 
12858 
12859 /*************************************************************************
12860 Lagrange intepolant on Chebyshev grid (first kind).
12861 This function has O(N) complexity.
12862 
12863 INPUT PARAMETERS:
12864  A - left boundary of [A,B]
12865  B - right boundary of [A,B]
12866  Y - function values at the nodes, array[0..N-1],
12867  Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
12868  N - number of points, N>=1
12869  for N=1 a constant model is constructed.
12870 
12871 OUTPUT PARAMETERS
12872  P - barycentric model which represents Lagrange interpolant
12873  (see ratint unit info and BarycentricCalc() description for
12874  more information).
12875 
12876  -- ALGLIB --
12877  Copyright 03.12.2009 by Bochkanov Sergey
12878 *************************************************************************/
12879 void polynomialbuildcheb1(double a,
12880  double b,
12881  /* Real */ ae_vector* y,
12882  ae_int_t n,
12884  ae_state *_state)
12885 {
12886  ae_frame _frame_block;
12887  ae_int_t i;
12888  ae_vector w;
12889  ae_vector x;
12890  double v;
12891  double t;
12892 
12893  ae_frame_make(_state, &_frame_block);
12895  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
12896  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
12897 
12898  ae_assert(n>0, "PolynomialBuildCheb1: N<=0!", _state);
12899  ae_assert(y->cnt>=n, "PolynomialBuildCheb1: Length(Y)<N!", _state);
12900  ae_assert(ae_isfinite(a, _state), "PolynomialBuildCheb1: A is infinite or NaN!", _state);
12901  ae_assert(ae_isfinite(b, _state), "PolynomialBuildCheb1: B is infinite or NaN!", _state);
12902  ae_assert(isfinitevector(y, n, _state), "PolynomialBuildCheb1: Y contains infinite or NaN values!", _state);
12903  ae_assert(ae_fp_neq(b,a), "PolynomialBuildCheb1: B=A!", _state);
12904 
12905  /*
12906  * Special case: N=1
12907  */
12908  if( n==1 )
12909  {
12910  ae_vector_set_length(&x, 1, _state);
12911  ae_vector_set_length(&w, 1, _state);
12912  x.ptr.p_double[0] = 0.5*(b+a);
12913  w.ptr.p_double[0] = 1;
12914  barycentricbuildxyw(&x, y, &w, 1, p, _state);
12915  ae_frame_leave(_state);
12916  return;
12917  }
12918 
12919  /*
12920  * general case
12921  */
12922  ae_vector_set_length(&x, n, _state);
12923  ae_vector_set_length(&w, n, _state);
12924  v = 1;
12925  for(i=0; i<=n-1; i++)
12926  {
12927  t = ae_tan(0.5*ae_pi*(2*i+1)/(2*n), _state);
12928  w.ptr.p_double[i] = 2*v*t/(1+ae_sqr(t, _state));
12929  x.ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*(1-ae_sqr(t, _state))/(1+ae_sqr(t, _state));
12930  v = -v;
12931  }
12932  barycentricbuildxyw(&x, y, &w, n, p, _state);
12933  ae_frame_leave(_state);
12934 }
12935 
12936 
12937 /*************************************************************************
12938 Lagrange intepolant on Chebyshev grid (second kind).
12939 This function has O(N) complexity.
12940 
12941 INPUT PARAMETERS:
12942  A - left boundary of [A,B]
12943  B - right boundary of [A,B]
12944  Y - function values at the nodes, array[0..N-1],
12945  Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
12946  N - number of points, N>=1
12947  for N=1 a constant model is constructed.
12948 
12949 OUTPUT PARAMETERS
12950  P - barycentric model which represents Lagrange interpolant
12951  (see ratint unit info and BarycentricCalc() description for
12952  more information).
12953 
12954  -- ALGLIB --
12955  Copyright 03.12.2009 by Bochkanov Sergey
12956 *************************************************************************/
12957 void polynomialbuildcheb2(double a,
12958  double b,
12959  /* Real */ ae_vector* y,
12960  ae_int_t n,
12962  ae_state *_state)
12963 {
12964  ae_frame _frame_block;
12965  ae_int_t i;
12966  ae_vector w;
12967  ae_vector x;
12968  double v;
12969 
12970  ae_frame_make(_state, &_frame_block);
12972  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
12973  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
12974 
12975  ae_assert(n>0, "PolynomialBuildCheb2: N<=0!", _state);
12976  ae_assert(y->cnt>=n, "PolynomialBuildCheb2: Length(Y)<N!", _state);
12977  ae_assert(ae_isfinite(a, _state), "PolynomialBuildCheb2: A is infinite or NaN!", _state);
12978  ae_assert(ae_isfinite(b, _state), "PolynomialBuildCheb2: B is infinite or NaN!", _state);
12979  ae_assert(ae_fp_neq(b,a), "PolynomialBuildCheb2: B=A!", _state);
12980  ae_assert(isfinitevector(y, n, _state), "PolynomialBuildCheb2: Y contains infinite or NaN values!", _state);
12981 
12982  /*
12983  * Special case: N=1
12984  */
12985  if( n==1 )
12986  {
12987  ae_vector_set_length(&x, 1, _state);
12988  ae_vector_set_length(&w, 1, _state);
12989  x.ptr.p_double[0] = 0.5*(b+a);
12990  w.ptr.p_double[0] = 1;
12991  barycentricbuildxyw(&x, y, &w, 1, p, _state);
12992  ae_frame_leave(_state);
12993  return;
12994  }
12995 
12996  /*
12997  * general case
12998  */
12999  ae_vector_set_length(&x, n, _state);
13000  ae_vector_set_length(&w, n, _state);
13001  v = 1;
13002  for(i=0; i<=n-1; i++)
13003  {
13004  if( i==0||i==n-1 )
13005  {
13006  w.ptr.p_double[i] = v*0.5;
13007  }
13008  else
13009  {
13010  w.ptr.p_double[i] = v;
13011  }
13012  x.ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*i/(n-1), _state);
13013  v = -v;
13014  }
13015  barycentricbuildxyw(&x, y, &w, n, p, _state);
13016  ae_frame_leave(_state);
13017 }
13018 
13019 
13020 /*************************************************************************
13021 Fast equidistant polynomial interpolation function with O(N) complexity
13022 
13023 INPUT PARAMETERS:
13024  A - left boundary of [A,B]
13025  B - right boundary of [A,B]
13026  F - function values, array[0..N-1]
13027  N - number of points on equidistant grid, N>=1
13028  for N=1 a constant model is constructed.
13029  T - position where P(x) is calculated
13030 
13031 RESULT
13032  value of the Lagrange interpolant at T
13033 
13034 IMPORTANT
13035  this function provides fast interface which is not overflow-safe
13036  nor it is very precise.
13037  the best option is to use PolynomialBuildEqDist()/BarycentricCalc()
13038  subroutines unless you are pretty sure that your data will not result
13039  in overflow.
13040 
13041  -- ALGLIB --
13042  Copyright 02.12.2009 by Bochkanov Sergey
13043 *************************************************************************/
13044 double polynomialcalceqdist(double a,
13045  double b,
13046  /* Real */ ae_vector* f,
13047  ae_int_t n,
13048  double t,
13049  ae_state *_state)
13050 {
13051  double s1;
13052  double s2;
13053  double v;
13054  double threshold;
13055  double s;
13056  double h;
13057  ae_int_t i;
13058  ae_int_t j;
13059  double w;
13060  double x;
13061  double result;
13062 
13063 
13064  ae_assert(n>0, "PolynomialCalcEqDist: N<=0!", _state);
13065  ae_assert(f->cnt>=n, "PolynomialCalcEqDist: Length(F)<N!", _state);
13066  ae_assert(ae_isfinite(a, _state), "PolynomialCalcEqDist: A is infinite or NaN!", _state);
13067  ae_assert(ae_isfinite(b, _state), "PolynomialCalcEqDist: B is infinite or NaN!", _state);
13068  ae_assert(isfinitevector(f, n, _state), "PolynomialCalcEqDist: F contains infinite or NaN values!", _state);
13069  ae_assert(ae_fp_neq(b,a), "PolynomialCalcEqDist: B=A!", _state);
13070  ae_assert(!ae_isinf(t, _state), "PolynomialCalcEqDist: T is infinite!", _state);
13071 
13072  /*
13073  * Special case: T is NAN
13074  */
13075  if( ae_isnan(t, _state) )
13076  {
13077  result = _state->v_nan;
13078  return result;
13079  }
13080 
13081  /*
13082  * Special case: N=1
13083  */
13084  if( n==1 )
13085  {
13086  result = f->ptr.p_double[0];
13087  return result;
13088  }
13089 
13090  /*
13091  * First, decide: should we use "safe" formula (guarded
13092  * against overflow) or fast one?
13093  */
13094  threshold = ae_sqrt(ae_minrealnumber, _state);
13095  j = 0;
13096  s = t-a;
13097  for(i=1; i<=n-1; i++)
13098  {
13099  x = a+(double)i/(double)(n-1)*(b-a);
13100  if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) )
13101  {
13102  s = t-x;
13103  j = i;
13104  }
13105  }
13106  if( ae_fp_eq(s,0) )
13107  {
13108  result = f->ptr.p_double[j];
13109  return result;
13110  }
13111  if( ae_fp_greater(ae_fabs(s, _state),threshold) )
13112  {
13113 
13114  /*
13115  * use fast formula
13116  */
13117  j = -1;
13118  s = 1.0;
13119  }
13120 
13121  /*
13122  * Calculate using safe or fast barycentric formula
13123  */
13124  s1 = 0;
13125  s2 = 0;
13126  w = 1.0;
13127  h = (b-a)/(n-1);
13128  for(i=0; i<=n-1; i++)
13129  {
13130  if( i!=j )
13131  {
13132  v = s*w/(t-(a+i*h));
13133  s1 = s1+v*f->ptr.p_double[i];
13134  s2 = s2+v;
13135  }
13136  else
13137  {
13138  v = w;
13139  s1 = s1+v*f->ptr.p_double[i];
13140  s2 = s2+v;
13141  }
13142  w = -w*(n-1-i);
13143  w = w/(i+1);
13144  }
13145  result = s1/s2;
13146  return result;
13147 }
13148 
13149 
13150 /*************************************************************************
13151 Fast polynomial interpolation function on Chebyshev points (first kind)
13152 with O(N) complexity.
13153 
13154 INPUT PARAMETERS:
13155  A - left boundary of [A,B]
13156  B - right boundary of [A,B]
13157  F - function values, array[0..N-1]
13158  N - number of points on Chebyshev grid (first kind),
13159  X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n))
13160  for N=1 a constant model is constructed.
13161  T - position where P(x) is calculated
13162 
13163 RESULT
13164  value of the Lagrange interpolant at T
13165 
13166 IMPORTANT
13167  this function provides fast interface which is not overflow-safe
13168  nor it is very precise.
13169  the best option is to use PolIntBuildCheb1()/BarycentricCalc()
13170  subroutines unless you are pretty sure that your data will not result
13171  in overflow.
13172 
13173  -- ALGLIB --
13174  Copyright 02.12.2009 by Bochkanov Sergey
13175 *************************************************************************/
13176 double polynomialcalccheb1(double a,
13177  double b,
13178  /* Real */ ae_vector* f,
13179  ae_int_t n,
13180  double t,
13181  ae_state *_state)
13182 {
13183  double s1;
13184  double s2;
13185  double v;
13186  double threshold;
13187  double s;
13188  ae_int_t i;
13189  ae_int_t j;
13190  double a0;
13191  double delta;
13192  double alpha;
13193  double beta;
13194  double ca;
13195  double sa;
13196  double tempc;
13197  double temps;
13198  double x;
13199  double w;
13200  double p1;
13201  double result;
13202 
13203 
13204  ae_assert(n>0, "PolynomialCalcCheb1: N<=0!", _state);
13205  ae_assert(f->cnt>=n, "PolynomialCalcCheb1: Length(F)<N!", _state);
13206  ae_assert(ae_isfinite(a, _state), "PolynomialCalcCheb1: A is infinite or NaN!", _state);
13207  ae_assert(ae_isfinite(b, _state), "PolynomialCalcCheb1: B is infinite or NaN!", _state);
13208  ae_assert(isfinitevector(f, n, _state), "PolynomialCalcCheb1: F contains infinite or NaN values!", _state);
13209  ae_assert(ae_fp_neq(b,a), "PolynomialCalcCheb1: B=A!", _state);
13210  ae_assert(!ae_isinf(t, _state), "PolynomialCalcCheb1: T is infinite!", _state);
13211 
13212  /*
13213  * Special case: T is NAN
13214  */
13215  if( ae_isnan(t, _state) )
13216  {
13217  result = _state->v_nan;
13218  return result;
13219  }
13220 
13221  /*
13222  * Special case: N=1
13223  */
13224  if( n==1 )
13225  {
13226  result = f->ptr.p_double[0];
13227  return result;
13228  }
13229 
13230  /*
13231  * Prepare information for the recurrence formula
13232  * used to calculate sin(pi*(2j+1)/(2n+2)) and
13233  * cos(pi*(2j+1)/(2n+2)):
13234  *
13235  * A0 = pi/(2n+2)
13236  * Delta = pi/(n+1)
13237  * Alpha = 2 sin^2 (Delta/2)
13238  * Beta = sin(Delta)
13239  *
13240  * so that sin(..) = sin(A0+j*delta) and cos(..) = cos(A0+j*delta).
13241  * Then we use
13242  *
13243  * sin(x+delta) = sin(x) - (alpha*sin(x) - beta*cos(x))
13244  * cos(x+delta) = cos(x) - (alpha*cos(x) - beta*sin(x))
13245  *
13246  * to repeatedly calculate sin(..) and cos(..).
13247  */
13248  threshold = ae_sqrt(ae_minrealnumber, _state);
13249  t = (t-0.5*(a+b))/(0.5*(b-a));
13250  a0 = ae_pi/(2*(n-1)+2);
13251  delta = 2*ae_pi/(2*(n-1)+2);
13252  alpha = 2*ae_sqr(ae_sin(delta/2, _state), _state);
13253  beta = ae_sin(delta, _state);
13254 
13255  /*
13256  * First, decide: should we use "safe" formula (guarded
13257  * against overflow) or fast one?
13258  */
13259  ca = ae_cos(a0, _state);
13260  sa = ae_sin(a0, _state);
13261  j = 0;
13262  x = ca;
13263  s = t-x;
13264  for(i=1; i<=n-1; i++)
13265  {
13266 
13267  /*
13268  * Next X[i]
13269  */
13270  temps = sa-(alpha*sa-beta*ca);
13271  tempc = ca-(alpha*ca+beta*sa);
13272  sa = temps;
13273  ca = tempc;
13274  x = ca;
13275 
13276  /*
13277  * Use X[i]
13278  */
13279  if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) )
13280  {
13281  s = t-x;
13282  j = i;
13283  }
13284  }
13285  if( ae_fp_eq(s,0) )
13286  {
13287  result = f->ptr.p_double[j];
13288  return result;
13289  }
13290  if( ae_fp_greater(ae_fabs(s, _state),threshold) )
13291  {
13292 
13293  /*
13294  * use fast formula
13295  */
13296  j = -1;
13297  s = 1.0;
13298  }
13299 
13300  /*
13301  * Calculate using safe or fast barycentric formula
13302  */
13303  s1 = 0;
13304  s2 = 0;
13305  ca = ae_cos(a0, _state);
13306  sa = ae_sin(a0, _state);
13307  p1 = 1.0;
13308  for(i=0; i<=n-1; i++)
13309  {
13310 
13311  /*
13312  * Calculate X[i], W[i]
13313  */
13314  x = ca;
13315  w = p1*sa;
13316 
13317  /*
13318  * Proceed
13319  */
13320  if( i!=j )
13321  {
13322  v = s*w/(t-x);
13323  s1 = s1+v*f->ptr.p_double[i];
13324  s2 = s2+v;
13325  }
13326  else
13327  {
13328  v = w;
13329  s1 = s1+v*f->ptr.p_double[i];
13330  s2 = s2+v;
13331  }
13332 
13333  /*
13334  * Next CA, SA, P1
13335  */
13336  temps = sa-(alpha*sa-beta*ca);
13337  tempc = ca-(alpha*ca+beta*sa);
13338  sa = temps;
13339  ca = tempc;
13340  p1 = -p1;
13341  }
13342  result = s1/s2;
13343  return result;
13344 }
13345 
13346 
13347 /*************************************************************************
13348 Fast polynomial interpolation function on Chebyshev points (second kind)
13349 with O(N) complexity.
13350 
13351 INPUT PARAMETERS:
13352  A - left boundary of [A,B]
13353  B - right boundary of [A,B]
13354  F - function values, array[0..N-1]
13355  N - number of points on Chebyshev grid (second kind),
13356  X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))
13357  for N=1 a constant model is constructed.
13358  T - position where P(x) is calculated
13359 
13360 RESULT
13361  value of the Lagrange interpolant at T
13362 
13363 IMPORTANT
13364  this function provides fast interface which is not overflow-safe
13365  nor it is very precise.
13366  the best option is to use PolIntBuildCheb2()/BarycentricCalc()
13367  subroutines unless you are pretty sure that your data will not result
13368  in overflow.
13369 
13370  -- ALGLIB --
13371  Copyright 02.12.2009 by Bochkanov Sergey
13372 *************************************************************************/
13373 double polynomialcalccheb2(double a,
13374  double b,
13375  /* Real */ ae_vector* f,
13376  ae_int_t n,
13377  double t,
13378  ae_state *_state)
13379 {
13380  double s1;
13381  double s2;
13382  double v;
13383  double threshold;
13384  double s;
13385  ae_int_t i;
13386  ae_int_t j;
13387  double a0;
13388  double delta;
13389  double alpha;
13390  double beta;
13391  double ca;
13392  double sa;
13393  double tempc;
13394  double temps;
13395  double x;
13396  double w;
13397  double p1;
13398  double result;
13399 
13400 
13401  ae_assert(n>0, "PolynomialCalcCheb2: N<=0!", _state);
13402  ae_assert(f->cnt>=n, "PolynomialCalcCheb2: Length(F)<N!", _state);
13403  ae_assert(ae_isfinite(a, _state), "PolynomialCalcCheb2: A is infinite or NaN!", _state);
13404  ae_assert(ae_isfinite(b, _state), "PolynomialCalcCheb2: B is infinite or NaN!", _state);
13405  ae_assert(ae_fp_neq(b,a), "PolynomialCalcCheb2: B=A!", _state);
13406  ae_assert(isfinitevector(f, n, _state), "PolynomialCalcCheb2: F contains infinite or NaN values!", _state);
13407  ae_assert(!ae_isinf(t, _state), "PolynomialCalcEqDist: T is infinite!", _state);
13408 
13409  /*
13410  * Special case: T is NAN
13411  */
13412  if( ae_isnan(t, _state) )
13413  {
13414  result = _state->v_nan;
13415  return result;
13416  }
13417 
13418  /*
13419  * Special case: N=1
13420  */
13421  if( n==1 )
13422  {
13423  result = f->ptr.p_double[0];
13424  return result;
13425  }
13426 
13427  /*
13428  * Prepare information for the recurrence formula
13429  * used to calculate sin(pi*i/n) and
13430  * cos(pi*i/n):
13431  *
13432  * A0 = 0
13433  * Delta = pi/n
13434  * Alpha = 2 sin^2 (Delta/2)
13435  * Beta = sin(Delta)
13436  *
13437  * so that sin(..) = sin(A0+j*delta) and cos(..) = cos(A0+j*delta).
13438  * Then we use
13439  *
13440  * sin(x+delta) = sin(x) - (alpha*sin(x) - beta*cos(x))
13441  * cos(x+delta) = cos(x) - (alpha*cos(x) - beta*sin(x))
13442  *
13443  * to repeatedly calculate sin(..) and cos(..).
13444  */
13445  threshold = ae_sqrt(ae_minrealnumber, _state);
13446  t = (t-0.5*(a+b))/(0.5*(b-a));
13447  a0 = 0.0;
13448  delta = ae_pi/(n-1);
13449  alpha = 2*ae_sqr(ae_sin(delta/2, _state), _state);
13450  beta = ae_sin(delta, _state);
13451 
13452  /*
13453  * First, decide: should we use "safe" formula (guarded
13454  * against overflow) or fast one?
13455  */
13456  ca = ae_cos(a0, _state);
13457  sa = ae_sin(a0, _state);
13458  j = 0;
13459  x = ca;
13460  s = t-x;
13461  for(i=1; i<=n-1; i++)
13462  {
13463 
13464  /*
13465  * Next X[i]
13466  */
13467  temps = sa-(alpha*sa-beta*ca);
13468  tempc = ca-(alpha*ca+beta*sa);
13469  sa = temps;
13470  ca = tempc;
13471  x = ca;
13472 
13473  /*
13474  * Use X[i]
13475  */
13476  if( ae_fp_less(ae_fabs(t-x, _state),ae_fabs(s, _state)) )
13477  {
13478  s = t-x;
13479  j = i;
13480  }
13481  }
13482  if( ae_fp_eq(s,0) )
13483  {
13484  result = f->ptr.p_double[j];
13485  return result;
13486  }
13487  if( ae_fp_greater(ae_fabs(s, _state),threshold) )
13488  {
13489 
13490  /*
13491  * use fast formula
13492  */
13493  j = -1;
13494  s = 1.0;
13495  }
13496 
13497  /*
13498  * Calculate using safe or fast barycentric formula
13499  */
13500  s1 = 0;
13501  s2 = 0;
13502  ca = ae_cos(a0, _state);
13503  sa = ae_sin(a0, _state);
13504  p1 = 1.0;
13505  for(i=0; i<=n-1; i++)
13506  {
13507 
13508  /*
13509  * Calculate X[i], W[i]
13510  */
13511  x = ca;
13512  if( i==0||i==n-1 )
13513  {
13514  w = 0.5*p1;
13515  }
13516  else
13517  {
13518  w = 1.0*p1;
13519  }
13520 
13521  /*
13522  * Proceed
13523  */
13524  if( i!=j )
13525  {
13526  v = s*w/(t-x);
13527  s1 = s1+v*f->ptr.p_double[i];
13528  s2 = s2+v;
13529  }
13530  else
13531  {
13532  v = w;
13533  s1 = s1+v*f->ptr.p_double[i];
13534  s2 = s2+v;
13535  }
13536 
13537  /*
13538  * Next CA, SA, P1
13539  */
13540  temps = sa-(alpha*sa-beta*ca);
13541  tempc = ca-(alpha*ca+beta*sa);
13542  sa = temps;
13543  ca = tempc;
13544  p1 = -p1;
13545  }
13546  result = s1/s2;
13547  return result;
13548 }
13549 
13550 
13551 
13552 
13553 /*************************************************************************
13554 This subroutine builds linear spline interpolant
13555 
13556 INPUT PARAMETERS:
13557  X - spline nodes, array[0..N-1]
13558  Y - function values, array[0..N-1]
13559  N - points count (optional):
13560  * N>=2
13561  * if given, only first N points are used to build spline
13562  * if not given, automatically detected from X/Y sizes
13563  (len(X) must be equal to len(Y))
13564 
13565 OUTPUT PARAMETERS:
13566  C - spline interpolant
13567 
13568 
13569 ORDER OF POINTS
13570 
13571 Subroutine automatically sorts points, so caller may pass unsorted array.
13572 
13573  -- ALGLIB PROJECT --
13574  Copyright 24.06.2007 by Bochkanov Sergey
13575 *************************************************************************/
13576 void spline1dbuildlinear(/* Real */ ae_vector* x,
13577  /* Real */ ae_vector* y,
13578  ae_int_t n,
13580  ae_state *_state)
13581 {
13582  ae_frame _frame_block;
13583  ae_vector _x;
13584  ae_vector _y;
13585  ae_int_t i;
13586 
13587  ae_frame_make(_state, &_frame_block);
13588  ae_vector_init_copy(&_x, x, _state, ae_true);
13589  x = &_x;
13590  ae_vector_init_copy(&_y, y, _state, ae_true);
13591  y = &_y;
13593 
13594  ae_assert(n>1, "Spline1DBuildLinear: N<2!", _state);
13595  ae_assert(x->cnt>=n, "Spline1DBuildLinear: Length(X)<N!", _state);
13596  ae_assert(y->cnt>=n, "Spline1DBuildLinear: Length(Y)<N!", _state);
13597 
13598  /*
13599  * check and sort points
13600  */
13601  ae_assert(isfinitevector(x, n, _state), "Spline1DBuildLinear: X contains infinite or NAN values!", _state);
13602  ae_assert(isfinitevector(y, n, _state), "Spline1DBuildLinear: Y contains infinite or NAN values!", _state);
13603  spline1d_heapsortpoints(x, y, n, _state);
13604  ae_assert(aredistinct(x, n, _state), "Spline1DBuildLinear: at least two consequent points are too close!", _state);
13605 
13606  /*
13607  * Build
13608  */
13609  c->periodic = ae_false;
13610  c->n = n;
13611  c->k = 3;
13612  c->continuity = 0;
13613  ae_vector_set_length(&c->x, n, _state);
13614  ae_vector_set_length(&c->c, 4*(n-1)+2, _state);
13615  for(i=0; i<=n-1; i++)
13616  {
13617  c->x.ptr.p_double[i] = x->ptr.p_double[i];
13618  }
13619  for(i=0; i<=n-2; i++)
13620  {
13621  c->c.ptr.p_double[4*i+0] = y->ptr.p_double[i];
13622  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]);
13623  c->c.ptr.p_double[4*i+2] = 0;
13624  c->c.ptr.p_double[4*i+3] = 0;
13625  }
13626  c->c.ptr.p_double[4*(n-1)+0] = y->ptr.p_double[n-1];
13627  c->c.ptr.p_double[4*(n-1)+1] = c->c.ptr.p_double[4*(n-2)+1];
13628  ae_frame_leave(_state);
13629 }
13630 
13631 
13632 /*************************************************************************
13633 This subroutine builds cubic spline interpolant.
13634 
13635 INPUT PARAMETERS:
13636  X - spline nodes, array[0..N-1].
13637  Y - function values, array[0..N-1].
13638 
13639 OPTIONAL PARAMETERS:
13640  N - points count:
13641  * N>=2
13642  * if given, only first N points are used to build spline
13643  * if not given, automatically detected from X/Y sizes
13644  (len(X) must be equal to len(Y))
13645  BoundLType - boundary condition type for the left boundary
13646  BoundL - left boundary condition (first or second derivative,
13647  depending on the BoundLType)
13648  BoundRType - boundary condition type for the right boundary
13649  BoundR - right boundary condition (first or second derivative,
13650  depending on the BoundRType)
13651 
13652 OUTPUT PARAMETERS:
13653  C - spline interpolant
13654 
13655 ORDER OF POINTS
13656 
13657 Subroutine automatically sorts points, so caller may pass unsorted array.
13658 
13659 SETTING BOUNDARY VALUES:
13660 
13661 The BoundLType/BoundRType parameters can have the following values:
13662  * -1, which corresonds to the periodic (cyclic) boundary conditions.
13663  In this case:
13664  * both BoundLType and BoundRType must be equal to -1.
13665  * BoundL/BoundR are ignored
13666  * Y[last] is ignored (it is assumed to be equal to Y[first]).
13667  * 0, which corresponds to the parabolically terminated spline
13668  (BoundL and/or BoundR are ignored).
13669  * 1, which corresponds to the first derivative boundary condition
13670  * 2, which corresponds to the second derivative boundary condition
13671  * by default, BoundType=0 is used
13672 
13673 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
13674 
13675 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
13676 However, this subroutine doesn't require you to specify equal values for
13677 the first and last points - it automatically forces them to be equal by
13678 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
13679 Y[last_point]. However it is recommended to pass consistent values of Y[],
13680 i.e. to make Y[first_point]=Y[last_point].
13681 
13682  -- ALGLIB PROJECT --
13683  Copyright 23.06.2007 by Bochkanov Sergey
13684 *************************************************************************/
13685 void spline1dbuildcubic(/* Real */ ae_vector* x,
13686  /* Real */ ae_vector* y,
13687  ae_int_t n,
13688  ae_int_t boundltype,
13689  double boundl,
13690  ae_int_t boundrtype,
13691  double boundr,
13693  ae_state *_state)
13694 {
13695  ae_frame _frame_block;
13696  ae_vector _x;
13697  ae_vector _y;
13698  ae_vector a1;
13699  ae_vector a2;
13700  ae_vector a3;
13701  ae_vector b;
13702  ae_vector dt;
13703  ae_vector d;
13704  ae_vector p;
13705  ae_int_t ylen;
13706 
13707  ae_frame_make(_state, &_frame_block);
13708  ae_vector_init_copy(&_x, x, _state, ae_true);
13709  x = &_x;
13710  ae_vector_init_copy(&_y, y, _state, ae_true);
13711  y = &_y;
13713  ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
13714  ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
13715  ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
13716  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
13717  ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
13718  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
13719  ae_vector_init(&p, 0, DT_INT, _state, ae_true);
13720 
13721 
13722  /*
13723  * check correctness of boundary conditions
13724  */
13725  ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DBuildCubic: incorrect BoundLType!", _state);
13726  ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DBuildCubic: incorrect BoundRType!", _state);
13727  ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DBuildCubic: incorrect BoundLType/BoundRType!", _state);
13728  if( boundltype==1||boundltype==2 )
13729  {
13730  ae_assert(ae_isfinite(boundl, _state), "Spline1DBuildCubic: BoundL is infinite or NAN!", _state);
13731  }
13732  if( boundrtype==1||boundrtype==2 )
13733  {
13734  ae_assert(ae_isfinite(boundr, _state), "Spline1DBuildCubic: BoundR is infinite or NAN!", _state);
13735  }
13736 
13737  /*
13738  * check lengths of arguments
13739  */
13740  ae_assert(n>=2, "Spline1DBuildCubic: N<2!", _state);
13741  ae_assert(x->cnt>=n, "Spline1DBuildCubic: Length(X)<N!", _state);
13742  ae_assert(y->cnt>=n, "Spline1DBuildCubic: Length(Y)<N!", _state);
13743 
13744  /*
13745  * check and sort points
13746  */
13747  ylen = n;
13748  if( boundltype==-1 )
13749  {
13750  ylen = n-1;
13751  }
13752  ae_assert(isfinitevector(x, n, _state), "Spline1DBuildCubic: X contains infinite or NAN values!", _state);
13753  ae_assert(isfinitevector(y, ylen, _state), "Spline1DBuildCubic: Y contains infinite or NAN values!", _state);
13754  spline1d_heapsortppoints(x, y, &p, n, _state);
13755  ae_assert(aredistinct(x, n, _state), "Spline1DBuildCubic: at least two consequent points are too close!", _state);
13756 
13757  /*
13758  * Now we've checked and preordered everything,
13759  * so we can call internal function to calculate derivatives,
13760  * and then build Hermite spline using these derivatives
13761  */
13762  if( boundltype==-1||boundrtype==-1 )
13763  {
13764  y->ptr.p_double[n-1] = y->ptr.p_double[0];
13765  }
13766  spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
13767  spline1dbuildhermite(x, y, &d, n, c, _state);
13768  c->periodic = boundltype==-1||boundrtype==-1;
13769  c->continuity = 2;
13770  ae_frame_leave(_state);
13771 }
13772 
13773 
13774 /*************************************************************************
13775 This function solves following problem: given table y[] of function values
13776 at nodes x[], it calculates and returns table of function derivatives d[]
13777 (calculated at the same nodes x[]).
13778 
13779 This function yields same result as Spline1DBuildCubic() call followed by
13780 sequence of Spline1DDiff() calls, but it can be several times faster when
13781 called for ordered X[] and X2[].
13782 
13783 INPUT PARAMETERS:
13784  X - spline nodes
13785  Y - function values
13786 
13787 OPTIONAL PARAMETERS:
13788  N - points count:
13789  * N>=2
13790  * if given, only first N points are used
13791  * if not given, automatically detected from X/Y sizes
13792  (len(X) must be equal to len(Y))
13793  BoundLType - boundary condition type for the left boundary
13794  BoundL - left boundary condition (first or second derivative,
13795  depending on the BoundLType)
13796  BoundRType - boundary condition type for the right boundary
13797  BoundR - right boundary condition (first or second derivative,
13798  depending on the BoundRType)
13799 
13800 OUTPUT PARAMETERS:
13801  D - derivative values at X[]
13802 
13803 ORDER OF POINTS
13804 
13805 Subroutine automatically sorts points, so caller may pass unsorted array.
13806 Derivative values are correctly reordered on return, so D[I] is always
13807 equal to S'(X[I]) independently of points order.
13808 
13809 SETTING BOUNDARY VALUES:
13810 
13811 The BoundLType/BoundRType parameters can have the following values:
13812  * -1, which corresonds to the periodic (cyclic) boundary conditions.
13813  In this case:
13814  * both BoundLType and BoundRType must be equal to -1.
13815  * BoundL/BoundR are ignored
13816  * Y[last] is ignored (it is assumed to be equal to Y[first]).
13817  * 0, which corresponds to the parabolically terminated spline
13818  (BoundL and/or BoundR are ignored).
13819  * 1, which corresponds to the first derivative boundary condition
13820  * 2, which corresponds to the second derivative boundary condition
13821  * by default, BoundType=0 is used
13822 
13823 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
13824 
13825 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
13826 However, this subroutine doesn't require you to specify equal values for
13827 the first and last points - it automatically forces them to be equal by
13828 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
13829 Y[last_point]. However it is recommended to pass consistent values of Y[],
13830 i.e. to make Y[first_point]=Y[last_point].
13831 
13832  -- ALGLIB PROJECT --
13833  Copyright 03.09.2010 by Bochkanov Sergey
13834 *************************************************************************/
13836  /* Real */ ae_vector* y,
13837  ae_int_t n,
13838  ae_int_t boundltype,
13839  double boundl,
13840  ae_int_t boundrtype,
13841  double boundr,
13842  /* Real */ ae_vector* d,
13843  ae_state *_state)
13844 {
13845  ae_frame _frame_block;
13846  ae_vector _x;
13847  ae_vector _y;
13848  ae_vector a1;
13849  ae_vector a2;
13850  ae_vector a3;
13851  ae_vector b;
13852  ae_vector dt;
13853  ae_vector p;
13854  ae_int_t i;
13855  ae_int_t ylen;
13856 
13857  ae_frame_make(_state, &_frame_block);
13858  ae_vector_init_copy(&_x, x, _state, ae_true);
13859  x = &_x;
13860  ae_vector_init_copy(&_y, y, _state, ae_true);
13861  y = &_y;
13862  ae_vector_clear(d);
13863  ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
13864  ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
13865  ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
13866  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
13867  ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
13868  ae_vector_init(&p, 0, DT_INT, _state, ae_true);
13869 
13870 
13871  /*
13872  * check correctness of boundary conditions
13873  */
13874  ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DGridDiffCubic: incorrect BoundLType!", _state);
13875  ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DGridDiffCubic: incorrect BoundRType!", _state);
13876  ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DGridDiffCubic: incorrect BoundLType/BoundRType!", _state);
13877  if( boundltype==1||boundltype==2 )
13878  {
13879  ae_assert(ae_isfinite(boundl, _state), "Spline1DGridDiffCubic: BoundL is infinite or NAN!", _state);
13880  }
13881  if( boundrtype==1||boundrtype==2 )
13882  {
13883  ae_assert(ae_isfinite(boundr, _state), "Spline1DGridDiffCubic: BoundR is infinite or NAN!", _state);
13884  }
13885 
13886  /*
13887  * check lengths of arguments
13888  */
13889  ae_assert(n>=2, "Spline1DGridDiffCubic: N<2!", _state);
13890  ae_assert(x->cnt>=n, "Spline1DGridDiffCubic: Length(X)<N!", _state);
13891  ae_assert(y->cnt>=n, "Spline1DGridDiffCubic: Length(Y)<N!", _state);
13892 
13893  /*
13894  * check and sort points
13895  */
13896  ylen = n;
13897  if( boundltype==-1 )
13898  {
13899  ylen = n-1;
13900  }
13901  ae_assert(isfinitevector(x, n, _state), "Spline1DGridDiffCubic: X contains infinite or NAN values!", _state);
13902  ae_assert(isfinitevector(y, ylen, _state), "Spline1DGridDiffCubic: Y contains infinite or NAN values!", _state);
13903  spline1d_heapsortppoints(x, y, &p, n, _state);
13904  ae_assert(aredistinct(x, n, _state), "Spline1DGridDiffCubic: at least two consequent points are too close!", _state);
13905 
13906  /*
13907  * Now we've checked and preordered everything,
13908  * so we can call internal function.
13909  */
13910  spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, d, &a1, &a2, &a3, &b, &dt, _state);
13911 
13912  /*
13913  * Remember that HeapSortPPoints() call?
13914  * Now we have to reorder them back.
13915  */
13916  if( dt.cnt<n )
13917  {
13918  ae_vector_set_length(&dt, n, _state);
13919  }
13920  for(i=0; i<=n-1; i++)
13921  {
13922  dt.ptr.p_double[p.ptr.p_int[i]] = d->ptr.p_double[i];
13923  }
13924  ae_v_move(&d->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1));
13925  ae_frame_leave(_state);
13926 }
13927 
13928 
13929 /*************************************************************************
13930 This function solves following problem: given table y[] of function values
13931 at nodes x[], it calculates and returns tables of first and second
13932 function derivatives d1[] and d2[] (calculated at the same nodes x[]).
13933 
13934 This function yields same result as Spline1DBuildCubic() call followed by
13935 sequence of Spline1DDiff() calls, but it can be several times faster when
13936 called for ordered X[] and X2[].
13937 
13938 INPUT PARAMETERS:
13939  X - spline nodes
13940  Y - function values
13941 
13942 OPTIONAL PARAMETERS:
13943  N - points count:
13944  * N>=2
13945  * if given, only first N points are used
13946  * if not given, automatically detected from X/Y sizes
13947  (len(X) must be equal to len(Y))
13948  BoundLType - boundary condition type for the left boundary
13949  BoundL - left boundary condition (first or second derivative,
13950  depending on the BoundLType)
13951  BoundRType - boundary condition type for the right boundary
13952  BoundR - right boundary condition (first or second derivative,
13953  depending on the BoundRType)
13954 
13955 OUTPUT PARAMETERS:
13956  D1 - S' values at X[]
13957  D2 - S'' values at X[]
13958 
13959 ORDER OF POINTS
13960 
13961 Subroutine automatically sorts points, so caller may pass unsorted array.
13962 Derivative values are correctly reordered on return, so D[I] is always
13963 equal to S'(X[I]) independently of points order.
13964 
13965 SETTING BOUNDARY VALUES:
13966 
13967 The BoundLType/BoundRType parameters can have the following values:
13968  * -1, which corresonds to the periodic (cyclic) boundary conditions.
13969  In this case:
13970  * both BoundLType and BoundRType must be equal to -1.
13971  * BoundL/BoundR are ignored
13972  * Y[last] is ignored (it is assumed to be equal to Y[first]).
13973  * 0, which corresponds to the parabolically terminated spline
13974  (BoundL and/or BoundR are ignored).
13975  * 1, which corresponds to the first derivative boundary condition
13976  * 2, which corresponds to the second derivative boundary condition
13977  * by default, BoundType=0 is used
13978 
13979 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
13980 
13981 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
13982 However, this subroutine doesn't require you to specify equal values for
13983 the first and last points - it automatically forces them to be equal by
13984 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
13985 Y[last_point]. However it is recommended to pass consistent values of Y[],
13986 i.e. to make Y[first_point]=Y[last_point].
13987 
13988  -- ALGLIB PROJECT --
13989  Copyright 03.09.2010 by Bochkanov Sergey
13990 *************************************************************************/
13992  /* Real */ ae_vector* y,
13993  ae_int_t n,
13994  ae_int_t boundltype,
13995  double boundl,
13996  ae_int_t boundrtype,
13997  double boundr,
13998  /* Real */ ae_vector* d1,
13999  /* Real */ ae_vector* d2,
14000  ae_state *_state)
14001 {
14002  ae_frame _frame_block;
14003  ae_vector _x;
14004  ae_vector _y;
14005  ae_vector a1;
14006  ae_vector a2;
14007  ae_vector a3;
14008  ae_vector b;
14009  ae_vector dt;
14010  ae_vector p;
14011  ae_int_t i;
14012  ae_int_t ylen;
14013  double delta;
14014  double delta2;
14015  double delta3;
14016  double s2;
14017  double s3;
14018 
14019  ae_frame_make(_state, &_frame_block);
14020  ae_vector_init_copy(&_x, x, _state, ae_true);
14021  x = &_x;
14022  ae_vector_init_copy(&_y, y, _state, ae_true);
14023  y = &_y;
14024  ae_vector_clear(d1);
14025  ae_vector_clear(d2);
14026  ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
14027  ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
14028  ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
14029  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
14030  ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
14031  ae_vector_init(&p, 0, DT_INT, _state, ae_true);
14032 
14033 
14034  /*
14035  * check correctness of boundary conditions
14036  */
14037  ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DGridDiff2Cubic: incorrect BoundLType!", _state);
14038  ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DGridDiff2Cubic: incorrect BoundRType!", _state);
14039  ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DGridDiff2Cubic: incorrect BoundLType/BoundRType!", _state);
14040  if( boundltype==1||boundltype==2 )
14041  {
14042  ae_assert(ae_isfinite(boundl, _state), "Spline1DGridDiff2Cubic: BoundL is infinite or NAN!", _state);
14043  }
14044  if( boundrtype==1||boundrtype==2 )
14045  {
14046  ae_assert(ae_isfinite(boundr, _state), "Spline1DGridDiff2Cubic: BoundR is infinite or NAN!", _state);
14047  }
14048 
14049  /*
14050  * check lengths of arguments
14051  */
14052  ae_assert(n>=2, "Spline1DGridDiff2Cubic: N<2!", _state);
14053  ae_assert(x->cnt>=n, "Spline1DGridDiff2Cubic: Length(X)<N!", _state);
14054  ae_assert(y->cnt>=n, "Spline1DGridDiff2Cubic: Length(Y)<N!", _state);
14055 
14056  /*
14057  * check and sort points
14058  */
14059  ylen = n;
14060  if( boundltype==-1 )
14061  {
14062  ylen = n-1;
14063  }
14064  ae_assert(isfinitevector(x, n, _state), "Spline1DGridDiff2Cubic: X contains infinite or NAN values!", _state);
14065  ae_assert(isfinitevector(y, ylen, _state), "Spline1DGridDiff2Cubic: Y contains infinite or NAN values!", _state);
14066  spline1d_heapsortppoints(x, y, &p, n, _state);
14067  ae_assert(aredistinct(x, n, _state), "Spline1DGridDiff2Cubic: at least two consequent points are too close!", _state);
14068 
14069  /*
14070  * Now we've checked and preordered everything,
14071  * so we can call internal function.
14072  *
14073  * After this call we will calculate second derivatives
14074  * (manually, by converting to the power basis)
14075  */
14076  spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, d1, &a1, &a2, &a3, &b, &dt, _state);
14077  ae_vector_set_length(d2, n, _state);
14078  delta = 0;
14079  s2 = 0;
14080  s3 = 0;
14081  for(i=0; i<=n-2; i++)
14082  {
14083 
14084  /*
14085  * We convert from Hermite basis to the power basis.
14086  * Si is coefficient before x^i.
14087  *
14088  * Inside this cycle we need just S2,
14089  * because we calculate S'' exactly at spline node,
14090  * (only x^2 matters at x=0), but after iterations
14091  * will be over, we will need other coefficients
14092  * to calculate spline value at the last node.
14093  */
14094  delta = x->ptr.p_double[i+1]-x->ptr.p_double[i];
14095  delta2 = ae_sqr(delta, _state);
14096  delta3 = delta*delta2;
14097  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;
14098  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;
14099  d2->ptr.p_double[i] = 2*s2;
14100  }
14101  d2->ptr.p_double[n-1] = 2*s2+6*s3*delta;
14102 
14103  /*
14104  * Remember that HeapSortPPoints() call?
14105  * Now we have to reorder them back.
14106  */
14107  if( dt.cnt<n )
14108  {
14109  ae_vector_set_length(&dt, n, _state);
14110  }
14111  for(i=0; i<=n-1; i++)
14112  {
14113  dt.ptr.p_double[p.ptr.p_int[i]] = d1->ptr.p_double[i];
14114  }
14115  ae_v_move(&d1->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1));
14116  for(i=0; i<=n-1; i++)
14117  {
14118  dt.ptr.p_double[p.ptr.p_int[i]] = d2->ptr.p_double[i];
14119  }
14120  ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n-1));
14121  ae_frame_leave(_state);
14122 }
14123 
14124 
14125 /*************************************************************************
14126 This function solves following problem: given table y[] of function values
14127 at old nodes x[] and new nodes x2[], it calculates and returns table of
14128 function values y2[] (calculated at x2[]).
14129 
14130 This function yields same result as Spline1DBuildCubic() call followed by
14131 sequence of Spline1DDiff() calls, but it can be several times faster when
14132 called for ordered X[] and X2[].
14133 
14134 INPUT PARAMETERS:
14135  X - old spline nodes
14136  Y - function values
14137  X2 - new spline nodes
14138 
14139 OPTIONAL PARAMETERS:
14140  N - points count:
14141  * N>=2
14142  * if given, only first N points from X/Y are used
14143  * if not given, automatically detected from X/Y sizes
14144  (len(X) must be equal to len(Y))
14145  BoundLType - boundary condition type for the left boundary
14146  BoundL - left boundary condition (first or second derivative,
14147  depending on the BoundLType)
14148  BoundRType - boundary condition type for the right boundary
14149  BoundR - right boundary condition (first or second derivative,
14150  depending on the BoundRType)
14151  N2 - new points count:
14152  * N2>=2
14153  * if given, only first N2 points from X2 are used
14154  * if not given, automatically detected from X2 size
14155 
14156 OUTPUT PARAMETERS:
14157  F2 - function values at X2[]
14158 
14159 ORDER OF POINTS
14160 
14161 Subroutine automatically sorts points, so caller may pass unsorted array.
14162 Function values are correctly reordered on return, so F2[I] is always
14163 equal to S(X2[I]) independently of points order.
14164 
14165 SETTING BOUNDARY VALUES:
14166 
14167 The BoundLType/BoundRType parameters can have the following values:
14168  * -1, which corresonds to the periodic (cyclic) boundary conditions.
14169  In this case:
14170  * both BoundLType and BoundRType must be equal to -1.
14171  * BoundL/BoundR are ignored
14172  * Y[last] is ignored (it is assumed to be equal to Y[first]).
14173  * 0, which corresponds to the parabolically terminated spline
14174  (BoundL and/or BoundR are ignored).
14175  * 1, which corresponds to the first derivative boundary condition
14176  * 2, which corresponds to the second derivative boundary condition
14177  * by default, BoundType=0 is used
14178 
14179 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
14180 
14181 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
14182 However, this subroutine doesn't require you to specify equal values for
14183 the first and last points - it automatically forces them to be equal by
14184 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
14185 Y[last_point]. However it is recommended to pass consistent values of Y[],
14186 i.e. to make Y[first_point]=Y[last_point].
14187 
14188  -- ALGLIB PROJECT --
14189  Copyright 03.09.2010 by Bochkanov Sergey
14190 *************************************************************************/
14191 void spline1dconvcubic(/* Real */ ae_vector* x,
14192  /* Real */ ae_vector* y,
14193  ae_int_t n,
14194  ae_int_t boundltype,
14195  double boundl,
14196  ae_int_t boundrtype,
14197  double boundr,
14198  /* Real */ ae_vector* x2,
14199  ae_int_t n2,
14200  /* Real */ ae_vector* y2,
14201  ae_state *_state)
14202 {
14203  ae_frame _frame_block;
14204  ae_vector _x;
14205  ae_vector _y;
14206  ae_vector _x2;
14207  ae_vector a1;
14208  ae_vector a2;
14209  ae_vector a3;
14210  ae_vector b;
14211  ae_vector d;
14212  ae_vector dt;
14213  ae_vector d1;
14214  ae_vector d2;
14215  ae_vector p;
14216  ae_vector p2;
14217  ae_int_t i;
14218  ae_int_t ylen;
14219  double t;
14220  double t2;
14221 
14222  ae_frame_make(_state, &_frame_block);
14223  ae_vector_init_copy(&_x, x, _state, ae_true);
14224  x = &_x;
14225  ae_vector_init_copy(&_y, y, _state, ae_true);
14226  y = &_y;
14227  ae_vector_init_copy(&_x2, x2, _state, ae_true);
14228  x2 = &_x2;
14229  ae_vector_clear(y2);
14230  ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
14231  ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
14232  ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
14233  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
14234  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
14235  ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
14236  ae_vector_init(&d1, 0, DT_REAL, _state, ae_true);
14237  ae_vector_init(&d2, 0, DT_REAL, _state, ae_true);
14238  ae_vector_init(&p, 0, DT_INT, _state, ae_true);
14239  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
14240 
14241 
14242  /*
14243  * check correctness of boundary conditions
14244  */
14245  ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvCubic: incorrect BoundLType!", _state);
14246  ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvCubic: incorrect BoundRType!", _state);
14247  ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvCubic: incorrect BoundLType/BoundRType!", _state);
14248  if( boundltype==1||boundltype==2 )
14249  {
14250  ae_assert(ae_isfinite(boundl, _state), "Spline1DConvCubic: BoundL is infinite or NAN!", _state);
14251  }
14252  if( boundrtype==1||boundrtype==2 )
14253  {
14254  ae_assert(ae_isfinite(boundr, _state), "Spline1DConvCubic: BoundR is infinite or NAN!", _state);
14255  }
14256 
14257  /*
14258  * check lengths of arguments
14259  */
14260  ae_assert(n>=2, "Spline1DConvCubic: N<2!", _state);
14261  ae_assert(x->cnt>=n, "Spline1DConvCubic: Length(X)<N!", _state);
14262  ae_assert(y->cnt>=n, "Spline1DConvCubic: Length(Y)<N!", _state);
14263  ae_assert(n2>=2, "Spline1DConvCubic: N2<2!", _state);
14264  ae_assert(x2->cnt>=n2, "Spline1DConvCubic: Length(X2)<N2!", _state);
14265 
14266  /*
14267  * check and sort X/Y
14268  */
14269  ylen = n;
14270  if( boundltype==-1 )
14271  {
14272  ylen = n-1;
14273  }
14274  ae_assert(isfinitevector(x, n, _state), "Spline1DConvCubic: X contains infinite or NAN values!", _state);
14275  ae_assert(isfinitevector(y, ylen, _state), "Spline1DConvCubic: Y contains infinite or NAN values!", _state);
14276  ae_assert(isfinitevector(x2, n2, _state), "Spline1DConvCubic: X2 contains infinite or NAN values!", _state);
14277  spline1d_heapsortppoints(x, y, &p, n, _state);
14278  ae_assert(aredistinct(x, n, _state), "Spline1DConvCubic: at least two consequent points are too close!", _state);
14279 
14280  /*
14281  * set up DT (we will need it below)
14282  */
14283  ae_vector_set_length(&dt, ae_maxint(n, n2, _state), _state);
14284 
14285  /*
14286  * sort X2:
14287  * * use fake array DT because HeapSortPPoints() needs both integer AND real arrays
14288  * * if we have periodic problem, wrap points
14289  * * sort them, store permutation at P2
14290  */
14291  if( boundrtype==-1&&boundltype==-1 )
14292  {
14293  for(i=0; i<=n2-1; i++)
14294  {
14295  t = x2->ptr.p_double[i];
14296  apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state);
14297  x2->ptr.p_double[i] = t;
14298  }
14299  }
14300  spline1d_heapsortppoints(x2, &dt, &p2, n2, _state);
14301 
14302  /*
14303  * Now we've checked and preordered everything, so we:
14304  * * call internal GridDiff() function to get Hermite form of spline
14305  * * convert using internal Conv() function
14306  * * convert Y2 back to original order
14307  */
14308  spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
14309  spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, &d1, ae_false, &d2, ae_false, _state);
14310  ae_assert(dt.cnt>=n2, "Spline1DConvCubic: internal error!", _state);
14311  for(i=0; i<=n2-1; i++)
14312  {
14313  dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i];
14314  }
14315  ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
14316  ae_frame_leave(_state);
14317 }
14318 
14319 
14320 /*************************************************************************
14321 This function solves following problem: given table y[] of function values
14322 at old nodes x[] and new nodes x2[], it calculates and returns table of
14323 function values y2[] and derivatives d2[] (calculated at x2[]).
14324 
14325 This function yields same result as Spline1DBuildCubic() call followed by
14326 sequence of Spline1DDiff() calls, but it can be several times faster when
14327 called for ordered X[] and X2[].
14328 
14329 INPUT PARAMETERS:
14330  X - old spline nodes
14331  Y - function values
14332  X2 - new spline nodes
14333 
14334 OPTIONAL PARAMETERS:
14335  N - points count:
14336  * N>=2
14337  * if given, only first N points from X/Y are used
14338  * if not given, automatically detected from X/Y sizes
14339  (len(X) must be equal to len(Y))
14340  BoundLType - boundary condition type for the left boundary
14341  BoundL - left boundary condition (first or second derivative,
14342  depending on the BoundLType)
14343  BoundRType - boundary condition type for the right boundary
14344  BoundR - right boundary condition (first or second derivative,
14345  depending on the BoundRType)
14346  N2 - new points count:
14347  * N2>=2
14348  * if given, only first N2 points from X2 are used
14349  * if not given, automatically detected from X2 size
14350 
14351 OUTPUT PARAMETERS:
14352  F2 - function values at X2[]
14353  D2 - first derivatives at X2[]
14354 
14355 ORDER OF POINTS
14356 
14357 Subroutine automatically sorts points, so caller may pass unsorted array.
14358 Function values are correctly reordered on return, so F2[I] is always
14359 equal to S(X2[I]) independently of points order.
14360 
14361 SETTING BOUNDARY VALUES:
14362 
14363 The BoundLType/BoundRType parameters can have the following values:
14364  * -1, which corresonds to the periodic (cyclic) boundary conditions.
14365  In this case:
14366  * both BoundLType and BoundRType must be equal to -1.
14367  * BoundL/BoundR are ignored
14368  * Y[last] is ignored (it is assumed to be equal to Y[first]).
14369  * 0, which corresponds to the parabolically terminated spline
14370  (BoundL and/or BoundR are ignored).
14371  * 1, which corresponds to the first derivative boundary condition
14372  * 2, which corresponds to the second derivative boundary condition
14373  * by default, BoundType=0 is used
14374 
14375 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
14376 
14377 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
14378 However, this subroutine doesn't require you to specify equal values for
14379 the first and last points - it automatically forces them to be equal by
14380 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
14381 Y[last_point]. However it is recommended to pass consistent values of Y[],
14382 i.e. to make Y[first_point]=Y[last_point].
14383 
14384  -- ALGLIB PROJECT --
14385  Copyright 03.09.2010 by Bochkanov Sergey
14386 *************************************************************************/
14388  /* Real */ ae_vector* y,
14389  ae_int_t n,
14390  ae_int_t boundltype,
14391  double boundl,
14392  ae_int_t boundrtype,
14393  double boundr,
14394  /* Real */ ae_vector* x2,
14395  ae_int_t n2,
14396  /* Real */ ae_vector* y2,
14397  /* Real */ ae_vector* d2,
14398  ae_state *_state)
14399 {
14400  ae_frame _frame_block;
14401  ae_vector _x;
14402  ae_vector _y;
14403  ae_vector _x2;
14404  ae_vector a1;
14405  ae_vector a2;
14406  ae_vector a3;
14407  ae_vector b;
14408  ae_vector d;
14409  ae_vector dt;
14410  ae_vector rt1;
14411  ae_vector p;
14412  ae_vector p2;
14413  ae_int_t i;
14414  ae_int_t ylen;
14415  double t;
14416  double t2;
14417 
14418  ae_frame_make(_state, &_frame_block);
14419  ae_vector_init_copy(&_x, x, _state, ae_true);
14420  x = &_x;
14421  ae_vector_init_copy(&_y, y, _state, ae_true);
14422  y = &_y;
14423  ae_vector_init_copy(&_x2, x2, _state, ae_true);
14424  x2 = &_x2;
14425  ae_vector_clear(y2);
14426  ae_vector_clear(d2);
14427  ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
14428  ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
14429  ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
14430  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
14431  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
14432  ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
14433  ae_vector_init(&rt1, 0, DT_REAL, _state, ae_true);
14434  ae_vector_init(&p, 0, DT_INT, _state, ae_true);
14435  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
14436 
14437 
14438  /*
14439  * check correctness of boundary conditions
14440  */
14441  ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvDiffCubic: incorrect BoundLType!", _state);
14442  ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvDiffCubic: incorrect BoundRType!", _state);
14443  ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvDiffCubic: incorrect BoundLType/BoundRType!", _state);
14444  if( boundltype==1||boundltype==2 )
14445  {
14446  ae_assert(ae_isfinite(boundl, _state), "Spline1DConvDiffCubic: BoundL is infinite or NAN!", _state);
14447  }
14448  if( boundrtype==1||boundrtype==2 )
14449  {
14450  ae_assert(ae_isfinite(boundr, _state), "Spline1DConvDiffCubic: BoundR is infinite or NAN!", _state);
14451  }
14452 
14453  /*
14454  * check lengths of arguments
14455  */
14456  ae_assert(n>=2, "Spline1DConvDiffCubic: N<2!", _state);
14457  ae_assert(x->cnt>=n, "Spline1DConvDiffCubic: Length(X)<N!", _state);
14458  ae_assert(y->cnt>=n, "Spline1DConvDiffCubic: Length(Y)<N!", _state);
14459  ae_assert(n2>=2, "Spline1DConvDiffCubic: N2<2!", _state);
14460  ae_assert(x2->cnt>=n2, "Spline1DConvDiffCubic: Length(X2)<N2!", _state);
14461 
14462  /*
14463  * check and sort X/Y
14464  */
14465  ylen = n;
14466  if( boundltype==-1 )
14467  {
14468  ylen = n-1;
14469  }
14470  ae_assert(isfinitevector(x, n, _state), "Spline1DConvDiffCubic: X contains infinite or NAN values!", _state);
14471  ae_assert(isfinitevector(y, ylen, _state), "Spline1DConvDiffCubic: Y contains infinite or NAN values!", _state);
14472  ae_assert(isfinitevector(x2, n2, _state), "Spline1DConvDiffCubic: X2 contains infinite or NAN values!", _state);
14473  spline1d_heapsortppoints(x, y, &p, n, _state);
14474  ae_assert(aredistinct(x, n, _state), "Spline1DConvDiffCubic: at least two consequent points are too close!", _state);
14475 
14476  /*
14477  * set up DT (we will need it below)
14478  */
14479  ae_vector_set_length(&dt, ae_maxint(n, n2, _state), _state);
14480 
14481  /*
14482  * sort X2:
14483  * * use fake array DT because HeapSortPPoints() needs both integer AND real arrays
14484  * * if we have periodic problem, wrap points
14485  * * sort them, store permutation at P2
14486  */
14487  if( boundrtype==-1&&boundltype==-1 )
14488  {
14489  for(i=0; i<=n2-1; i++)
14490  {
14491  t = x2->ptr.p_double[i];
14492  apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state);
14493  x2->ptr.p_double[i] = t;
14494  }
14495  }
14496  spline1d_heapsortppoints(x2, &dt, &p2, n2, _state);
14497 
14498  /*
14499  * Now we've checked and preordered everything, so we:
14500  * * call internal GridDiff() function to get Hermite form of spline
14501  * * convert using internal Conv() function
14502  * * convert Y2 back to original order
14503  */
14504  spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
14505  spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, d2, ae_true, &rt1, ae_false, _state);
14506  ae_assert(dt.cnt>=n2, "Spline1DConvDiffCubic: internal error!", _state);
14507  for(i=0; i<=n2-1; i++)
14508  {
14509  dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i];
14510  }
14511  ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
14512  for(i=0; i<=n2-1; i++)
14513  {
14514  dt.ptr.p_double[p2.ptr.p_int[i]] = d2->ptr.p_double[i];
14515  }
14516  ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
14517  ae_frame_leave(_state);
14518 }
14519 
14520 
14521 /*************************************************************************
14522 This function solves following problem: given table y[] of function values
14523 at old nodes x[] and new nodes x2[], it calculates and returns table of
14524 function values y2[], first and second derivatives d2[] and dd2[]
14525 (calculated at x2[]).
14526 
14527 This function yields same result as Spline1DBuildCubic() call followed by
14528 sequence of Spline1DDiff() calls, but it can be several times faster when
14529 called for ordered X[] and X2[].
14530 
14531 INPUT PARAMETERS:
14532  X - old spline nodes
14533  Y - function values
14534  X2 - new spline nodes
14535 
14536 OPTIONAL PARAMETERS:
14537  N - points count:
14538  * N>=2
14539  * if given, only first N points from X/Y are used
14540  * if not given, automatically detected from X/Y sizes
14541  (len(X) must be equal to len(Y))
14542  BoundLType - boundary condition type for the left boundary
14543  BoundL - left boundary condition (first or second derivative,
14544  depending on the BoundLType)
14545  BoundRType - boundary condition type for the right boundary
14546  BoundR - right boundary condition (first or second derivative,
14547  depending on the BoundRType)
14548  N2 - new points count:
14549  * N2>=2
14550  * if given, only first N2 points from X2 are used
14551  * if not given, automatically detected from X2 size
14552 
14553 OUTPUT PARAMETERS:
14554  F2 - function values at X2[]
14555  D2 - first derivatives at X2[]
14556  DD2 - second derivatives at X2[]
14557 
14558 ORDER OF POINTS
14559 
14560 Subroutine automatically sorts points, so caller may pass unsorted array.
14561 Function values are correctly reordered on return, so F2[I] is always
14562 equal to S(X2[I]) independently of points order.
14563 
14564 SETTING BOUNDARY VALUES:
14565 
14566 The BoundLType/BoundRType parameters can have the following values:
14567  * -1, which corresonds to the periodic (cyclic) boundary conditions.
14568  In this case:
14569  * both BoundLType and BoundRType must be equal to -1.
14570  * BoundL/BoundR are ignored
14571  * Y[last] is ignored (it is assumed to be equal to Y[first]).
14572  * 0, which corresponds to the parabolically terminated spline
14573  (BoundL and/or BoundR are ignored).
14574  * 1, which corresponds to the first derivative boundary condition
14575  * 2, which corresponds to the second derivative boundary condition
14576  * by default, BoundType=0 is used
14577 
14578 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
14579 
14580 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
14581 However, this subroutine doesn't require you to specify equal values for
14582 the first and last points - it automatically forces them to be equal by
14583 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
14584 Y[last_point]. However it is recommended to pass consistent values of Y[],
14585 i.e. to make Y[first_point]=Y[last_point].
14586 
14587  -- ALGLIB PROJECT --
14588  Copyright 03.09.2010 by Bochkanov Sergey
14589 *************************************************************************/
14591  /* Real */ ae_vector* y,
14592  ae_int_t n,
14593  ae_int_t boundltype,
14594  double boundl,
14595  ae_int_t boundrtype,
14596  double boundr,
14597  /* Real */ ae_vector* x2,
14598  ae_int_t n2,
14599  /* Real */ ae_vector* y2,
14600  /* Real */ ae_vector* d2,
14601  /* Real */ ae_vector* dd2,
14602  ae_state *_state)
14603 {
14604  ae_frame _frame_block;
14605  ae_vector _x;
14606  ae_vector _y;
14607  ae_vector _x2;
14608  ae_vector a1;
14609  ae_vector a2;
14610  ae_vector a3;
14611  ae_vector b;
14612  ae_vector d;
14613  ae_vector dt;
14614  ae_vector p;
14615  ae_vector p2;
14616  ae_int_t i;
14617  ae_int_t ylen;
14618  double t;
14619  double t2;
14620 
14621  ae_frame_make(_state, &_frame_block);
14622  ae_vector_init_copy(&_x, x, _state, ae_true);
14623  x = &_x;
14624  ae_vector_init_copy(&_y, y, _state, ae_true);
14625  y = &_y;
14626  ae_vector_init_copy(&_x2, x2, _state, ae_true);
14627  x2 = &_x2;
14628  ae_vector_clear(y2);
14629  ae_vector_clear(d2);
14630  ae_vector_clear(dd2);
14631  ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
14632  ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
14633  ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
14634  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
14635  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
14636  ae_vector_init(&dt, 0, DT_REAL, _state, ae_true);
14637  ae_vector_init(&p, 0, DT_INT, _state, ae_true);
14638  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
14639 
14640 
14641  /*
14642  * check correctness of boundary conditions
14643  */
14644  ae_assert(((boundltype==-1||boundltype==0)||boundltype==1)||boundltype==2, "Spline1DConvDiff2Cubic: incorrect BoundLType!", _state);
14645  ae_assert(((boundrtype==-1||boundrtype==0)||boundrtype==1)||boundrtype==2, "Spline1DConvDiff2Cubic: incorrect BoundRType!", _state);
14646  ae_assert((boundrtype==-1&&boundltype==-1)||(boundrtype!=-1&&boundltype!=-1), "Spline1DConvDiff2Cubic: incorrect BoundLType/BoundRType!", _state);
14647  if( boundltype==1||boundltype==2 )
14648  {
14649  ae_assert(ae_isfinite(boundl, _state), "Spline1DConvDiff2Cubic: BoundL is infinite or NAN!", _state);
14650  }
14651  if( boundrtype==1||boundrtype==2 )
14652  {
14653  ae_assert(ae_isfinite(boundr, _state), "Spline1DConvDiff2Cubic: BoundR is infinite or NAN!", _state);
14654  }
14655 
14656  /*
14657  * check lengths of arguments
14658  */
14659  ae_assert(n>=2, "Spline1DConvDiff2Cubic: N<2!", _state);
14660  ae_assert(x->cnt>=n, "Spline1DConvDiff2Cubic: Length(X)<N!", _state);
14661  ae_assert(y->cnt>=n, "Spline1DConvDiff2Cubic: Length(Y)<N!", _state);
14662  ae_assert(n2>=2, "Spline1DConvDiff2Cubic: N2<2!", _state);
14663  ae_assert(x2->cnt>=n2, "Spline1DConvDiff2Cubic: Length(X2)<N2!", _state);
14664 
14665  /*
14666  * check and sort X/Y
14667  */
14668  ylen = n;
14669  if( boundltype==-1 )
14670  {
14671  ylen = n-1;
14672  }
14673  ae_assert(isfinitevector(x, n, _state), "Spline1DConvDiff2Cubic: X contains infinite or NAN values!", _state);
14674  ae_assert(isfinitevector(y, ylen, _state), "Spline1DConvDiff2Cubic: Y contains infinite or NAN values!", _state);
14675  ae_assert(isfinitevector(x2, n2, _state), "Spline1DConvDiff2Cubic: X2 contains infinite or NAN values!", _state);
14676  spline1d_heapsortppoints(x, y, &p, n, _state);
14677  ae_assert(aredistinct(x, n, _state), "Spline1DConvDiff2Cubic: at least two consequent points are too close!", _state);
14678 
14679  /*
14680  * set up DT (we will need it below)
14681  */
14682  ae_vector_set_length(&dt, ae_maxint(n, n2, _state), _state);
14683 
14684  /*
14685  * sort X2:
14686  * * use fake array DT because HeapSortPPoints() needs both integer AND real arrays
14687  * * if we have periodic problem, wrap points
14688  * * sort them, store permutation at P2
14689  */
14690  if( boundrtype==-1&&boundltype==-1 )
14691  {
14692  for(i=0; i<=n2-1; i++)
14693  {
14694  t = x2->ptr.p_double[i];
14695  apperiodicmap(&t, x->ptr.p_double[0], x->ptr.p_double[n-1], &t2, _state);
14696  x2->ptr.p_double[i] = t;
14697  }
14698  }
14699  spline1d_heapsortppoints(x2, &dt, &p2, n2, _state);
14700 
14701  /*
14702  * Now we've checked and preordered everything, so we:
14703  * * call internal GridDiff() function to get Hermite form of spline
14704  * * convert using internal Conv() function
14705  * * convert Y2 back to original order
14706  */
14707  spline1d_spline1dgriddiffcubicinternal(x, y, n, boundltype, boundl, boundrtype, boundr, &d, &a1, &a2, &a3, &b, &dt, _state);
14708  spline1dconvdiffinternal(x, y, &d, n, x2, n2, y2, ae_true, d2, ae_true, dd2, ae_true, _state);
14709  ae_assert(dt.cnt>=n2, "Spline1DConvDiff2Cubic: internal error!", _state);
14710  for(i=0; i<=n2-1; i++)
14711  {
14712  dt.ptr.p_double[p2.ptr.p_int[i]] = y2->ptr.p_double[i];
14713  }
14714  ae_v_move(&y2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
14715  for(i=0; i<=n2-1; i++)
14716  {
14717  dt.ptr.p_double[p2.ptr.p_int[i]] = d2->ptr.p_double[i];
14718  }
14719  ae_v_move(&d2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
14720  for(i=0; i<=n2-1; i++)
14721  {
14722  dt.ptr.p_double[p2.ptr.p_int[i]] = dd2->ptr.p_double[i];
14723  }
14724  ae_v_move(&dd2->ptr.p_double[0], 1, &dt.ptr.p_double[0], 1, ae_v_len(0,n2-1));
14725  ae_frame_leave(_state);
14726 }
14727 
14728 
14729 /*************************************************************************
14730 This subroutine builds Catmull-Rom spline interpolant.
14731 
14732 INPUT PARAMETERS:
14733  X - spline nodes, array[0..N-1].
14734  Y - function values, array[0..N-1].
14735 
14736 OPTIONAL PARAMETERS:
14737  N - points count:
14738  * N>=2
14739  * if given, only first N points are used to build spline
14740  * if not given, automatically detected from X/Y sizes
14741  (len(X) must be equal to len(Y))
14742  BoundType - boundary condition type:
14743  * -1 for periodic boundary condition
14744  * 0 for parabolically terminated spline (default)
14745  Tension - tension parameter:
14746  * tension=0 corresponds to classic Catmull-Rom spline (default)
14747  * 0<tension<1 corresponds to more general form - cardinal spline
14748 
14749 OUTPUT PARAMETERS:
14750  C - spline interpolant
14751 
14752 
14753 ORDER OF POINTS
14754 
14755 Subroutine automatically sorts points, so caller may pass unsorted array.
14756 
14757 PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
14758 
14759 Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
14760 However, this subroutine doesn't require you to specify equal values for
14761 the first and last points - it automatically forces them to be equal by
14762 copying Y[first_point] (corresponds to the leftmost, minimal X[]) to
14763 Y[last_point]. However it is recommended to pass consistent values of Y[],
14764 i.e. to make Y[first_point]=Y[last_point].
14765 
14766  -- ALGLIB PROJECT --
14767  Copyright 23.06.2007 by Bochkanov Sergey
14768 *************************************************************************/
14770  /* Real */ ae_vector* y,
14771  ae_int_t n,
14772  ae_int_t boundtype,
14773  double tension,
14775  ae_state *_state)
14776 {
14777  ae_frame _frame_block;
14778  ae_vector _x;
14779  ae_vector _y;
14780  ae_vector d;
14781  ae_int_t i;
14782 
14783  ae_frame_make(_state, &_frame_block);
14784  ae_vector_init_copy(&_x, x, _state, ae_true);
14785  x = &_x;
14786  ae_vector_init_copy(&_y, y, _state, ae_true);
14787  y = &_y;
14789  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
14790 
14791  ae_assert(n>=2, "Spline1DBuildCatmullRom: N<2!", _state);
14792  ae_assert(boundtype==-1||boundtype==0, "Spline1DBuildCatmullRom: incorrect BoundType!", _state);
14793  ae_assert(ae_fp_greater_eq(tension,0), "Spline1DBuildCatmullRom: Tension<0!", _state);
14794  ae_assert(ae_fp_less_eq(tension,1), "Spline1DBuildCatmullRom: Tension>1!", _state);
14795  ae_assert(x->cnt>=n, "Spline1DBuildCatmullRom: Length(X)<N!", _state);
14796  ae_assert(y->cnt>=n, "Spline1DBuildCatmullRom: Length(Y)<N!", _state);
14797 
14798  /*
14799  * check and sort points
14800  */
14801  ae_assert(isfinitevector(x, n, _state), "Spline1DBuildCatmullRom: X contains infinite or NAN values!", _state);
14802  ae_assert(isfinitevector(y, n, _state), "Spline1DBuildCatmullRom: Y contains infinite or NAN values!", _state);
14803  spline1d_heapsortpoints(x, y, n, _state);
14804  ae_assert(aredistinct(x, n, _state), "Spline1DBuildCatmullRom: at least two consequent points are too close!", _state);
14805 
14806  /*
14807  * Special cases:
14808  * * N=2, parabolic terminated boundary condition on both ends
14809  * * N=2, periodic boundary condition
14810  */
14811  if( n==2&&boundtype==0 )
14812  {
14813 
14814  /*
14815  * Just linear spline
14816  */
14817  spline1dbuildlinear(x, y, n, c, _state);
14818  ae_frame_leave(_state);
14819  return;
14820  }
14821  if( n==2&&boundtype==-1 )
14822  {
14823 
14824  /*
14825  * Same as cubic spline with periodic conditions
14826  */
14827  spline1dbuildcubic(x, y, n, -1, 0.0, -1, 0.0, c, _state);
14828  ae_frame_leave(_state);
14829  return;
14830  }
14831 
14832  /*
14833  * Periodic or non-periodic boundary conditions
14834  */
14835  if( boundtype==-1 )
14836  {
14837 
14838  /*
14839  * Periodic boundary conditions
14840  */
14841  y->ptr.p_double[n-1] = y->ptr.p_double[0];
14842  ae_vector_set_length(&d, n, _state);
14843  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]));
14844  for(i=1; i<=n-2; i++)
14845  {
14846  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]);
14847  }
14848  d.ptr.p_double[n-1] = d.ptr.p_double[0];
14849 
14850  /*
14851  * Now problem is reduced to the cubic Hermite spline
14852  */
14853  spline1dbuildhermite(x, y, &d, n, c, _state);
14854  c->periodic = ae_true;
14855  }
14856  else
14857  {
14858 
14859  /*
14860  * Non-periodic boundary conditions
14861  */
14862  ae_vector_set_length(&d, n, _state);
14863  for(i=1; i<=n-2; i++)
14864  {
14865  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]);
14866  }
14867  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];
14868  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];
14869 
14870  /*
14871  * Now problem is reduced to the cubic Hermite spline
14872  */
14873  spline1dbuildhermite(x, y, &d, n, c, _state);
14874  }
14875  ae_frame_leave(_state);
14876 }
14877 
14878 
14879 /*************************************************************************
14880 This subroutine builds Hermite spline interpolant.
14881 
14882 INPUT PARAMETERS:
14883  X - spline nodes, array[0..N-1]
14884  Y - function values, array[0..N-1]
14885  D - derivatives, array[0..N-1]
14886  N - points count (optional):
14887  * N>=2
14888  * if given, only first N points are used to build spline
14889  * if not given, automatically detected from X/Y sizes
14890  (len(X) must be equal to len(Y))
14891 
14892 OUTPUT PARAMETERS:
14893  C - spline interpolant.
14894 
14895 
14896 ORDER OF POINTS
14897 
14898 Subroutine automatically sorts points, so caller may pass unsorted array.
14899 
14900  -- ALGLIB PROJECT --
14901  Copyright 23.06.2007 by Bochkanov Sergey
14902 *************************************************************************/
14903 void spline1dbuildhermite(/* Real */ ae_vector* x,
14904  /* Real */ ae_vector* y,
14905  /* Real */ ae_vector* d,
14906  ae_int_t n,
14908  ae_state *_state)
14909 {
14910  ae_frame _frame_block;
14911  ae_vector _x;
14912  ae_vector _y;
14913  ae_vector _d;
14914  ae_int_t i;
14915  double delta;
14916  double delta2;
14917  double delta3;
14918 
14919  ae_frame_make(_state, &_frame_block);
14920  ae_vector_init_copy(&_x, x, _state, ae_true);
14921  x = &_x;
14922  ae_vector_init_copy(&_y, y, _state, ae_true);
14923  y = &_y;
14924  ae_vector_init_copy(&_d, d, _state, ae_true);
14925  d = &_d;
14927 
14928  ae_assert(n>=2, "Spline1DBuildHermite: N<2!", _state);
14929  ae_assert(x->cnt>=n, "Spline1DBuildHermite: Length(X)<N!", _state);
14930  ae_assert(y->cnt>=n, "Spline1DBuildHermite: Length(Y)<N!", _state);
14931  ae_assert(d->cnt>=n, "Spline1DBuildHermite: Length(D)<N!", _state);
14932 
14933  /*
14934  * check and sort points
14935  */
14936  ae_assert(isfinitevector(x, n, _state), "Spline1DBuildHermite: X contains infinite or NAN values!", _state);
14937  ae_assert(isfinitevector(y, n, _state), "Spline1DBuildHermite: Y contains infinite or NAN values!", _state);
14938  ae_assert(isfinitevector(d, n, _state), "Spline1DBuildHermite: D contains infinite or NAN values!", _state);
14939  heapsortdpoints(x, y, d, n, _state);
14940  ae_assert(aredistinct(x, n, _state), "Spline1DBuildHermite: at least two consequent points are too close!", _state);
14941 
14942  /*
14943  * Build
14944  */
14945  ae_vector_set_length(&c->x, n, _state);
14946  ae_vector_set_length(&c->c, 4*(n-1)+2, _state);
14947  c->periodic = ae_false;
14948  c->k = 3;
14949  c->n = n;
14950  c->continuity = 1;
14951  for(i=0; i<=n-1; i++)
14952  {
14953  c->x.ptr.p_double[i] = x->ptr.p_double[i];
14954  }
14955  for(i=0; i<=n-2; i++)
14956  {
14957  delta = x->ptr.p_double[i+1]-x->ptr.p_double[i];
14958  delta2 = ae_sqr(delta, _state);
14959  delta3 = delta*delta2;
14960  c->c.ptr.p_double[4*i+0] = y->ptr.p_double[i];
14961  c->c.ptr.p_double[4*i+1] = d->ptr.p_double[i];
14962  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;
14963  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;
14964  }
14965  c->c.ptr.p_double[4*(n-1)+0] = y->ptr.p_double[n-1];
14966  c->c.ptr.p_double[4*(n-1)+1] = d->ptr.p_double[n-1];
14967  ae_frame_leave(_state);
14968 }
14969 
14970 
14971 /*************************************************************************
14972 This subroutine builds Akima spline interpolant
14973 
14974 INPUT PARAMETERS:
14975  X - spline nodes, array[0..N-1]
14976  Y - function values, array[0..N-1]
14977  N - points count (optional):
14978  * N>=2
14979  * if given, only first N points are used to build spline
14980  * if not given, automatically detected from X/Y sizes
14981  (len(X) must be equal to len(Y))
14982 
14983 OUTPUT PARAMETERS:
14984  C - spline interpolant
14985 
14986 
14987 ORDER OF POINTS
14988 
14989 Subroutine automatically sorts points, so caller may pass unsorted array.
14990 
14991  -- ALGLIB PROJECT --
14992  Copyright 24.06.2007 by Bochkanov Sergey
14993 *************************************************************************/
14994 void spline1dbuildakima(/* Real */ ae_vector* x,
14995  /* Real */ ae_vector* y,
14996  ae_int_t n,
14998  ae_state *_state)
14999 {
15000  ae_frame _frame_block;
15001  ae_vector _x;
15002  ae_vector _y;
15003  ae_int_t i;
15004  ae_vector d;
15005  ae_vector w;
15006  ae_vector diff;
15007 
15008  ae_frame_make(_state, &_frame_block);
15009  ae_vector_init_copy(&_x, x, _state, ae_true);
15010  x = &_x;
15011  ae_vector_init_copy(&_y, y, _state, ae_true);
15012  y = &_y;
15014  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
15015  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
15016  ae_vector_init(&diff, 0, DT_REAL, _state, ae_true);
15017 
15018  ae_assert(n>=2, "Spline1DBuildAkima: N<2!", _state);
15019  ae_assert(x->cnt>=n, "Spline1DBuildAkima: Length(X)<N!", _state);
15020  ae_assert(y->cnt>=n, "Spline1DBuildAkima: Length(Y)<N!", _state);
15021 
15022  /*
15023  * check and sort points
15024  */
15025  ae_assert(isfinitevector(x, n, _state), "Spline1DBuildAkima: X contains infinite or NAN values!", _state);
15026  ae_assert(isfinitevector(y, n, _state), "Spline1DBuildAkima: Y contains infinite or NAN values!", _state);
15027  spline1d_heapsortpoints(x, y, n, _state);
15028  ae_assert(aredistinct(x, n, _state), "Spline1DBuildAkima: at least two consequent points are too close!", _state);
15029 
15030  /*
15031  * Handle special cases: N=2, N=3, N=4
15032  */
15033  if( n<=4 )
15034  {
15035  spline1dbuildcubic(x, y, n, 0, 0.0, 0, 0.0, c, _state);
15036  ae_frame_leave(_state);
15037  return;
15038  }
15039 
15040  /*
15041  * Prepare W (weights), Diff (divided differences)
15042  */
15043  ae_vector_set_length(&w, n-1, _state);
15044  ae_vector_set_length(&diff, n-1, _state);
15045  for(i=0; i<=n-2; i++)
15046  {
15047  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]);
15048  }
15049  for(i=1; i<=n-2; i++)
15050  {
15051  w.ptr.p_double[i] = ae_fabs(diff.ptr.p_double[i]-diff.ptr.p_double[i-1], _state);
15052  }
15053 
15054  /*
15055  * Prepare Hermite interpolation scheme
15056  */
15057  ae_vector_set_length(&d, n, _state);
15058  for(i=2; i<=n-3; i++)
15059  {
15060  if( ae_fp_neq(ae_fabs(w.ptr.p_double[i-1], _state)+ae_fabs(w.ptr.p_double[i+1], _state),0) )
15061  {
15062  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]);
15063  }
15064  else
15065  {
15066  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]);
15067  }
15068  }
15069  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);
15070  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);
15071  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);
15072  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);
15073 
15074  /*
15075  * Build Akima spline using Hermite interpolation scheme
15076  */
15077  spline1dbuildhermite(x, y, &d, n, c, _state);
15078  ae_frame_leave(_state);
15079 }
15080 
15081 
15082 /*************************************************************************
15083 This subroutine calculates the value of the spline at the given point X.
15084 
15085 INPUT PARAMETERS:
15086  C - spline interpolant
15087  X - point
15088 
15089 Result:
15090  S(x)
15091 
15092  -- ALGLIB PROJECT --
15093  Copyright 23.06.2007 by Bochkanov Sergey
15094 *************************************************************************/
15095 double spline1dcalc(spline1dinterpolant* c, double x, ae_state *_state)
15096 {
15097  ae_int_t l;
15098  ae_int_t r;
15099  ae_int_t m;
15100  double t;
15101  double result;
15102 
15103 
15104  ae_assert(c->k==3, "Spline1DCalc: internal error", _state);
15105  ae_assert(!ae_isinf(x, _state), "Spline1DCalc: infinite X!", _state);
15106 
15107  /*
15108  * special case: NaN
15109  */
15110  if( ae_isnan(x, _state) )
15111  {
15112  result = _state->v_nan;
15113  return result;
15114  }
15115 
15116  /*
15117  * correct if periodic
15118  */
15119  if( c->periodic )
15120  {
15121  apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state);
15122  }
15123 
15124  /*
15125  * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
15126  */
15127  l = 0;
15128  r = c->n-2+1;
15129  while(l!=r-1)
15130  {
15131  m = (l+r)/2;
15132  if( c->x.ptr.p_double[m]>=x )
15133  {
15134  r = m;
15135  }
15136  else
15137  {
15138  l = m;
15139  }
15140  }
15141 
15142  /*
15143  * Interpolation
15144  */
15145  x = x-c->x.ptr.p_double[l];
15146  m = 4*l;
15147  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]));
15148  return result;
15149 }
15150 
15151 
15152 /*************************************************************************
15153 This subroutine differentiates the spline.
15154 
15155 INPUT PARAMETERS:
15156  C - spline interpolant.
15157  X - point
15158 
15159 Result:
15160  S - S(x)
15161  DS - S'(x)
15162  D2S - S''(x)
15163 
15164  -- ALGLIB PROJECT --
15165  Copyright 24.06.2007 by Bochkanov Sergey
15166 *************************************************************************/
15168  double x,
15169  double* s,
15170  double* ds,
15171  double* d2s,
15172  ae_state *_state)
15173 {
15174  ae_int_t l;
15175  ae_int_t r;
15176  ae_int_t m;
15177  double t;
15178 
15179  *s = 0;
15180  *ds = 0;
15181  *d2s = 0;
15182 
15183  ae_assert(c->k==3, "Spline1DDiff: internal error", _state);
15184  ae_assert(!ae_isinf(x, _state), "Spline1DDiff: infinite X!", _state);
15185 
15186  /*
15187  * special case: NaN
15188  */
15189  if( ae_isnan(x, _state) )
15190  {
15191  *s = _state->v_nan;
15192  *ds = _state->v_nan;
15193  *d2s = _state->v_nan;
15194  return;
15195  }
15196 
15197  /*
15198  * correct if periodic
15199  */
15200  if( c->periodic )
15201  {
15202  apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state);
15203  }
15204 
15205  /*
15206  * Binary search
15207  */
15208  l = 0;
15209  r = c->n-2+1;
15210  while(l!=r-1)
15211  {
15212  m = (l+r)/2;
15213  if( c->x.ptr.p_double[m]>=x )
15214  {
15215  r = m;
15216  }
15217  else
15218  {
15219  l = m;
15220  }
15221  }
15222 
15223  /*
15224  * Differentiation
15225  */
15226  x = x-c->x.ptr.p_double[l];
15227  m = 4*l;
15228  *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]));
15229  *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];
15230  *d2s = 2*c->c.ptr.p_double[m+2]+6*x*c->c.ptr.p_double[m+3];
15231 }
15232 
15233 
15234 /*************************************************************************
15235 This subroutine makes the copy of the spline.
15236 
15237 INPUT PARAMETERS:
15238  C - spline interpolant.
15239 
15240 Result:
15241  CC - spline copy
15242 
15243  -- ALGLIB PROJECT --
15244  Copyright 29.06.2007 by Bochkanov Sergey
15245 *************************************************************************/
15247  spline1dinterpolant* cc,
15248  ae_state *_state)
15249 {
15250  ae_int_t s;
15251 
15253 
15254  cc->periodic = c->periodic;
15255  cc->n = c->n;
15256  cc->k = c->k;
15257  cc->continuity = c->continuity;
15258  ae_vector_set_length(&cc->x, cc->n, _state);
15259  ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1));
15260  s = c->c.cnt;
15261  ae_vector_set_length(&cc->c, s, _state);
15262  ae_v_move(&cc->c.ptr.p_double[0], 1, &c->c.ptr.p_double[0], 1, ae_v_len(0,s-1));
15263 }
15264 
15265 
15266 /*************************************************************************
15267 This subroutine unpacks the spline into the coefficients table.
15268 
15269 INPUT PARAMETERS:
15270  C - spline interpolant.
15271  X - point
15272 
15273 OUTPUT PARAMETERS:
15274  Tbl - coefficients table, unpacked format, array[0..N-2, 0..5].
15275  For I = 0...N-2:
15276  Tbl[I,0] = X[i]
15277  Tbl[I,1] = X[i+1]
15278  Tbl[I,2] = C0
15279  Tbl[I,3] = C1
15280  Tbl[I,4] = C2
15281  Tbl[I,5] = C3
15282  On [x[i], x[i+1]] spline is equals to:
15283  S(x) = C0 + C1*t + C2*t^2 + C3*t^3
15284  t = x-x[i]
15285 
15286 NOTE:
15287  You can rebuild spline with Spline1DBuildHermite() function, which
15288  accepts as inputs function values and derivatives at nodes, which are
15289  easy to calculate when you have coefficients.
15290 
15291  -- ALGLIB PROJECT --
15292  Copyright 29.06.2007 by Bochkanov Sergey
15293 *************************************************************************/
15295  ae_int_t* n,
15296  /* Real */ ae_matrix* tbl,
15297  ae_state *_state)
15298 {
15299  ae_int_t i;
15300  ae_int_t j;
15301 
15302  *n = 0;
15303  ae_matrix_clear(tbl);
15304 
15305  ae_matrix_set_length(tbl, c->n-2+1, 2+c->k+1, _state);
15306  *n = c->n;
15307 
15308  /*
15309  * Fill
15310  */
15311  for(i=0; i<=*n-2; i++)
15312  {
15313  tbl->ptr.pp_double[i][0] = c->x.ptr.p_double[i];
15314  tbl->ptr.pp_double[i][1] = c->x.ptr.p_double[i+1];
15315  for(j=0; j<=c->k; j++)
15316  {
15317  tbl->ptr.pp_double[i][2+j] = c->c.ptr.p_double[(c->k+1)*i+j];
15318  }
15319  }
15320 }
15321 
15322 
15323 /*************************************************************************
15324 This subroutine performs linear transformation of the spline argument.
15325 
15326 INPUT PARAMETERS:
15327  C - spline interpolant.
15328  A, B- transformation coefficients: x = A*t + B
15329 Result:
15330  C - transformed spline
15331 
15332  -- ALGLIB PROJECT --
15333  Copyright 30.06.2007 by Bochkanov Sergey
15334 *************************************************************************/
15336  double a,
15337  double b,
15338  ae_state *_state)
15339 {
15340  ae_frame _frame_block;
15341  ae_int_t i;
15342  ae_int_t n;
15343  double v;
15344  double dv;
15345  double d2v;
15346  ae_vector x;
15347  ae_vector y;
15348  ae_vector d;
15349  ae_bool isperiodic;
15350  ae_int_t contval;
15351 
15352  ae_frame_make(_state, &_frame_block);
15353  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
15354  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
15355  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
15356 
15357  ae_assert(c->k==3, "Spline1DLinTransX: internal error", _state);
15358  n = c->n;
15359  ae_vector_set_length(&x, n, _state);
15360  ae_vector_set_length(&y, n, _state);
15361  ae_vector_set_length(&d, n, _state);
15362 
15363  /*
15364  * Unpack, X, Y, dY/dX.
15365  * Scale and pack with Spline1DBuildHermite again.
15366  */
15367  if( ae_fp_eq(a,0) )
15368  {
15369 
15370  /*
15371  * Special case: A=0
15372  */
15373  v = spline1dcalc(c, b, _state);
15374  for(i=0; i<=n-1; i++)
15375  {
15376  x.ptr.p_double[i] = c->x.ptr.p_double[i];
15377  y.ptr.p_double[i] = v;
15378  d.ptr.p_double[i] = 0.0;
15379  }
15380  }
15381  else
15382  {
15383 
15384  /*
15385  * General case, A<>0
15386  */
15387  for(i=0; i<=n-1; i++)
15388  {
15389  x.ptr.p_double[i] = c->x.ptr.p_double[i];
15390  spline1ddiff(c, x.ptr.p_double[i], &v, &dv, &d2v, _state);
15391  x.ptr.p_double[i] = (x.ptr.p_double[i]-b)/a;
15392  y.ptr.p_double[i] = v;
15393  d.ptr.p_double[i] = a*dv;
15394  }
15395  }
15396  isperiodic = c->periodic;
15397  contval = c->continuity;
15398  if( contval>0 )
15399  {
15400  spline1dbuildhermite(&x, &y, &d, n, c, _state);
15401  }
15402  else
15403  {
15404  spline1dbuildlinear(&x, &y, n, c, _state);
15405  }
15406  c->periodic = isperiodic;
15407  c->continuity = contval;
15408  ae_frame_leave(_state);
15409 }
15410 
15411 
15412 /*************************************************************************
15413 This subroutine performs linear transformation of the spline.
15414 
15415 INPUT PARAMETERS:
15416  C - spline interpolant.
15417  A, B- transformation coefficients: S2(x) = A*S(x) + B
15418 Result:
15419  C - transformed spline
15420 
15421  -- ALGLIB PROJECT --
15422  Copyright 30.06.2007 by Bochkanov Sergey
15423 *************************************************************************/
15425  double a,
15426  double b,
15427  ae_state *_state)
15428 {
15429  ae_int_t i;
15430  ae_int_t j;
15431  ae_int_t n;
15432 
15433 
15434  ae_assert(c->k==3, "Spline1DLinTransX: internal error", _state);
15435  n = c->n;
15436  for(i=0; i<=n-2; i++)
15437  {
15438  c->c.ptr.p_double[4*i] = a*c->c.ptr.p_double[4*i]+b;
15439  for(j=1; j<=3; j++)
15440  {
15441  c->c.ptr.p_double[4*i+j] = a*c->c.ptr.p_double[4*i+j];
15442  }
15443  }
15444  c->c.ptr.p_double[4*(n-1)+0] = a*c->c.ptr.p_double[4*(n-1)+0]+b;
15445  c->c.ptr.p_double[4*(n-1)+1] = a*c->c.ptr.p_double[4*(n-1)+1];
15446 }
15447 
15448 
15449 /*************************************************************************
15450 This subroutine integrates the spline.
15451 
15452 INPUT PARAMETERS:
15453  C - spline interpolant.
15454  X - right bound of the integration interval [a, x],
15455  here 'a' denotes min(x[])
15456 Result:
15457  integral(S(t)dt,a,x)
15458 
15459  -- ALGLIB PROJECT --
15460  Copyright 23.06.2007 by Bochkanov Sergey
15461 *************************************************************************/
15463  double x,
15464  ae_state *_state)
15465 {
15466  ae_int_t n;
15467  ae_int_t i;
15468  ae_int_t j;
15469  ae_int_t l;
15470  ae_int_t r;
15471  ae_int_t m;
15472  double w;
15473  double v;
15474  double t;
15475  double intab;
15476  double additionalterm;
15477  double result;
15478 
15479 
15480  n = c->n;
15481 
15482  /*
15483  * Periodic splines require special treatment. We make
15484  * following transformation:
15485  *
15486  * integral(S(t)dt,A,X) = integral(S(t)dt,A,Z)+AdditionalTerm
15487  *
15488  * here X may lie outside of [A,B], Z lies strictly in [A,B],
15489  * AdditionalTerm is equals to integral(S(t)dt,A,B) times some
15490  * integer number (may be zero).
15491  */
15492  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])) )
15493  {
15494 
15495  /*
15496  * compute integral(S(x)dx,A,B)
15497  */
15498  intab = 0;
15499  for(i=0; i<=c->n-2; i++)
15500  {
15501  w = c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i];
15502  m = (c->k+1)*i;
15503  intab = intab+c->c.ptr.p_double[m]*w;
15504  v = w;
15505  for(j=1; j<=c->k; j++)
15506  {
15507  v = v*w;
15508  intab = intab+c->c.ptr.p_double[m+j]*v/(j+1);
15509  }
15510  }
15511 
15512  /*
15513  * map X into [A,B]
15514  */
15515  apperiodicmap(&x, c->x.ptr.p_double[0], c->x.ptr.p_double[c->n-1], &t, _state);
15516  additionalterm = t*intab;
15517  }
15518  else
15519  {
15520  additionalterm = 0;
15521  }
15522 
15523  /*
15524  * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
15525  */
15526  l = 0;
15527  r = n-2+1;
15528  while(l!=r-1)
15529  {
15530  m = (l+r)/2;
15531  if( ae_fp_greater_eq(c->x.ptr.p_double[m],x) )
15532  {
15533  r = m;
15534  }
15535  else
15536  {
15537  l = m;
15538  }
15539  }
15540 
15541  /*
15542  * Integration
15543  */
15544  result = 0;
15545  for(i=0; i<=l-1; i++)
15546  {
15547  w = c->x.ptr.p_double[i+1]-c->x.ptr.p_double[i];
15548  m = (c->k+1)*i;
15549  result = result+c->c.ptr.p_double[m]*w;
15550  v = w;
15551  for(j=1; j<=c->k; j++)
15552  {
15553  v = v*w;
15554  result = result+c->c.ptr.p_double[m+j]*v/(j+1);
15555  }
15556  }
15557  w = x-c->x.ptr.p_double[l];
15558  m = (c->k+1)*l;
15559  v = w;
15560  result = result+c->c.ptr.p_double[m]*w;
15561  for(j=1; j<=c->k; j++)
15562  {
15563  v = v*w;
15564  result = result+c->c.ptr.p_double[m+j]*v/(j+1);
15565  }
15566  result = result+additionalterm;
15567  return result;
15568 }
15569 
15570 
15571 /*************************************************************************
15572 Internal version of Spline1DConvDiff
15573 
15574 Converts from Hermite spline given by grid XOld to new grid X2
15575 
15576 INPUT PARAMETERS:
15577  XOld - old grid
15578  YOld - values at old grid
15579  DOld - first derivative at old grid
15580  N - grid size
15581  X2 - new grid
15582  N2 - new grid size
15583  Y - possibly preallocated output array
15584  (reallocate if too small)
15585  NeedY - do we need Y?
15586  D1 - possibly preallocated output array
15587  (reallocate if too small)
15588  NeedD1 - do we need D1?
15589  D2 - possibly preallocated output array
15590  (reallocate if too small)
15591  NeedD2 - do we need D1?
15592 
15593 OUTPUT ARRAYS:
15594  Y - values, if needed
15595  D1 - first derivative, if needed
15596  D2 - second derivative, if needed
15597 
15598  -- ALGLIB PROJECT --
15599  Copyright 03.09.2010 by Bochkanov Sergey
15600 *************************************************************************/
15601 void spline1dconvdiffinternal(/* Real */ ae_vector* xold,
15602  /* Real */ ae_vector* yold,
15603  /* Real */ ae_vector* dold,
15604  ae_int_t n,
15605  /* Real */ ae_vector* x2,
15606  ae_int_t n2,
15607  /* Real */ ae_vector* y,
15608  ae_bool needy,
15609  /* Real */ ae_vector* d1,
15610  ae_bool needd1,
15611  /* Real */ ae_vector* d2,
15612  ae_bool needd2,
15613  ae_state *_state)
15614 {
15615  ae_int_t intervalindex;
15616  ae_int_t pointindex;
15617  ae_bool havetoadvance;
15618  double c0;
15619  double c1;
15620  double c2;
15621  double c3;
15622  double a;
15623  double b;
15624  double w;
15625  double w2;
15626  double w3;
15627  double fa;
15628  double fb;
15629  double da;
15630  double db;
15631  double t;
15632 
15633 
15634 
15635  /*
15636  * Prepare space
15637  */
15638  if( needy&&y->cnt<n2 )
15639  {
15640  ae_vector_set_length(y, n2, _state);
15641  }
15642  if( needd1&&d1->cnt<n2 )
15643  {
15644  ae_vector_set_length(d1, n2, _state);
15645  }
15646  if( needd2&&d2->cnt<n2 )
15647  {
15648  ae_vector_set_length(d2, n2, _state);
15649  }
15650 
15651  /*
15652  * These assignments aren't actually needed
15653  * (variables are initialized in the loop below),
15654  * but without them compiler will complain about uninitialized locals
15655  */
15656  c0 = 0;
15657  c1 = 0;
15658  c2 = 0;
15659  c3 = 0;
15660  a = 0;
15661  b = 0;
15662 
15663  /*
15664  * Cycle
15665  */
15666  intervalindex = -1;
15667  pointindex = 0;
15668  for(;;)
15669  {
15670 
15671  /*
15672  * are we ready to exit?
15673  */
15674  if( pointindex>=n2 )
15675  {
15676  break;
15677  }
15678  t = x2->ptr.p_double[pointindex];
15679 
15680  /*
15681  * do we need to advance interval?
15682  */
15683  havetoadvance = ae_false;
15684  if( intervalindex==-1 )
15685  {
15686  havetoadvance = ae_true;
15687  }
15688  else
15689  {
15690  if( intervalindex<n-2 )
15691  {
15692  havetoadvance = ae_fp_greater_eq(t,b);
15693  }
15694  }
15695  if( havetoadvance )
15696  {
15697  intervalindex = intervalindex+1;
15698  a = xold->ptr.p_double[intervalindex];
15699  b = xold->ptr.p_double[intervalindex+1];
15700  w = b-a;
15701  w2 = w*w;
15702  w3 = w*w2;
15703  fa = yold->ptr.p_double[intervalindex];
15704  fb = yold->ptr.p_double[intervalindex+1];
15705  da = dold->ptr.p_double[intervalindex];
15706  db = dold->ptr.p_double[intervalindex+1];
15707  c0 = fa;
15708  c1 = da;
15709  c2 = (3*(fb-fa)-2*da*w-db*w)/w2;
15710  c3 = (2*(fa-fb)+da*w+db*w)/w3;
15711  continue;
15712  }
15713 
15714  /*
15715  * Calculate spline and its derivatives using power basis
15716  */
15717  t = t-a;
15718  if( needy )
15719  {
15720  y->ptr.p_double[pointindex] = c0+t*(c1+t*(c2+t*c3));
15721  }
15722  if( needd1 )
15723  {
15724  d1->ptr.p_double[pointindex] = c1+2*t*c2+3*t*t*c3;
15725  }
15726  if( needd2 )
15727  {
15728  d2->ptr.p_double[pointindex] = 2*c2+6*t*c3;
15729  }
15730  pointindex = pointindex+1;
15731  }
15732 }
15733 
15734 
15735 /*************************************************************************
15736 This function finds all roots and extrema of the spline S(x) defined at
15737 [A,B] (interval which contains spline nodes).
15738 
15739 It does not extrapolates function, so roots and extrema located outside
15740 of [A,B] will not be found. It returns all isolated (including multiple)
15741 roots and extrema.
15742 
15743 INPUT PARAMETERS
15744  C - spline interpolant
15745 
15746 OUTPUT PARAMETERS
15747  R - array[NR], contains roots of the spline.
15748  In case there is no roots, this array has zero length.
15749  NR - number of roots, >=0
15750  DR - is set to True in case there is at least one interval
15751  where spline is just a zero constant. Such degenerate
15752  cases are not reported in the R/NR
15753  E - array[NE], contains extrema (maximums/minimums) of
15754  the spline. In case there is no extrema, this array
15755  has zero length.
15756  ET - array[NE], extrema types:
15757  * ET[i]>0 in case I-th extrema is a minimum
15758  * ET[i]<0 in case I-th extrema is a maximum
15759  NE - number of extrema, >=0
15760  DE - is set to True in case there is at least one interval
15761  where spline is a constant. Such degenerate cases are
15762  not reported in the E/NE.
15763 
15764 NOTES:
15765 
15766 1. This function does NOT report following kinds of roots:
15767  * intervals where function is constantly zero
15768  * roots which are outside of [A,B] (note: it CAN return A or B)
15769 
15770 2. This function does NOT report following kinds of extrema:
15771  * intervals where function is a constant
15772  * extrema which are outside of (A,B) (note: it WON'T return A or B)
15773 
15774  -- ALGLIB PROJECT --
15775  Copyright 26.09.2011 by Bochkanov Sergey
15776 *************************************************************************/
15778  /* Real */ ae_vector* r,
15779  ae_int_t* nr,
15780  ae_bool* dr,
15781  /* Real */ ae_vector* e,
15782  /* Integer */ ae_vector* et,
15783  ae_int_t* ne,
15784  ae_bool* de,
15785  ae_state *_state)
15786 {
15787  ae_frame _frame_block;
15788  double pl;
15789  double ml;
15790  double pll;
15791  double pr;
15792  double mr;
15793  ae_vector tr;
15794  ae_vector tmpr;
15795  ae_vector tmpe;
15796  ae_vector tmpet;
15797  ae_vector tmpc;
15798  double x0;
15799  double x1;
15800  double x2;
15801  double ex0;
15802  double ex1;
15803  ae_int_t tne;
15804  ae_int_t tnr;
15805  ae_int_t i;
15806  ae_int_t j;
15807  ae_bool nstep;
15808 
15809  ae_frame_make(_state, &_frame_block);
15810  ae_vector_clear(r);
15811  *nr = 0;
15812  *dr = ae_false;
15813  ae_vector_clear(e);
15814  ae_vector_clear(et);
15815  *ne = 0;
15816  *de = ae_false;
15817  ae_vector_init(&tr, 0, DT_REAL, _state, ae_true);
15818  ae_vector_init(&tmpr, 0, DT_REAL, _state, ae_true);
15819  ae_vector_init(&tmpe, 0, DT_REAL, _state, ae_true);
15820  ae_vector_init(&tmpet, 0, DT_INT, _state, ae_true);
15821  ae_vector_init(&tmpc, 0, DT_REAL, _state, ae_true);
15822 
15823 
15824  /*
15825  *exception handling
15826  */
15827  ae_assert(c->k==3, "Spline1DRootsAndExtrema : incorrect parameter C.K!", _state);
15828  ae_assert(c->continuity>=0, "Spline1DRootsAndExtrema : parameter C.Continuity must not be less than 0!", _state);
15829 
15830  /*
15831  *initialization of variable
15832  */
15833  *nr = 0;
15834  *ne = 0;
15835  *dr = ae_false;
15836  *de = ae_false;
15837  nstep = ae_true;
15838 
15839  /*
15840  *consider case, when C.Continuty=0
15841  */
15842  if( c->continuity==0 )
15843  {
15844 
15845  /*
15846  *allocation for auxiliary arrays
15847  *'TmpR ' - it stores a time value for roots
15848  *'TmpE ' - it stores a time value for extremums
15849  *'TmpET '- it stores a time value for extremums type
15850  */
15851  rvectorsetlengthatleast(&tmpr, 3*(c->n-1), _state);
15852  rvectorsetlengthatleast(&tmpe, 2*(c->n-1), _state);
15853  ivectorsetlengthatleast(&tmpet, 2*(c->n-1), _state);
15854 
15855  /*
15856  *start calculating
15857  */
15858  for(i=0; i<=c->n-2; i++)
15859  {
15860 
15861  /*
15862  *initialization pL, mL, pR, mR
15863  */
15864  pl = c->c.ptr.p_double[4*i];
15865  ml = c->c.ptr.p_double[4*i+1];
15866  pr = c->c.ptr.p_double[4*(i+1)];
15867  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]);
15868 
15869  /*
15870  *pre-searching roots and extremums
15871  */
15872  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);
15873  *dr = *dr||tnr==-1;
15874  *de = *de||tne==-1;
15875 
15876  /*
15877  *searching of roots
15878  */
15879  if( tnr==1&&nstep )
15880  {
15881 
15882  /*
15883  *is there roots?
15884  */
15885  if( *nr>0 )
15886  {
15887 
15888  /*
15889  *is a next root equal a previous root?
15890  *if is't, then write new root
15891  */
15892  if( ae_fp_neq(x0,tmpr.ptr.p_double[*nr-1]) )
15893  {
15894  tmpr.ptr.p_double[*nr] = x0;
15895  *nr = *nr+1;
15896  }
15897  }
15898  else
15899  {
15900 
15901  /*
15902  *write a first root
15903  */
15904  tmpr.ptr.p_double[*nr] = x0;
15905  *nr = *nr+1;
15906  }
15907  }
15908  else
15909  {
15910 
15911  /*
15912  *case when function at a segment identically to zero
15913  *then we have to clear a root, if the one located on a
15914  *constant segment
15915  */
15916  if( tnr==-1 )
15917  {
15918 
15919  /*
15920  *safe state variable as constant
15921  */
15922  if( nstep )
15923  {
15924  nstep = ae_false;
15925  }
15926 
15927  /*
15928  *clear the root, if there is
15929  */
15930  if( *nr>0 )
15931  {
15932  if( ae_fp_eq(c->x.ptr.p_double[i],tmpr.ptr.p_double[*nr-1]) )
15933  {
15934  *nr = *nr-1;
15935  }
15936  }
15937 
15938  /*
15939  *change state for 'DR'
15940  */
15941  if( !*dr )
15942  {
15943  *dr = ae_true;
15944  }
15945  }
15946  else
15947  {
15948  nstep = ae_true;
15949  }
15950  }
15951 
15952  /*
15953  *searching of extremums
15954  */
15955  if( i>0 )
15956  {
15957  pll = c->c.ptr.p_double[4*(i-1)];
15958 
15959  /*
15960  *if pL=pLL or pL=pR then
15961  */
15962  if( tne==-1 )
15963  {
15964  if( !*de )
15965  {
15966  *de = ae_true;
15967  }
15968  }
15969  else
15970  {
15971  if( ae_fp_greater(pl,pll)&&ae_fp_greater(pl,pr) )
15972  {
15973 
15974  /*
15975  *maximum
15976  */
15977  tmpet.ptr.p_int[*ne] = -1;
15978  tmpe.ptr.p_double[*ne] = c->x.ptr.p_double[i];
15979  *ne = *ne+1;
15980  }
15981  else
15982  {
15983  if( ae_fp_less(pl,pll)&&ae_fp_less(pl,pr) )
15984  {
15985 
15986  /*
15987  *minimum
15988  */
15989  tmpet.ptr.p_int[*ne] = 1;
15990  tmpe.ptr.p_double[*ne] = c->x.ptr.p_double[i];
15991  *ne = *ne+1;
15992  }
15993  }
15994  }
15995  }
15996  }
15997 
15998  /*
15999  *write final result
16000  */
16001  rvectorsetlengthatleast(r, *nr, _state);
16002  rvectorsetlengthatleast(e, *ne, _state);
16003  ivectorsetlengthatleast(et, *ne, _state);
16004 
16005  /*
16006  *write roots
16007  */
16008  for(i=0; i<=*nr-1; i++)
16009  {
16010  r->ptr.p_double[i] = tmpr.ptr.p_double[i];
16011  }
16012 
16013  /*
16014  *write extremums and their types
16015  */
16016  for(i=0; i<=*ne-1; i++)
16017  {
16018  e->ptr.p_double[i] = tmpe.ptr.p_double[i];
16019  et->ptr.p_int[i] = tmpet.ptr.p_int[i];
16020  }
16021  }
16022  else
16023  {
16024 
16025  /*
16026  *case, when C.Continuity>=1
16027  *'TmpR ' - it stores a time value for roots
16028  *'TmpC' - it stores a time value for extremums and
16029  *their function value (TmpC={EX0,F(EX0), EX1,F(EX1), ..., EXn,F(EXn)};)
16030  *'TmpE' - it stores a time value for extremums only
16031  *'TmpET'- it stores a time value for extremums type
16032  */
16033  rvectorsetlengthatleast(&tmpr, 2*c->n-1, _state);
16034  rvectorsetlengthatleast(&tmpc, 4*c->n, _state);
16035  rvectorsetlengthatleast(&tmpe, 2*c->n, _state);
16036  ivectorsetlengthatleast(&tmpet, 2*c->n, _state);
16037 
16038  /*
16039  *start calculating
16040  */
16041  for(i=0; i<=c->n-2; i++)
16042  {
16043 
16044  /*
16045  *we calculate pL,mL, pR,mR as Fi+1(F'i+1) at left border
16046  */
16047  pl = c->c.ptr.p_double[4*i];
16048  ml = c->c.ptr.p_double[4*i+1];
16049  pr = c->c.ptr.p_double[4*(i+1)];
16050  mr = c->c.ptr.p_double[4*(i+1)+1];
16051 
16052  /*
16053  *calculating roots and extremums at [X[i],X[i+1]]
16054  */
16055  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);
16056 
16057  /*
16058  *searching roots
16059  */
16060  if( tnr>0 )
16061  {
16062 
16063  /*
16064  *re-init tR
16065  */
16066  if( tnr>=1 )
16067  {
16068  tr.ptr.p_double[0] = x0;
16069  }
16070  if( tnr>=2 )
16071  {
16072  tr.ptr.p_double[1] = x1;
16073  }
16074  if( tnr==3 )
16075  {
16076  tr.ptr.p_double[2] = x2;
16077  }
16078 
16079  /*
16080  *start root selection
16081  */
16082  if( *nr>0 )
16083  {
16084  if( ae_fp_neq(tmpr.ptr.p_double[*nr-1],x0) )
16085  {
16086 
16087  /*
16088  *previous segment was't constant identical zero
16089  */
16090  if( nstep )
16091  {
16092  for(j=0; j<=tnr-1; j++)
16093  {
16094  tmpr.ptr.p_double[*nr+j] = tr.ptr.p_double[j];
16095  }
16096  *nr = *nr+tnr;
16097  }
16098  else
16099  {
16100 
16101  /*
16102  *previous segment was constant identical zero
16103  *and we must ignore [NR+j-1] root
16104  */
16105  for(j=1; j<=tnr-1; j++)
16106  {
16107  tmpr.ptr.p_double[*nr+j-1] = tr.ptr.p_double[j];
16108  }
16109  *nr = *nr+tnr-1;
16110  nstep = ae_true;
16111  }
16112  }
16113  else
16114  {
16115  for(j=1; j<=tnr-1; j++)
16116  {
16117  tmpr.ptr.p_double[*nr+j-1] = tr.ptr.p_double[j];
16118  }
16119  *nr = *nr+tnr-1;
16120  }
16121  }
16122  else
16123  {
16124 
16125  /*
16126  *write first root
16127  */
16128  for(j=0; j<=tnr-1; j++)
16129  {
16130  tmpr.ptr.p_double[*nr+j] = tr.ptr.p_double[j];
16131  }
16132  *nr = *nr+tnr;
16133  }
16134  }
16135  else
16136  {
16137  if( tnr==-1 )
16138  {
16139 
16140  /*
16141  *decrement 'NR' if at previous step was written a root
16142  *(previous segment identical zero)
16143  */
16144  if( *nr>0&&nstep )
16145  {
16146  *nr = *nr-1;
16147  }
16148 
16149  /*
16150  *previous segment is't constant
16151  */
16152  if( nstep )
16153  {
16154  nstep = ae_false;
16155  }
16156 
16157  /*
16158  *rewrite 'DR'
16159  */
16160  if( !*dr )
16161  {
16162  *dr = ae_true;
16163  }
16164  }
16165  }
16166 
16167  /*
16168  *searching extremums
16169  *write all term like extremums
16170  */
16171  if( tne==1 )
16172  {
16173  if( *ne>0 )
16174  {
16175 
16176  /*
16177  *just ignore identical extremums
16178  *because he must be one
16179  */
16180  if( ae_fp_neq(tmpc.ptr.p_double[*ne-2],ex0) )
16181  {
16182  tmpc.ptr.p_double[*ne] = ex0;
16183  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]);
16184  *ne = *ne+2;
16185  }
16186  }
16187  else
16188  {
16189 
16190  /*
16191  *write first extremum and it function value
16192  */
16193  tmpc.ptr.p_double[*ne] = ex0;
16194  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]);
16195  *ne = *ne+2;
16196  }
16197  }
16198  else
16199  {
16200  if( tne==2 )
16201  {
16202  if( *ne>0 )
16203  {
16204 
16205  /*
16206  *ignore identical extremum
16207  */
16208  if( ae_fp_neq(tmpc.ptr.p_double[*ne-2],ex0) )
16209  {
16210  tmpc.ptr.p_double[*ne] = ex0;
16211  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]);
16212  *ne = *ne+2;
16213  }
16214  }
16215  else
16216  {
16217 
16218  /*
16219  *write first extremum
16220  */
16221  tmpc.ptr.p_double[*ne] = ex0;
16222  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]);
16223  *ne = *ne+2;
16224  }
16225 
16226  /*
16227  *write second extremum
16228  */
16229  tmpc.ptr.p_double[*ne] = ex1;
16230  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]);
16231  *ne = *ne+2;
16232  }
16233  else
16234  {
16235  if( tne==-1 )
16236  {
16237  if( !*de )
16238  {
16239  *de = ae_true;
16240  }
16241  }
16242  }
16243  }
16244  }
16245 
16246  /*
16247  *checking of arrays
16248  *get number of extremums (tNe=NE/2)
16249  *initialize pL as value F0(X[0]) and
16250  *initialize pR as value Fn-1(X[N])
16251  */
16252  tne = *ne/2;
16253  *ne = 0;
16254  pl = c->c.ptr.p_double[0];
16255  pr = c->c.ptr.p_double[4*(c->n-1)];
16256  for(i=0; i<=tne-1; i++)
16257  {
16258  if( i>0&&i<tne-1 )
16259  {
16260  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]) )
16261  {
16262 
16263  /*
16264  *maximum
16265  */
16266  tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
16267  tmpet.ptr.p_int[*ne] = -1;
16268  *ne = *ne+1;
16269  }
16270  else
16271  {
16272  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]) )
16273  {
16274 
16275  /*
16276  *minimum
16277  */
16278  tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
16279  tmpet.ptr.p_int[*ne] = 1;
16280  *ne = *ne+1;
16281  }
16282  }
16283  }
16284  else
16285  {
16286  if( i==0 )
16287  {
16288  if( ae_fp_neq(tmpc.ptr.p_double[2*i],c->x.ptr.p_double[0]) )
16289  {
16290  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]) )
16291  {
16292 
16293  /*
16294  *maximum
16295  */
16296  tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
16297  tmpet.ptr.p_int[*ne] = -1;
16298  *ne = *ne+1;
16299  }
16300  else
16301  {
16302  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]) )
16303  {
16304 
16305  /*
16306  *minimum
16307  */
16308  tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
16309  tmpet.ptr.p_int[*ne] = 1;
16310  *ne = *ne+1;
16311  }
16312  }
16313  }
16314  }
16315  else
16316  {
16317  if( i==tne-1 )
16318  {
16319  if( ae_fp_neq(tmpc.ptr.p_double[2*i],c->x.ptr.p_double[c->n-1]) )
16320  {
16321  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) )
16322  {
16323 
16324  /*
16325  *maximum
16326  */
16327  tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
16328  tmpet.ptr.p_int[*ne] = -1;
16329  *ne = *ne+1;
16330  }
16331  else
16332  {
16333  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) )
16334  {
16335 
16336  /*
16337  *minimum
16338  */
16339  tmpe.ptr.p_double[*ne] = tmpc.ptr.p_double[2*i];
16340  tmpet.ptr.p_int[*ne] = 1;
16341  *ne = *ne+1;
16342  }
16343  }
16344  }
16345  }
16346  }
16347  }
16348  }
16349 
16350  /*
16351  *final results
16352  *allocate R, E, ET
16353  */
16354  rvectorsetlengthatleast(r, *nr, _state);
16355  rvectorsetlengthatleast(e, *ne, _state);
16356  ivectorsetlengthatleast(et, *ne, _state);
16357 
16358  /*
16359  *write result for extremus and their types
16360  */
16361  for(i=0; i<=*ne-1; i++)
16362  {
16363  e->ptr.p_double[i] = tmpe.ptr.p_double[i];
16364  et->ptr.p_int[i] = tmpet.ptr.p_int[i];
16365  }
16366 
16367  /*
16368  *write result for roots
16369  */
16370  for(i=0; i<=*nr-1; i++)
16371  {
16372  r->ptr.p_double[i] = tmpr.ptr.p_double[i];
16373  }
16374  }
16375  ae_frame_leave(_state);
16376 }
16377 
16378 
16379 /*************************************************************************
16380 Internal subroutine. Heap sort.
16381 *************************************************************************/
16382 void heapsortdpoints(/* Real */ ae_vector* x,
16383  /* Real */ ae_vector* y,
16384  /* Real */ ae_vector* d,
16385  ae_int_t n,
16386  ae_state *_state)
16387 {
16388  ae_frame _frame_block;
16389  ae_vector rbuf;
16390  ae_vector ibuf;
16391  ae_vector rbuf2;
16392  ae_vector ibuf2;
16393  ae_int_t i;
16394 
16395  ae_frame_make(_state, &_frame_block);
16396  ae_vector_init(&rbuf, 0, DT_REAL, _state, ae_true);
16397  ae_vector_init(&ibuf, 0, DT_INT, _state, ae_true);
16398  ae_vector_init(&rbuf2, 0, DT_REAL, _state, ae_true);
16399  ae_vector_init(&ibuf2, 0, DT_INT, _state, ae_true);
16400 
16401  ae_vector_set_length(&ibuf, n, _state);
16402  ae_vector_set_length(&rbuf, n, _state);
16403  for(i=0; i<=n-1; i++)
16404  {
16405  ibuf.ptr.p_int[i] = i;
16406  }
16407  tagsortfasti(x, &ibuf, &rbuf2, &ibuf2, n, _state);
16408  for(i=0; i<=n-1; i++)
16409  {
16410  rbuf.ptr.p_double[i] = y->ptr.p_double[ibuf.ptr.p_int[i]];
16411  }
16412  ae_v_move(&y->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1));
16413  for(i=0; i<=n-1; i++)
16414  {
16415  rbuf.ptr.p_double[i] = d->ptr.p_double[ibuf.ptr.p_int[i]];
16416  }
16417  ae_v_move(&d->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1));
16418  ae_frame_leave(_state);
16419 }
16420 
16421 
16422 /*************************************************************************
16423 This procedure search roots of an quadratic equation inside [0;1] and it number of roots.
16424 
16425 INPUT PARAMETERS:
16426  P0 - value of a function at 0
16427  M0 - value of a derivative at 0
16428  P1 - value of a function at 1
16429  M1 - value of a derivative at 1
16430 
16431 OUTPUT PARAMETERS:
16432  X0 - first root of an equation
16433  X1 - second root of an equation
16434  NR - number of roots
16435 
16436 RESTRICTIONS OF PARAMETERS:
16437 
16438 Parameters for this procedure has't to be zero simultaneously. Is expected,
16439 that input polinom is't degenerate or constant identicaly ZERO.
16440 
16441 
16442 REMARK:
16443 
16444 The procedure always fill value for X1 and X2, even if it is't belongs to [0;1].
16445 But first true root(even if existing one) is in X1.
16446 Number of roots is NR.
16447 
16448  -- ALGLIB PROJECT --
16449  Copyright 26.09.2011 by Bochkanov Sergey
16450 *************************************************************************/
16451 void solvepolinom2(double p0,
16452  double m0,
16453  double p1,
16454  double m1,
16455  double* x0,
16456  double* x1,
16457  ae_int_t* nr,
16458  ae_state *_state)
16459 {
16460  double a;
16461  double b;
16462  double c;
16463  double dd;
16464  double tmp;
16465  double exf;
16466  double extr;
16467 
16468  *x0 = 0;
16469  *x1 = 0;
16470  *nr = 0;
16471 
16472 
16473  /*
16474  *calculate parameters for equation: A, B and C
16475  */
16476  a = 6*p0+3*m0-6*p1+3*m1;
16477  b = -6*p0-4*m0+6*p1-2*m1;
16478  c = m0;
16479 
16480  /*
16481  *check case, when A=0
16482  *we are considering the linear equation
16483  */
16484  if( ae_fp_eq(a,0) )
16485  {
16486 
16487  /*
16488  *B<>0 and root inside [0;1]
16489  *one root
16490  */
16491  if( (ae_fp_neq(b,0)&&ae_sign(c, _state)*ae_sign(b, _state)<=0)&&ae_fp_greater_eq(ae_fabs(b, _state),ae_fabs(c, _state)) )
16492  {
16493  *x0 = -c/b;
16494  *nr = 1;
16495  return;
16496  }
16497  else
16498  {
16499  *nr = 0;
16500  return;
16501  }
16502  }
16503 
16504  /*
16505  *consider case, when extremumu outside (0;1)
16506  *exist one root only
16507  */
16508  if( ae_fp_less_eq(ae_fabs(2*a, _state),ae_fabs(b, _state))||ae_sign(b, _state)*ae_sign(a, _state)>=0 )
16509  {
16510  if( ae_sign(m0, _state)*ae_sign(m1, _state)>0 )
16511  {
16512  *nr = 0;
16513  return;
16514  }
16515 
16516  /*
16517  *consider case, when the one exist
16518  *same sign of derivative
16519  */
16520  if( ae_sign(m0, _state)*ae_sign(m1, _state)<0 )
16521  {
16522  *nr = 1;
16523  extr = -b/(2*a);
16524  dd = b*b-4*a*c;
16525  if( ae_fp_less(dd,0) )
16526  {
16527  return;
16528  }
16529  *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
16530  *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
16531  if( (ae_fp_greater_eq(extr,1)&&ae_fp_less_eq(*x1,extr))||(ae_fp_less_eq(extr,0)&&ae_fp_greater_eq(*x1,extr)) )
16532  {
16533  *x0 = *x1;
16534  }
16535  return;
16536  }
16537 
16538  /*
16539  *consider case, when the one is 0
16540  */
16541  if( ae_fp_eq(m0,0) )
16542  {
16543  *x0 = 0;
16544  *nr = 1;
16545  return;
16546  }
16547  if( ae_fp_eq(m1,0) )
16548  {
16549  *x0 = 1;
16550  *nr = 1;
16551  return;
16552  }
16553  }
16554  else
16555  {
16556 
16557  /*
16558  *consider case, when both of derivatives is 0
16559  */
16560  if( ae_fp_eq(m0,0)&&ae_fp_eq(m1,0) )
16561  {
16562  *x0 = 0;
16563  *x1 = 1;
16564  *nr = 2;
16565  return;
16566  }
16567 
16568  /*
16569  *consider case, when derivative at 0 is 0, and derivative at 1 is't 0
16570  */
16571  if( ae_fp_eq(m0,0)&&ae_fp_neq(m1,0) )
16572  {
16573  dd = b*b-4*a*c;
16574  if( ae_fp_less(dd,0) )
16575  {
16576  *x0 = 0;
16577  *nr = 1;
16578  return;
16579  }
16580  *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
16581  *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
16582  extr = -b/(2*a);
16583  exf = a*extr*extr+b*extr+c;
16584  if( ae_sign(exf, _state)*ae_sign(m1, _state)>0 )
16585  {
16586  *x0 = 0;
16587  *nr = 1;
16588  return;
16589  }
16590  else
16591  {
16592  if( ae_fp_greater(extr,*x0) )
16593  {
16594  *x0 = 0;
16595  }
16596  else
16597  {
16598  *x1 = 0;
16599  }
16600  *nr = 2;
16601 
16602  /*
16603  *roots must placed ascending
16604  */
16605  if( ae_fp_greater(*x0,*x1) )
16606  {
16607  tmp = *x0;
16608  *x0 = *x1;
16609  *x1 = tmp;
16610  }
16611  return;
16612  }
16613  }
16614  if( ae_fp_eq(m1,0)&&ae_fp_neq(m0,0) )
16615  {
16616  dd = b*b-4*a*c;
16617  if( ae_fp_less(dd,0) )
16618  {
16619  *x0 = 1;
16620  *nr = 1;
16621  return;
16622  }
16623  *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
16624  *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
16625  extr = -b/(2*a);
16626  exf = a*extr*extr+b*extr+c;
16627  if( ae_sign(exf, _state)*ae_sign(m0, _state)>0 )
16628  {
16629  *x0 = 1;
16630  *nr = 1;
16631  return;
16632  }
16633  else
16634  {
16635  if( ae_fp_less(extr,*x0) )
16636  {
16637  *x0 = 1;
16638  }
16639  else
16640  {
16641  *x1 = 1;
16642  }
16643  *nr = 2;
16644 
16645  /*
16646  *roots must placed ascending
16647  */
16648  if( ae_fp_greater(*x0,*x1) )
16649  {
16650  tmp = *x0;
16651  *x0 = *x1;
16652  *x1 = tmp;
16653  }
16654  return;
16655  }
16656  }
16657  else
16658  {
16659  extr = -b/(2*a);
16660  exf = a*extr*extr+b*extr+c;
16661  if( ae_sign(exf, _state)*ae_sign(m0, _state)>0&&ae_sign(exf, _state)*ae_sign(m1, _state)>0 )
16662  {
16663  *nr = 0;
16664  return;
16665  }
16666  dd = b*b-4*a*c;
16667  if( ae_fp_less(dd,0) )
16668  {
16669  *nr = 0;
16670  return;
16671  }
16672  *x0 = (-b-ae_sqrt(dd, _state))/(2*a);
16673  *x1 = (-b+ae_sqrt(dd, _state))/(2*a);
16674 
16675  /*
16676  *if EXF and m0, EXF and m1 has different signs, then equation has two roots
16677  */
16678  if( ae_sign(exf, _state)*ae_sign(m0, _state)<0&&ae_sign(exf, _state)*ae_sign(m1, _state)<0 )
16679  {
16680  *nr = 2;
16681 
16682  /*
16683  *roots must placed ascending
16684  */
16685  if( ae_fp_greater(*x0,*x1) )
16686  {
16687  tmp = *x0;
16688  *x0 = *x1;
16689  *x1 = tmp;
16690  }
16691  return;
16692  }
16693  else
16694  {
16695  *nr = 1;
16696  if( ae_sign(exf, _state)*ae_sign(m0, _state)<0 )
16697  {
16698  if( ae_fp_less(*x1,extr) )
16699  {
16700  *x0 = *x1;
16701  }
16702  return;
16703  }
16704  if( ae_sign(exf, _state)*ae_sign(m1, _state)<0 )
16705  {
16706  if( ae_fp_greater(*x1,extr) )
16707  {
16708  *x0 = *x1;
16709  }
16710  return;
16711  }
16712  }
16713  }
16714  }
16715 }
16716 
16717 
16718 /*************************************************************************
16719 This procedure search roots of an cubic equation inside [A;B], it number of roots
16720 and number of extremums.
16721 
16722 INPUT PARAMETERS:
16723  pA - value of a function at A
16724  mA - value of a derivative at A
16725  pB - value of a function at B
16726  mB - value of a derivative at B
16727  A0 - left border [A0;B0]
16728  B0 - right border [A0;B0]
16729 
16730 OUTPUT PARAMETERS:
16731  X0 - first root of an equation
16732  X1 - second root of an equation
16733  X2 - third root of an equation
16734  EX0 - first extremum of a function
16735  EX0 - second extremum of a function
16736  NR - number of roots
16737  NR - number of extrmums
16738 
16739 RESTRICTIONS OF PARAMETERS:
16740 
16741 Length of [A;B] must be positive and is't zero, i.e. A<>B and A<B.
16742 
16743 
16744 REMARK:
16745 
16746 If 'NR' is -1 it's mean, than polinom has infiniti roots.
16747 If 'NE' is -1 it's mean, than polinom has infiniti extremums.
16748 
16749  -- ALGLIB PROJECT --
16750  Copyright 26.09.2011 by Bochkanov Sergey
16751 *************************************************************************/
16752 void solvecubicpolinom(double pa,
16753  double ma,
16754  double pb,
16755  double mb,
16756  double a,
16757  double b,
16758  double* x0,
16759  double* x1,
16760  double* x2,
16761  double* ex0,
16762  double* ex1,
16763  ae_int_t* nr,
16764  ae_int_t* ne,
16765  /* Real */ ae_vector* tempdata,
16766  ae_state *_state)
16767 {
16768  ae_int_t i;
16769  double tmpma;
16770  double tmpmb;
16771  double tex0;
16772  double tex1;
16773 
16774  *x0 = 0;
16775  *x1 = 0;
16776  *x2 = 0;
16777  *ex0 = 0;
16778  *ex1 = 0;
16779  *nr = 0;
16780  *ne = 0;
16781 
16782  rvectorsetlengthatleast(tempdata, 3, _state);
16783 
16784  /*
16785  *case, when A>B
16786  */
16787  ae_assert(ae_fp_less(a,b), "\nSolveCubicPolinom: incorrect borders for [A;B]!\n", _state);
16788 
16789  /*
16790  *case 1
16791  *function can be identicaly to ZERO
16792  */
16793  if( ((ae_fp_eq(ma,0)&&ae_fp_eq(mb,0))&&ae_fp_eq(pa,pb))&&ae_fp_eq(pa,0) )
16794  {
16795  *nr = -1;
16796  *ne = -1;
16797  return;
16798  }
16799  if( (ae_fp_eq(ma,0)&&ae_fp_eq(mb,0))&&ae_fp_eq(pa,pb) )
16800  {
16801  *nr = 0;
16802  *ne = -1;
16803  return;
16804  }
16805  tmpma = ma*(b-a);
16806  tmpmb = mb*(b-a);
16807  solvepolinom2(pa, tmpma, pb, tmpmb, ex0, ex1, ne, _state);
16808  *ex0 = spline1d_rescaleval(0, 1, a, b, *ex0, _state);
16809  *ex1 = spline1d_rescaleval(0, 1, a, b, *ex1, _state);
16810 
16811  /*
16812  *case 3.1
16813  *no extremums at [A;B]
16814  */
16815  if( *ne==0 )
16816  {
16817  *nr = bisectmethod(pa, tmpma, pb, tmpmb, 0, 1, x0, _state);
16818  if( *nr==1 )
16819  {
16820  *x0 = spline1d_rescaleval(0, 1, a, b, *x0, _state);
16821  }
16822  return;
16823  }
16824 
16825  /*
16826  *case 3.2
16827  *one extremum
16828  */
16829  if( *ne==1 )
16830  {
16831  if( ae_fp_eq(*ex0,a)||ae_fp_eq(*ex0,b) )
16832  {
16833  *nr = bisectmethod(pa, tmpma, pb, tmpmb, 0, 1, x0, _state);
16834  if( *nr==1 )
16835  {
16836  *x0 = spline1d_rescaleval(0, 1, a, b, *x0, _state);
16837  }
16838  return;
16839  }
16840  else
16841  {
16842  *nr = 0;
16843  i = 0;
16844  tex0 = spline1d_rescaleval(a, b, 0, 1, *ex0, _state);
16845  *nr = bisectmethod(pa, tmpma, pb, tmpmb, 0, tex0, x0, _state)+(*nr);
16846  if( *nr>i )
16847  {
16848  tempdata->ptr.p_double[i] = spline1d_rescaleval(0, tex0, a, *ex0, *x0, _state);
16849  i = i+1;
16850  }
16851  *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, 1, x0, _state)+(*nr);
16852  if( *nr>i )
16853  {
16854  *x0 = spline1d_rescaleval(tex0, 1, *ex0, b, *x0, _state);
16855  if( i>0 )
16856  {
16857  if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
16858  {
16859  tempdata->ptr.p_double[i] = *x0;
16860  i = i+1;
16861  }
16862  else
16863  {
16864  *nr = *nr-1;
16865  }
16866  }
16867  else
16868  {
16869  tempdata->ptr.p_double[i] = *x0;
16870  i = i+1;
16871  }
16872  }
16873  if( *nr>0 )
16874  {
16875  *x0 = tempdata->ptr.p_double[0];
16876  if( *nr>1 )
16877  {
16878  *x1 = tempdata->ptr.p_double[1];
16879  }
16880  return;
16881  }
16882  }
16883  return;
16884  }
16885  else
16886  {
16887 
16888  /*
16889  *case 3.3
16890  *two extremums(or more, but it's impossible)
16891  *
16892  *
16893  *case 3.3.0
16894  *both extremums at the border
16895  */
16896  if( ae_fp_eq(*ex0,a)&&ae_fp_eq(*ex1,b) )
16897  {
16898  *nr = bisectmethod(pa, tmpma, pb, tmpmb, 0, 1, x0, _state);
16899  if( *nr==1 )
16900  {
16901  *x0 = spline1d_rescaleval(0, 1, a, b, *x0, _state);
16902  }
16903  return;
16904  }
16905  if( ae_fp_eq(*ex0,a)&&ae_fp_neq(*ex1,b) )
16906  {
16907  *nr = 0;
16908  i = 0;
16909  tex1 = spline1d_rescaleval(a, b, 0, 1, *ex1, _state);
16910  *nr = bisectmethod(pa, tmpma, pb, tmpmb, 0, tex1, x0, _state)+(*nr);
16911  if( *nr>i )
16912  {
16913  tempdata->ptr.p_double[i] = spline1d_rescaleval(0, tex1, a, *ex1, *x0, _state);
16914  i = i+1;
16915  }
16916  *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex1, 1, x0, _state)+(*nr);
16917  if( *nr>i )
16918  {
16919  *x0 = spline1d_rescaleval(tex1, 1, *ex1, b, *x0, _state);
16920  if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
16921  {
16922  tempdata->ptr.p_double[i] = *x0;
16923  i = i+1;
16924  }
16925  else
16926  {
16927  *nr = *nr-1;
16928  }
16929  }
16930  if( *nr>0 )
16931  {
16932  *x0 = tempdata->ptr.p_double[0];
16933  if( *nr>1 )
16934  {
16935  *x1 = tempdata->ptr.p_double[1];
16936  }
16937  return;
16938  }
16939  }
16940  if( ae_fp_eq(*ex1,b)&&ae_fp_neq(*ex0,a) )
16941  {
16942  *nr = 0;
16943  i = 0;
16944  tex0 = spline1d_rescaleval(a, b, 0, 1, *ex0, _state);
16945  *nr = bisectmethod(pa, tmpma, pb, tmpmb, 0, tex0, x0, _state)+(*nr);
16946  if( *nr>i )
16947  {
16948  tempdata->ptr.p_double[i] = spline1d_rescaleval(0, tex0, a, *ex0, *x0, _state);
16949  i = i+1;
16950  }
16951  *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, 1, x0, _state)+(*nr);
16952  if( *nr>i )
16953  {
16954  *x0 = spline1d_rescaleval(tex0, 1, *ex0, b, *x0, _state);
16955  if( i>0 )
16956  {
16957  if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
16958  {
16959  tempdata->ptr.p_double[i] = *x0;
16960  i = i+1;
16961  }
16962  else
16963  {
16964  *nr = *nr-1;
16965  }
16966  }
16967  else
16968  {
16969  tempdata->ptr.p_double[i] = *x0;
16970  i = i+1;
16971  }
16972  }
16973  if( *nr>0 )
16974  {
16975  *x0 = tempdata->ptr.p_double[0];
16976  if( *nr>1 )
16977  {
16978  *x1 = tempdata->ptr.p_double[1];
16979  }
16980  return;
16981  }
16982  }
16983  else
16984  {
16985 
16986  /*
16987  *case 3.3.2
16988  *both extremums inside (0;1)
16989  */
16990  *nr = 0;
16991  i = 0;
16992  tex0 = spline1d_rescaleval(a, b, 0, 1, *ex0, _state);
16993  tex1 = spline1d_rescaleval(a, b, 0, 1, *ex1, _state);
16994  *nr = bisectmethod(pa, tmpma, pb, tmpmb, 0, tex0, x0, _state)+(*nr);
16995  if( *nr>i )
16996  {
16997  tempdata->ptr.p_double[i] = spline1d_rescaleval(0, tex0, a, *ex0, *x0, _state);
16998  i = i+1;
16999  }
17000  *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex0, tex1, x0, _state)+(*nr);
17001  if( *nr>i )
17002  {
17003  *x0 = spline1d_rescaleval(tex0, tex1, *ex0, *ex1, *x0, _state);
17004  if( i>0 )
17005  {
17006  if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
17007  {
17008  tempdata->ptr.p_double[i] = *x0;
17009  i = i+1;
17010  }
17011  else
17012  {
17013  *nr = *nr-1;
17014  }
17015  }
17016  else
17017  {
17018  tempdata->ptr.p_double[i] = *x0;
17019  i = i+1;
17020  }
17021  }
17022  *nr = bisectmethod(pa, tmpma, pb, tmpmb, tex1, 1, x0, _state)+(*nr);
17023  if( *nr>i )
17024  {
17025  *x0 = spline1d_rescaleval(tex1, 1, *ex1, b, *x0, _state);
17026  if( i>0 )
17027  {
17028  if( ae_fp_neq(*x0,tempdata->ptr.p_double[i-1]) )
17029  {
17030  tempdata->ptr.p_double[i] = *x0;
17031  i = i+1;
17032  }
17033  else
17034  {
17035  *nr = *nr-1;
17036  }
17037  }
17038  else
17039  {
17040  tempdata->ptr.p_double[i] = *x0;
17041  i = i+1;
17042  }
17043  }
17044 
17045  /*
17046  *write are found roots
17047  */
17048  if( *nr>0 )
17049  {
17050  *x0 = tempdata->ptr.p_double[0];
17051  if( *nr>1 )
17052  {
17053  *x1 = tempdata->ptr.p_double[1];
17054  }
17055  if( *nr>2 )
17056  {
17057  *x2 = tempdata->ptr.p_double[2];
17058  }
17059  return;
17060  }
17061  }
17062  }
17063 }
17064 
17065 
17066 /*************************************************************************
17067 Function for searching a root at [A;B] by bisection method and return number of roots
17068 (0 or 1)
17069 
17070 INPUT PARAMETERS:
17071  pA - value of a function at A
17072  mA - value of a derivative at A
17073  pB - value of a function at B
17074  mB - value of a derivative at B
17075  A0 - left border [A0;B0]
17076  B0 - right border [A0;B0]
17077 
17078 RESTRICTIONS OF PARAMETERS:
17079 
17080 We assume, that B0>A0.
17081 
17082 
17083 REMARK:
17084 
17085 Assume, that exist one root only at [A;B], else
17086 function may be work incorrectly.
17087 The function don't check value A0,B0!
17088 
17089  -- ALGLIB PROJECT --
17090  Copyright 26.09.2011 by Bochkanov Sergey
17091 *************************************************************************/
17093  double ma,
17094  double pb,
17095  double mb,
17096  double a,
17097  double b,
17098  double* x,
17099  ae_state *_state)
17100 {
17101  double vacuum;
17102  double eps;
17103  double a0;
17104  double b0;
17105  double m;
17106  double lf;
17107  double rf;
17108  double mf;
17109  ae_int_t result;
17110 
17111  *x = 0;
17112 
17113 
17114  /*
17115  *accuracy
17116  */
17117  eps = 1000*(b-a)*ae_machineepsilon;
17118 
17119  /*
17120  *initialization left and right borders
17121  */
17122  a0 = a;
17123  b0 = b;
17124 
17125  /*
17126  *initialize function value at 'A' and 'B'
17127  */
17128  spline1d_hermitecalc(pa, ma, pb, mb, a, &lf, &vacuum, _state);
17129  spline1d_hermitecalc(pa, ma, pb, mb, b, &rf, &vacuum, _state);
17130 
17131  /*
17132  *check, that 'A' and 'B' are't roots,
17133  *and that root exist
17134  */
17135  if( ae_sign(lf, _state)*ae_sign(rf, _state)>0 )
17136  {
17137  result = 0;
17138  return result;
17139  }
17140  else
17141  {
17142  if( ae_fp_eq(lf,0) )
17143  {
17144  *x = a;
17145  result = 1;
17146  return result;
17147  }
17148  else
17149  {
17150  if( ae_fp_eq(rf,0) )
17151  {
17152  *x = b;
17153  result = 1;
17154  return result;
17155  }
17156  }
17157  }
17158 
17159  /*
17160  *searching a root
17161  */
17162  do
17163  {
17164  m = (b0+a0)/2;
17165  spline1d_hermitecalc(pa, ma, pb, mb, a0, &lf, &vacuum, _state);
17166  spline1d_hermitecalc(pa, ma, pb, mb, b0, &rf, &vacuum, _state);
17167  spline1d_hermitecalc(pa, ma, pb, mb, m, &mf, &vacuum, _state);
17168  if( ae_sign(mf, _state)*ae_sign(lf, _state)<0 )
17169  {
17170  b0 = m;
17171  }
17172  else
17173  {
17174  if( ae_sign(mf, _state)*ae_sign(rf, _state)<0 )
17175  {
17176  a0 = m;
17177  }
17178  else
17179  {
17180  if( ae_fp_eq(lf,0) )
17181  {
17182  *x = a0;
17183  result = 1;
17184  return result;
17185  }
17186  if( ae_fp_eq(rf,0) )
17187  {
17188  *x = b0;
17189  result = 1;
17190  return result;
17191  }
17192  if( ae_fp_eq(mf,0) )
17193  {
17194  *x = m;
17195  result = 1;
17196  return result;
17197  }
17198  }
17199  }
17200  }
17201  while(ae_fp_greater_eq(ae_fabs(b0-a0, _state),eps));
17202  *x = m;
17203  result = 1;
17204  return result;
17205 }
17206 
17207 
17208 /*************************************************************************
17209 This function builds monotone cubic Hermite interpolant. This interpolant
17210 is monotonic in [x(0),x(n-1)] and is constant outside of this interval.
17211 
17212 In case y[] form non-monotonic sequence, interpolant is piecewise
17213 monotonic. Say, for x=(0,1,2,3,4) and y=(0,1,2,1,0) interpolant will
17214 monotonically grow at [0..2] and monotonically decrease at [2..4].
17215 
17216 INPUT PARAMETERS:
17217  X - spline nodes, array[0..N-1]. Subroutine automatically
17218  sorts points, so caller may pass unsorted array.
17219  Y - function values, array[0..N-1]
17220  N - the number of points(N>=2).
17221 
17222 OUTPUT PARAMETERS:
17223  C - spline interpolant.
17224 
17225  -- ALGLIB PROJECT --
17226  Copyright 21.06.2012 by Bochkanov Sergey
17227 *************************************************************************/
17229  /* Real */ ae_vector* y,
17230  ae_int_t n,
17232  ae_state *_state)
17233 {
17234  ae_frame _frame_block;
17235  ae_vector _x;
17236  ae_vector _y;
17237  ae_vector d;
17238  ae_vector ex;
17239  ae_vector ey;
17240  ae_vector p;
17241  double delta;
17242  double alpha;
17243  double beta;
17244  ae_int_t tmpn;
17245  ae_int_t sn;
17246  double ca;
17247  double cb;
17248  double epsilon;
17249  ae_int_t i;
17250  ae_int_t j;
17251 
17252  ae_frame_make(_state, &_frame_block);
17253  ae_vector_init_copy(&_x, x, _state, ae_true);
17254  x = &_x;
17255  ae_vector_init_copy(&_y, y, _state, ae_true);
17256  y = &_y;
17258  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
17259  ae_vector_init(&ex, 0, DT_REAL, _state, ae_true);
17260  ae_vector_init(&ey, 0, DT_REAL, _state, ae_true);
17261  ae_vector_init(&p, 0, DT_INT, _state, ae_true);
17262 
17263 
17264  /*
17265  * Check lengths of arguments
17266  */
17267  ae_assert(n>=2, "Spline1DBuildMonotone: N<2", _state);
17268  ae_assert(x->cnt>=n, "Spline1DBuildMonotone: Length(X)<N", _state);
17269  ae_assert(y->cnt>=n, "Spline1DBuildMonotone: Length(Y)<N", _state);
17270 
17271  /*
17272  * Check and sort points
17273  */
17274  ae_assert(isfinitevector(x, n, _state), "Spline1DBuildMonotone: X contains infinite or NAN values", _state);
17275  ae_assert(isfinitevector(y, n, _state), "Spline1DBuildMonotone: Y contains infinite or NAN values", _state);
17276  spline1d_heapsortppoints(x, y, &p, n, _state);
17277  ae_assert(aredistinct(x, n, _state), "Spline1DBuildMonotone: at least two consequent points are too close", _state);
17278  epsilon = ae_machineepsilon;
17279  n = n+2;
17280  ae_vector_set_length(&d, n, _state);
17281  ae_vector_set_length(&ex, n, _state);
17282  ae_vector_set_length(&ey, n, _state);
17283  ex.ptr.p_double[0] = x->ptr.p_double[0]-ae_fabs(x->ptr.p_double[1]-x->ptr.p_double[0], _state);
17284  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);
17285  ey.ptr.p_double[0] = y->ptr.p_double[0];
17286  ey.ptr.p_double[n-1] = y->ptr.p_double[n-3];
17287  for(i=1; i<=n-2; i++)
17288  {
17289  ex.ptr.p_double[i] = x->ptr.p_double[i-1];
17290  ey.ptr.p_double[i] = y->ptr.p_double[i-1];
17291  }
17292 
17293  /*
17294  * Init sign of the function for first segment
17295  */
17296  i = 0;
17297  ca = 0;
17298  do
17299  {
17300  ca = ey.ptr.p_double[i+1]-ey.ptr.p_double[i];
17301  i = i+1;
17302  }
17303  while(!(ae_fp_neq(ca,0)||i>n-2));
17304  if( ae_fp_neq(ca,0) )
17305  {
17306  ca = ca/ae_fabs(ca, _state);
17307  }
17308  i = 0;
17309  while(i<n-1)
17310  {
17311 
17312  /*
17313  * Partition of the segment [X0;Xn]
17314  */
17315  tmpn = 1;
17316  for(j=i; j<=n-2; j++)
17317  {
17318  cb = ey.ptr.p_double[j+1]-ey.ptr.p_double[j];
17319  if( ae_fp_greater_eq(ca*cb,0) )
17320  {
17321  tmpn = tmpn+1;
17322  }
17323  else
17324  {
17325  ca = cb/ae_fabs(cb, _state);
17326  break;
17327  }
17328  }
17329  sn = i+tmpn;
17330  ae_assert(tmpn>=2, "Spline1DBuildMonotone: internal error", _state);
17331 
17332  /*
17333  * Calculate derivatives for current segment
17334  */
17335  d.ptr.p_double[i] = 0;
17336  d.ptr.p_double[sn-1] = 0;
17337  for(j=i+1; j<=sn-2; j++)
17338  {
17339  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;
17340  }
17341  for(j=i; j<=sn-2; j++)
17342  {
17343  delta = (ey.ptr.p_double[j+1]-ey.ptr.p_double[j])/(ex.ptr.p_double[j+1]-ex.ptr.p_double[j]);
17344  if( ae_fp_less_eq(ae_fabs(delta, _state),epsilon) )
17345  {
17346  d.ptr.p_double[j] = 0;
17347  d.ptr.p_double[j+1] = 0;
17348  }
17349  else
17350  {
17351  alpha = d.ptr.p_double[j]/delta;
17352  beta = d.ptr.p_double[j+1]/delta;
17353  if( ae_fp_neq(alpha,0) )
17354  {
17355  cb = alpha*ae_sqrt(1+ae_sqr(beta/alpha, _state), _state);
17356  }
17357  else
17358  {
17359  if( ae_fp_neq(beta,0) )
17360  {
17361  cb = beta;
17362  }
17363  else
17364  {
17365  continue;
17366  }
17367  }
17368  if( ae_fp_greater(cb,3) )
17369  {
17370  d.ptr.p_double[j] = 3*alpha*delta/cb;
17371  d.ptr.p_double[j+1] = 3*beta*delta/cb;
17372  }
17373  }
17374  }
17375 
17376  /*
17377  * Transition to next segment
17378  */
17379  i = sn-1;
17380  }
17381  spline1dbuildhermite(&ex, &ey, &d, n, c, _state);
17382  c->continuity = 2;
17383  ae_frame_leave(_state);
17384 }
17385 
17386 
17387 /*************************************************************************
17388 Internal version of Spline1DGridDiffCubic.
17389 
17390 Accepts pre-ordered X/Y, temporary arrays (which may be preallocated, if
17391 you want to save time, or not) and output array (which may be preallocated
17392 too).
17393 
17394 Y is passed as var-parameter because we may need to force last element to
17395 be equal to the first one (if periodic boundary conditions are specified).
17396 
17397  -- ALGLIB PROJECT --
17398  Copyright 03.09.2010 by Bochkanov Sergey
17399 *************************************************************************/
17400 static void spline1d_spline1dgriddiffcubicinternal(/* Real */ ae_vector* x,
17401  /* Real */ ae_vector* y,
17402  ae_int_t n,
17403  ae_int_t boundltype,
17404  double boundl,
17405  ae_int_t boundrtype,
17406  double boundr,
17407  /* Real */ ae_vector* d,
17408  /* Real */ ae_vector* a1,
17409  /* Real */ ae_vector* a2,
17410  /* Real */ ae_vector* a3,
17411  /* Real */ ae_vector* b,
17412  /* Real */ ae_vector* dt,
17413  ae_state *_state)
17414 {
17415  ae_int_t i;
17416 
17417 
17418 
17419  /*
17420  * allocate arrays
17421  */
17422  if( d->cnt<n )
17423  {
17424  ae_vector_set_length(d, n, _state);
17425  }
17426  if( a1->cnt<n )
17427  {
17428  ae_vector_set_length(a1, n, _state);
17429  }
17430  if( a2->cnt<n )
17431  {
17432  ae_vector_set_length(a2, n, _state);
17433  }
17434  if( a3->cnt<n )
17435  {
17436  ae_vector_set_length(a3, n, _state);
17437  }
17438  if( b->cnt<n )
17439  {
17440  ae_vector_set_length(b, n, _state);
17441  }
17442  if( dt->cnt<n )
17443  {
17444  ae_vector_set_length(dt, n, _state);
17445  }
17446 
17447  /*
17448  * Special cases:
17449  * * N=2, parabolic terminated boundary condition on both ends
17450  * * N=2, periodic boundary condition
17451  */
17452  if( (n==2&&boundltype==0)&&boundrtype==0 )
17453  {
17454  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]);
17455  d->ptr.p_double[1] = d->ptr.p_double[0];
17456  return;
17457  }
17458  if( (n==2&&boundltype==-1)&&boundrtype==-1 )
17459  {
17460  d->ptr.p_double[0] = 0;
17461  d->ptr.p_double[1] = 0;
17462  return;
17463  }
17464 
17465  /*
17466  * Periodic and non-periodic boundary conditions are
17467  * two separate classes
17468  */
17469  if( boundrtype==-1&&boundltype==-1 )
17470  {
17471 
17472  /*
17473  * Periodic boundary conditions
17474  */
17475  y->ptr.p_double[n-1] = y->ptr.p_double[0];
17476 
17477  /*
17478  * Boundary conditions at N-1 points
17479  * (one point less because last point is the same as first point).
17480  */
17481  a1->ptr.p_double[0] = x->ptr.p_double[1]-x->ptr.p_double[0];
17482  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]);
17483  a3->ptr.p_double[0] = x->ptr.p_double[n-1]-x->ptr.p_double[n-2];
17484  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]);
17485  for(i=1; i<=n-2; i++)
17486  {
17487 
17488  /*
17489  * Although last point is [N-2], we use X[N-1] and Y[N-1]
17490  * (because of periodicity)
17491  */
17492  a1->ptr.p_double[i] = x->ptr.p_double[i+1]-x->ptr.p_double[i];
17493  a2->ptr.p_double[i] = 2*(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]);
17494  a3->ptr.p_double[i] = x->ptr.p_double[i]-x->ptr.p_double[i-1];
17495  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]);
17496  }
17497 
17498  /*
17499  * Solve, add last point (with index N-1)
17500  */
17501  spline1d_solvecyclictridiagonal(a1, a2, a3, b, n-1, dt, _state);
17502  ae_v_move(&d->ptr.p_double[0], 1, &dt->ptr.p_double[0], 1, ae_v_len(0,n-2));
17503  d->ptr.p_double[n-1] = d->ptr.p_double[0];
17504  }
17505  else
17506  {
17507 
17508  /*
17509  * Non-periodic boundary condition.
17510  * Left boundary conditions.
17511  */
17512  if( boundltype==0 )
17513  {
17514  a1->ptr.p_double[0] = 0;
17515  a2->ptr.p_double[0] = 1;
17516  a3->ptr.p_double[0] = 1;
17517  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]);
17518  }
17519  if( boundltype==1 )
17520  {
17521  a1->ptr.p_double[0] = 0;
17522  a2->ptr.p_double[0] = 1;
17523  a3->ptr.p_double[0] = 0;
17524  b->ptr.p_double[0] = boundl;
17525  }
17526  if( boundltype==2 )
17527  {
17528  a1->ptr.p_double[0] = 0;
17529  a2->ptr.p_double[0] = 2;
17530  a3->ptr.p_double[0] = 1;
17531  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]);
17532  }
17533 
17534  /*
17535  * Central conditions
17536  */
17537  for(i=1; i<=n-2; i++)
17538  {
17539  a1->ptr.p_double[i] = x->ptr.p_double[i+1]-x->ptr.p_double[i];
17540  a2->ptr.p_double[i] = 2*(x->ptr.p_double[i+1]-x->ptr.p_double[i-1]);
17541  a3->ptr.p_double[i] = x->ptr.p_double[i]-x->ptr.p_double[i-1];
17542  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]);
17543  }
17544 
17545  /*
17546  * Right boundary conditions
17547  */
17548  if( boundrtype==0 )
17549  {
17550  a1->ptr.p_double[n-1] = 1;
17551  a2->ptr.p_double[n-1] = 1;
17552  a3->ptr.p_double[n-1] = 0;
17553  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]);
17554  }
17555  if( boundrtype==1 )
17556  {
17557  a1->ptr.p_double[n-1] = 0;
17558  a2->ptr.p_double[n-1] = 1;
17559  a3->ptr.p_double[n-1] = 0;
17560  b->ptr.p_double[n-1] = boundr;
17561  }
17562  if( boundrtype==2 )
17563  {
17564  a1->ptr.p_double[n-1] = 1;
17565  a2->ptr.p_double[n-1] = 2;
17566  a3->ptr.p_double[n-1] = 0;
17567  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]);
17568  }
17569 
17570  /*
17571  * Solve
17572  */
17573  spline1d_solvetridiagonal(a1, a2, a3, b, n, d, _state);
17574  }
17575 }
17576 
17577 
17578 /*************************************************************************
17579 Internal subroutine. Heap sort.
17580 *************************************************************************/
17581 static void spline1d_heapsortpoints(/* Real */ ae_vector* x,
17582  /* Real */ ae_vector* y,
17583  ae_int_t n,
17584  ae_state *_state)
17585 {
17586  ae_frame _frame_block;
17587  ae_vector bufx;
17588  ae_vector bufy;
17589 
17590  ae_frame_make(_state, &_frame_block);
17591  ae_vector_init(&bufx, 0, DT_REAL, _state, ae_true);
17592  ae_vector_init(&bufy, 0, DT_REAL, _state, ae_true);
17593 
17594  tagsortfastr(x, y, &bufx, &bufy, n, _state);
17595  ae_frame_leave(_state);
17596 }
17597 
17598 
17599 /*************************************************************************
17600 Internal subroutine. Heap sort.
17601 
17602 Accepts:
17603  X, Y - points
17604  P - empty or preallocated array
17605 
17606 Returns:
17607  X, Y - sorted by X
17608  P - array of permutations; I-th position of output
17609  arrays X/Y contains (X[P[I]],Y[P[I]])
17610 *************************************************************************/
17611 static void spline1d_heapsortppoints(/* Real */ ae_vector* x,
17612  /* Real */ ae_vector* y,
17613  /* Integer */ ae_vector* p,
17614  ae_int_t n,
17615  ae_state *_state)
17616 {
17617  ae_frame _frame_block;
17618  ae_vector rbuf;
17619  ae_vector ibuf;
17620  ae_int_t i;
17621 
17622  ae_frame_make(_state, &_frame_block);
17623  ae_vector_init(&rbuf, 0, DT_REAL, _state, ae_true);
17624  ae_vector_init(&ibuf, 0, DT_INT, _state, ae_true);
17625 
17626  if( p->cnt<n )
17627  {
17628  ae_vector_set_length(p, n, _state);
17629  }
17630  ae_vector_set_length(&rbuf, n, _state);
17631  for(i=0; i<=n-1; i++)
17632  {
17633  p->ptr.p_int[i] = i;
17634  }
17635  tagsortfasti(x, p, &rbuf, &ibuf, n, _state);
17636  for(i=0; i<=n-1; i++)
17637  {
17638  rbuf.ptr.p_double[i] = y->ptr.p_double[p->ptr.p_int[i]];
17639  }
17640  ae_v_move(&y->ptr.p_double[0], 1, &rbuf.ptr.p_double[0], 1, ae_v_len(0,n-1));
17641  ae_frame_leave(_state);
17642 }
17643 
17644 
17645 /*************************************************************************
17646 Internal subroutine. Tridiagonal solver. Solves
17647 
17648 ( B[0] C[0]
17649 ( A[1] B[1] C[1] )
17650 ( A[2] B[2] C[2] )
17651 ( .......... ) * X = D
17652 ( .......... )
17653 ( A[N-2] B[N-2] C[N-2] )
17654 ( A[N-1] B[N-1] )
17655 
17656 *************************************************************************/
17657 static void spline1d_solvetridiagonal(/* Real */ ae_vector* a,
17658  /* Real */ ae_vector* b,
17659  /* Real */ ae_vector* c,
17660  /* Real */ ae_vector* d,
17661  ae_int_t n,
17662  /* Real */ ae_vector* x,
17663  ae_state *_state)
17664 {
17665  ae_frame _frame_block;
17666  ae_vector _b;
17667  ae_vector _d;
17668  ae_int_t k;
17669  double t;
17670 
17671  ae_frame_make(_state, &_frame_block);
17672  ae_vector_init_copy(&_b, b, _state, ae_true);
17673  b = &_b;
17674  ae_vector_init_copy(&_d, d, _state, ae_true);
17675  d = &_d;
17676 
17677  if( x->cnt<n )
17678  {
17679  ae_vector_set_length(x, n, _state);
17680  }
17681  for(k=1; k<=n-1; k++)
17682  {
17683  t = a->ptr.p_double[k]/b->ptr.p_double[k-1];
17684  b->ptr.p_double[k] = b->ptr.p_double[k]-t*c->ptr.p_double[k-1];
17685  d->ptr.p_double[k] = d->ptr.p_double[k]-t*d->ptr.p_double[k-1];
17686  }
17687  x->ptr.p_double[n-1] = d->ptr.p_double[n-1]/b->ptr.p_double[n-1];
17688  for(k=n-2; k>=0; k--)
17689  {
17690  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];
17691  }
17692  ae_frame_leave(_state);
17693 }
17694 
17695 
17696 /*************************************************************************
17697 Internal subroutine. Cyclic tridiagonal solver. Solves
17698 
17699 ( B[0] C[0] A[0] )
17700 ( A[1] B[1] C[1] )
17701 ( A[2] B[2] C[2] )
17702 ( .......... ) * X = D
17703 ( .......... )
17704 ( A[N-2] B[N-2] C[N-2] )
17705 ( C[N-1] A[N-1] B[N-1] )
17706 *************************************************************************/
17707 static void spline1d_solvecyclictridiagonal(/* Real */ ae_vector* a,
17708  /* Real */ ae_vector* b,
17709  /* Real */ ae_vector* c,
17710  /* Real */ ae_vector* d,
17711  ae_int_t n,
17712  /* Real */ ae_vector* x,
17713  ae_state *_state)
17714 {
17715  ae_frame _frame_block;
17716  ae_vector _b;
17717  ae_int_t k;
17718  double alpha;
17719  double beta;
17720  double gamma;
17721  ae_vector y;
17722  ae_vector z;
17723  ae_vector u;
17724 
17725  ae_frame_make(_state, &_frame_block);
17726  ae_vector_init_copy(&_b, b, _state, ae_true);
17727  b = &_b;
17728  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
17729  ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
17730  ae_vector_init(&u, 0, DT_REAL, _state, ae_true);
17731 
17732  if( x->cnt<n )
17733  {
17734  ae_vector_set_length(x, n, _state);
17735  }
17736  beta = a->ptr.p_double[0];
17737  alpha = c->ptr.p_double[n-1];
17738  gamma = -b->ptr.p_double[0];
17739  b->ptr.p_double[0] = 2*b->ptr.p_double[0];
17740  b->ptr.p_double[n-1] = b->ptr.p_double[n-1]-alpha*beta/gamma;
17741  ae_vector_set_length(&u, n, _state);
17742  for(k=0; k<=n-1; k++)
17743  {
17744  u.ptr.p_double[k] = 0;
17745  }
17746  u.ptr.p_double[0] = gamma;
17747  u.ptr.p_double[n-1] = alpha;
17748  spline1d_solvetridiagonal(a, b, c, d, n, &y, _state);
17749  spline1d_solvetridiagonal(a, b, c, &u, n, &z, _state);
17750  for(k=0; k<=n-1; k++)
17751  {
17752  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];
17753  }
17754  ae_frame_leave(_state);
17755 }
17756 
17757 
17758 /*************************************************************************
17759 Internal subroutine. Three-point differentiation
17760 *************************************************************************/
17761 static double spline1d_diffthreepoint(double t,
17762  double x0,
17763  double f0,
17764  double x1,
17765  double f1,
17766  double x2,
17767  double f2,
17768  ae_state *_state)
17769 {
17770  double a;
17771  double b;
17772  double result;
17773 
17774 
17775  t = t-x0;
17776  x1 = x1-x0;
17777  x2 = x2-x0;
17778  a = (f2-f0-x2/x1*(f1-f0))/(ae_sqr(x2, _state)-x1*x2);
17779  b = (f1-f0-a*ae_sqr(x1, _state))/x1;
17780  result = 2*a*t+b;
17781  return result;
17782 }
17783 
17784 
17785 /*************************************************************************
17786 Procedure for calculating value of a function is providet in the form of
17787 Hermite polinom
17788 
17789 INPUT PARAMETERS:
17790  P0 - value of a function at 0
17791  M0 - value of a derivative at 0
17792  P1 - value of a function at 1
17793  M1 - value of a derivative at 1
17794  T - point inside [0;1]
17795 
17796 OUTPUT PARAMETERS:
17797  S - value of a function at T
17798  B0 - value of a derivative function at T
17799 
17800  -- ALGLIB PROJECT --
17801  Copyright 26.09.2011 by Bochkanov Sergey
17802 *************************************************************************/
17803 static void spline1d_hermitecalc(double p0,
17804  double m0,
17805  double p1,
17806  double m1,
17807  double t,
17808  double* s,
17809  double* ds,
17810  ae_state *_state)
17811 {
17812 
17813  *s = 0;
17814  *ds = 0;
17815 
17816  *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);
17817  *ds = -p0*6*t*(1-t)+m0*(1-t)*(1-3*t)+p1*6*t*(1-t)+m1*t*(3*t-2);
17818 }
17819 
17820 
17821 /*************************************************************************
17822 Function for mapping from [A0;B0] to [A1;B1]
17823 
17824 INPUT PARAMETERS:
17825  A0 - left border [A0;B0]
17826  B0 - right border [A0;B0]
17827  A1 - left border [A1;B1]
17828  B1 - right border [A1;B1]
17829  T - value inside [A0;B0]
17830 
17831 RESTRICTIONS OF PARAMETERS:
17832 
17833 We assume, that B0>A0 and B1>A1. But we chech, that T is inside [A0;B0],
17834 and if T<A0 then T become A1, if T>B0 then T - B1.
17835 
17836 INPUT PARAMETERS:
17837  A0 - left border for segment [A0;B0] from 'T' is converted to [A1;B1]
17838  B0 - right border for segment [A0;B0] from 'T' is converted to [A1;B1]
17839  A1 - left border for segment [A1;B1] to 'T' is converted from [A0;B0]
17840  B1 - right border for segment [A1;B1] to 'T' is converted from [A0;B0]
17841  T - the parameter is mapped from [A0;B0] to [A1;B1]
17842 
17843 Result:
17844  is converted value for 'T' from [A0;B0] to [A1;B1]
17845 
17846 REMARK:
17847 
17848 The function don't check value A0,B0 and A1,B1!
17849 
17850  -- ALGLIB PROJECT --
17851  Copyright 26.09.2011 by Bochkanov Sergey
17852 *************************************************************************/
17853 static double spline1d_rescaleval(double a0,
17854  double b0,
17855  double a1,
17856  double b1,
17857  double t,
17858  ae_state *_state)
17859 {
17860  double result;
17861 
17862 
17863 
17864  /*
17865  *return left border
17866  */
17867  if( ae_fp_less_eq(t,a0) )
17868  {
17869  result = a1;
17870  return result;
17871  }
17872 
17873  /*
17874  *return right border
17875  */
17876  if( ae_fp_greater_eq(t,b0) )
17877  {
17878  result = b1;
17879  return result;
17880  }
17881 
17882  /*
17883  *return value between left and right borders
17884  */
17885  result = (b1-a1)*(t-a0)/(b0-a0)+a1;
17886  return result;
17887 }
17888 
17889 
17890 ae_bool _spline1dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
17891 {
17893  ae_touch_ptr((void*)p);
17894  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
17895  return ae_false;
17896  if( !ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic) )
17897  return ae_false;
17898  return ae_true;
17899 }
17900 
17901 
17902 ae_bool _spline1dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
17903 {
17906  dst->periodic = src->periodic;
17907  dst->n = src->n;
17908  dst->k = src->k;
17909  dst->continuity = src->continuity;
17910  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
17911  return ae_false;
17912  if( !ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic) )
17913  return ae_false;
17914  return ae_true;
17915 }
17916 
17917 
17919 {
17921  ae_touch_ptr((void*)p);
17922  ae_vector_clear(&p->x);
17923  ae_vector_clear(&p->c);
17924 }
17925 
17926 
17928 {
17930  ae_touch_ptr((void*)p);
17931  ae_vector_destroy(&p->x);
17932  ae_vector_destroy(&p->c);
17933 }
17934 
17935 
17936 
17937 
17938 /*************************************************************************
17939 Fitting by polynomials in barycentric form. This function provides simple
17940 unterface for unconstrained unweighted fitting. See PolynomialFitWC() if
17941 you need constrained fitting.
17942 
17943 Task is linear, so linear least squares solver is used. Complexity of this
17944 computational scheme is O(N*M^2), mostly dominated by least squares solver
17945 
17946 SEE ALSO:
17947  PolynomialFitWC()
17948 
17949 INPUT PARAMETERS:
17950  X - points, array[0..N-1].
17951  Y - function values, array[0..N-1].
17952  N - number of points, N>0
17953  * if given, only leading N elements of X/Y are used
17954  * if not given, automatically determined from sizes of X/Y
17955  M - number of basis functions (= polynomial_degree + 1), M>=1
17956 
17957 OUTPUT PARAMETERS:
17958  Info- same format as in LSFitLinearW() subroutine:
17959  * Info>0 task is solved
17960  * Info<=0 an error occurred:
17961  -4 means inconvergence of internal SVD
17962  P - interpolant in barycentric form.
17963  Rep - report, same format as in LSFitLinearW() subroutine.
17964  Following fields are set:
17965  * RMSError rms error on the (X,Y).
17966  * AvgError average error on the (X,Y).
17967  * AvgRelError average relative error on the non-zero Y
17968  * MaxError maximum error
17969  NON-WEIGHTED ERRORS ARE CALCULATED
17970 
17971 NOTES:
17972  you can convert P from barycentric form to the power or Chebyshev
17973  basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
17974  POLINT subpackage.
17975 
17976  -- ALGLIB PROJECT --
17977  Copyright 10.12.2009 by Bochkanov Sergey
17978 *************************************************************************/
17979 void polynomialfit(/* Real */ ae_vector* x,
17980  /* Real */ ae_vector* y,
17981  ae_int_t n,
17982  ae_int_t m,
17983  ae_int_t* info,
17985  polynomialfitreport* rep,
17986  ae_state *_state)
17987 {
17988  ae_frame _frame_block;
17989  ae_int_t i;
17990  ae_vector w;
17991  ae_vector xc;
17992  ae_vector yc;
17993  ae_vector dc;
17994 
17995  ae_frame_make(_state, &_frame_block);
17996  *info = 0;
17999  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
18000  ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
18001  ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
18002  ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
18003 
18004  ae_assert(n>0, "PolynomialFit: N<=0!", _state);
18005  ae_assert(m>0, "PolynomialFit: M<=0!", _state);
18006  ae_assert(x->cnt>=n, "PolynomialFit: Length(X)<N!", _state);
18007  ae_assert(y->cnt>=n, "PolynomialFit: Length(Y)<N!", _state);
18008  ae_assert(isfinitevector(x, n, _state), "PolynomialFit: X contains infinite or NaN values!", _state);
18009  ae_assert(isfinitevector(y, n, _state), "PolynomialFit: Y contains infinite or NaN values!", _state);
18010  ae_vector_set_length(&w, n, _state);
18011  for(i=0; i<=n-1; i++)
18012  {
18013  w.ptr.p_double[i] = 1;
18014  }
18015  polynomialfitwc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, p, rep, _state);
18016  ae_frame_leave(_state);
18017 }
18018 
18019 
18020 /*************************************************************************
18021 Weighted fitting by polynomials in barycentric form, with constraints on
18022 function values or first derivatives.
18023 
18024 Small regularizing term is used when solving constrained tasks (to improve
18025 stability).
18026 
18027 Task is linear, so linear least squares solver is used. Complexity of this
18028 computational scheme is O(N*M^2), mostly dominated by least squares solver
18029 
18030 SEE ALSO:
18031  PolynomialFit()
18032 
18033 INPUT PARAMETERS:
18034  X - points, array[0..N-1].
18035  Y - function values, array[0..N-1].
18036  W - weights, array[0..N-1]
18037  Each summand in square sum of approximation deviations from
18038  given values is multiplied by the square of corresponding
18039  weight. Fill it by 1's if you don't want to solve weighted
18040  task.
18041  N - number of points, N>0.
18042  * if given, only leading N elements of X/Y/W are used
18043  * if not given, automatically determined from sizes of X/Y/W
18044  XC - points where polynomial values/derivatives are constrained,
18045  array[0..K-1].
18046  YC - values of constraints, array[0..K-1]
18047  DC - array[0..K-1], types of constraints:
18048  * DC[i]=0 means that P(XC[i])=YC[i]
18049  * DC[i]=1 means that P'(XC[i])=YC[i]
18050  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
18051  K - number of constraints, 0<=K<M.
18052  K=0 means no constraints (XC/YC/DC are not used in such cases)
18053  M - number of basis functions (= polynomial_degree + 1), M>=1
18054 
18055 OUTPUT PARAMETERS:
18056  Info- same format as in LSFitLinearW() subroutine:
18057  * Info>0 task is solved
18058  * Info<=0 an error occurred:
18059  -4 means inconvergence of internal SVD
18060  -3 means inconsistent constraints
18061  P - interpolant in barycentric form.
18062  Rep - report, same format as in LSFitLinearW() subroutine.
18063  Following fields are set:
18064  * RMSError rms error on the (X,Y).
18065  * AvgError average error on the (X,Y).
18066  * AvgRelError average relative error on the non-zero Y
18067  * MaxError maximum error
18068  NON-WEIGHTED ERRORS ARE CALCULATED
18069 
18070 IMPORTANT:
18071  this subroitine doesn't calculate task's condition number for K<>0.
18072 
18073 NOTES:
18074  you can convert P from barycentric form to the power or Chebyshev
18075  basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions from
18076  POLINT subpackage.
18077 
18078 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
18079 
18080 Setting constraints can lead to undesired results, like ill-conditioned
18081 behavior, or inconsistency being detected. From the other side, it allows
18082 us to improve quality of the fit. Here we summarize our experience with
18083 constrained regression splines:
18084 * even simple constraints can be inconsistent, see Wikipedia article on
18085  this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
18086 * the greater is M (given fixed constraints), the more chances that
18087  constraints will be consistent
18088 * in the general case, consistency of constraints is NOT GUARANTEED.
18089 * in the one special cases, however, we can guarantee consistency. This
18090  case is: M>1 and constraints on the function values (NOT DERIVATIVES)
18091 
18092 Our final recommendation is to use constraints WHEN AND ONLY when you
18093 can't solve your task without them. Anything beyond special cases given
18094 above is not guaranteed and may result in inconsistency.
18095 
18096  -- ALGLIB PROJECT --
18097  Copyright 10.12.2009 by Bochkanov Sergey
18098 *************************************************************************/
18099 void polynomialfitwc(/* Real */ ae_vector* x,
18100  /* Real */ ae_vector* y,
18101  /* Real */ ae_vector* w,
18102  ae_int_t n,
18103  /* Real */ ae_vector* xc,
18104  /* Real */ ae_vector* yc,
18105  /* Integer */ ae_vector* dc,
18106  ae_int_t k,
18107  ae_int_t m,
18108  ae_int_t* info,
18110  polynomialfitreport* rep,
18111  ae_state *_state)
18112 {
18113  ae_frame _frame_block;
18114  ae_vector _x;
18115  ae_vector _y;
18116  ae_vector _w;
18117  ae_vector _xc;
18118  ae_vector _yc;
18119  double xa;
18120  double xb;
18121  double sa;
18122  double sb;
18123  ae_vector xoriginal;
18124  ae_vector yoriginal;
18125  ae_vector y2;
18126  ae_vector w2;
18127  ae_vector tmp;
18128  ae_vector tmp2;
18129  ae_vector bx;
18130  ae_vector by;
18131  ae_vector bw;
18132  ae_int_t i;
18133  ae_int_t j;
18134  double u;
18135  double v;
18136  double s;
18137  ae_int_t relcnt;
18138  lsfitreport lrep;
18139 
18140  ae_frame_make(_state, &_frame_block);
18141  ae_vector_init_copy(&_x, x, _state, ae_true);
18142  x = &_x;
18143  ae_vector_init_copy(&_y, y, _state, ae_true);
18144  y = &_y;
18145  ae_vector_init_copy(&_w, w, _state, ae_true);
18146  w = &_w;
18147  ae_vector_init_copy(&_xc, xc, _state, ae_true);
18148  xc = &_xc;
18149  ae_vector_init_copy(&_yc, yc, _state, ae_true);
18150  yc = &_yc;
18151  *info = 0;
18154  ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
18155  ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
18156  ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
18157  ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
18158  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
18159  ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
18160  ae_vector_init(&bx, 0, DT_REAL, _state, ae_true);
18161  ae_vector_init(&by, 0, DT_REAL, _state, ae_true);
18162  ae_vector_init(&bw, 0, DT_REAL, _state, ae_true);
18163  _lsfitreport_init(&lrep, _state, ae_true);
18164 
18165  ae_assert(n>0, "PolynomialFitWC: N<=0!", _state);
18166  ae_assert(m>0, "PolynomialFitWC: M<=0!", _state);
18167  ae_assert(k>=0, "PolynomialFitWC: K<0!", _state);
18168  ae_assert(k<m, "PolynomialFitWC: K>=M!", _state);
18169  ae_assert(x->cnt>=n, "PolynomialFitWC: Length(X)<N!", _state);
18170  ae_assert(y->cnt>=n, "PolynomialFitWC: Length(Y)<N!", _state);
18171  ae_assert(w->cnt>=n, "PolynomialFitWC: Length(W)<N!", _state);
18172  ae_assert(xc->cnt>=k, "PolynomialFitWC: Length(XC)<K!", _state);
18173  ae_assert(yc->cnt>=k, "PolynomialFitWC: Length(YC)<K!", _state);
18174  ae_assert(dc->cnt>=k, "PolynomialFitWC: Length(DC)<K!", _state);
18175  ae_assert(isfinitevector(x, n, _state), "PolynomialFitWC: X contains infinite or NaN values!", _state);
18176  ae_assert(isfinitevector(y, n, _state), "PolynomialFitWC: Y contains infinite or NaN values!", _state);
18177  ae_assert(isfinitevector(w, n, _state), "PolynomialFitWC: X contains infinite or NaN values!", _state);
18178  ae_assert(isfinitevector(xc, k, _state), "PolynomialFitWC: XC contains infinite or NaN values!", _state);
18179  ae_assert(isfinitevector(yc, k, _state), "PolynomialFitWC: YC contains infinite or NaN values!", _state);
18180  for(i=0; i<=k-1; i++)
18181  {
18182  ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "PolynomialFitWC: one of DC[] is not 0 or 1!", _state);
18183  }
18184 
18185  /*
18186  * Scale X, Y, XC, YC.
18187  * Solve scaled problem using internal Chebyshev fitting function.
18188  */
18189  lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
18190  lsfit_internalchebyshevfit(x, y, w, n, xc, yc, dc, k, m, info, &tmp, &lrep, _state);
18191  if( *info<0 )
18192  {
18193  ae_frame_leave(_state);
18194  return;
18195  }
18196 
18197  /*
18198  * Generate barycentric model and scale it
18199  * * BX, BY store barycentric model nodes
18200  * * FMatrix is reused (remember - it is at least MxM, what we need)
18201  *
18202  * Model initialization is done in O(M^2). In principle, it can be
18203  * done in O(M*log(M)), but before it we solved task with O(N*M^2)
18204  * complexity, so it is only a small amount of total time spent.
18205  */
18206  ae_vector_set_length(&bx, m, _state);
18207  ae_vector_set_length(&by, m, _state);
18208  ae_vector_set_length(&bw, m, _state);
18209  ae_vector_set_length(&tmp2, m, _state);
18210  s = 1;
18211  for(i=0; i<=m-1; i++)
18212  {
18213  if( m!=1 )
18214  {
18215  u = ae_cos(ae_pi*i/(m-1), _state);
18216  }
18217  else
18218  {
18219  u = 0;
18220  }
18221  v = 0;
18222  for(j=0; j<=m-1; j++)
18223  {
18224  if( j==0 )
18225  {
18226  tmp2.ptr.p_double[j] = 1;
18227  }
18228  else
18229  {
18230  if( j==1 )
18231  {
18232  tmp2.ptr.p_double[j] = u;
18233  }
18234  else
18235  {
18236  tmp2.ptr.p_double[j] = 2*u*tmp2.ptr.p_double[j-1]-tmp2.ptr.p_double[j-2];
18237  }
18238  }
18239  v = v+tmp.ptr.p_double[j]*tmp2.ptr.p_double[j];
18240  }
18241  bx.ptr.p_double[i] = u;
18242  by.ptr.p_double[i] = v;
18243  bw.ptr.p_double[i] = s;
18244  if( i==0||i==m-1 )
18245  {
18246  bw.ptr.p_double[i] = 0.5*bw.ptr.p_double[i];
18247  }
18248  s = -s;
18249  }
18250  barycentricbuildxyw(&bx, &by, &bw, m, p, _state);
18251  barycentriclintransx(p, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
18252  barycentriclintransy(p, sb-sa, sa, _state);
18253 
18254  /*
18255  * Scale absolute errors obtained from LSFitLinearW.
18256  * Relative error should be calculated separately
18257  * (because of shifting/scaling of the task)
18258  */
18259  rep->taskrcond = lrep.taskrcond;
18260  rep->rmserror = lrep.rmserror*(sb-sa);
18261  rep->avgerror = lrep.avgerror*(sb-sa);
18262  rep->maxerror = lrep.maxerror*(sb-sa);
18263  rep->avgrelerror = 0;
18264  relcnt = 0;
18265  for(i=0; i<=n-1; i++)
18266  {
18267  if( ae_fp_neq(yoriginal.ptr.p_double[i],0) )
18268  {
18269  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);
18270  relcnt = relcnt+1;
18271  }
18272  }
18273  if( relcnt!=0 )
18274  {
18275  rep->avgrelerror = rep->avgrelerror/relcnt;
18276  }
18277  ae_frame_leave(_state);
18278 }
18279 
18280 
18281 /*************************************************************************
18282 Weghted rational least squares fitting using Floater-Hormann rational
18283 functions with optimal D chosen from [0,9], with constraints and
18284 individual weights.
18285 
18286 Equidistant grid with M node on [min(x),max(x)] is used to build basis
18287 functions. Different values of D are tried, optimal D (least WEIGHTED root
18288 mean square error) is chosen. Task is linear, so linear least squares
18289 solver is used. Complexity of this computational scheme is O(N*M^2)
18290 (mostly dominated by the least squares solver).
18291 
18292 SEE ALSO
18293 * BarycentricFitFloaterHormann(), "lightweight" fitting without invididual
18294  weights and constraints.
18295 
18296 INPUT PARAMETERS:
18297  X - points, array[0..N-1].
18298  Y - function values, array[0..N-1].
18299  W - weights, array[0..N-1]
18300  Each summand in square sum of approximation deviations from
18301  given values is multiplied by the square of corresponding
18302  weight. Fill it by 1's if you don't want to solve weighted
18303  task.
18304  N - number of points, N>0.
18305  XC - points where function values/derivatives are constrained,
18306  array[0..K-1].
18307  YC - values of constraints, array[0..K-1]
18308  DC - array[0..K-1], types of constraints:
18309  * DC[i]=0 means that S(XC[i])=YC[i]
18310  * DC[i]=1 means that S'(XC[i])=YC[i]
18311  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
18312  K - number of constraints, 0<=K<M.
18313  K=0 means no constraints (XC/YC/DC are not used in such cases)
18314  M - number of basis functions ( = number_of_nodes), M>=2.
18315 
18316 OUTPUT PARAMETERS:
18317  Info- same format as in LSFitLinearWC() subroutine.
18318  * Info>0 task is solved
18319  * Info<=0 an error occurred:
18320  -4 means inconvergence of internal SVD
18321  -3 means inconsistent constraints
18322  -1 means another errors in parameters passed
18323  (N<=0, for example)
18324  B - barycentric interpolant.
18325  Rep - report, same format as in LSFitLinearWC() subroutine.
18326  Following fields are set:
18327  * DBest best value of the D parameter
18328  * RMSError rms error on the (X,Y).
18329  * AvgError average error on the (X,Y).
18330  * AvgRelError average relative error on the non-zero Y
18331  * MaxError maximum error
18332  NON-WEIGHTED ERRORS ARE CALCULATED
18333 
18334 IMPORTANT:
18335  this subroutine doesn't calculate task's condition number for K<>0.
18336 
18337 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
18338 
18339 Setting constraints can lead to undesired results, like ill-conditioned
18340 behavior, or inconsistency being detected. From the other side, it allows
18341 us to improve quality of the fit. Here we summarize our experience with
18342 constrained barycentric interpolants:
18343 * excessive constraints can be inconsistent. Floater-Hormann basis
18344  functions aren't as flexible as splines (although they are very smooth).
18345 * the more evenly constraints are spread across [min(x),max(x)], the more
18346  chances that they will be consistent
18347 * the greater is M (given fixed constraints), the more chances that
18348  constraints will be consistent
18349 * in the general case, consistency of constraints IS NOT GUARANTEED.
18350 * in the several special cases, however, we CAN guarantee consistency.
18351 * one of this cases is constraints on the function VALUES at the interval
18352  boundaries. Note that consustency of the constraints on the function
18353  DERIVATIVES is NOT guaranteed (you can use in such cases cubic splines
18354  which are more flexible).
18355 * another special case is ONE constraint on the function value (OR, but
18356  not AND, derivative) anywhere in the interval
18357 
18358 Our final recommendation is to use constraints WHEN AND ONLY WHEN you
18359 can't solve your task without them. Anything beyond special cases given
18360 above is not guaranteed and may result in inconsistency.
18361 
18362  -- ALGLIB PROJECT --
18363  Copyright 18.08.2009 by Bochkanov Sergey
18364 *************************************************************************/
18365 void barycentricfitfloaterhormannwc(/* Real */ ae_vector* x,
18366  /* Real */ ae_vector* y,
18367  /* Real */ ae_vector* w,
18368  ae_int_t n,
18369  /* Real */ ae_vector* xc,
18370  /* Real */ ae_vector* yc,
18371  /* Integer */ ae_vector* dc,
18372  ae_int_t k,
18373  ae_int_t m,
18374  ae_int_t* info,
18375  barycentricinterpolant* b,
18376  barycentricfitreport* rep,
18377  ae_state *_state)
18378 {
18379  ae_frame _frame_block;
18380  ae_int_t d;
18381  ae_int_t i;
18382  double wrmscur;
18383  double wrmsbest;
18384  barycentricinterpolant locb;
18385  barycentricfitreport locrep;
18386  ae_int_t locinfo;
18387 
18388  ae_frame_make(_state, &_frame_block);
18389  *info = 0;
18390  _barycentricinterpolant_clear(b);
18391  _barycentricfitreport_clear(rep);
18392  _barycentricinterpolant_init(&locb, _state, ae_true);
18393  _barycentricfitreport_init(&locrep, _state, ae_true);
18394 
18395  ae_assert(n>0, "BarycentricFitFloaterHormannWC: N<=0!", _state);
18396  ae_assert(m>0, "BarycentricFitFloaterHormannWC: M<=0!", _state);
18397  ae_assert(k>=0, "BarycentricFitFloaterHormannWC: K<0!", _state);
18398  ae_assert(k<m, "BarycentricFitFloaterHormannWC: K>=M!", _state);
18399  ae_assert(x->cnt>=n, "BarycentricFitFloaterHormannWC: Length(X)<N!", _state);
18400  ae_assert(y->cnt>=n, "BarycentricFitFloaterHormannWC: Length(Y)<N!", _state);
18401  ae_assert(w->cnt>=n, "BarycentricFitFloaterHormannWC: Length(W)<N!", _state);
18402  ae_assert(xc->cnt>=k, "BarycentricFitFloaterHormannWC: Length(XC)<K!", _state);
18403  ae_assert(yc->cnt>=k, "BarycentricFitFloaterHormannWC: Length(YC)<K!", _state);
18404  ae_assert(dc->cnt>=k, "BarycentricFitFloaterHormannWC: Length(DC)<K!", _state);
18405  ae_assert(isfinitevector(x, n, _state), "BarycentricFitFloaterHormannWC: X contains infinite or NaN values!", _state);
18406  ae_assert(isfinitevector(y, n, _state), "BarycentricFitFloaterHormannWC: Y contains infinite or NaN values!", _state);
18407  ae_assert(isfinitevector(w, n, _state), "BarycentricFitFloaterHormannWC: X contains infinite or NaN values!", _state);
18408  ae_assert(isfinitevector(xc, k, _state), "BarycentricFitFloaterHormannWC: XC contains infinite or NaN values!", _state);
18409  ae_assert(isfinitevector(yc, k, _state), "BarycentricFitFloaterHormannWC: YC contains infinite or NaN values!", _state);
18410  for(i=0; i<=k-1; i++)
18411  {
18412  ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "BarycentricFitFloaterHormannWC: one of DC[] is not 0 or 1!", _state);
18413  }
18414 
18415  /*
18416  * Find optimal D
18417  *
18418  * Info is -3 by default (degenerate constraints).
18419  * If LocInfo will always be equal to -3, Info will remain equal to -3.
18420  * If at least once LocInfo will be -4, Info will be -4.
18421  */
18422  wrmsbest = ae_maxrealnumber;
18423  rep->dbest = -1;
18424  *info = -3;
18425  for(d=0; d<=ae_minint(9, n-1, _state); d++)
18426  {
18427  lsfit_barycentricfitwcfixedd(x, y, w, n, xc, yc, dc, k, m, d, &locinfo, &locb, &locrep, _state);
18428  ae_assert((locinfo==-4||locinfo==-3)||locinfo>0, "BarycentricFitFloaterHormannWC: unexpected result from BarycentricFitWCFixedD!", _state);
18429  if( locinfo>0 )
18430  {
18431 
18432  /*
18433  * Calculate weghted RMS
18434  */
18435  wrmscur = 0;
18436  for(i=0; i<=n-1; i++)
18437  {
18438  wrmscur = wrmscur+ae_sqr(w->ptr.p_double[i]*(y->ptr.p_double[i]-barycentriccalc(&locb, x->ptr.p_double[i], _state)), _state);
18439  }
18440  wrmscur = ae_sqrt(wrmscur/n, _state);
18441  if( ae_fp_less(wrmscur,wrmsbest)||rep->dbest<0 )
18442  {
18443  barycentriccopy(&locb, b, _state);
18444  rep->dbest = d;
18445  *info = 1;
18446  rep->rmserror = locrep.rmserror;
18447  rep->avgerror = locrep.avgerror;
18448  rep->avgrelerror = locrep.avgrelerror;
18449  rep->maxerror = locrep.maxerror;
18450  rep->taskrcond = locrep.taskrcond;
18451  wrmsbest = wrmscur;
18452  }
18453  }
18454  else
18455  {
18456  if( locinfo!=-3&&*info<0 )
18457  {
18458  *info = locinfo;
18459  }
18460  }
18461  }
18462  ae_frame_leave(_state);
18463 }
18464 
18465 
18466 /*************************************************************************
18467 Rational least squares fitting using Floater-Hormann rational functions
18468 with optimal D chosen from [0,9].
18469 
18470 Equidistant grid with M node on [min(x),max(x)] is used to build basis
18471 functions. Different values of D are tried, optimal D (least root mean
18472 square error) is chosen. Task is linear, so linear least squares solver
18473 is used. Complexity of this computational scheme is O(N*M^2) (mostly
18474 dominated by the least squares solver).
18475 
18476 INPUT PARAMETERS:
18477  X - points, array[0..N-1].
18478  Y - function values, array[0..N-1].
18479  N - number of points, N>0.
18480  M - number of basis functions ( = number_of_nodes), M>=2.
18481 
18482 OUTPUT PARAMETERS:
18483  Info- same format as in LSFitLinearWC() subroutine.
18484  * Info>0 task is solved
18485  * Info<=0 an error occurred:
18486  -4 means inconvergence of internal SVD
18487  -3 means inconsistent constraints
18488  B - barycentric interpolant.
18489  Rep - report, same format as in LSFitLinearWC() subroutine.
18490  Following fields are set:
18491  * DBest best value of the D parameter
18492  * RMSError rms error on the (X,Y).
18493  * AvgError average error on the (X,Y).
18494  * AvgRelError average relative error on the non-zero Y
18495  * MaxError maximum error
18496  NON-WEIGHTED ERRORS ARE CALCULATED
18497 
18498  -- ALGLIB PROJECT --
18499  Copyright 18.08.2009 by Bochkanov Sergey
18500 *************************************************************************/
18501 void barycentricfitfloaterhormann(/* Real */ ae_vector* x,
18502  /* Real */ ae_vector* y,
18503  ae_int_t n,
18504  ae_int_t m,
18505  ae_int_t* info,
18506  barycentricinterpolant* b,
18507  barycentricfitreport* rep,
18508  ae_state *_state)
18509 {
18510  ae_frame _frame_block;
18511  ae_vector w;
18512  ae_vector xc;
18513  ae_vector yc;
18514  ae_vector dc;
18515  ae_int_t i;
18516 
18517  ae_frame_make(_state, &_frame_block);
18518  *info = 0;
18519  _barycentricinterpolant_clear(b);
18520  _barycentricfitreport_clear(rep);
18521  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
18522  ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
18523  ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
18524  ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
18525 
18526  ae_assert(n>0, "BarycentricFitFloaterHormann: N<=0!", _state);
18527  ae_assert(m>0, "BarycentricFitFloaterHormann: M<=0!", _state);
18528  ae_assert(x->cnt>=n, "BarycentricFitFloaterHormann: Length(X)<N!", _state);
18529  ae_assert(y->cnt>=n, "BarycentricFitFloaterHormann: Length(Y)<N!", _state);
18530  ae_assert(isfinitevector(x, n, _state), "BarycentricFitFloaterHormann: X contains infinite or NaN values!", _state);
18531  ae_assert(isfinitevector(y, n, _state), "BarycentricFitFloaterHormann: Y contains infinite or NaN values!", _state);
18532  ae_vector_set_length(&w, n, _state);
18533  for(i=0; i<=n-1; i++)
18534  {
18535  w.ptr.p_double[i] = 1;
18536  }
18537  barycentricfitfloaterhormannwc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, b, rep, _state);
18538  ae_frame_leave(_state);
18539 }
18540 
18541 
18542 /*************************************************************************
18543 Rational least squares fitting using Floater-Hormann rational functions
18544 with optimal D chosen from [0,9].
18545 
18546 Equidistant grid with M node on [min(x),max(x)] is used to build basis
18547 functions. Different values of D are tried, optimal D (least root mean
18548 square error) is chosen. Task is linear, so linear least squares solver
18549 is used. Complexity of this computational scheme is O(N*M^2) (mostly
18550 dominated by the least squares solver).
18551 
18552 INPUT PARAMETERS:
18553  X - points, array[0..N-1].
18554  Y - function values, array[0..N-1].
18555  N - number of points, N>0.
18556  M - number of basis functions ( = number_of_nodes), M>=2.
18557 
18558 OUTPUT PARAMETERS:
18559  Info- same format as in LSFitLinearWC() subroutine.
18560  * Info>0 task is solved
18561  * Info<=0 an error occurred:
18562  -4 means inconvergence of internal SVD
18563  -3 means inconsistent constraints
18564  B - barycentric interpolant.
18565  Rep - report, same format as in LSFitLinearWC() subroutine.
18566  Following fields are set:
18567  * DBest best value of the D parameter
18568  * RMSError rms error on the (X,Y).
18569  * AvgError average error on the (X,Y).
18570  * AvgRelError average relative error on the non-zero Y
18571  * MaxError maximum error
18572  NON-WEIGHTED ERRORS ARE CALCULATED
18573 
18574  -- ALGLIB PROJECT --
18575  Copyright 18.08.2009 by Bochkanov Sergey
18576 *************************************************************************/
18577 void spline1dfitpenalized(/* Real */ ae_vector* x,
18578  /* Real */ ae_vector* y,
18579  ae_int_t n,
18580  ae_int_t m,
18581  double rho,
18582  ae_int_t* info,
18583  spline1dinterpolant* s,
18584  spline1dfitreport* rep,
18585  ae_state *_state)
18586 {
18587  ae_frame _frame_block;
18588  ae_vector _x;
18589  ae_vector _y;
18590  ae_vector w;
18591  ae_int_t i;
18592 
18593  ae_frame_make(_state, &_frame_block);
18594  ae_vector_init_copy(&_x, x, _state, ae_true);
18595  x = &_x;
18596  ae_vector_init_copy(&_y, y, _state, ae_true);
18597  y = &_y;
18598  *info = 0;
18599  _spline1dinterpolant_clear(s);
18600  _spline1dfitreport_clear(rep);
18601  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
18602 
18603  ae_assert(n>=1, "Spline1DFitPenalized: N<1!", _state);
18604  ae_assert(m>=4, "Spline1DFitPenalized: M<4!", _state);
18605  ae_assert(x->cnt>=n, "Spline1DFitPenalized: Length(X)<N!", _state);
18606  ae_assert(y->cnt>=n, "Spline1DFitPenalized: Length(Y)<N!", _state);
18607  ae_assert(isfinitevector(x, n, _state), "Spline1DFitPenalized: X contains infinite or NAN values!", _state);
18608  ae_assert(isfinitevector(y, n, _state), "Spline1DFitPenalized: Y contains infinite or NAN values!", _state);
18609  ae_assert(ae_isfinite(rho, _state), "Spline1DFitPenalized: Rho is infinite!", _state);
18610  ae_vector_set_length(&w, n, _state);
18611  for(i=0; i<=n-1; i++)
18612  {
18613  w.ptr.p_double[i] = 1;
18614  }
18615  spline1dfitpenalizedw(x, y, &w, n, m, rho, info, s, rep, _state);
18616  ae_frame_leave(_state);
18617 }
18618 
18619 
18620 /*************************************************************************
18621 Weighted fitting by penalized cubic spline.
18622 
18623 Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
18624 basis functions. Basis functions are cubic splines with natural boundary
18625 conditions. Problem is regularized by adding non-linearity penalty to the
18626 usual least squares penalty function:
18627 
18628  S(x) = arg min { LS + P }, where
18629  LS = SUM { w[i]^2*(y[i] - S(x[i]))^2 } - least squares penalty
18630  P = C*10^rho*integral{ S''(x)^2*dx } - non-linearity penalty
18631  rho - tunable constant given by user
18632  C - automatically determined scale parameter,
18633  makes penalty invariant with respect to scaling of X, Y, W.
18634 
18635 INPUT PARAMETERS:
18636  X - points, array[0..N-1].
18637  Y - function values, array[0..N-1].
18638  W - weights, array[0..N-1]
18639  Each summand in square sum of approximation deviations from
18640  given values is multiplied by the square of corresponding
18641  weight. Fill it by 1's if you don't want to solve weighted
18642  problem.
18643  N - number of points (optional):
18644  * N>0
18645  * if given, only first N elements of X/Y/W are processed
18646  * if not given, automatically determined from X/Y/W sizes
18647  M - number of basis functions ( = number_of_nodes), M>=4.
18648  Rho - regularization constant passed by user. It penalizes
18649  nonlinearity in the regression spline. It is logarithmically
18650  scaled, i.e. actual value of regularization constant is
18651  calculated as 10^Rho. It is automatically scaled so that:
18652  * Rho=2.0 corresponds to moderate amount of nonlinearity
18653  * generally, it should be somewhere in the [-8.0,+8.0]
18654  If you do not want to penalize nonlineary,
18655  pass small Rho. Values as low as -15 should work.
18656 
18657 OUTPUT PARAMETERS:
18658  Info- same format as in LSFitLinearWC() subroutine.
18659  * Info>0 task is solved
18660  * Info<=0 an error occurred:
18661  -4 means inconvergence of internal SVD or
18662  Cholesky decomposition; problem may be
18663  too ill-conditioned (very rare)
18664  S - spline interpolant.
18665  Rep - Following fields are set:
18666  * RMSError rms error on the (X,Y).
18667  * AvgError average error on the (X,Y).
18668  * AvgRelError average relative error on the non-zero Y
18669  * MaxError maximum error
18670  NON-WEIGHTED ERRORS ARE CALCULATED
18671 
18672 IMPORTANT:
18673  this subroitine doesn't calculate task's condition number for K<>0.
18674 
18675 NOTE 1: additional nodes are added to the spline outside of the fitting
18676 interval to force linearity when x<min(x,xc) or x>max(x,xc). It is done
18677 for consistency - we penalize non-linearity at [min(x,xc),max(x,xc)], so
18678 it is natural to force linearity outside of this interval.
18679 
18680 NOTE 2: function automatically sorts points, so caller may pass unsorted
18681 array.
18682 
18683  -- ALGLIB PROJECT --
18684  Copyright 19.10.2010 by Bochkanov Sergey
18685 *************************************************************************/
18686 void spline1dfitpenalizedw(/* Real */ ae_vector* x,
18687  /* Real */ ae_vector* y,
18688  /* Real */ ae_vector* w,
18689  ae_int_t n,
18690  ae_int_t m,
18691  double rho,
18692  ae_int_t* info,
18693  spline1dinterpolant* s,
18694  spline1dfitreport* rep,
18695  ae_state *_state)
18696 {
18697  ae_frame _frame_block;
18698  ae_vector _x;
18699  ae_vector _y;
18700  ae_vector _w;
18701  ae_int_t i;
18702  ae_int_t j;
18703  ae_int_t b;
18704  double v;
18705  double relcnt;
18706  double xa;
18707  double xb;
18708  double sa;
18709  double sb;
18710  ae_vector xoriginal;
18711  ae_vector yoriginal;
18712  double pdecay;
18713  double tdecay;
18714  ae_matrix fmatrix;
18715  ae_vector fcolumn;
18716  ae_vector y2;
18717  ae_vector w2;
18718  ae_vector xc;
18719  ae_vector yc;
18720  ae_vector dc;
18721  double fdmax;
18722  double admax;
18723  ae_matrix amatrix;
18724  ae_matrix d2matrix;
18725  double fa;
18726  double ga;
18727  double fb;
18728  double gb;
18729  double lambdav;
18730  ae_vector bx;
18731  ae_vector by;
18732  ae_vector bd1;
18733  ae_vector bd2;
18734  ae_vector tx;
18735  ae_vector ty;
18736  ae_vector td;
18737  spline1dinterpolant bs;
18738  ae_matrix nmatrix;
18739  ae_vector rightpart;
18740  fblslincgstate cgstate;
18741  ae_vector c;
18742  ae_vector tmp0;
18743 
18744  ae_frame_make(_state, &_frame_block);
18745  ae_vector_init_copy(&_x, x, _state, ae_true);
18746  x = &_x;
18747  ae_vector_init_copy(&_y, y, _state, ae_true);
18748  y = &_y;
18749  ae_vector_init_copy(&_w, w, _state, ae_true);
18750  w = &_w;
18751  *info = 0;
18752  _spline1dinterpolant_clear(s);
18753  _spline1dfitreport_clear(rep);
18754  ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
18755  ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
18756  ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
18757  ae_vector_init(&fcolumn, 0, DT_REAL, _state, ae_true);
18758  ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
18759  ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
18760  ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
18761  ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
18762  ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
18763  ae_matrix_init(&amatrix, 0, 0, DT_REAL, _state, ae_true);
18764  ae_matrix_init(&d2matrix, 0, 0, DT_REAL, _state, ae_true);
18765  ae_vector_init(&bx, 0, DT_REAL, _state, ae_true);
18766  ae_vector_init(&by, 0, DT_REAL, _state, ae_true);
18767  ae_vector_init(&bd1, 0, DT_REAL, _state, ae_true);
18768  ae_vector_init(&bd2, 0, DT_REAL, _state, ae_true);
18769  ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
18770  ae_vector_init(&ty, 0, DT_REAL, _state, ae_true);
18771  ae_vector_init(&td, 0, DT_REAL, _state, ae_true);
18772  _spline1dinterpolant_init(&bs, _state, ae_true);
18773  ae_matrix_init(&nmatrix, 0, 0, DT_REAL, _state, ae_true);
18774  ae_vector_init(&rightpart, 0, DT_REAL, _state, ae_true);
18775  _fblslincgstate_init(&cgstate, _state, ae_true);
18776  ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
18777  ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
18778 
18779  ae_assert(n>=1, "Spline1DFitPenalizedW: N<1!", _state);
18780  ae_assert(m>=4, "Spline1DFitPenalizedW: M<4!", _state);
18781  ae_assert(x->cnt>=n, "Spline1DFitPenalizedW: Length(X)<N!", _state);
18782  ae_assert(y->cnt>=n, "Spline1DFitPenalizedW: Length(Y)<N!", _state);
18783  ae_assert(w->cnt>=n, "Spline1DFitPenalizedW: Length(W)<N!", _state);
18784  ae_assert(isfinitevector(x, n, _state), "Spline1DFitPenalizedW: X contains infinite or NAN values!", _state);
18785  ae_assert(isfinitevector(y, n, _state), "Spline1DFitPenalizedW: Y contains infinite or NAN values!", _state);
18786  ae_assert(isfinitevector(w, n, _state), "Spline1DFitPenalizedW: Y contains infinite or NAN values!", _state);
18787  ae_assert(ae_isfinite(rho, _state), "Spline1DFitPenalizedW: Rho is infinite!", _state);
18788 
18789  /*
18790  * Prepare LambdaV
18791  */
18792  v = -ae_log(ae_machineepsilon, _state)/ae_log(10, _state);
18793  if( ae_fp_less(rho,-v) )
18794  {
18795  rho = -v;
18796  }
18797  if( ae_fp_greater(rho,v) )
18798  {
18799  rho = v;
18800  }
18801  lambdav = ae_pow(10, rho, _state);
18802 
18803  /*
18804  * Sort X, Y, W
18805  */
18806  heapsortdpoints(x, y, w, n, _state);
18807 
18808  /*
18809  * Scale X, Y, XC, YC
18810  */
18811  lsfitscalexy(x, y, w, n, &xc, &yc, &dc, 0, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
18812 
18813  /*
18814  * Allocate space
18815  */
18816  ae_matrix_set_length(&fmatrix, n, m, _state);
18817  ae_matrix_set_length(&amatrix, m, m, _state);
18818  ae_matrix_set_length(&d2matrix, m, m, _state);
18819  ae_vector_set_length(&bx, m, _state);
18820  ae_vector_set_length(&by, m, _state);
18821  ae_vector_set_length(&fcolumn, n, _state);
18822  ae_matrix_set_length(&nmatrix, m, m, _state);
18823  ae_vector_set_length(&rightpart, m, _state);
18824  ae_vector_set_length(&tmp0, ae_maxint(m, n, _state), _state);
18825  ae_vector_set_length(&c, m, _state);
18826 
18827  /*
18828  * Fill:
18829  * * FMatrix by values of basis functions
18830  * * TmpAMatrix by second derivatives of I-th function at J-th point
18831  * * CMatrix by constraints
18832  */
18833  fdmax = 0;
18834  for(b=0; b<=m-1; b++)
18835  {
18836 
18837  /*
18838  * Prepare I-th basis function
18839  */
18840  for(j=0; j<=m-1; j++)
18841  {
18842  bx.ptr.p_double[j] = (double)(2*j)/(double)(m-1)-1;
18843  by.ptr.p_double[j] = 0;
18844  }
18845  by.ptr.p_double[b] = 1;
18846  spline1dgriddiff2cubic(&bx, &by, m, 2, 0.0, 2, 0.0, &bd1, &bd2, _state);
18847  spline1dbuildcubic(&bx, &by, m, 2, 0.0, 2, 0.0, &bs, _state);
18848 
18849  /*
18850  * Calculate B-th column of FMatrix
18851  * Update FDMax (maximum column norm)
18852  */
18853  spline1dconvcubic(&bx, &by, m, 2, 0.0, 2, 0.0, x, n, &fcolumn, _state);
18854  ae_v_move(&fmatrix.ptr.pp_double[0][b], fmatrix.stride, &fcolumn.ptr.p_double[0], 1, ae_v_len(0,n-1));
18855  v = 0;
18856  for(i=0; i<=n-1; i++)
18857  {
18858  v = v+ae_sqr(w->ptr.p_double[i]*fcolumn.ptr.p_double[i], _state);
18859  }
18860  fdmax = ae_maxreal(fdmax, v, _state);
18861 
18862  /*
18863  * Fill temporary with second derivatives of basis function
18864  */
18865  ae_v_move(&d2matrix.ptr.pp_double[b][0], 1, &bd2.ptr.p_double[0], 1, ae_v_len(0,m-1));
18866  }
18867 
18868  /*
18869  * * calculate penalty matrix A
18870  * * calculate max of diagonal elements of A
18871  * * calculate PDecay - coefficient before penalty matrix
18872  */
18873  for(i=0; i<=m-1; i++)
18874  {
18875  for(j=i; j<=m-1; j++)
18876  {
18877 
18878  /*
18879  * calculate integral(B_i''*B_j'') where B_i and B_j are
18880  * i-th and j-th basis splines.
18881  * B_i and B_j are piecewise linear functions.
18882  */
18883  v = 0;
18884  for(b=0; b<=m-2; b++)
18885  {
18886  fa = d2matrix.ptr.pp_double[i][b];
18887  fb = d2matrix.ptr.pp_double[i][b+1];
18888  ga = d2matrix.ptr.pp_double[j][b];
18889  gb = d2matrix.ptr.pp_double[j][b+1];
18890  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);
18891  }
18892  amatrix.ptr.pp_double[i][j] = v;
18893  amatrix.ptr.pp_double[j][i] = v;
18894  }
18895  }
18896  admax = 0;
18897  for(i=0; i<=m-1; i++)
18898  {
18899  admax = ae_maxreal(admax, ae_fabs(amatrix.ptr.pp_double[i][i], _state), _state);
18900  }
18901  pdecay = lambdav*fdmax/admax;
18902 
18903  /*
18904  * Calculate TDecay for Tikhonov regularization
18905  */
18906  tdecay = fdmax*(1+pdecay)*10*ae_machineepsilon;
18907 
18908  /*
18909  * Prepare system
18910  *
18911  * NOTE: FMatrix is spoiled during this process
18912  */
18913  for(i=0; i<=n-1; i++)
18914  {
18915  v = w->ptr.p_double[i];
18916  ae_v_muld(&fmatrix.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
18917  }
18918  rmatrixgemm(m, m, n, 1.0, &fmatrix, 0, 0, 1, &fmatrix, 0, 0, 0, 0.0, &nmatrix, 0, 0, _state);
18919  for(i=0; i<=m-1; i++)
18920  {
18921  for(j=0; j<=m-1; j++)
18922  {
18923  nmatrix.ptr.pp_double[i][j] = nmatrix.ptr.pp_double[i][j]+pdecay*amatrix.ptr.pp_double[i][j];
18924  }
18925  }
18926  for(i=0; i<=m-1; i++)
18927  {
18928  nmatrix.ptr.pp_double[i][i] = nmatrix.ptr.pp_double[i][i]+tdecay;
18929  }
18930  for(i=0; i<=m-1; i++)
18931  {
18932  rightpart.ptr.p_double[i] = 0;
18933  }
18934  for(i=0; i<=n-1; i++)
18935  {
18936  v = y->ptr.p_double[i]*w->ptr.p_double[i];
18937  ae_v_addd(&rightpart.ptr.p_double[0], 1, &fmatrix.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
18938  }
18939 
18940  /*
18941  * Solve system
18942  */
18943  if( !spdmatrixcholesky(&nmatrix, m, ae_true, _state) )
18944  {
18945  *info = -4;
18946  ae_frame_leave(_state);
18947  return;
18948  }
18949  fblscholeskysolve(&nmatrix, 1.0, m, ae_true, &rightpart, &tmp0, _state);
18950  ae_v_move(&c.ptr.p_double[0], 1, &rightpart.ptr.p_double[0], 1, ae_v_len(0,m-1));
18951 
18952  /*
18953  * add nodes to force linearity outside of the fitting interval
18954  */
18955  spline1dgriddiffcubic(&bx, &c, m, 2, 0.0, 2, 0.0, &bd1, _state);
18956  ae_vector_set_length(&tx, m+2, _state);
18957  ae_vector_set_length(&ty, m+2, _state);
18958  ae_vector_set_length(&td, m+2, _state);
18959  ae_v_move(&tx.ptr.p_double[1], 1, &bx.ptr.p_double[0], 1, ae_v_len(1,m));
18960  ae_v_move(&ty.ptr.p_double[1], 1, &rightpart.ptr.p_double[0], 1, ae_v_len(1,m));
18961  ae_v_move(&td.ptr.p_double[1], 1, &bd1.ptr.p_double[0], 1, ae_v_len(1,m));
18962  tx.ptr.p_double[0] = tx.ptr.p_double[1]-(tx.ptr.p_double[2]-tx.ptr.p_double[1]);
18963  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]);
18964  td.ptr.p_double[0] = td.ptr.p_double[1];
18965  tx.ptr.p_double[m+1] = tx.ptr.p_double[m]+(tx.ptr.p_double[m]-tx.ptr.p_double[m-1]);
18966  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]);
18967  td.ptr.p_double[m+1] = td.ptr.p_double[m];
18968  spline1dbuildhermite(&tx, &ty, &td, m+2, s, _state);
18969  spline1dlintransx(s, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
18970  spline1dlintransy(s, sb-sa, sa, _state);
18971  *info = 1;
18972 
18973  /*
18974  * Fill report
18975  */
18976  rep->rmserror = 0;
18977  rep->avgerror = 0;
18978  rep->avgrelerror = 0;
18979  rep->maxerror = 0;
18980  relcnt = 0;
18981  spline1dconvcubic(&bx, &rightpart, m, 2, 0.0, 2, 0.0, x, n, &fcolumn, _state);
18982  for(i=0; i<=n-1; i++)
18983  {
18984  v = (sb-sa)*fcolumn.ptr.p_double[i]+sa;
18985  rep->rmserror = rep->rmserror+ae_sqr(v-yoriginal.ptr.p_double[i], _state);
18986  rep->avgerror = rep->avgerror+ae_fabs(v-yoriginal.ptr.p_double[i], _state);
18987  if( ae_fp_neq(yoriginal.ptr.p_double[i],0) )
18988  {
18989  rep->avgrelerror = rep->avgrelerror+ae_fabs(v-yoriginal.ptr.p_double[i], _state)/ae_fabs(yoriginal.ptr.p_double[i], _state);
18990  relcnt = relcnt+1;
18991  }
18992  rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v-yoriginal.ptr.p_double[i], _state), _state);
18993  }
18994  rep->rmserror = ae_sqrt(rep->rmserror/n, _state);
18995  rep->avgerror = rep->avgerror/n;
18996  if( ae_fp_neq(relcnt,0) )
18997  {
18998  rep->avgrelerror = rep->avgrelerror/relcnt;
18999  }
19000  ae_frame_leave(_state);
19001 }
19002 
19003 
19004 /*************************************************************************
19005 Weighted fitting by cubic spline, with constraints on function values or
19006 derivatives.
19007 
19008 Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used to build
19009 basis functions. Basis functions are cubic splines with continuous second
19010 derivatives and non-fixed first derivatives at interval ends. Small
19011 regularizing term is used when solving constrained tasks (to improve
19012 stability).
19013 
19014 Task is linear, so linear least squares solver is used. Complexity of this
19015 computational scheme is O(N*M^2), mostly dominated by least squares solver
19016 
19017 SEE ALSO
19018  Spline1DFitHermiteWC() - fitting by Hermite splines (more flexible,
19019  less smooth)
19020  Spline1DFitCubic() - "lightweight" fitting by cubic splines,
19021  without invididual weights and constraints
19022 
19023 INPUT PARAMETERS:
19024  X - points, array[0..N-1].
19025  Y - function values, array[0..N-1].
19026  W - weights, array[0..N-1]
19027  Each summand in square sum of approximation deviations from
19028  given values is multiplied by the square of corresponding
19029  weight. Fill it by 1's if you don't want to solve weighted
19030  task.
19031  N - number of points (optional):
19032  * N>0
19033  * if given, only first N elements of X/Y/W are processed
19034  * if not given, automatically determined from X/Y/W sizes
19035  XC - points where spline values/derivatives are constrained,
19036  array[0..K-1].
19037  YC - values of constraints, array[0..K-1]
19038  DC - array[0..K-1], types of constraints:
19039  * DC[i]=0 means that S(XC[i])=YC[i]
19040  * DC[i]=1 means that S'(XC[i])=YC[i]
19041  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
19042  K - number of constraints (optional):
19043  * 0<=K<M.
19044  * K=0 means no constraints (XC/YC/DC are not used)
19045  * if given, only first K elements of XC/YC/DC are used
19046  * if not given, automatically determined from XC/YC/DC
19047  M - number of basis functions ( = number_of_nodes+2), M>=4.
19048 
19049 OUTPUT PARAMETERS:
19050  Info- same format as in LSFitLinearWC() subroutine.
19051  * Info>0 task is solved
19052  * Info<=0 an error occurred:
19053  -4 means inconvergence of internal SVD
19054  -3 means inconsistent constraints
19055  S - spline interpolant.
19056  Rep - report, same format as in LSFitLinearWC() subroutine.
19057  Following fields are set:
19058  * RMSError rms error on the (X,Y).
19059  * AvgError average error on the (X,Y).
19060  * AvgRelError average relative error on the non-zero Y
19061  * MaxError maximum error
19062  NON-WEIGHTED ERRORS ARE CALCULATED
19063 
19064 IMPORTANT:
19065  this subroitine doesn't calculate task's condition number for K<>0.
19066 
19067 
19068 ORDER OF POINTS
19069 
19070 Subroutine automatically sorts points, so caller may pass unsorted array.
19071 
19072 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
19073 
19074 Setting constraints can lead to undesired results, like ill-conditioned
19075 behavior, or inconsistency being detected. From the other side, it allows
19076 us to improve quality of the fit. Here we summarize our experience with
19077 constrained regression splines:
19078 * excessive constraints can be inconsistent. Splines are piecewise cubic
19079  functions, and it is easy to create an example, where large number of
19080  constraints concentrated in small area will result in inconsistency.
19081  Just because spline is not flexible enough to satisfy all of them. And
19082  same constraints spread across the [min(x),max(x)] will be perfectly
19083  consistent.
19084 * the more evenly constraints are spread across [min(x),max(x)], the more
19085  chances that they will be consistent
19086 * the greater is M (given fixed constraints), the more chances that
19087  constraints will be consistent
19088 * in the general case, consistency of constraints IS NOT GUARANTEED.
19089 * in the several special cases, however, we CAN guarantee consistency.
19090 * one of this cases is constraints on the function values AND/OR its
19091  derivatives at the interval boundaries.
19092 * another special case is ONE constraint on the function value (OR, but
19093  not AND, derivative) anywhere in the interval
19094 
19095 Our final recommendation is to use constraints WHEN AND ONLY WHEN you
19096 can't solve your task without them. Anything beyond special cases given
19097 above is not guaranteed and may result in inconsistency.
19098 
19099 
19100  -- ALGLIB PROJECT --
19101  Copyright 18.08.2009 by Bochkanov Sergey
19102 *************************************************************************/
19103 void spline1dfitcubicwc(/* Real */ ae_vector* x,
19104  /* Real */ ae_vector* y,
19105  /* Real */ ae_vector* w,
19106  ae_int_t n,
19107  /* Real */ ae_vector* xc,
19108  /* Real */ ae_vector* yc,
19109  /* Integer */ ae_vector* dc,
19110  ae_int_t k,
19111  ae_int_t m,
19112  ae_int_t* info,
19113  spline1dinterpolant* s,
19114  spline1dfitreport* rep,
19115  ae_state *_state)
19116 {
19117  ae_int_t i;
19118 
19119  *info = 0;
19120  _spline1dinterpolant_clear(s);
19121  _spline1dfitreport_clear(rep);
19122 
19123  ae_assert(n>=1, "Spline1DFitCubicWC: N<1!", _state);
19124  ae_assert(m>=4, "Spline1DFitCubicWC: M<4!", _state);
19125  ae_assert(k>=0, "Spline1DFitCubicWC: K<0!", _state);
19126  ae_assert(k<m, "Spline1DFitCubicWC: K>=M!", _state);
19127  ae_assert(x->cnt>=n, "Spline1DFitCubicWC: Length(X)<N!", _state);
19128  ae_assert(y->cnt>=n, "Spline1DFitCubicWC: Length(Y)<N!", _state);
19129  ae_assert(w->cnt>=n, "Spline1DFitCubicWC: Length(W)<N!", _state);
19130  ae_assert(xc->cnt>=k, "Spline1DFitCubicWC: Length(XC)<K!", _state);
19131  ae_assert(yc->cnt>=k, "Spline1DFitCubicWC: Length(YC)<K!", _state);
19132  ae_assert(dc->cnt>=k, "Spline1DFitCubicWC: Length(DC)<K!", _state);
19133  ae_assert(isfinitevector(x, n, _state), "Spline1DFitCubicWC: X contains infinite or NAN values!", _state);
19134  ae_assert(isfinitevector(y, n, _state), "Spline1DFitCubicWC: Y contains infinite or NAN values!", _state);
19135  ae_assert(isfinitevector(w, n, _state), "Spline1DFitCubicWC: Y contains infinite or NAN values!", _state);
19136  ae_assert(isfinitevector(xc, k, _state), "Spline1DFitCubicWC: X contains infinite or NAN values!", _state);
19137  ae_assert(isfinitevector(yc, k, _state), "Spline1DFitCubicWC: Y contains infinite or NAN values!", _state);
19138  for(i=0; i<=k-1; i++)
19139  {
19140  ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "Spline1DFitCubicWC: DC[i] is neither 0 or 1!", _state);
19141  }
19142  lsfit_spline1dfitinternal(0, x, y, w, n, xc, yc, dc, k, m, info, s, rep, _state);
19143 }
19144 
19145 
19146 /*************************************************************************
19147 Weighted fitting by Hermite spline, with constraints on function values
19148 or first derivatives.
19149 
19150 Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to build
19151 basis functions. Basis functions are Hermite splines. Small regularizing
19152 term is used when solving constrained tasks (to improve stability).
19153 
19154 Task is linear, so linear least squares solver is used. Complexity of this
19155 computational scheme is O(N*M^2), mostly dominated by least squares solver
19156 
19157 SEE ALSO
19158  Spline1DFitCubicWC() - fitting by Cubic splines (less flexible,
19159  more smooth)
19160  Spline1DFitHermite() - "lightweight" Hermite fitting, without
19161  invididual weights and constraints
19162 
19163 INPUT PARAMETERS:
19164  X - points, array[0..N-1].
19165  Y - function values, array[0..N-1].
19166  W - weights, array[0..N-1]
19167  Each summand in square sum of approximation deviations from
19168  given values is multiplied by the square of corresponding
19169  weight. Fill it by 1's if you don't want to solve weighted
19170  task.
19171  N - number of points (optional):
19172  * N>0
19173  * if given, only first N elements of X/Y/W are processed
19174  * if not given, automatically determined from X/Y/W sizes
19175  XC - points where spline values/derivatives are constrained,
19176  array[0..K-1].
19177  YC - values of constraints, array[0..K-1]
19178  DC - array[0..K-1], types of constraints:
19179  * DC[i]=0 means that S(XC[i])=YC[i]
19180  * DC[i]=1 means that S'(XC[i])=YC[i]
19181  SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
19182  K - number of constraints (optional):
19183  * 0<=K<M.
19184  * K=0 means no constraints (XC/YC/DC are not used)
19185  * if given, only first K elements of XC/YC/DC are used
19186  * if not given, automatically determined from XC/YC/DC
19187  M - number of basis functions (= 2 * number of nodes),
19188  M>=4,
19189  M IS EVEN!
19190 
19191 OUTPUT PARAMETERS:
19192  Info- same format as in LSFitLinearW() subroutine:
19193  * Info>0 task is solved
19194  * Info<=0 an error occurred:
19195  -4 means inconvergence of internal SVD
19196  -3 means inconsistent constraints
19197  -2 means odd M was passed (which is not supported)
19198  -1 means another errors in parameters passed
19199  (N<=0, for example)
19200  S - spline interpolant.
19201  Rep - report, same format as in LSFitLinearW() subroutine.
19202  Following fields are set:
19203  * RMSError rms error on the (X,Y).
19204  * AvgError average error on the (X,Y).
19205  * AvgRelError average relative error on the non-zero Y
19206  * MaxError maximum error
19207  NON-WEIGHTED ERRORS ARE CALCULATED
19208 
19209 IMPORTANT:
19210  this subroitine doesn't calculate task's condition number for K<>0.
19211 
19212 IMPORTANT:
19213  this subroitine supports only even M's
19214 
19215 
19216 ORDER OF POINTS
19217 
19218 Subroutine automatically sorts points, so caller may pass unsorted array.
19219 
19220 SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
19221 
19222 Setting constraints can lead to undesired results, like ill-conditioned
19223 behavior, or inconsistency being detected. From the other side, it allows
19224 us to improve quality of the fit. Here we summarize our experience with
19225 constrained regression splines:
19226 * excessive constraints can be inconsistent. Splines are piecewise cubic
19227  functions, and it is easy to create an example, where large number of
19228  constraints concentrated in small area will result in inconsistency.
19229  Just because spline is not flexible enough to satisfy all of them. And
19230  same constraints spread across the [min(x),max(x)] will be perfectly
19231  consistent.
19232 * the more evenly constraints are spread across [min(x),max(x)], the more
19233  chances that they will be consistent
19234 * the greater is M (given fixed constraints), the more chances that
19235  constraints will be consistent
19236 * in the general case, consistency of constraints is NOT GUARANTEED.
19237 * in the several special cases, however, we can guarantee consistency.
19238 * one of this cases is M>=4 and constraints on the function value
19239  (AND/OR its derivative) at the interval boundaries.
19240 * another special case is M>=4 and ONE constraint on the function value
19241  (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]
19242 
19243 Our final recommendation is to use constraints WHEN AND ONLY when you
19244 can't solve your task without them. Anything beyond special cases given
19245 above is not guaranteed and may result in inconsistency.
19246 
19247  -- ALGLIB PROJECT --
19248  Copyright 18.08.2009 by Bochkanov Sergey
19249 *************************************************************************/
19250 void spline1dfithermitewc(/* Real */ ae_vector* x,
19251  /* Real */ ae_vector* y,
19252  /* Real */ ae_vector* w,
19253  ae_int_t n,
19254  /* Real */ ae_vector* xc,
19255  /* Real */ ae_vector* yc,
19256  /* Integer */ ae_vector* dc,
19257  ae_int_t k,
19258  ae_int_t m,
19259  ae_int_t* info,
19260  spline1dinterpolant* s,
19261  spline1dfitreport* rep,
19262  ae_state *_state)
19263 {
19264  ae_int_t i;
19265 
19266  *info = 0;
19267  _spline1dinterpolant_clear(s);
19268  _spline1dfitreport_clear(rep);
19269 
19270  ae_assert(n>=1, "Spline1DFitHermiteWC: N<1!", _state);
19271  ae_assert(m>=4, "Spline1DFitHermiteWC: M<4!", _state);
19272  ae_assert(m%2==0, "Spline1DFitHermiteWC: M is odd!", _state);
19273  ae_assert(k>=0, "Spline1DFitHermiteWC: K<0!", _state);
19274  ae_assert(k<m, "Spline1DFitHermiteWC: K>=M!", _state);
19275  ae_assert(x->cnt>=n, "Spline1DFitHermiteWC: Length(X)<N!", _state);
19276  ae_assert(y->cnt>=n, "Spline1DFitHermiteWC: Length(Y)<N!", _state);
19277  ae_assert(w->cnt>=n, "Spline1DFitHermiteWC: Length(W)<N!", _state);
19278  ae_assert(xc->cnt>=k, "Spline1DFitHermiteWC: Length(XC)<K!", _state);
19279  ae_assert(yc->cnt>=k, "Spline1DFitHermiteWC: Length(YC)<K!", _state);
19280  ae_assert(dc->cnt>=k, "Spline1DFitHermiteWC: Length(DC)<K!", _state);
19281  ae_assert(isfinitevector(x, n, _state), "Spline1DFitHermiteWC: X contains infinite or NAN values!", _state);
19282  ae_assert(isfinitevector(y, n, _state), "Spline1DFitHermiteWC: Y contains infinite or NAN values!", _state);
19283  ae_assert(isfinitevector(w, n, _state), "Spline1DFitHermiteWC: Y contains infinite or NAN values!", _state);
19284  ae_assert(isfinitevector(xc, k, _state), "Spline1DFitHermiteWC: X contains infinite or NAN values!", _state);
19285  ae_assert(isfinitevector(yc, k, _state), "Spline1DFitHermiteWC: Y contains infinite or NAN values!", _state);
19286  for(i=0; i<=k-1; i++)
19287  {
19288  ae_assert(dc->ptr.p_int[i]==0||dc->ptr.p_int[i]==1, "Spline1DFitHermiteWC: DC[i] is neither 0 or 1!", _state);
19289  }
19290  lsfit_spline1dfitinternal(1, x, y, w, n, xc, yc, dc, k, m, info, s, rep, _state);
19291 }
19292 
19293 
19294 /*************************************************************************
19295 Least squares fitting by cubic spline.
19296 
19297 This subroutine is "lightweight" alternative for more complex and feature-
19298 rich Spline1DFitCubicWC(). See Spline1DFitCubicWC() for more information
19299 about subroutine parameters (we don't duplicate it here because of length)
19300 
19301  -- ALGLIB PROJECT --
19302  Copyright 18.08.2009 by Bochkanov Sergey
19303 *************************************************************************/
19304 void spline1dfitcubic(/* Real */ ae_vector* x,
19305  /* Real */ ae_vector* y,
19306  ae_int_t n,
19307  ae_int_t m,
19308  ae_int_t* info,
19309  spline1dinterpolant* s,
19310  spline1dfitreport* rep,
19311  ae_state *_state)
19312 {
19313  ae_frame _frame_block;
19314  ae_int_t i;
19315  ae_vector w;
19316  ae_vector xc;
19317  ae_vector yc;
19318  ae_vector dc;
19319 
19320  ae_frame_make(_state, &_frame_block);
19321  *info = 0;
19322  _spline1dinterpolant_clear(s);
19323  _spline1dfitreport_clear(rep);
19324  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
19325  ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
19326  ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
19327  ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
19328 
19329  ae_assert(n>=1, "Spline1DFitCubic: N<1!", _state);
19330  ae_assert(m>=4, "Spline1DFitCubic: M<4!", _state);
19331  ae_assert(x->cnt>=n, "Spline1DFitCubic: Length(X)<N!", _state);
19332  ae_assert(y->cnt>=n, "Spline1DFitCubic: Length(Y)<N!", _state);
19333  ae_assert(isfinitevector(x, n, _state), "Spline1DFitCubic: X contains infinite or NAN values!", _state);
19334  ae_assert(isfinitevector(y, n, _state), "Spline1DFitCubic: Y contains infinite or NAN values!", _state);
19335  ae_vector_set_length(&w, n, _state);
19336  for(i=0; i<=n-1; i++)
19337  {
19338  w.ptr.p_double[i] = 1;
19339  }
19340  spline1dfitcubicwc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, s, rep, _state);
19341  ae_frame_leave(_state);
19342 }
19343 
19344 
19345 /*************************************************************************
19346 Least squares fitting by Hermite spline.
19347 
19348 This subroutine is "lightweight" alternative for more complex and feature-
19349 rich Spline1DFitHermiteWC(). See Spline1DFitHermiteWC() description for
19350 more information about subroutine parameters (we don't duplicate it here
19351 because of length).
19352 
19353  -- ALGLIB PROJECT --
19354  Copyright 18.08.2009 by Bochkanov Sergey
19355 *************************************************************************/
19356 void spline1dfithermite(/* Real */ ae_vector* x,
19357  /* Real */ ae_vector* y,
19358  ae_int_t n,
19359  ae_int_t m,
19360  ae_int_t* info,
19361  spline1dinterpolant* s,
19362  spline1dfitreport* rep,
19363  ae_state *_state)
19364 {
19365  ae_frame _frame_block;
19366  ae_int_t i;
19367  ae_vector w;
19368  ae_vector xc;
19369  ae_vector yc;
19370  ae_vector dc;
19371 
19372  ae_frame_make(_state, &_frame_block);
19373  *info = 0;
19374  _spline1dinterpolant_clear(s);
19375  _spline1dfitreport_clear(rep);
19376  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
19377  ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
19378  ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
19379  ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
19380 
19381  ae_assert(n>=1, "Spline1DFitHermite: N<1!", _state);
19382  ae_assert(m>=4, "Spline1DFitHermite: M<4!", _state);
19383  ae_assert(m%2==0, "Spline1DFitHermite: M is odd!", _state);
19384  ae_assert(x->cnt>=n, "Spline1DFitHermite: Length(X)<N!", _state);
19385  ae_assert(y->cnt>=n, "Spline1DFitHermite: Length(Y)<N!", _state);
19386  ae_assert(isfinitevector(x, n, _state), "Spline1DFitHermite: X contains infinite or NAN values!", _state);
19387  ae_assert(isfinitevector(y, n, _state), "Spline1DFitHermite: Y contains infinite or NAN values!", _state);
19388  ae_vector_set_length(&w, n, _state);
19389  for(i=0; i<=n-1; i++)
19390  {
19391  w.ptr.p_double[i] = 1;
19392  }
19393  spline1dfithermitewc(x, y, &w, n, &xc, &yc, &dc, 0, m, info, s, rep, _state);
19394  ae_frame_leave(_state);
19395 }
19396 
19397 
19398 /*************************************************************************
19399 Weighted linear least squares fitting.
19400 
19401 QR decomposition is used to reduce task to MxM, then triangular solver or
19402 SVD-based solver is used depending on condition number of the system. It
19403 allows to maximize speed and retain decent accuracy.
19404 
19405 IMPORTANT: if you want to perform polynomial fitting, it may be more
19406  convenient to use PolynomialFit() function. This function gives
19407  best results on polynomial problems and solves numerical
19408  stability issues which arise when you fit high-degree
19409  polynomials to your data.
19410 
19411 INPUT PARAMETERS:
19412  Y - array[0..N-1] Function values in N points.
19413  W - array[0..N-1] Weights corresponding to function values.
19414  Each summand in square sum of approximation deviations
19415  from given values is multiplied by the square of
19416  corresponding weight.
19417  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
19418  FMatrix[I, J] - value of J-th basis function in I-th point.
19419  N - number of points used. N>=1.
19420  M - number of basis functions, M>=1.
19421 
19422 OUTPUT PARAMETERS:
19423  Info - error code:
19424  * -4 internal SVD decomposition subroutine failed (very
19425  rare and for degenerate systems only)
19426  * -1 incorrect N/M were specified
19427  * 1 task is solved
19428  C - decomposition coefficients, array[0..M-1]
19429  Rep - fitting report. Following fields are set:
19430  * Rep.TaskRCond reciprocal of condition number
19431  * R2 non-adjusted coefficient of determination
19432  (non-weighted)
19433  * RMSError rms error on the (X,Y).
19434  * AvgError average error on the (X,Y).
19435  * AvgRelError average relative error on the non-zero Y
19436  * MaxError maximum error
19437  NON-WEIGHTED ERRORS ARE CALCULATED
19438 
19439 ERRORS IN PARAMETERS
19440 
19441 This solver also calculates different kinds of errors in parameters and
19442 fills corresponding fields of report:
19443 * Rep.CovPar covariance matrix for parameters, array[K,K].
19444 * Rep.ErrPar errors in parameters, array[K],
19445  errpar = sqrt(diag(CovPar))
19446 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
19447  best-fit curve from "ideal" best-fit curve built with
19448  infinite number of samples, array[N].
19449  errcurve = sqrt(diag(F*CovPar*F')),
19450  where F is functions matrix.
19451 * Rep.Noise vector of per-point estimates of noise, array[N]
19452 
19453 NOTE: noise in the data is estimated as follows:
19454  * for fitting without user-supplied weights all points are
19455  assumed to have same level of noise, which is estimated from
19456  the data
19457  * for fitting with user-supplied weights we assume that noise
19458  level in I-th point is inversely proportional to Ith weight.
19459  Coefficient of proportionality is estimated from the data.
19460 
19461 NOTE: we apply small amount of regularization when we invert squared
19462  Jacobian and calculate covariance matrix. It guarantees that
19463  algorithm won't divide by zero during inversion, but skews
19464  error estimates a bit (fractional error is about 10^-9).
19465 
19466  However, we believe that this difference is insignificant for
19467  all practical purposes except for the situation when you want
19468  to compare ALGLIB results with "reference" implementation up
19469  to the last significant digit.
19470 
19471 NOTE: covariance matrix is estimated using correction for degrees
19472  of freedom (covariances are divided by N-M instead of dividing
19473  by N).
19474 
19475  -- ALGLIB --
19476  Copyright 17.08.2009 by Bochkanov Sergey
19477 *************************************************************************/
19478 void lsfitlinearw(/* Real */ ae_vector* y,
19479  /* Real */ ae_vector* w,
19480  /* Real */ ae_matrix* fmatrix,
19481  ae_int_t n,
19482  ae_int_t m,
19483  ae_int_t* info,
19484  /* Real */ ae_vector* c,
19485  lsfitreport* rep,
19486  ae_state *_state)
19487 {
19488 
19489  *info = 0;
19490  ae_vector_clear(c);
19491  _lsfitreport_clear(rep);
19492 
19493  ae_assert(n>=1, "LSFitLinearW: N<1!", _state);
19494  ae_assert(m>=1, "LSFitLinearW: M<1!", _state);
19495  ae_assert(y->cnt>=n, "LSFitLinearW: length(Y)<N!", _state);
19496  ae_assert(isfinitevector(y, n, _state), "LSFitLinearW: Y contains infinite or NaN values!", _state);
19497  ae_assert(w->cnt>=n, "LSFitLinearW: length(W)<N!", _state);
19498  ae_assert(isfinitevector(w, n, _state), "LSFitLinearW: W contains infinite or NaN values!", _state);
19499  ae_assert(fmatrix->rows>=n, "LSFitLinearW: rows(FMatrix)<N!", _state);
19500  ae_assert(fmatrix->cols>=m, "LSFitLinearW: cols(FMatrix)<M!", _state);
19501  ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinearW: FMatrix contains infinite or NaN values!", _state);
19502  lsfit_lsfitlinearinternal(y, w, fmatrix, n, m, info, c, rep, _state);
19503 }
19504 
19505 
19506 /*************************************************************************
19507 Weighted constained linear least squares fitting.
19508 
19509 This is variation of LSFitLinearW(), which searchs for min|A*x=b| given
19510 that K additional constraints C*x=bc are satisfied. It reduces original
19511 task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinearW()
19512 is called.
19513 
19514 IMPORTANT: if you want to perform polynomial fitting, it may be more
19515  convenient to use PolynomialFit() function. This function gives
19516  best results on polynomial problems and solves numerical
19517  stability issues which arise when you fit high-degree
19518  polynomials to your data.
19519 
19520 INPUT PARAMETERS:
19521  Y - array[0..N-1] Function values in N points.
19522  W - array[0..N-1] Weights corresponding to function values.
19523  Each summand in square sum of approximation deviations
19524  from given values is multiplied by the square of
19525  corresponding weight.
19526  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
19527  FMatrix[I,J] - value of J-th basis function in I-th point.
19528  CMatrix - a table of constraints, array[0..K-1,0..M].
19529  I-th row of CMatrix corresponds to I-th linear constraint:
19530  CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
19531  N - number of points used. N>=1.
19532  M - number of basis functions, M>=1.
19533  K - number of constraints, 0 <= K < M
19534  K=0 corresponds to absence of constraints.
19535 
19536 OUTPUT PARAMETERS:
19537  Info - error code:
19538  * -4 internal SVD decomposition subroutine failed (very
19539  rare and for degenerate systems only)
19540  * -3 either too many constraints (M or more),
19541  degenerate constraints (some constraints are
19542  repetead twice) or inconsistent constraints were
19543  specified.
19544  * 1 task is solved
19545  C - decomposition coefficients, array[0..M-1]
19546  Rep - fitting report. Following fields are set:
19547  * R2 non-adjusted coefficient of determination
19548  (non-weighted)
19549  * RMSError rms error on the (X,Y).
19550  * AvgError average error on the (X,Y).
19551  * AvgRelError average relative error on the non-zero Y
19552  * MaxError maximum error
19553  NON-WEIGHTED ERRORS ARE CALCULATED
19554 
19555 IMPORTANT:
19556  this subroitine doesn't calculate task's condition number for K<>0.
19557 
19558 ERRORS IN PARAMETERS
19559 
19560 This solver also calculates different kinds of errors in parameters and
19561 fills corresponding fields of report:
19562 * Rep.CovPar covariance matrix for parameters, array[K,K].
19563 * Rep.ErrPar errors in parameters, array[K],
19564  errpar = sqrt(diag(CovPar))
19565 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
19566  best-fit curve from "ideal" best-fit curve built with
19567  infinite number of samples, array[N].
19568  errcurve = sqrt(diag(F*CovPar*F')),
19569  where F is functions matrix.
19570 * Rep.Noise vector of per-point estimates of noise, array[N]
19571 
19572 IMPORTANT: errors in parameters are calculated without taking into
19573  account boundary/linear constraints! Presence of constraints
19574  changes distribution of errors, but there is no easy way to
19575  account for constraints when you calculate covariance matrix.
19576 
19577 NOTE: noise in the data is estimated as follows:
19578  * for fitting without user-supplied weights all points are
19579  assumed to have same level of noise, which is estimated from
19580  the data
19581  * for fitting with user-supplied weights we assume that noise
19582  level in I-th point is inversely proportional to Ith weight.
19583  Coefficient of proportionality is estimated from the data.
19584 
19585 NOTE: we apply small amount of regularization when we invert squared
19586  Jacobian and calculate covariance matrix. It guarantees that
19587  algorithm won't divide by zero during inversion, but skews
19588  error estimates a bit (fractional error is about 10^-9).
19589 
19590  However, we believe that this difference is insignificant for
19591  all practical purposes except for the situation when you want
19592  to compare ALGLIB results with "reference" implementation up
19593  to the last significant digit.
19594 
19595 NOTE: covariance matrix is estimated using correction for degrees
19596  of freedom (covariances are divided by N-M instead of dividing
19597  by N).
19598 
19599  -- ALGLIB --
19600  Copyright 07.09.2009 by Bochkanov Sergey
19601 *************************************************************************/
19602 void lsfitlinearwc(/* Real */ ae_vector* y,
19603  /* Real */ ae_vector* w,
19604  /* Real */ ae_matrix* fmatrix,
19605  /* Real */ ae_matrix* cmatrix,
19606  ae_int_t n,
19607  ae_int_t m,
19608  ae_int_t k,
19609  ae_int_t* info,
19610  /* Real */ ae_vector* c,
19611  lsfitreport* rep,
19612  ae_state *_state)
19613 {
19614  ae_frame _frame_block;
19615  ae_vector _y;
19616  ae_matrix _cmatrix;
19617  ae_int_t i;
19618  ae_int_t j;
19619  ae_vector tau;
19620  ae_matrix q;
19621  ae_matrix f2;
19622  ae_vector tmp;
19623  ae_vector c0;
19624  double v;
19625 
19626  ae_frame_make(_state, &_frame_block);
19627  ae_vector_init_copy(&_y, y, _state, ae_true);
19628  y = &_y;
19629  ae_matrix_init_copy(&_cmatrix, cmatrix, _state, ae_true);
19630  cmatrix = &_cmatrix;
19631  *info = 0;
19632  ae_vector_clear(c);
19633  _lsfitreport_clear(rep);
19634  ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
19635  ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
19636  ae_matrix_init(&f2, 0, 0, DT_REAL, _state, ae_true);
19637  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
19638  ae_vector_init(&c0, 0, DT_REAL, _state, ae_true);
19639 
19640  ae_assert(n>=1, "LSFitLinearWC: N<1!", _state);
19641  ae_assert(m>=1, "LSFitLinearWC: M<1!", _state);
19642  ae_assert(k>=0, "LSFitLinearWC: K<0!", _state);
19643  ae_assert(y->cnt>=n, "LSFitLinearWC: length(Y)<N!", _state);
19644  ae_assert(isfinitevector(y, n, _state), "LSFitLinearWC: Y contains infinite or NaN values!", _state);
19645  ae_assert(w->cnt>=n, "LSFitLinearWC: length(W)<N!", _state);
19646  ae_assert(isfinitevector(w, n, _state), "LSFitLinearWC: W contains infinite or NaN values!", _state);
19647  ae_assert(fmatrix->rows>=n, "LSFitLinearWC: rows(FMatrix)<N!", _state);
19648  ae_assert(fmatrix->cols>=m, "LSFitLinearWC: cols(FMatrix)<M!", _state);
19649  ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinearWC: FMatrix contains infinite or NaN values!", _state);
19650  ae_assert(cmatrix->rows>=k, "LSFitLinearWC: rows(CMatrix)<K!", _state);
19651  ae_assert(cmatrix->cols>=m+1||k==0, "LSFitLinearWC: cols(CMatrix)<M+1!", _state);
19652  ae_assert(apservisfinitematrix(cmatrix, k, m+1, _state), "LSFitLinearWC: CMatrix contains infinite or NaN values!", _state);
19653  if( k>=m )
19654  {
19655  *info = -3;
19656  ae_frame_leave(_state);
19657  return;
19658  }
19659 
19660  /*
19661  * Solve
19662  */
19663  if( k==0 )
19664  {
19665 
19666  /*
19667  * no constraints
19668  */
19669  lsfit_lsfitlinearinternal(y, w, fmatrix, n, m, info, c, rep, _state);
19670  }
19671  else
19672  {
19673 
19674  /*
19675  * First, find general form solution of constraints system:
19676  * * factorize C = L*Q
19677  * * unpack Q
19678  * * fill upper part of C with zeros (for RCond)
19679  *
19680  * We got C=C0+Q2'*y where Q2 is lower M-K rows of Q.
19681  */
19682  rmatrixlq(cmatrix, k, m, &tau, _state);
19683  rmatrixlqunpackq(cmatrix, k, m, &tau, m, &q, _state);
19684  for(i=0; i<=k-1; i++)
19685  {
19686  for(j=i+1; j<=m-1; j++)
19687  {
19688  cmatrix->ptr.pp_double[i][j] = 0.0;
19689  }
19690  }
19691  if( ae_fp_less(rmatrixlurcondinf(cmatrix, k, _state),1000*ae_machineepsilon) )
19692  {
19693  *info = -3;
19694  ae_frame_leave(_state);
19695  return;
19696  }
19697  ae_vector_set_length(&tmp, k, _state);
19698  for(i=0; i<=k-1; i++)
19699  {
19700  if( i>0 )
19701  {
19702  v = ae_v_dotproduct(&cmatrix->ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,i-1));
19703  }
19704  else
19705  {
19706  v = 0;
19707  }
19708  tmp.ptr.p_double[i] = (cmatrix->ptr.pp_double[i][m]-v)/cmatrix->ptr.pp_double[i][i];
19709  }
19710  ae_vector_set_length(&c0, m, _state);
19711  for(i=0; i<=m-1; i++)
19712  {
19713  c0.ptr.p_double[i] = 0;
19714  }
19715  for(i=0; i<=k-1; i++)
19716  {
19717  v = tmp.ptr.p_double[i];
19718  ae_v_addd(&c0.ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
19719  }
19720 
19721  /*
19722  * Second, prepare modified matrix F2 = F*Q2' and solve modified task
19723  */
19724  ae_vector_set_length(&tmp, ae_maxint(n, m, _state)+1, _state);
19725  ae_matrix_set_length(&f2, n, m-k, _state);
19726  matrixvectormultiply(fmatrix, 0, n-1, 0, m-1, ae_false, &c0, 0, m-1, -1.0, y, 0, n-1, 1.0, _state);
19727  matrixmatrixmultiply(fmatrix, 0, n-1, 0, m-1, ae_false, &q, k, m-1, 0, m-1, ae_true, 1.0, &f2, 0, n-1, 0, m-k-1, 0.0, &tmp, _state);
19728  lsfit_lsfitlinearinternal(y, w, &f2, n, m-k, info, &tmp, rep, _state);
19729  rep->taskrcond = -1;
19730  if( *info<=0 )
19731  {
19732  ae_frame_leave(_state);
19733  return;
19734  }
19735 
19736  /*
19737  * then, convert back to original answer: C = C0 + Q2'*Y0
19738  */
19739  ae_vector_set_length(c, m, _state);
19740  ae_v_move(&c->ptr.p_double[0], 1, &c0.ptr.p_double[0], 1, ae_v_len(0,m-1));
19741  matrixvectormultiply(&q, k, m-1, 0, m-1, ae_true, &tmp, 0, m-k-1, 1.0, c, 0, m-1, 1.0, _state);
19742  }
19743  ae_frame_leave(_state);
19744 }
19745 
19746 
19747 /*************************************************************************
19748 Linear least squares fitting.
19749 
19750 QR decomposition is used to reduce task to MxM, then triangular solver or
19751 SVD-based solver is used depending on condition number of the system. It
19752 allows to maximize speed and retain decent accuracy.
19753 
19754 IMPORTANT: if you want to perform polynomial fitting, it may be more
19755  convenient to use PolynomialFit() function. This function gives
19756  best results on polynomial problems and solves numerical
19757  stability issues which arise when you fit high-degree
19758  polynomials to your data.
19759 
19760 INPUT PARAMETERS:
19761  Y - array[0..N-1] Function values in N points.
19762  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
19763  FMatrix[I, J] - value of J-th basis function in I-th point.
19764  N - number of points used. N>=1.
19765  M - number of basis functions, M>=1.
19766 
19767 OUTPUT PARAMETERS:
19768  Info - error code:
19769  * -4 internal SVD decomposition subroutine failed (very
19770  rare and for degenerate systems only)
19771  * 1 task is solved
19772  C - decomposition coefficients, array[0..M-1]
19773  Rep - fitting report. Following fields are set:
19774  * Rep.TaskRCond reciprocal of condition number
19775  * R2 non-adjusted coefficient of determination
19776  (non-weighted)
19777  * RMSError rms error on the (X,Y).
19778  * AvgError average error on the (X,Y).
19779  * AvgRelError average relative error on the non-zero Y
19780  * MaxError maximum error
19781  NON-WEIGHTED ERRORS ARE CALCULATED
19782 
19783 ERRORS IN PARAMETERS
19784 
19785 This solver also calculates different kinds of errors in parameters and
19786 fills corresponding fields of report:
19787 * Rep.CovPar covariance matrix for parameters, array[K,K].
19788 * Rep.ErrPar errors in parameters, array[K],
19789  errpar = sqrt(diag(CovPar))
19790 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
19791  best-fit curve from "ideal" best-fit curve built with
19792  infinite number of samples, array[N].
19793  errcurve = sqrt(diag(F*CovPar*F')),
19794  where F is functions matrix.
19795 * Rep.Noise vector of per-point estimates of noise, array[N]
19796 
19797 NOTE: noise in the data is estimated as follows:
19798  * for fitting without user-supplied weights all points are
19799  assumed to have same level of noise, which is estimated from
19800  the data
19801  * for fitting with user-supplied weights we assume that noise
19802  level in I-th point is inversely proportional to Ith weight.
19803  Coefficient of proportionality is estimated from the data.
19804 
19805 NOTE: we apply small amount of regularization when we invert squared
19806  Jacobian and calculate covariance matrix. It guarantees that
19807  algorithm won't divide by zero during inversion, but skews
19808  error estimates a bit (fractional error is about 10^-9).
19809 
19810  However, we believe that this difference is insignificant for
19811  all practical purposes except for the situation when you want
19812  to compare ALGLIB results with "reference" implementation up
19813  to the last significant digit.
19814 
19815 NOTE: covariance matrix is estimated using correction for degrees
19816  of freedom (covariances are divided by N-M instead of dividing
19817  by N).
19818 
19819  -- ALGLIB --
19820  Copyright 17.08.2009 by Bochkanov Sergey
19821 *************************************************************************/
19822 void lsfitlinear(/* Real */ ae_vector* y,
19823  /* Real */ ae_matrix* fmatrix,
19824  ae_int_t n,
19825  ae_int_t m,
19826  ae_int_t* info,
19827  /* Real */ ae_vector* c,
19828  lsfitreport* rep,
19829  ae_state *_state)
19830 {
19831  ae_frame _frame_block;
19832  ae_vector w;
19833  ae_int_t i;
19834 
19835  ae_frame_make(_state, &_frame_block);
19836  *info = 0;
19837  ae_vector_clear(c);
19838  _lsfitreport_clear(rep);
19839  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
19840 
19841  ae_assert(n>=1, "LSFitLinear: N<1!", _state);
19842  ae_assert(m>=1, "LSFitLinear: M<1!", _state);
19843  ae_assert(y->cnt>=n, "LSFitLinear: length(Y)<N!", _state);
19844  ae_assert(isfinitevector(y, n, _state), "LSFitLinear: Y contains infinite or NaN values!", _state);
19845  ae_assert(fmatrix->rows>=n, "LSFitLinear: rows(FMatrix)<N!", _state);
19846  ae_assert(fmatrix->cols>=m, "LSFitLinear: cols(FMatrix)<M!", _state);
19847  ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinear: FMatrix contains infinite or NaN values!", _state);
19848  ae_vector_set_length(&w, n, _state);
19849  for(i=0; i<=n-1; i++)
19850  {
19851  w.ptr.p_double[i] = 1;
19852  }
19853  lsfit_lsfitlinearinternal(y, &w, fmatrix, n, m, info, c, rep, _state);
19854  ae_frame_leave(_state);
19855 }
19856 
19857 
19858 /*************************************************************************
19859 Constained linear least squares fitting.
19860 
19861 This is variation of LSFitLinear(), which searchs for min|A*x=b| given
19862 that K additional constraints C*x=bc are satisfied. It reduces original
19863 task to modified one: min|B*y-d| WITHOUT constraints, then LSFitLinear()
19864 is called.
19865 
19866 IMPORTANT: if you want to perform polynomial fitting, it may be more
19867  convenient to use PolynomialFit() function. This function gives
19868  best results on polynomial problems and solves numerical
19869  stability issues which arise when you fit high-degree
19870  polynomials to your data.
19871 
19872 INPUT PARAMETERS:
19873  Y - array[0..N-1] Function values in N points.
19874  FMatrix - a table of basis functions values, array[0..N-1, 0..M-1].
19875  FMatrix[I,J] - value of J-th basis function in I-th point.
19876  CMatrix - a table of constraints, array[0..K-1,0..M].
19877  I-th row of CMatrix corresponds to I-th linear constraint:
19878  CMatrix[I,0]*C[0] + ... + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M]
19879  N - number of points used. N>=1.
19880  M - number of basis functions, M>=1.
19881  K - number of constraints, 0 <= K < M
19882  K=0 corresponds to absence of constraints.
19883 
19884 OUTPUT PARAMETERS:
19885  Info - error code:
19886  * -4 internal SVD decomposition subroutine failed (very
19887  rare and for degenerate systems only)
19888  * -3 either too many constraints (M or more),
19889  degenerate constraints (some constraints are
19890  repetead twice) or inconsistent constraints were
19891  specified.
19892  * 1 task is solved
19893  C - decomposition coefficients, array[0..M-1]
19894  Rep - fitting report. Following fields are set:
19895  * R2 non-adjusted coefficient of determination
19896  (non-weighted)
19897  * RMSError rms error on the (X,Y).
19898  * AvgError average error on the (X,Y).
19899  * AvgRelError average relative error on the non-zero Y
19900  * MaxError maximum error
19901  NON-WEIGHTED ERRORS ARE CALCULATED
19902 
19903 IMPORTANT:
19904  this subroitine doesn't calculate task's condition number for K<>0.
19905 
19906 ERRORS IN PARAMETERS
19907 
19908 This solver also calculates different kinds of errors in parameters and
19909 fills corresponding fields of report:
19910 * Rep.CovPar covariance matrix for parameters, array[K,K].
19911 * Rep.ErrPar errors in parameters, array[K],
19912  errpar = sqrt(diag(CovPar))
19913 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
19914  best-fit curve from "ideal" best-fit curve built with
19915  infinite number of samples, array[N].
19916  errcurve = sqrt(diag(F*CovPar*F')),
19917  where F is functions matrix.
19918 * Rep.Noise vector of per-point estimates of noise, array[N]
19919 
19920 IMPORTANT: errors in parameters are calculated without taking into
19921  account boundary/linear constraints! Presence of constraints
19922  changes distribution of errors, but there is no easy way to
19923  account for constraints when you calculate covariance matrix.
19924 
19925 NOTE: noise in the data is estimated as follows:
19926  * for fitting without user-supplied weights all points are
19927  assumed to have same level of noise, which is estimated from
19928  the data
19929  * for fitting with user-supplied weights we assume that noise
19930  level in I-th point is inversely proportional to Ith weight.
19931  Coefficient of proportionality is estimated from the data.
19932 
19933 NOTE: we apply small amount of regularization when we invert squared
19934  Jacobian and calculate covariance matrix. It guarantees that
19935  algorithm won't divide by zero during inversion, but skews
19936  error estimates a bit (fractional error is about 10^-9).
19937 
19938  However, we believe that this difference is insignificant for
19939  all practical purposes except for the situation when you want
19940  to compare ALGLIB results with "reference" implementation up
19941  to the last significant digit.
19942 
19943 NOTE: covariance matrix is estimated using correction for degrees
19944  of freedom (covariances are divided by N-M instead of dividing
19945  by N).
19946 
19947  -- ALGLIB --
19948  Copyright 07.09.2009 by Bochkanov Sergey
19949 *************************************************************************/
19950 void lsfitlinearc(/* Real */ ae_vector* y,
19951  /* Real */ ae_matrix* fmatrix,
19952  /* Real */ ae_matrix* cmatrix,
19953  ae_int_t n,
19954  ae_int_t m,
19955  ae_int_t k,
19956  ae_int_t* info,
19957  /* Real */ ae_vector* c,
19958  lsfitreport* rep,
19959  ae_state *_state)
19960 {
19961  ae_frame _frame_block;
19962  ae_vector _y;
19963  ae_vector w;
19964  ae_int_t i;
19965 
19966  ae_frame_make(_state, &_frame_block);
19967  ae_vector_init_copy(&_y, y, _state, ae_true);
19968  y = &_y;
19969  *info = 0;
19970  ae_vector_clear(c);
19971  _lsfitreport_clear(rep);
19972  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
19973 
19974  ae_assert(n>=1, "LSFitLinearC: N<1!", _state);
19975  ae_assert(m>=1, "LSFitLinearC: M<1!", _state);
19976  ae_assert(k>=0, "LSFitLinearC: K<0!", _state);
19977  ae_assert(y->cnt>=n, "LSFitLinearC: length(Y)<N!", _state);
19978  ae_assert(isfinitevector(y, n, _state), "LSFitLinearC: Y contains infinite or NaN values!", _state);
19979  ae_assert(fmatrix->rows>=n, "LSFitLinearC: rows(FMatrix)<N!", _state);
19980  ae_assert(fmatrix->cols>=m, "LSFitLinearC: cols(FMatrix)<M!", _state);
19981  ae_assert(apservisfinitematrix(fmatrix, n, m, _state), "LSFitLinearC: FMatrix contains infinite or NaN values!", _state);
19982  ae_assert(cmatrix->rows>=k, "LSFitLinearC: rows(CMatrix)<K!", _state);
19983  ae_assert(cmatrix->cols>=m+1||k==0, "LSFitLinearC: cols(CMatrix)<M+1!", _state);
19984  ae_assert(apservisfinitematrix(cmatrix, k, m+1, _state), "LSFitLinearC: CMatrix contains infinite or NaN values!", _state);
19985  ae_vector_set_length(&w, n, _state);
19986  for(i=0; i<=n-1; i++)
19987  {
19988  w.ptr.p_double[i] = 1;
19989  }
19990  lsfitlinearwc(y, &w, fmatrix, cmatrix, n, m, k, info, c, rep, _state);
19991  ae_frame_leave(_state);
19992 }
19993 
19994 
19995 /*************************************************************************
19996 Weighted nonlinear least squares fitting using function values only.
19997 
19998 Combination of numerical differentiation and secant updates is used to
19999 obtain function Jacobian.
20000 
20001 Nonlinear task min(F(c)) is solved, where
20002 
20003  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
20004 
20005  * N is a number of points,
20006  * M is a dimension of a space points belong to,
20007  * K is a dimension of a space of parameters being fitted,
20008  * w is an N-dimensional vector of weight coefficients,
20009  * x is a set of N points, each of them is an M-dimensional vector,
20010  * c is a K-dimensional vector of parameters being fitted
20011 
20012 This subroutine uses only f(c,x[i]).
20013 
20014 INPUT PARAMETERS:
20015  X - array[0..N-1,0..M-1], points (one row = one point)
20016  Y - array[0..N-1], function values.
20017  W - weights, array[0..N-1]
20018  C - array[0..K-1], initial approximation to the solution,
20019  N - number of points, N>1
20020  M - dimension of space
20021  K - number of parameters being fitted
20022  DiffStep- numerical differentiation step;
20023  should not be very small or large;
20024  large = loss of accuracy
20025  small = growth of round-off errors
20026 
20027 OUTPUT PARAMETERS:
20028  State - structure which stores algorithm state
20029 
20030  -- ALGLIB --
20031  Copyright 18.10.2008 by Bochkanov Sergey
20032 *************************************************************************/
20033 void lsfitcreatewf(/* Real */ ae_matrix* x,
20034  /* Real */ ae_vector* y,
20035  /* Real */ ae_vector* w,
20036  /* Real */ ae_vector* c,
20037  ae_int_t n,
20038  ae_int_t m,
20039  ae_int_t k,
20040  double diffstep,
20041  lsfitstate* state,
20042  ae_state *_state)
20043 {
20044  ae_int_t i;
20045 
20046  _lsfitstate_clear(state);
20047 
20048  ae_assert(n>=1, "LSFitCreateWF: N<1!", _state);
20049  ae_assert(m>=1, "LSFitCreateWF: M<1!", _state);
20050  ae_assert(k>=1, "LSFitCreateWF: K<1!", _state);
20051  ae_assert(c->cnt>=k, "LSFitCreateWF: length(C)<K!", _state);
20052  ae_assert(isfinitevector(c, k, _state), "LSFitCreateWF: C contains infinite or NaN values!", _state);
20053  ae_assert(y->cnt>=n, "LSFitCreateWF: length(Y)<N!", _state);
20054  ae_assert(isfinitevector(y, n, _state), "LSFitCreateWF: Y contains infinite or NaN values!", _state);
20055  ae_assert(w->cnt>=n, "LSFitCreateWF: length(W)<N!", _state);
20056  ae_assert(isfinitevector(w, n, _state), "LSFitCreateWF: W contains infinite or NaN values!", _state);
20057  ae_assert(x->rows>=n, "LSFitCreateWF: rows(X)<N!", _state);
20058  ae_assert(x->cols>=m, "LSFitCreateWF: cols(X)<M!", _state);
20059  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateWF: X contains infinite or NaN values!", _state);
20060  ae_assert(ae_isfinite(diffstep, _state), "LSFitCreateWF: DiffStep is not finite!", _state);
20061  ae_assert(ae_fp_greater(diffstep,0), "LSFitCreateWF: DiffStep<=0!", _state);
20062  state->teststep = 0;
20063  state->diffstep = diffstep;
20064  state->npoints = n;
20065  state->nweights = n;
20066  state->wkind = 1;
20067  state->m = m;
20068  state->k = k;
20069  lsfitsetcond(state, 0.0, 0.0, 0, _state);
20070  lsfitsetstpmax(state, 0.0, _state);
20071  lsfitsetxrep(state, ae_false, _state);
20072  ae_matrix_set_length(&state->taskx, n, m, _state);
20073  ae_vector_set_length(&state->tasky, n, _state);
20074  ae_vector_set_length(&state->taskw, n, _state);
20075  ae_vector_set_length(&state->c, k, _state);
20076  ae_vector_set_length(&state->x, m, _state);
20077  ae_v_move(&state->c.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
20078  ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
20079  for(i=0; i<=n-1; i++)
20080  {
20081  ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
20082  state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
20083  }
20084  ae_vector_set_length(&state->s, k, _state);
20085  ae_vector_set_length(&state->bndl, k, _state);
20086  ae_vector_set_length(&state->bndu, k, _state);
20087  for(i=0; i<=k-1; i++)
20088  {
20089  state->s.ptr.p_double[i] = 1.0;
20090  state->bndl.ptr.p_double[i] = _state->v_neginf;
20091  state->bndu.ptr.p_double[i] = _state->v_posinf;
20092  }
20093  state->optalgo = 0;
20094  state->prevnpt = -1;
20095  state->prevalgo = -1;
20096  minlmcreatev(k, n, &state->c, diffstep, &state->optstate, _state);
20097  lsfit_lsfitclearrequestfields(state, _state);
20098  ae_vector_set_length(&state->rstate.ia, 6+1, _state);
20099  ae_vector_set_length(&state->rstate.ra, 8+1, _state);
20100  state->rstate.stage = -1;
20101 }
20102 
20103 
20104 /*************************************************************************
20105 Nonlinear least squares fitting using function values only.
20106 
20107 Combination of numerical differentiation and secant updates is used to
20108 obtain function Jacobian.
20109 
20110 Nonlinear task min(F(c)) is solved, where
20111 
20112  F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2,
20113 
20114  * N is a number of points,
20115  * M is a dimension of a space points belong to,
20116  * K is a dimension of a space of parameters being fitted,
20117  * w is an N-dimensional vector of weight coefficients,
20118  * x is a set of N points, each of them is an M-dimensional vector,
20119  * c is a K-dimensional vector of parameters being fitted
20120 
20121 This subroutine uses only f(c,x[i]).
20122 
20123 INPUT PARAMETERS:
20124  X - array[0..N-1,0..M-1], points (one row = one point)
20125  Y - array[0..N-1], function values.
20126  C - array[0..K-1], initial approximation to the solution,
20127  N - number of points, N>1
20128  M - dimension of space
20129  K - number of parameters being fitted
20130  DiffStep- numerical differentiation step;
20131  should not be very small or large;
20132  large = loss of accuracy
20133  small = growth of round-off errors
20134 
20135 OUTPUT PARAMETERS:
20136  State - structure which stores algorithm state
20137 
20138  -- ALGLIB --
20139  Copyright 18.10.2008 by Bochkanov Sergey
20140 *************************************************************************/
20141 void lsfitcreatef(/* Real */ ae_matrix* x,
20142  /* Real */ ae_vector* y,
20143  /* Real */ ae_vector* c,
20144  ae_int_t n,
20145  ae_int_t m,
20146  ae_int_t k,
20147  double diffstep,
20148  lsfitstate* state,
20149  ae_state *_state)
20150 {
20151  ae_int_t i;
20152 
20153  _lsfitstate_clear(state);
20154 
20155  ae_assert(n>=1, "LSFitCreateF: N<1!", _state);
20156  ae_assert(m>=1, "LSFitCreateF: M<1!", _state);
20157  ae_assert(k>=1, "LSFitCreateF: K<1!", _state);
20158  ae_assert(c->cnt>=k, "LSFitCreateF: length(C)<K!", _state);
20159  ae_assert(isfinitevector(c, k, _state), "LSFitCreateF: C contains infinite or NaN values!", _state);
20160  ae_assert(y->cnt>=n, "LSFitCreateF: length(Y)<N!", _state);
20161  ae_assert(isfinitevector(y, n, _state), "LSFitCreateF: Y contains infinite or NaN values!", _state);
20162  ae_assert(x->rows>=n, "LSFitCreateF: rows(X)<N!", _state);
20163  ae_assert(x->cols>=m, "LSFitCreateF: cols(X)<M!", _state);
20164  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateF: X contains infinite or NaN values!", _state);
20165  ae_assert(x->rows>=n, "LSFitCreateF: rows(X)<N!", _state);
20166  ae_assert(x->cols>=m, "LSFitCreateF: cols(X)<M!", _state);
20167  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateF: X contains infinite or NaN values!", _state);
20168  ae_assert(ae_isfinite(diffstep, _state), "LSFitCreateF: DiffStep is not finite!", _state);
20169  ae_assert(ae_fp_greater(diffstep,0), "LSFitCreateF: DiffStep<=0!", _state);
20170  state->teststep = 0;
20171  state->diffstep = diffstep;
20172  state->npoints = n;
20173  state->wkind = 0;
20174  state->m = m;
20175  state->k = k;
20176  lsfitsetcond(state, 0.0, 0.0, 0, _state);
20177  lsfitsetstpmax(state, 0.0, _state);
20178  lsfitsetxrep(state, ae_false, _state);
20179  ae_matrix_set_length(&state->taskx, n, m, _state);
20180  ae_vector_set_length(&state->tasky, n, _state);
20181  ae_vector_set_length(&state->c, k, _state);
20182  ae_vector_set_length(&state->x, m, _state);
20183  ae_v_move(&state->c.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
20184  for(i=0; i<=n-1; i++)
20185  {
20186  ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
20187  state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
20188  }
20189  ae_vector_set_length(&state->s, k, _state);
20190  ae_vector_set_length(&state->bndl, k, _state);
20191  ae_vector_set_length(&state->bndu, k, _state);
20192  for(i=0; i<=k-1; i++)
20193  {
20194  state->s.ptr.p_double[i] = 1.0;
20195  state->bndl.ptr.p_double[i] = _state->v_neginf;
20196  state->bndu.ptr.p_double[i] = _state->v_posinf;
20197  }
20198  state->optalgo = 0;
20199  state->prevnpt = -1;
20200  state->prevalgo = -1;
20201  minlmcreatev(k, n, &state->c, diffstep, &state->optstate, _state);
20202  lsfit_lsfitclearrequestfields(state, _state);
20203  ae_vector_set_length(&state->rstate.ia, 6+1, _state);
20204  ae_vector_set_length(&state->rstate.ra, 8+1, _state);
20205  state->rstate.stage = -1;
20206 }
20207 
20208 
20209 /*************************************************************************
20210 Weighted nonlinear least squares fitting using gradient only.
20211 
20212 Nonlinear task min(F(c)) is solved, where
20213 
20214  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
20215 
20216  * N is a number of points,
20217  * M is a dimension of a space points belong to,
20218  * K is a dimension of a space of parameters being fitted,
20219  * w is an N-dimensional vector of weight coefficients,
20220  * x is a set of N points, each of them is an M-dimensional vector,
20221  * c is a K-dimensional vector of parameters being fitted
20222 
20223 This subroutine uses only f(c,x[i]) and its gradient.
20224 
20225 INPUT PARAMETERS:
20226  X - array[0..N-1,0..M-1], points (one row = one point)
20227  Y - array[0..N-1], function values.
20228  W - weights, array[0..N-1]
20229  C - array[0..K-1], initial approximation to the solution,
20230  N - number of points, N>1
20231  M - dimension of space
20232  K - number of parameters being fitted
20233  CheapFG - boolean flag, which is:
20234  * True if both function and gradient calculation complexity
20235  are less than O(M^2). An improved algorithm can
20236  be used which corresponds to FGJ scheme from
20237  MINLM unit.
20238  * False otherwise.
20239  Standard Jacibian-bases Levenberg-Marquardt algo
20240  will be used (FJ scheme).
20241 
20242 OUTPUT PARAMETERS:
20243  State - structure which stores algorithm state
20244 
20245 See also:
20246  LSFitResults
20247  LSFitCreateFG (fitting without weights)
20248  LSFitCreateWFGH (fitting using Hessian)
20249  LSFitCreateFGH (fitting using Hessian, without weights)
20250 
20251  -- ALGLIB --
20252  Copyright 17.08.2009 by Bochkanov Sergey
20253 *************************************************************************/
20254 void lsfitcreatewfg(/* Real */ ae_matrix* x,
20255  /* Real */ ae_vector* y,
20256  /* Real */ ae_vector* w,
20257  /* Real */ ae_vector* c,
20258  ae_int_t n,
20259  ae_int_t m,
20260  ae_int_t k,
20261  ae_bool cheapfg,
20262  lsfitstate* state,
20263  ae_state *_state)
20264 {
20265  ae_int_t i;
20266 
20267  _lsfitstate_clear(state);
20268 
20269  ae_assert(n>=1, "LSFitCreateWFG: N<1!", _state);
20270  ae_assert(m>=1, "LSFitCreateWFG: M<1!", _state);
20271  ae_assert(k>=1, "LSFitCreateWFG: K<1!", _state);
20272  ae_assert(c->cnt>=k, "LSFitCreateWFG: length(C)<K!", _state);
20273  ae_assert(isfinitevector(c, k, _state), "LSFitCreateWFG: C contains infinite or NaN values!", _state);
20274  ae_assert(y->cnt>=n, "LSFitCreateWFG: length(Y)<N!", _state);
20275  ae_assert(isfinitevector(y, n, _state), "LSFitCreateWFG: Y contains infinite or NaN values!", _state);
20276  ae_assert(w->cnt>=n, "LSFitCreateWFG: length(W)<N!", _state);
20277  ae_assert(isfinitevector(w, n, _state), "LSFitCreateWFG: W contains infinite or NaN values!", _state);
20278  ae_assert(x->rows>=n, "LSFitCreateWFG: rows(X)<N!", _state);
20279  ae_assert(x->cols>=m, "LSFitCreateWFG: cols(X)<M!", _state);
20280  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateWFG: X contains infinite or NaN values!", _state);
20281  state->teststep = 0;
20282  state->diffstep = 0;
20283  state->npoints = n;
20284  state->nweights = n;
20285  state->wkind = 1;
20286  state->m = m;
20287  state->k = k;
20288  lsfitsetcond(state, 0.0, 0.0, 0, _state);
20289  lsfitsetstpmax(state, 0.0, _state);
20290  lsfitsetxrep(state, ae_false, _state);
20291  ae_matrix_set_length(&state->taskx, n, m, _state);
20292  ae_vector_set_length(&state->tasky, n, _state);
20293  ae_vector_set_length(&state->taskw, n, _state);
20294  ae_vector_set_length(&state->c, k, _state);
20295  ae_vector_set_length(&state->x, m, _state);
20296  ae_vector_set_length(&state->g, k, _state);
20297  ae_v_move(&state->c.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
20298  ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
20299  for(i=0; i<=n-1; i++)
20300  {
20301  ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
20302  state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
20303  }
20304  ae_vector_set_length(&state->s, k, _state);
20305  ae_vector_set_length(&state->bndl, k, _state);
20306  ae_vector_set_length(&state->bndu, k, _state);
20307  for(i=0; i<=k-1; i++)
20308  {
20309  state->s.ptr.p_double[i] = 1.0;
20310  state->bndl.ptr.p_double[i] = _state->v_neginf;
20311  state->bndu.ptr.p_double[i] = _state->v_posinf;
20312  }
20313  state->optalgo = 1;
20314  state->prevnpt = -1;
20315  state->prevalgo = -1;
20316  if( cheapfg )
20317  {
20318  minlmcreatevgj(k, n, &state->c, &state->optstate, _state);
20319  }
20320  else
20321  {
20322  minlmcreatevj(k, n, &state->c, &state->optstate, _state);
20323  }
20324  lsfit_lsfitclearrequestfields(state, _state);
20325  ae_vector_set_length(&state->rstate.ia, 6+1, _state);
20326  ae_vector_set_length(&state->rstate.ra, 8+1, _state);
20327  state->rstate.stage = -1;
20328 }
20329 
20330 
20331 /*************************************************************************
20332 Nonlinear least squares fitting using gradient only, without individual
20333 weights.
20334 
20335 Nonlinear task min(F(c)) is solved, where
20336 
20337  F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
20338 
20339  * N is a number of points,
20340  * M is a dimension of a space points belong to,
20341  * K is a dimension of a space of parameters being fitted,
20342  * x is a set of N points, each of them is an M-dimensional vector,
20343  * c is a K-dimensional vector of parameters being fitted
20344 
20345 This subroutine uses only f(c,x[i]) and its gradient.
20346 
20347 INPUT PARAMETERS:
20348  X - array[0..N-1,0..M-1], points (one row = one point)
20349  Y - array[0..N-1], function values.
20350  C - array[0..K-1], initial approximation to the solution,
20351  N - number of points, N>1
20352  M - dimension of space
20353  K - number of parameters being fitted
20354  CheapFG - boolean flag, which is:
20355  * True if both function and gradient calculation complexity
20356  are less than O(M^2). An improved algorithm can
20357  be used which corresponds to FGJ scheme from
20358  MINLM unit.
20359  * False otherwise.
20360  Standard Jacibian-bases Levenberg-Marquardt algo
20361  will be used (FJ scheme).
20362 
20363 OUTPUT PARAMETERS:
20364  State - structure which stores algorithm state
20365 
20366  -- ALGLIB --
20367  Copyright 17.08.2009 by Bochkanov Sergey
20368 *************************************************************************/
20369 void lsfitcreatefg(/* Real */ ae_matrix* x,
20370  /* Real */ ae_vector* y,
20371  /* Real */ ae_vector* c,
20372  ae_int_t n,
20373  ae_int_t m,
20374  ae_int_t k,
20375  ae_bool cheapfg,
20376  lsfitstate* state,
20377  ae_state *_state)
20378 {
20379  ae_int_t i;
20380 
20381  _lsfitstate_clear(state);
20382 
20383  ae_assert(n>=1, "LSFitCreateFG: N<1!", _state);
20384  ae_assert(m>=1, "LSFitCreateFG: M<1!", _state);
20385  ae_assert(k>=1, "LSFitCreateFG: K<1!", _state);
20386  ae_assert(c->cnt>=k, "LSFitCreateFG: length(C)<K!", _state);
20387  ae_assert(isfinitevector(c, k, _state), "LSFitCreateFG: C contains infinite or NaN values!", _state);
20388  ae_assert(y->cnt>=n, "LSFitCreateFG: length(Y)<N!", _state);
20389  ae_assert(isfinitevector(y, n, _state), "LSFitCreateFG: Y contains infinite or NaN values!", _state);
20390  ae_assert(x->rows>=n, "LSFitCreateFG: rows(X)<N!", _state);
20391  ae_assert(x->cols>=m, "LSFitCreateFG: cols(X)<M!", _state);
20392  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateFG: X contains infinite or NaN values!", _state);
20393  ae_assert(x->rows>=n, "LSFitCreateFG: rows(X)<N!", _state);
20394  ae_assert(x->cols>=m, "LSFitCreateFG: cols(X)<M!", _state);
20395  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateFG: X contains infinite or NaN values!", _state);
20396  state->teststep = 0;
20397  state->diffstep = 0;
20398  state->npoints = n;
20399  state->wkind = 0;
20400  state->m = m;
20401  state->k = k;
20402  lsfitsetcond(state, 0.0, 0.0, 0, _state);
20403  lsfitsetstpmax(state, 0.0, _state);
20404  lsfitsetxrep(state, ae_false, _state);
20405  ae_matrix_set_length(&state->taskx, n, m, _state);
20406  ae_vector_set_length(&state->tasky, n, _state);
20407  ae_vector_set_length(&state->c, k, _state);
20408  ae_vector_set_length(&state->x, m, _state);
20409  ae_vector_set_length(&state->g, k, _state);
20410  ae_v_move(&state->c.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
20411  for(i=0; i<=n-1; i++)
20412  {
20413  ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
20414  state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
20415  }
20416  ae_vector_set_length(&state->s, k, _state);
20417  ae_vector_set_length(&state->bndl, k, _state);
20418  ae_vector_set_length(&state->bndu, k, _state);
20419  for(i=0; i<=k-1; i++)
20420  {
20421  state->s.ptr.p_double[i] = 1.0;
20422  state->bndl.ptr.p_double[i] = _state->v_neginf;
20423  state->bndu.ptr.p_double[i] = _state->v_posinf;
20424  }
20425  state->optalgo = 1;
20426  state->prevnpt = -1;
20427  state->prevalgo = -1;
20428  if( cheapfg )
20429  {
20430  minlmcreatevgj(k, n, &state->c, &state->optstate, _state);
20431  }
20432  else
20433  {
20434  minlmcreatevj(k, n, &state->c, &state->optstate, _state);
20435  }
20436  lsfit_lsfitclearrequestfields(state, _state);
20437  ae_vector_set_length(&state->rstate.ia, 6+1, _state);
20438  ae_vector_set_length(&state->rstate.ra, 8+1, _state);
20439  state->rstate.stage = -1;
20440 }
20441 
20442 
20443 /*************************************************************************
20444 Weighted nonlinear least squares fitting using gradient/Hessian.
20445 
20446 Nonlinear task min(F(c)) is solved, where
20447 
20448  F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2,
20449 
20450  * N is a number of points,
20451  * M is a dimension of a space points belong to,
20452  * K is a dimension of a space of parameters being fitted,
20453  * w is an N-dimensional vector of weight coefficients,
20454  * x is a set of N points, each of them is an M-dimensional vector,
20455  * c is a K-dimensional vector of parameters being fitted
20456 
20457 This subroutine uses f(c,x[i]), its gradient and its Hessian.
20458 
20459 INPUT PARAMETERS:
20460  X - array[0..N-1,0..M-1], points (one row = one point)
20461  Y - array[0..N-1], function values.
20462  W - weights, array[0..N-1]
20463  C - array[0..K-1], initial approximation to the solution,
20464  N - number of points, N>1
20465  M - dimension of space
20466  K - number of parameters being fitted
20467 
20468 OUTPUT PARAMETERS:
20469  State - structure which stores algorithm state
20470 
20471  -- ALGLIB --
20472  Copyright 17.08.2009 by Bochkanov Sergey
20473 *************************************************************************/
20474 void lsfitcreatewfgh(/* Real */ ae_matrix* x,
20475  /* Real */ ae_vector* y,
20476  /* Real */ ae_vector* w,
20477  /* Real */ ae_vector* c,
20478  ae_int_t n,
20479  ae_int_t m,
20480  ae_int_t k,
20481  lsfitstate* state,
20482  ae_state *_state)
20483 {
20484  ae_int_t i;
20485 
20486  _lsfitstate_clear(state);
20487 
20488  ae_assert(n>=1, "LSFitCreateWFGH: N<1!", _state);
20489  ae_assert(m>=1, "LSFitCreateWFGH: M<1!", _state);
20490  ae_assert(k>=1, "LSFitCreateWFGH: K<1!", _state);
20491  ae_assert(c->cnt>=k, "LSFitCreateWFGH: length(C)<K!", _state);
20492  ae_assert(isfinitevector(c, k, _state), "LSFitCreateWFGH: C contains infinite or NaN values!", _state);
20493  ae_assert(y->cnt>=n, "LSFitCreateWFGH: length(Y)<N!", _state);
20494  ae_assert(isfinitevector(y, n, _state), "LSFitCreateWFGH: Y contains infinite or NaN values!", _state);
20495  ae_assert(w->cnt>=n, "LSFitCreateWFGH: length(W)<N!", _state);
20496  ae_assert(isfinitevector(w, n, _state), "LSFitCreateWFGH: W contains infinite or NaN values!", _state);
20497  ae_assert(x->rows>=n, "LSFitCreateWFGH: rows(X)<N!", _state);
20498  ae_assert(x->cols>=m, "LSFitCreateWFGH: cols(X)<M!", _state);
20499  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateWFGH: X contains infinite or NaN values!", _state);
20500  state->teststep = 0;
20501  state->diffstep = 0;
20502  state->npoints = n;
20503  state->nweights = n;
20504  state->wkind = 1;
20505  state->m = m;
20506  state->k = k;
20507  lsfitsetcond(state, 0.0, 0.0, 0, _state);
20508  lsfitsetstpmax(state, 0.0, _state);
20509  lsfitsetxrep(state, ae_false, _state);
20510  ae_matrix_set_length(&state->taskx, n, m, _state);
20511  ae_vector_set_length(&state->tasky, n, _state);
20512  ae_vector_set_length(&state->taskw, n, _state);
20513  ae_vector_set_length(&state->c, k, _state);
20514  ae_matrix_set_length(&state->h, k, k, _state);
20515  ae_vector_set_length(&state->x, m, _state);
20516  ae_vector_set_length(&state->g, k, _state);
20517  ae_v_move(&state->c.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
20518  ae_v_move(&state->taskw.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
20519  for(i=0; i<=n-1; i++)
20520  {
20521  ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
20522  state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
20523  }
20524  ae_vector_set_length(&state->s, k, _state);
20525  ae_vector_set_length(&state->bndl, k, _state);
20526  ae_vector_set_length(&state->bndu, k, _state);
20527  for(i=0; i<=k-1; i++)
20528  {
20529  state->s.ptr.p_double[i] = 1.0;
20530  state->bndl.ptr.p_double[i] = _state->v_neginf;
20531  state->bndu.ptr.p_double[i] = _state->v_posinf;
20532  }
20533  state->optalgo = 2;
20534  state->prevnpt = -1;
20535  state->prevalgo = -1;
20536  minlmcreatefgh(k, &state->c, &state->optstate, _state);
20537  lsfit_lsfitclearrequestfields(state, _state);
20538  ae_vector_set_length(&state->rstate.ia, 6+1, _state);
20539  ae_vector_set_length(&state->rstate.ra, 8+1, _state);
20540  state->rstate.stage = -1;
20541 }
20542 
20543 
20544 /*************************************************************************
20545 Nonlinear least squares fitting using gradient/Hessian, without individial
20546 weights.
20547 
20548 Nonlinear task min(F(c)) is solved, where
20549 
20550  F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,
20551 
20552  * N is a number of points,
20553  * M is a dimension of a space points belong to,
20554  * K is a dimension of a space of parameters being fitted,
20555  * x is a set of N points, each of them is an M-dimensional vector,
20556  * c is a K-dimensional vector of parameters being fitted
20557 
20558 This subroutine uses f(c,x[i]), its gradient and its Hessian.
20559 
20560 INPUT PARAMETERS:
20561  X - array[0..N-1,0..M-1], points (one row = one point)
20562  Y - array[0..N-1], function values.
20563  C - array[0..K-1], initial approximation to the solution,
20564  N - number of points, N>1
20565  M - dimension of space
20566  K - number of parameters being fitted
20567 
20568 OUTPUT PARAMETERS:
20569  State - structure which stores algorithm state
20570 
20571 
20572  -- ALGLIB --
20573  Copyright 17.08.2009 by Bochkanov Sergey
20574 *************************************************************************/
20575 void lsfitcreatefgh(/* Real */ ae_matrix* x,
20576  /* Real */ ae_vector* y,
20577  /* Real */ ae_vector* c,
20578  ae_int_t n,
20579  ae_int_t m,
20580  ae_int_t k,
20581  lsfitstate* state,
20582  ae_state *_state)
20583 {
20584  ae_int_t i;
20585 
20586  _lsfitstate_clear(state);
20587 
20588  ae_assert(n>=1, "LSFitCreateFGH: N<1!", _state);
20589  ae_assert(m>=1, "LSFitCreateFGH: M<1!", _state);
20590  ae_assert(k>=1, "LSFitCreateFGH: K<1!", _state);
20591  ae_assert(c->cnt>=k, "LSFitCreateFGH: length(C)<K!", _state);
20592  ae_assert(isfinitevector(c, k, _state), "LSFitCreateFGH: C contains infinite or NaN values!", _state);
20593  ae_assert(y->cnt>=n, "LSFitCreateFGH: length(Y)<N!", _state);
20594  ae_assert(isfinitevector(y, n, _state), "LSFitCreateFGH: Y contains infinite or NaN values!", _state);
20595  ae_assert(x->rows>=n, "LSFitCreateFGH: rows(X)<N!", _state);
20596  ae_assert(x->cols>=m, "LSFitCreateFGH: cols(X)<M!", _state);
20597  ae_assert(apservisfinitematrix(x, n, m, _state), "LSFitCreateFGH: X contains infinite or NaN values!", _state);
20598  state->teststep = 0;
20599  state->diffstep = 0;
20600  state->npoints = n;
20601  state->wkind = 0;
20602  state->m = m;
20603  state->k = k;
20604  lsfitsetcond(state, 0.0, 0.0, 0, _state);
20605  lsfitsetstpmax(state, 0.0, _state);
20606  lsfitsetxrep(state, ae_false, _state);
20607  ae_matrix_set_length(&state->taskx, n, m, _state);
20608  ae_vector_set_length(&state->tasky, n, _state);
20609  ae_vector_set_length(&state->c, k, _state);
20610  ae_matrix_set_length(&state->h, k, k, _state);
20611  ae_vector_set_length(&state->x, m, _state);
20612  ae_vector_set_length(&state->g, k, _state);
20613  ae_v_move(&state->c.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,k-1));
20614  for(i=0; i<=n-1; i++)
20615  {
20616  ae_v_move(&state->taskx.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
20617  state->tasky.ptr.p_double[i] = y->ptr.p_double[i];
20618  }
20619  ae_vector_set_length(&state->s, k, _state);
20620  ae_vector_set_length(&state->bndl, k, _state);
20621  ae_vector_set_length(&state->bndu, k, _state);
20622  for(i=0; i<=k-1; i++)
20623  {
20624  state->s.ptr.p_double[i] = 1.0;
20625  state->bndl.ptr.p_double[i] = _state->v_neginf;
20626  state->bndu.ptr.p_double[i] = _state->v_posinf;
20627  }
20628  state->optalgo = 2;
20629  state->prevnpt = -1;
20630  state->prevalgo = -1;
20631  minlmcreatefgh(k, &state->c, &state->optstate, _state);
20632  lsfit_lsfitclearrequestfields(state, _state);
20633  ae_vector_set_length(&state->rstate.ia, 6+1, _state);
20634  ae_vector_set_length(&state->rstate.ra, 8+1, _state);
20635  state->rstate.stage = -1;
20636 }
20637 
20638 
20639 /*************************************************************************
20640 Stopping conditions for nonlinear least squares fitting.
20641 
20642 INPUT PARAMETERS:
20643  State - structure which stores algorithm state
20644  EpsF - stopping criterion. Algorithm stops if
20645  |F(k+1)-F(k)| <= EpsF*max{|F(k)|, |F(k+1)|, 1}
20646  EpsX - >=0
20647  The subroutine finishes its work if on k+1-th iteration
20648  the condition |v|<=EpsX is fulfilled, where:
20649  * |.| means Euclidian norm
20650  * v - scaled step vector, v[i]=dx[i]/s[i]
20651  * dx - ste pvector, dx=X(k+1)-X(k)
20652  * s - scaling coefficients set by LSFitSetScale()
20653  MaxIts - maximum number of iterations. If MaxIts=0, the number of
20654  iterations is unlimited. Only Levenberg-Marquardt
20655  iterations are counted (L-BFGS/CG iterations are NOT
20656  counted because their cost is very low compared to that of
20657  LM).
20658 
20659 NOTE
20660 
20661 Passing EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
20662 stopping criterion selection (according to the scheme used by MINLM unit).
20663 
20664 
20665  -- ALGLIB --
20666  Copyright 17.08.2009 by Bochkanov Sergey
20667 *************************************************************************/
20668 void lsfitsetcond(lsfitstate* state,
20669  double epsf,
20670  double epsx,
20671  ae_int_t maxits,
20672  ae_state *_state)
20673 {
20674 
20675 
20676  ae_assert(ae_isfinite(epsf, _state), "LSFitSetCond: EpsF is not finite!", _state);
20677  ae_assert(ae_fp_greater_eq(epsf,0), "LSFitSetCond: negative EpsF!", _state);
20678  ae_assert(ae_isfinite(epsx, _state), "LSFitSetCond: EpsX is not finite!", _state);
20679  ae_assert(ae_fp_greater_eq(epsx,0), "LSFitSetCond: negative EpsX!", _state);
20680  ae_assert(maxits>=0, "LSFitSetCond: negative MaxIts!", _state);
20681  state->epsf = epsf;
20682  state->epsx = epsx;
20683  state->maxits = maxits;
20684 }
20685 
20686 
20687 /*************************************************************************
20688 This function sets maximum step length
20689 
20690 INPUT PARAMETERS:
20691  State - structure which stores algorithm state
20692  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
20693  want to limit step length.
20694 
20695 Use this subroutine when you optimize target function which contains exp()
20696 or other fast growing functions, and optimization algorithm makes too
20697 large steps which leads to overflow. This function allows us to reject
20698 steps that are too large (and therefore expose us to the possible
20699 overflow) without actually calculating function value at the x+stp*d.
20700 
20701 NOTE: non-zero StpMax leads to moderate performance degradation because
20702 intermediate step of preconditioned L-BFGS optimization is incompatible
20703 with limits on step size.
20704 
20705  -- ALGLIB --
20706  Copyright 02.04.2010 by Bochkanov Sergey
20707 *************************************************************************/
20708 void lsfitsetstpmax(lsfitstate* state, double stpmax, ae_state *_state)
20709 {
20710 
20711 
20712  ae_assert(ae_fp_greater_eq(stpmax,0), "LSFitSetStpMax: StpMax<0!", _state);
20713  state->stpmax = stpmax;
20714 }
20715 
20716 
20717 /*************************************************************************
20718 This function turns on/off reporting.
20719 
20720 INPUT PARAMETERS:
20721  State - structure which stores algorithm state
20722  NeedXRep- whether iteration reports are needed or not
20723 
20724 When reports are needed, State.C (current parameters) and State.F (current
20725 value of fitting function) are reported.
20726 
20727 
20728  -- ALGLIB --
20729  Copyright 15.08.2010 by Bochkanov Sergey
20730 *************************************************************************/
20731 void lsfitsetxrep(lsfitstate* state, ae_bool needxrep, ae_state *_state)
20732 {
20733 
20734 
20735  state->xrep = needxrep;
20736 }
20737 
20738 
20739 /*************************************************************************
20740 This function sets scaling coefficients for underlying optimizer.
20741 
20742 ALGLIB optimizers use scaling matrices to test stopping conditions (step
20743 size and gradient are scaled before comparison with tolerances). Scale of
20744 the I-th variable is a translation invariant measure of:
20745 a) "how large" the variable is
20746 b) how large the step should be to make significant changes in the function
20747 
20748 Generally, scale is NOT considered to be a form of preconditioner. But LM
20749 optimizer is unique in that it uses scaling matrix both in the stopping
20750 condition tests and as Marquardt damping factor.
20751 
20752 Proper scaling is very important for the algorithm performance. It is less
20753 important for the quality of results, but still has some influence (it is
20754 easier to converge when variables are properly scaled, so premature
20755 stopping is possible when very badly scalled variables are combined with
20756 relaxed stopping conditions).
20757 
20758 INPUT PARAMETERS:
20759  State - structure stores algorithm state
20760  S - array[N], non-zero scaling coefficients
20761  S[i] may be negative, sign doesn't matter.
20762 
20763  -- ALGLIB --
20764  Copyright 14.01.2011 by Bochkanov Sergey
20765 *************************************************************************/
20766 void lsfitsetscale(lsfitstate* state,
20767  /* Real */ ae_vector* s,
20768  ae_state *_state)
20769 {
20770  ae_int_t i;
20771 
20772 
20773  ae_assert(s->cnt>=state->k, "LSFitSetScale: Length(S)<K", _state);
20774  for(i=0; i<=state->k-1; i++)
20775  {
20776  ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "LSFitSetScale: S contains infinite or NAN elements", _state);
20777  ae_assert(ae_fp_neq(s->ptr.p_double[i],0), "LSFitSetScale: S contains infinite or NAN elements", _state);
20778  state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
20779  }
20780 }
20781 
20782 
20783 /*************************************************************************
20784 This function sets boundary constraints for underlying optimizer
20785 
20786 Boundary constraints are inactive by default (after initial creation).
20787 They are preserved until explicitly turned off with another SetBC() call.
20788 
20789 INPUT PARAMETERS:
20790  State - structure stores algorithm state
20791  BndL - lower bounds, array[K].
20792  If some (all) variables are unbounded, you may specify
20793  very small number or -INF (latter is recommended because
20794  it will allow solver to use better algorithm).
20795  BndU - upper bounds, array[K].
20796  If some (all) variables are unbounded, you may specify
20797  very large number or +INF (latter is recommended because
20798  it will allow solver to use better algorithm).
20799 
20800 NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
20801 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
20802 
20803 NOTE 2: unlike other constrained optimization algorithms, this solver has
20804 following useful properties:
20805 * bound constraints are always satisfied exactly
20806 * function is evaluated only INSIDE area specified by bound constraints
20807 
20808  -- ALGLIB --
20809  Copyright 14.01.2011 by Bochkanov Sergey
20810 *************************************************************************/
20811 void lsfitsetbc(lsfitstate* state,
20812  /* Real */ ae_vector* bndl,
20813  /* Real */ ae_vector* bndu,
20814  ae_state *_state)
20815 {
20816  ae_int_t i;
20817  ae_int_t k;
20818 
20819 
20820  k = state->k;
20821  ae_assert(bndl->cnt>=k, "LSFitSetBC: Length(BndL)<K", _state);
20822  ae_assert(bndu->cnt>=k, "LSFitSetBC: Length(BndU)<K", _state);
20823  for(i=0; i<=k-1; i++)
20824  {
20825  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);
20826  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);
20827  if( ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state) )
20828  {
20829  ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "LSFitSetBC: BndL[i]>BndU[i]", _state);
20830  }
20831  state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
20832  state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
20833  }
20834 }
20835 
20836 
20837 /*************************************************************************
20838 NOTES:
20839 
20840 1. this algorithm is somewhat unusual because it works with parameterized
20841  function f(C,X), where X is a function argument (we have many points
20842  which are characterized by different argument values), and C is a
20843  parameter to fit.
20844 
20845  For example, if we want to do linear fit by f(c0,c1,x) = c0*x+c1, then
20846  x will be argument, and {c0,c1} will be parameters.
20847 
20848  It is important to understand that this algorithm finds minimum in the
20849  space of function PARAMETERS (not arguments), so it needs derivatives
20850  of f() with respect to C, not X.
20851 
20852  In the example above it will need f=c0*x+c1 and {df/dc0,df/dc1} = {x,1}
20853  instead of {df/dx} = {c0}.
20854 
20855 2. Callback functions accept C as the first parameter, and X as the second
20856 
20857 3. If state was created with LSFitCreateFG(), algorithm needs just
20858  function and its gradient, but if state was created with
20859  LSFitCreateFGH(), algorithm will need function, gradient and Hessian.
20860 
20861  According to the said above, there ase several versions of this
20862  function, which accept different sets of callbacks.
20863 
20864  This flexibility opens way to subtle errors - you may create state with
20865  LSFitCreateFGH() (optimization using Hessian), but call function which
20866  does not accept Hessian. So when algorithm will request Hessian, there
20867  will be no callback to call. In this case exception will be thrown.
20868 
20869  Be careful to avoid such errors because there is no way to find them at
20870  compile time - you can see them at runtime only.
20871 
20872  -- ALGLIB --
20873  Copyright 17.08.2009 by Bochkanov Sergey
20874 *************************************************************************/
20875 ae_bool lsfititeration(lsfitstate* state, ae_state *_state)
20876 {
20877  double lx;
20878  double lf;
20879  double ld;
20880  double rx;
20881  double rf;
20882  double rd;
20883  ae_int_t n;
20884  ae_int_t m;
20885  ae_int_t k;
20886  double v;
20887  double vv;
20888  double relcnt;
20889  ae_int_t i;
20890  ae_int_t j;
20891  ae_int_t j1;
20892  ae_int_t info;
20893  ae_bool result;
20894 
20895 
20896 
20897  /*
20898  * Reverse communication preparations
20899  * I know it looks ugly, but it works the same way
20900  * anywhere from C++ to Python.
20901  *
20902  * This code initializes locals by:
20903  * * random values determined during code
20904  * generation - on first subroutine call
20905  * * values from previous call - on subsequent calls
20906  */
20907  if( state->rstate.stage>=0 )
20908  {
20909  n = state->rstate.ia.ptr.p_int[0];
20910  m = state->rstate.ia.ptr.p_int[1];
20911  k = state->rstate.ia.ptr.p_int[2];
20912  i = state->rstate.ia.ptr.p_int[3];
20913  j = state->rstate.ia.ptr.p_int[4];
20914  j1 = state->rstate.ia.ptr.p_int[5];
20915  info = state->rstate.ia.ptr.p_int[6];
20916  lx = state->rstate.ra.ptr.p_double[0];
20917  lf = state->rstate.ra.ptr.p_double[1];
20918  ld = state->rstate.ra.ptr.p_double[2];
20919  rx = state->rstate.ra.ptr.p_double[3];
20920  rf = state->rstate.ra.ptr.p_double[4];
20921  rd = state->rstate.ra.ptr.p_double[5];
20922  v = state->rstate.ra.ptr.p_double[6];
20923  vv = state->rstate.ra.ptr.p_double[7];
20924  relcnt = state->rstate.ra.ptr.p_double[8];
20925  }
20926  else
20927  {
20928  n = -983;
20929  m = -989;
20930  k = -834;
20931  i = 900;
20932  j = -287;
20933  j1 = 364;
20934  info = 214;
20935  lx = -338;
20936  lf = -686;
20937  ld = 912;
20938  rx = 585;
20939  rf = 497;
20940  rd = -271;
20941  v = -581;
20942  vv = 745;
20943  relcnt = -533;
20944  }
20945  if( state->rstate.stage==0 )
20946  {
20947  goto lbl_0;
20948  }
20949  if( state->rstate.stage==1 )
20950  {
20951  goto lbl_1;
20952  }
20953  if( state->rstate.stage==2 )
20954  {
20955  goto lbl_2;
20956  }
20957  if( state->rstate.stage==3 )
20958  {
20959  goto lbl_3;
20960  }
20961  if( state->rstate.stage==4 )
20962  {
20963  goto lbl_4;
20964  }
20965  if( state->rstate.stage==5 )
20966  {
20967  goto lbl_5;
20968  }
20969  if( state->rstate.stage==6 )
20970  {
20971  goto lbl_6;
20972  }
20973  if( state->rstate.stage==7 )
20974  {
20975  goto lbl_7;
20976  }
20977  if( state->rstate.stage==8 )
20978  {
20979  goto lbl_8;
20980  }
20981  if( state->rstate.stage==9 )
20982  {
20983  goto lbl_9;
20984  }
20985  if( state->rstate.stage==10 )
20986  {
20987  goto lbl_10;
20988  }
20989  if( state->rstate.stage==11 )
20990  {
20991  goto lbl_11;
20992  }
20993  if( state->rstate.stage==12 )
20994  {
20995  goto lbl_12;
20996  }
20997  if( state->rstate.stage==13 )
20998  {
20999  goto lbl_13;
21000  }
21001 
21002  /*
21003  * Routine body
21004  */
21005 
21006  /*
21007  * Init
21008  */
21009  if( state->wkind==1 )
21010  {
21011  ae_assert(state->npoints==state->nweights, "LSFitFit: number of points is not equal to the number of weights", _state);
21012  }
21013  state->repvaridx = -1;
21014  n = state->npoints;
21015  m = state->m;
21016  k = state->k;
21017  minlmsetcond(&state->optstate, 0.0, state->epsf, state->epsx, state->maxits, _state);
21018  minlmsetstpmax(&state->optstate, state->stpmax, _state);
21019  minlmsetxrep(&state->optstate, state->xrep, _state);
21020  minlmsetscale(&state->optstate, &state->s, _state);
21021  minlmsetbc(&state->optstate, &state->bndl, &state->bndu, _state);
21022 
21023  /*
21024  * Check that user-supplied gradient is correct
21025  */
21026  lsfit_lsfitclearrequestfields(state, _state);
21027  if( !(ae_fp_greater(state->teststep,0)&&state->optalgo==1) )
21028  {
21029  goto lbl_14;
21030  }
21031  for(i=0; i<=k-1; i++)
21032  {
21033  if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
21034  {
21035  state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
21036  }
21037  if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
21038  {
21039  state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
21040  }
21041  }
21042  state->needfg = ae_true;
21043  i = 0;
21044 lbl_16:
21045  if( i>k-1 )
21046  {
21047  goto lbl_18;
21048  }
21049  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);
21050  v = state->c.ptr.p_double[i];
21051  j = 0;
21052 lbl_19:
21053  if( j>n-1 )
21054  {
21055  goto lbl_21;
21056  }
21057  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[j][0], 1, ae_v_len(0,m-1));
21058  state->c.ptr.p_double[i] = v-state->teststep*state->s.ptr.p_double[i];
21059  if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
21060  {
21061  state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
21062  }
21063  lx = state->c.ptr.p_double[i];
21064  state->rstate.stage = 0;
21065  goto lbl_rcomm;
21066 lbl_0:
21067  lf = state->f;
21068  ld = state->g.ptr.p_double[i];
21069  state->c.ptr.p_double[i] = v+state->teststep*state->s.ptr.p_double[i];
21070  if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
21071  {
21072  state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
21073  }
21074  rx = state->c.ptr.p_double[i];
21075  state->rstate.stage = 1;
21076  goto lbl_rcomm;
21077 lbl_1:
21078  rf = state->f;
21079  rd = state->g.ptr.p_double[i];
21080  state->c.ptr.p_double[i] = (lx+rx)/2;
21081  if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
21082  {
21083  state->c.ptr.p_double[i] = ae_maxreal(state->c.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
21084  }
21085  if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
21086  {
21087  state->c.ptr.p_double[i] = ae_minreal(state->c.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
21088  }
21089  state->rstate.stage = 2;
21090  goto lbl_rcomm;
21091 lbl_2:
21092  state->c.ptr.p_double[i] = v;
21093  if( !derivativecheck(lf, ld, rf, rd, state->f, state->g.ptr.p_double[i], rx-lx, _state) )
21094  {
21095  state->repvaridx = i;
21096  state->repterminationtype = -7;
21097  result = ae_false;
21098  return result;
21099  }
21100  j = j+1;
21101  goto lbl_19;
21102 lbl_21:
21103  i = i+1;
21104  goto lbl_16;
21105 lbl_18:
21106  state->needfg = ae_false;
21107 lbl_14:
21108 
21109  /*
21110  * Fill WCur by weights:
21111  * * for WKind=0 unit weights are chosen
21112  * * for WKind=1 we use user-supplied weights stored in State.TaskW
21113  */
21114  rvectorsetlengthatleast(&state->wcur, n, _state);
21115  for(i=0; i<=n-1; i++)
21116  {
21117  state->wcur.ptr.p_double[i] = 1.0;
21118  if( state->wkind==1 )
21119  {
21120  state->wcur.ptr.p_double[i] = state->taskw.ptr.p_double[i];
21121  }
21122  }
21123 
21124  /*
21125  * Optimize
21126  */
21127 lbl_22:
21128  if( !minlmiteration(&state->optstate, _state) )
21129  {
21130  goto lbl_23;
21131  }
21132  if( !state->optstate.needfi )
21133  {
21134  goto lbl_24;
21135  }
21136 
21137  /*
21138  * calculate f[] = wi*(f(xi,c)-yi)
21139  */
21140  i = 0;
21141 lbl_26:
21142  if( i>n-1 )
21143  {
21144  goto lbl_28;
21145  }
21146  ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
21147  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21148  state->pointindex = i;
21149  lsfit_lsfitclearrequestfields(state, _state);
21150  state->needf = ae_true;
21151  state->rstate.stage = 3;
21152  goto lbl_rcomm;
21153 lbl_3:
21154  state->needf = ae_false;
21155  vv = state->wcur.ptr.p_double[i];
21156  state->optstate.fi.ptr.p_double[i] = vv*(state->f-state->tasky.ptr.p_double[i]);
21157  i = i+1;
21158  goto lbl_26;
21159 lbl_28:
21160  goto lbl_22;
21161 lbl_24:
21162  if( !state->optstate.needf )
21163  {
21164  goto lbl_29;
21165  }
21166 
21167  /*
21168  * calculate F = sum (wi*(f(xi,c)-yi))^2
21169  */
21170  state->optstate.f = 0;
21171  i = 0;
21172 lbl_31:
21173  if( i>n-1 )
21174  {
21175  goto lbl_33;
21176  }
21177  ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
21178  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21179  state->pointindex = i;
21180  lsfit_lsfitclearrequestfields(state, _state);
21181  state->needf = ae_true;
21182  state->rstate.stage = 4;
21183  goto lbl_rcomm;
21184 lbl_4:
21185  state->needf = ae_false;
21186  vv = state->wcur.ptr.p_double[i];
21187  state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state);
21188  i = i+1;
21189  goto lbl_31;
21190 lbl_33:
21191  goto lbl_22;
21192 lbl_29:
21193  if( !state->optstate.needfg )
21194  {
21195  goto lbl_34;
21196  }
21197 
21198  /*
21199  * calculate F/gradF
21200  */
21201  state->optstate.f = 0;
21202  for(i=0; i<=k-1; i++)
21203  {
21204  state->optstate.g.ptr.p_double[i] = 0;
21205  }
21206  i = 0;
21207 lbl_36:
21208  if( i>n-1 )
21209  {
21210  goto lbl_38;
21211  }
21212  ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
21213  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21214  state->pointindex = i;
21215  lsfit_lsfitclearrequestfields(state, _state);
21216  state->needfg = ae_true;
21217  state->rstate.stage = 5;
21218  goto lbl_rcomm;
21219 lbl_5:
21220  state->needfg = ae_false;
21221  vv = state->wcur.ptr.p_double[i];
21222  state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state);
21223  v = ae_sqr(vv, _state)*2*(state->f-state->tasky.ptr.p_double[i]);
21224  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);
21225  i = i+1;
21226  goto lbl_36;
21227 lbl_38:
21228  goto lbl_22;
21229 lbl_34:
21230  if( !state->optstate.needfij )
21231  {
21232  goto lbl_39;
21233  }
21234 
21235  /*
21236  * calculate Fi/jac(Fi)
21237  */
21238  i = 0;
21239 lbl_41:
21240  if( i>n-1 )
21241  {
21242  goto lbl_43;
21243  }
21244  ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
21245  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21246  state->pointindex = i;
21247  lsfit_lsfitclearrequestfields(state, _state);
21248  state->needfg = ae_true;
21249  state->rstate.stage = 6;
21250  goto lbl_rcomm;
21251 lbl_6:
21252  state->needfg = ae_false;
21253  vv = state->wcur.ptr.p_double[i];
21254  state->optstate.fi.ptr.p_double[i] = vv*(state->f-state->tasky.ptr.p_double[i]);
21255  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);
21256  i = i+1;
21257  goto lbl_41;
21258 lbl_43:
21259  goto lbl_22;
21260 lbl_39:
21261  if( !state->optstate.needfgh )
21262  {
21263  goto lbl_44;
21264  }
21265 
21266  /*
21267  * calculate F/grad(F)/hess(F)
21268  */
21269  state->optstate.f = 0;
21270  for(i=0; i<=k-1; i++)
21271  {
21272  state->optstate.g.ptr.p_double[i] = 0;
21273  }
21274  for(i=0; i<=k-1; i++)
21275  {
21276  for(j=0; j<=k-1; j++)
21277  {
21278  state->optstate.h.ptr.pp_double[i][j] = 0;
21279  }
21280  }
21281  i = 0;
21282 lbl_46:
21283  if( i>n-1 )
21284  {
21285  goto lbl_48;
21286  }
21287  ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
21288  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21289  state->pointindex = i;
21290  lsfit_lsfitclearrequestfields(state, _state);
21291  state->needfgh = ae_true;
21292  state->rstate.stage = 7;
21293  goto lbl_rcomm;
21294 lbl_7:
21295  state->needfgh = ae_false;
21296  vv = state->wcur.ptr.p_double[i];
21297  state->optstate.f = state->optstate.f+ae_sqr(vv*(state->f-state->tasky.ptr.p_double[i]), _state);
21298  v = ae_sqr(vv, _state)*2*(state->f-state->tasky.ptr.p_double[i]);
21299  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);
21300  for(j=0; j<=k-1; j++)
21301  {
21302  v = 2*ae_sqr(vv, _state)*state->g.ptr.p_double[j];
21303  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);
21304  v = 2*ae_sqr(vv, _state)*(state->f-state->tasky.ptr.p_double[i]);
21305  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);
21306  }
21307  i = i+1;
21308  goto lbl_46;
21309 lbl_48:
21310  goto lbl_22;
21311 lbl_44:
21312  if( !state->optstate.xupdated )
21313  {
21314  goto lbl_49;
21315  }
21316 
21317  /*
21318  * Report new iteration
21319  */
21320  ae_v_move(&state->c.ptr.p_double[0], 1, &state->optstate.x.ptr.p_double[0], 1, ae_v_len(0,k-1));
21321  state->f = state->optstate.f;
21322  lsfit_lsfitclearrequestfields(state, _state);
21323  state->xupdated = ae_true;
21324  state->rstate.stage = 8;
21325  goto lbl_rcomm;
21326 lbl_8:
21327  state->xupdated = ae_false;
21328  goto lbl_22;
21329 lbl_49:
21330  goto lbl_22;
21331 lbl_23:
21332  minlmresults(&state->optstate, &state->c, &state->optrep, _state);
21333  state->repterminationtype = state->optrep.terminationtype;
21334  state->repiterationscount = state->optrep.iterationscount;
21335 
21336  /*
21337  * calculate errors
21338  */
21339  if( state->repterminationtype<=0 )
21340  {
21341  goto lbl_51;
21342  }
21343 
21344  /*
21345  * Calculate RMS/Avg/Max/... errors
21346  */
21347  state->reprmserror = 0;
21348  state->repwrmserror = 0;
21349  state->repavgerror = 0;
21350  state->repavgrelerror = 0;
21351  state->repmaxerror = 0;
21352  relcnt = 0;
21353  i = 0;
21354 lbl_53:
21355  if( i>n-1 )
21356  {
21357  goto lbl_55;
21358  }
21359  ae_v_move(&state->c.ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,k-1));
21360  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21361  state->pointindex = i;
21362  lsfit_lsfitclearrequestfields(state, _state);
21363  state->needf = ae_true;
21364  state->rstate.stage = 9;
21365  goto lbl_rcomm;
21366 lbl_9:
21367  state->needf = ae_false;
21368  v = state->f;
21369  vv = state->wcur.ptr.p_double[i];
21370  state->reprmserror = state->reprmserror+ae_sqr(v-state->tasky.ptr.p_double[i], _state);
21371  state->repwrmserror = state->repwrmserror+ae_sqr(vv*(v-state->tasky.ptr.p_double[i]), _state);
21372  state->repavgerror = state->repavgerror+ae_fabs(v-state->tasky.ptr.p_double[i], _state);
21373  if( ae_fp_neq(state->tasky.ptr.p_double[i],0) )
21374  {
21375  state->repavgrelerror = state->repavgrelerror+ae_fabs(v-state->tasky.ptr.p_double[i], _state)/ae_fabs(state->tasky.ptr.p_double[i], _state);
21376  relcnt = relcnt+1;
21377  }
21378  state->repmaxerror = ae_maxreal(state->repmaxerror, ae_fabs(v-state->tasky.ptr.p_double[i], _state), _state);
21379  i = i+1;
21380  goto lbl_53;
21381 lbl_55:
21382  state->reprmserror = ae_sqrt(state->reprmserror/n, _state);
21383  state->repwrmserror = ae_sqrt(state->repwrmserror/n, _state);
21384  state->repavgerror = state->repavgerror/n;
21385  if( ae_fp_neq(relcnt,0) )
21386  {
21387  state->repavgrelerror = state->repavgrelerror/relcnt;
21388  }
21389 
21390  /*
21391  * Calculate covariance matrix
21392  */
21393  rmatrixsetlengthatleast(&state->tmpjac, n, k, _state);
21394  rvectorsetlengthatleast(&state->tmpf, n, _state);
21395  rvectorsetlengthatleast(&state->tmp, k, _state);
21396  if( ae_fp_less_eq(state->diffstep,0) )
21397  {
21398  goto lbl_56;
21399  }
21400 
21401  /*
21402  * Compute Jacobian by means of numerical differentiation
21403  */
21404  lsfit_lsfitclearrequestfields(state, _state);
21405  state->needf = ae_true;
21406  i = 0;
21407 lbl_58:
21408  if( i>n-1 )
21409  {
21410  goto lbl_60;
21411  }
21412  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21413  state->pointindex = i;
21414  state->rstate.stage = 10;
21415  goto lbl_rcomm;
21416 lbl_10:
21417  state->tmpf.ptr.p_double[i] = state->f;
21418  j = 0;
21419 lbl_61:
21420  if( j>k-1 )
21421  {
21422  goto lbl_63;
21423  }
21424  v = state->c.ptr.p_double[j];
21425  lx = v-state->diffstep*state->s.ptr.p_double[j];
21426  state->c.ptr.p_double[j] = lx;
21427  if( ae_isfinite(state->bndl.ptr.p_double[j], _state) )
21428  {
21429  state->c.ptr.p_double[j] = ae_maxreal(state->c.ptr.p_double[j], state->bndl.ptr.p_double[j], _state);
21430  }
21431  state->rstate.stage = 11;
21432  goto lbl_rcomm;
21433 lbl_11:
21434  lf = state->f;
21435  rx = v+state->diffstep*state->s.ptr.p_double[j];
21436  state->c.ptr.p_double[j] = rx;
21437  if( ae_isfinite(state->bndu.ptr.p_double[j], _state) )
21438  {
21439  state->c.ptr.p_double[j] = ae_minreal(state->c.ptr.p_double[j], state->bndu.ptr.p_double[j], _state);
21440  }
21441  state->rstate.stage = 12;
21442  goto lbl_rcomm;
21443 lbl_12:
21444  rf = state->f;
21445  state->c.ptr.p_double[j] = v;
21446  if( ae_fp_neq(rx,lx) )
21447  {
21448  state->tmpjac.ptr.pp_double[i][j] = (rf-lf)/(rx-lx);
21449  }
21450  else
21451  {
21452  state->tmpjac.ptr.pp_double[i][j] = 0;
21453  }
21454  j = j+1;
21455  goto lbl_61;
21456 lbl_63:
21457  i = i+1;
21458  goto lbl_58;
21459 lbl_60:
21460  state->needf = ae_false;
21461  goto lbl_57;
21462 lbl_56:
21463 
21464  /*
21465  * Jacobian is calculated with user-provided analytic gradient
21466  */
21467  lsfit_lsfitclearrequestfields(state, _state);
21468  state->needfg = ae_true;
21469  i = 0;
21470 lbl_64:
21471  if( i>n-1 )
21472  {
21473  goto lbl_66;
21474  }
21475  ae_v_move(&state->x.ptr.p_double[0], 1, &state->taskx.ptr.pp_double[i][0], 1, ae_v_len(0,m-1));
21476  state->pointindex = i;
21477  state->rstate.stage = 13;
21478  goto lbl_rcomm;
21479 lbl_13:
21480  state->tmpf.ptr.p_double[i] = state->f;
21481  for(j=0; j<=k-1; j++)
21482  {
21483  state->tmpjac.ptr.pp_double[i][j] = state->g.ptr.p_double[j];
21484  }
21485  i = i+1;
21486  goto lbl_64;
21487 lbl_66:
21488  state->needfg = ae_false;
21489 lbl_57:
21490  for(i=0; i<=k-1; i++)
21491  {
21492  state->tmp.ptr.p_double[i] = 0.0;
21493  }
21494  lsfit_estimateerrors(&state->tmpjac, &state->tmpf, &state->tasky, &state->wcur, &state->tmp, &state->s, n, k, &state->rep, &state->tmpjacw, 0, _state);
21495 lbl_51:
21496  result = ae_false;
21497  return result;
21498 
21499  /*
21500  * Saving state
21501  */
21502 lbl_rcomm:
21503  result = ae_true;
21504  state->rstate.ia.ptr.p_int[0] = n;
21505  state->rstate.ia.ptr.p_int[1] = m;
21506  state->rstate.ia.ptr.p_int[2] = k;
21507  state->rstate.ia.ptr.p_int[3] = i;
21508  state->rstate.ia.ptr.p_int[4] = j;
21509  state->rstate.ia.ptr.p_int[5] = j1;
21510  state->rstate.ia.ptr.p_int[6] = info;
21511  state->rstate.ra.ptr.p_double[0] = lx;
21512  state->rstate.ra.ptr.p_double[1] = lf;
21513  state->rstate.ra.ptr.p_double[2] = ld;
21514  state->rstate.ra.ptr.p_double[3] = rx;
21515  state->rstate.ra.ptr.p_double[4] = rf;
21516  state->rstate.ra.ptr.p_double[5] = rd;
21517  state->rstate.ra.ptr.p_double[6] = v;
21518  state->rstate.ra.ptr.p_double[7] = vv;
21519  state->rstate.ra.ptr.p_double[8] = relcnt;
21520  return result;
21521 }
21522 
21523 
21524 /*************************************************************************
21525 Nonlinear least squares fitting results.
21526 
21527 Called after return from LSFitFit().
21528 
21529 INPUT PARAMETERS:
21530  State - algorithm state
21531 
21532 OUTPUT PARAMETERS:
21533  Info - completion code:
21534  * -7 gradient verification failed.
21535  See LSFitSetGradientCheck() for more information.
21536  * 1 relative function improvement is no more than
21537  EpsF.
21538  * 2 relative step is no more than EpsX.
21539  * 4 gradient norm is no more than EpsG
21540  * 5 MaxIts steps was taken
21541  * 7 stopping conditions are too stringent,
21542  further improvement is impossible
21543  C - array[0..K-1], solution
21544  Rep - optimization report. On success following fields are set:
21545  * R2 non-adjusted coefficient of determination
21546  (non-weighted)
21547  * RMSError rms error on the (X,Y).
21548  * AvgError average error on the (X,Y).
21549  * AvgRelError average relative error on the non-zero Y
21550  * MaxError maximum error
21551  NON-WEIGHTED ERRORS ARE CALCULATED
21552  * WRMSError weighted rms error on the (X,Y).
21553 
21554 ERRORS IN PARAMETERS
21555 
21556 This solver also calculates different kinds of errors in parameters and
21557 fills corresponding fields of report:
21558 * Rep.CovPar covariance matrix for parameters, array[K,K].
21559 * Rep.ErrPar errors in parameters, array[K],
21560  errpar = sqrt(diag(CovPar))
21561 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
21562  best-fit curve from "ideal" best-fit curve built with
21563  infinite number of samples, array[N].
21564  errcurve = sqrt(diag(J*CovPar*J')),
21565  where J is Jacobian matrix.
21566 * Rep.Noise vector of per-point estimates of noise, array[N]
21567 
21568 IMPORTANT: errors in parameters are calculated without taking into
21569  account boundary/linear constraints! Presence of constraints
21570  changes distribution of errors, but there is no easy way to
21571  account for constraints when you calculate covariance matrix.
21572 
21573 NOTE: noise in the data is estimated as follows:
21574  * for fitting without user-supplied weights all points are
21575  assumed to have same level of noise, which is estimated from
21576  the data
21577  * for fitting with user-supplied weights we assume that noise
21578  level in I-th point is inversely proportional to Ith weight.
21579  Coefficient of proportionality is estimated from the data.
21580 
21581 NOTE: we apply small amount of regularization when we invert squared
21582  Jacobian and calculate covariance matrix. It guarantees that
21583  algorithm won't divide by zero during inversion, but skews
21584  error estimates a bit (fractional error is about 10^-9).
21585 
21586  However, we believe that this difference is insignificant for
21587  all practical purposes except for the situation when you want
21588  to compare ALGLIB results with "reference" implementation up
21589  to the last significant digit.
21590 
21591 NOTE: covariance matrix is estimated using correction for degrees
21592  of freedom (covariances are divided by N-M instead of dividing
21593  by N).
21594 
21595  -- ALGLIB --
21596  Copyright 17.08.2009 by Bochkanov Sergey
21597 *************************************************************************/
21598 void lsfitresults(lsfitstate* state,
21599  ae_int_t* info,
21600  /* Real */ ae_vector* c,
21601  lsfitreport* rep,
21602  ae_state *_state)
21603 {
21604  ae_int_t i;
21605  ae_int_t j;
21606 
21607  *info = 0;
21608  ae_vector_clear(c);
21609  _lsfitreport_clear(rep);
21610 
21611  lsfit_clearreport(rep, _state);
21612  *info = state->repterminationtype;
21613  rep->varidx = state->repvaridx;
21614  if( *info>0 )
21615  {
21616  ae_vector_set_length(c, state->k, _state);
21617  ae_v_move(&c->ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,state->k-1));
21618  rep->rmserror = state->reprmserror;
21619  rep->wrmserror = state->repwrmserror;
21620  rep->avgerror = state->repavgerror;
21621  rep->avgrelerror = state->repavgrelerror;
21622  rep->maxerror = state->repmaxerror;
21623  rep->iterationscount = state->repiterationscount;
21624  ae_matrix_set_length(&rep->covpar, state->k, state->k, _state);
21625  ae_vector_set_length(&rep->errpar, state->k, _state);
21626  ae_vector_set_length(&rep->errcurve, state->npoints, _state);
21627  ae_vector_set_length(&rep->noise, state->npoints, _state);
21628  rep->r2 = state->rep.r2;
21629  for(i=0; i<=state->k-1; i++)
21630  {
21631  for(j=0; j<=state->k-1; j++)
21632  {
21633  rep->covpar.ptr.pp_double[i][j] = state->rep.covpar.ptr.pp_double[i][j];
21634  }
21635  rep->errpar.ptr.p_double[i] = state->rep.errpar.ptr.p_double[i];
21636  }
21637  for(i=0; i<=state->npoints-1; i++)
21638  {
21639  rep->errcurve.ptr.p_double[i] = state->rep.errcurve.ptr.p_double[i];
21640  rep->noise.ptr.p_double[i] = state->rep.noise.ptr.p_double[i];
21641  }
21642  }
21643 }
21644 
21645 
21646 /*************************************************************************
21647 This subroutine turns on verification of the user-supplied analytic
21648 gradient:
21649 * user calls this subroutine before fitting begins
21650 * LSFitFit() is called
21651 * prior to actual fitting, for each point in data set X_i and each
21652  component of parameters being fited C_j algorithm performs following
21653  steps:
21654  * two trial steps are made to C_j-TestStep*S[j] and C_j+TestStep*S[j],
21655  where C_j is j-th parameter and S[j] is a scale of j-th parameter
21656  * if needed, steps are bounded with respect to constraints on C[]
21657  * F(X_i|C) is evaluated at these trial points
21658  * we perform one more evaluation in the middle point of the interval
21659  * we build cubic model using function values and derivatives at trial
21660  points and we compare its prediction with actual value in the middle
21661  point
21662  * in case difference between prediction and actual value is higher than
21663  some predetermined threshold, algorithm stops with completion code -7;
21664  Rep.VarIdx is set to index of the parameter with incorrect derivative.
21665 * after verification is over, algorithm proceeds to the actual optimization.
21666 
21667 NOTE 1: verification needs N*K (points count * parameters count) gradient
21668  evaluations. It is very costly and you should use it only for low
21669  dimensional problems, when you want to be sure that you've
21670  correctly calculated analytic derivatives. You should not use it
21671  in the production code (unless you want to check derivatives
21672  provided by some third party).
21673 
21674 NOTE 2: you should carefully choose TestStep. Value which is too large
21675  (so large that function behaviour is significantly non-cubic) will
21676  lead to false alarms. You may use different step for different
21677  parameters by means of setting scale with LSFitSetScale().
21678 
21679 NOTE 3: this function may lead to false positives. In case it reports that
21680  I-th derivative was calculated incorrectly, you may decrease test
21681  step and try one more time - maybe your function changes too
21682  sharply and your step is too large for such rapidly chanding
21683  function.
21684 
21685 NOTE 4: this function works only for optimizers created with LSFitCreateWFG()
21686  or LSFitCreateFG() constructors.
21687 
21688 INPUT PARAMETERS:
21689  State - structure used to store algorithm state
21690  TestStep - verification step:
21691  * TestStep=0 turns verification off
21692  * TestStep>0 activates verification
21693 
21694  -- ALGLIB --
21695  Copyright 15.06.2012 by Bochkanov Sergey
21696 *************************************************************************/
21697 void lsfitsetgradientcheck(lsfitstate* state,
21698  double teststep,
21699  ae_state *_state)
21700 {
21701 
21702 
21703  ae_assert(ae_isfinite(teststep, _state), "LSFitSetGradientCheck: TestStep contains NaN or Infinite", _state);
21704  ae_assert(ae_fp_greater_eq(teststep,0), "LSFitSetGradientCheck: invalid argument TestStep(TestStep<0)", _state);
21705  state->teststep = teststep;
21706 }
21707 
21708 
21709 /*************************************************************************
21710 Internal subroutine: automatic scaling for LLS tasks.
21711 NEVER CALL IT DIRECTLY!
21712 
21713 Maps abscissas to [-1,1], standartizes ordinates and correspondingly scales
21714 constraints. It also scales weights so that max(W[i])=1
21715 
21716 Transformations performed:
21717 * X, XC [XA,XB] => [-1,+1]
21718  transformation makes min(X)=-1, max(X)=+1
21719 
21720 * Y [SA,SB] => [0,1]
21721  transformation makes mean(Y)=0, stddev(Y)=1
21722 
21723 * YC transformed accordingly to SA, SB, DC[I]
21724 
21725  -- ALGLIB PROJECT --
21726  Copyright 08.09.2009 by Bochkanov Sergey
21727 *************************************************************************/
21728 void lsfitscalexy(/* Real */ ae_vector* x,
21729  /* Real */ ae_vector* y,
21730  /* Real */ ae_vector* w,
21731  ae_int_t n,
21732  /* Real */ ae_vector* xc,
21733  /* Real */ ae_vector* yc,
21734  /* Integer */ ae_vector* dc,
21735  ae_int_t k,
21736  double* xa,
21737  double* xb,
21738  double* sa,
21739  double* sb,
21740  /* Real */ ae_vector* xoriginal,
21741  /* Real */ ae_vector* yoriginal,
21742  ae_state *_state)
21743 {
21744  double xmin;
21745  double xmax;
21746  ae_int_t i;
21747  double mx;
21748 
21749  *xa = 0;
21750  *xb = 0;
21751  *sa = 0;
21752  *sb = 0;
21753  ae_vector_clear(xoriginal);
21754  ae_vector_clear(yoriginal);
21755 
21756  ae_assert(n>=1, "LSFitScaleXY: incorrect N", _state);
21757  ae_assert(k>=0, "LSFitScaleXY: incorrect K", _state);
21758 
21759  /*
21760  * Calculate xmin/xmax.
21761  * Force xmin<>xmax.
21762  */
21763  xmin = x->ptr.p_double[0];
21764  xmax = x->ptr.p_double[0];
21765  for(i=1; i<=n-1; i++)
21766  {
21767  xmin = ae_minreal(xmin, x->ptr.p_double[i], _state);
21768  xmax = ae_maxreal(xmax, x->ptr.p_double[i], _state);
21769  }
21770  for(i=0; i<=k-1; i++)
21771  {
21772  xmin = ae_minreal(xmin, xc->ptr.p_double[i], _state);
21773  xmax = ae_maxreal(xmax, xc->ptr.p_double[i], _state);
21774  }
21775  if( ae_fp_eq(xmin,xmax) )
21776  {
21777  if( ae_fp_eq(xmin,0) )
21778  {
21779  xmin = -1;
21780  xmax = 1;
21781  }
21782  else
21783  {
21784  if( ae_fp_greater(xmin,0) )
21785  {
21786  xmin = 0.5*xmin;
21787  }
21788  else
21789  {
21790  xmax = 0.5*xmax;
21791  }
21792  }
21793  }
21794 
21795  /*
21796  * Transform abscissas: map [XA,XB] to [0,1]
21797  *
21798  * Store old X[] in XOriginal[] (it will be used
21799  * to calculate relative error).
21800  */
21801  ae_vector_set_length(xoriginal, n, _state);
21802  ae_v_move(&xoriginal->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
21803  *xa = xmin;
21804  *xb = xmax;
21805  for(i=0; i<=n-1; i++)
21806  {
21807  x->ptr.p_double[i] = 2*(x->ptr.p_double[i]-0.5*(*xa+(*xb)))/(*xb-(*xa));
21808  }
21809  for(i=0; i<=k-1; i++)
21810  {
21811  ae_assert(dc->ptr.p_int[i]>=0, "LSFitScaleXY: internal error!", _state);
21812  xc->ptr.p_double[i] = 2*(xc->ptr.p_double[i]-0.5*(*xa+(*xb)))/(*xb-(*xa));
21813  yc->ptr.p_double[i] = yc->ptr.p_double[i]*ae_pow(0.5*(*xb-(*xa)), dc->ptr.p_int[i], _state);
21814  }
21815 
21816  /*
21817  * Transform function values: map [SA,SB] to [0,1]
21818  * SA = mean(Y),
21819  * SB = SA+stddev(Y).
21820  *
21821  * Store old Y[] in YOriginal[] (it will be used
21822  * to calculate relative error).
21823  */
21824  ae_vector_set_length(yoriginal, n, _state);
21825  ae_v_move(&yoriginal->ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
21826  *sa = 0;
21827  for(i=0; i<=n-1; i++)
21828  {
21829  *sa = *sa+y->ptr.p_double[i];
21830  }
21831  *sa = *sa/n;
21832  *sb = 0;
21833  for(i=0; i<=n-1; i++)
21834  {
21835  *sb = *sb+ae_sqr(y->ptr.p_double[i]-(*sa), _state);
21836  }
21837  *sb = ae_sqrt(*sb/n, _state)+(*sa);
21838  if( ae_fp_eq(*sb,*sa) )
21839  {
21840  *sb = 2*(*sa);
21841  }
21842  if( ae_fp_eq(*sb,*sa) )
21843  {
21844  *sb = *sa+1;
21845  }
21846  for(i=0; i<=n-1; i++)
21847  {
21848  y->ptr.p_double[i] = (y->ptr.p_double[i]-(*sa))/(*sb-(*sa));
21849  }
21850  for(i=0; i<=k-1; i++)
21851  {
21852  if( dc->ptr.p_int[i]==0 )
21853  {
21854  yc->ptr.p_double[i] = (yc->ptr.p_double[i]-(*sa))/(*sb-(*sa));
21855  }
21856  else
21857  {
21858  yc->ptr.p_double[i] = yc->ptr.p_double[i]/(*sb-(*sa));
21859  }
21860  }
21861 
21862  /*
21863  * Scale weights
21864  */
21865  mx = 0;
21866  for(i=0; i<=n-1; i++)
21867  {
21868  mx = ae_maxreal(mx, ae_fabs(w->ptr.p_double[i], _state), _state);
21869  }
21870  if( ae_fp_neq(mx,0) )
21871  {
21872  for(i=0; i<=n-1; i++)
21873  {
21874  w->ptr.p_double[i] = w->ptr.p_double[i]/mx;
21875  }
21876  }
21877 }
21878 
21879 
21880 /*************************************************************************
21881 Internal spline fitting subroutine
21882 
21883  -- ALGLIB PROJECT --
21884  Copyright 08.09.2009 by Bochkanov Sergey
21885 *************************************************************************/
21886 static void lsfit_spline1dfitinternal(ae_int_t st,
21887  /* Real */ ae_vector* x,
21888  /* Real */ ae_vector* y,
21889  /* Real */ ae_vector* w,
21890  ae_int_t n,
21891  /* Real */ ae_vector* xc,
21892  /* Real */ ae_vector* yc,
21893  /* Integer */ ae_vector* dc,
21894  ae_int_t k,
21895  ae_int_t m,
21896  ae_int_t* info,
21897  spline1dinterpolant* s,
21898  spline1dfitreport* rep,
21899  ae_state *_state)
21900 {
21901  ae_frame _frame_block;
21902  ae_vector _x;
21903  ae_vector _y;
21904  ae_vector _w;
21905  ae_vector _xc;
21906  ae_vector _yc;
21907  ae_matrix fmatrix;
21908  ae_matrix cmatrix;
21909  ae_vector y2;
21910  ae_vector w2;
21911  ae_vector sx;
21912  ae_vector sy;
21913  ae_vector sd;
21914  ae_vector tmp;
21915  ae_vector xoriginal;
21916  ae_vector yoriginal;
21917  lsfitreport lrep;
21918  double v0;
21919  double v1;
21920  double v2;
21921  double mx;
21922  spline1dinterpolant s2;
21923  ae_int_t i;
21924  ae_int_t j;
21925  ae_int_t relcnt;
21926  double xa;
21927  double xb;
21928  double sa;
21929  double sb;
21930  double bl;
21931  double br;
21932  double decay;
21933 
21934  ae_frame_make(_state, &_frame_block);
21935  ae_vector_init_copy(&_x, x, _state, ae_true);
21936  x = &_x;
21937  ae_vector_init_copy(&_y, y, _state, ae_true);
21938  y = &_y;
21939  ae_vector_init_copy(&_w, w, _state, ae_true);
21940  w = &_w;
21941  ae_vector_init_copy(&_xc, xc, _state, ae_true);
21942  xc = &_xc;
21943  ae_vector_init_copy(&_yc, yc, _state, ae_true);
21944  yc = &_yc;
21945  *info = 0;
21946  _spline1dinterpolant_clear(s);
21947  _spline1dfitreport_clear(rep);
21948  ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
21949  ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true);
21950  ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
21951  ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
21952  ae_vector_init(&sx, 0, DT_REAL, _state, ae_true);
21953  ae_vector_init(&sy, 0, DT_REAL, _state, ae_true);
21954  ae_vector_init(&sd, 0, DT_REAL, _state, ae_true);
21955  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
21956  ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
21957  ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
21958  _lsfitreport_init(&lrep, _state, ae_true);
21959  _spline1dinterpolant_init(&s2, _state, ae_true);
21960 
21961  ae_assert(st==0||st==1, "Spline1DFit: internal error!", _state);
21962  if( st==0&&m<4 )
21963  {
21964  *info = -1;
21965  ae_frame_leave(_state);
21966  return;
21967  }
21968  if( st==1&&m<4 )
21969  {
21970  *info = -1;
21971  ae_frame_leave(_state);
21972  return;
21973  }
21974  if( (n<1||k<0)||k>=m )
21975  {
21976  *info = -1;
21977  ae_frame_leave(_state);
21978  return;
21979  }
21980  for(i=0; i<=k-1; i++)
21981  {
21982  *info = 0;
21983  if( dc->ptr.p_int[i]<0 )
21984  {
21985  *info = -1;
21986  }
21987  if( dc->ptr.p_int[i]>1 )
21988  {
21989  *info = -1;
21990  }
21991  if( *info<0 )
21992  {
21993  ae_frame_leave(_state);
21994  return;
21995  }
21996  }
21997  if( st==1&&m%2!=0 )
21998  {
21999 
22000  /*
22001  * Hermite fitter must have even number of basis functions
22002  */
22003  *info = -2;
22004  ae_frame_leave(_state);
22005  return;
22006  }
22007 
22008  /*
22009  * weight decay for correct handling of task which becomes
22010  * degenerate after constraints are applied
22011  */
22012  decay = 10000*ae_machineepsilon;
22013 
22014  /*
22015  * Scale X, Y, XC, YC
22016  */
22017  lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
22018 
22019  /*
22020  * allocate space, initialize:
22021  * * SX - grid for basis functions
22022  * * SY - values of basis functions at grid points
22023  * * FMatrix- values of basis functions at X[]
22024  * * CMatrix- values (derivatives) of basis functions at XC[]
22025  */
22026  ae_vector_set_length(&y2, n+m, _state);
22027  ae_vector_set_length(&w2, n+m, _state);
22028  ae_matrix_set_length(&fmatrix, n+m, m, _state);
22029  if( k>0 )
22030  {
22031  ae_matrix_set_length(&cmatrix, k, m+1, _state);
22032  }
22033  if( st==0 )
22034  {
22035 
22036  /*
22037  * allocate space for cubic spline
22038  */
22039  ae_vector_set_length(&sx, m-2, _state);
22040  ae_vector_set_length(&sy, m-2, _state);
22041  for(j=0; j<=m-2-1; j++)
22042  {
22043  sx.ptr.p_double[j] = (double)(2*j)/(double)(m-2-1)-1;
22044  }
22045  }
22046  if( st==1 )
22047  {
22048 
22049  /*
22050  * allocate space for Hermite spline
22051  */
22052  ae_vector_set_length(&sx, m/2, _state);
22053  ae_vector_set_length(&sy, m/2, _state);
22054  ae_vector_set_length(&sd, m/2, _state);
22055  for(j=0; j<=m/2-1; j++)
22056  {
22057  sx.ptr.p_double[j] = (double)(2*j)/(double)(m/2-1)-1;
22058  }
22059  }
22060 
22061  /*
22062  * Prepare design and constraints matrices:
22063  * * fill constraints matrix
22064  * * fill first N rows of design matrix with values
22065  * * fill next M rows of design matrix with regularizing term
22066  * * append M zeros to Y
22067  * * append M elements, mean(abs(W)) each, to W
22068  */
22069  for(j=0; j<=m-1; j++)
22070  {
22071 
22072  /*
22073  * prepare Jth basis function
22074  */
22075  if( st==0 )
22076  {
22077 
22078  /*
22079  * cubic spline basis
22080  */
22081  for(i=0; i<=m-2-1; i++)
22082  {
22083  sy.ptr.p_double[i] = 0;
22084  }
22085  bl = 0;
22086  br = 0;
22087  if( j<m-2 )
22088  {
22089  sy.ptr.p_double[j] = 1;
22090  }
22091  if( j==m-2 )
22092  {
22093  bl = 1;
22094  }
22095  if( j==m-1 )
22096  {
22097  br = 1;
22098  }
22099  spline1dbuildcubic(&sx, &sy, m-2, 1, bl, 1, br, &s2, _state);
22100  }
22101  if( st==1 )
22102  {
22103 
22104  /*
22105  * Hermite basis
22106  */
22107  for(i=0; i<=m/2-1; i++)
22108  {
22109  sy.ptr.p_double[i] = 0;
22110  sd.ptr.p_double[i] = 0;
22111  }
22112  if( j%2==0 )
22113  {
22114  sy.ptr.p_double[j/2] = 1;
22115  }
22116  else
22117  {
22118  sd.ptr.p_double[j/2] = 1;
22119  }
22120  spline1dbuildhermite(&sx, &sy, &sd, m/2, &s2, _state);
22121  }
22122 
22123  /*
22124  * values at X[], XC[]
22125  */
22126  for(i=0; i<=n-1; i++)
22127  {
22128  fmatrix.ptr.pp_double[i][j] = spline1dcalc(&s2, x->ptr.p_double[i], _state);
22129  }
22130  for(i=0; i<=k-1; i++)
22131  {
22132  ae_assert(dc->ptr.p_int[i]>=0&&dc->ptr.p_int[i]<=2, "Spline1DFit: internal error!", _state);
22133  spline1ddiff(&s2, xc->ptr.p_double[i], &v0, &v1, &v2, _state);
22134  if( dc->ptr.p_int[i]==0 )
22135  {
22136  cmatrix.ptr.pp_double[i][j] = v0;
22137  }
22138  if( dc->ptr.p_int[i]==1 )
22139  {
22140  cmatrix.ptr.pp_double[i][j] = v1;
22141  }
22142  if( dc->ptr.p_int[i]==2 )
22143  {
22144  cmatrix.ptr.pp_double[i][j] = v2;
22145  }
22146  }
22147  }
22148  for(i=0; i<=k-1; i++)
22149  {
22150  cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i];
22151  }
22152  for(i=0; i<=m-1; i++)
22153  {
22154  for(j=0; j<=m-1; j++)
22155  {
22156  if( i==j )
22157  {
22158  fmatrix.ptr.pp_double[n+i][j] = decay;
22159  }
22160  else
22161  {
22162  fmatrix.ptr.pp_double[n+i][j] = 0;
22163  }
22164  }
22165  }
22166  ae_vector_set_length(&y2, n+m, _state);
22167  ae_vector_set_length(&w2, n+m, _state);
22168  ae_v_move(&y2.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
22169  ae_v_move(&w2.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
22170  mx = 0;
22171  for(i=0; i<=n-1; i++)
22172  {
22173  mx = mx+ae_fabs(w->ptr.p_double[i], _state);
22174  }
22175  mx = mx/n;
22176  for(i=0; i<=m-1; i++)
22177  {
22178  y2.ptr.p_double[n+i] = 0;
22179  w2.ptr.p_double[n+i] = mx;
22180  }
22181 
22182  /*
22183  * Solve constrained task
22184  */
22185  if( k>0 )
22186  {
22187 
22188  /*
22189  * solve using regularization
22190  */
22191  lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, &tmp, &lrep, _state);
22192  }
22193  else
22194  {
22195 
22196  /*
22197  * no constraints, no regularization needed
22198  */
22199  lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, k, info, &tmp, &lrep, _state);
22200  }
22201  if( *info<0 )
22202  {
22203  ae_frame_leave(_state);
22204  return;
22205  }
22206 
22207  /*
22208  * Generate spline and scale it
22209  */
22210  if( st==0 )
22211  {
22212 
22213  /*
22214  * cubic spline basis
22215  */
22216  ae_v_move(&sy.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-2-1));
22217  spline1dbuildcubic(&sx, &sy, m-2, 1, tmp.ptr.p_double[m-2], 1, tmp.ptr.p_double[m-1], s, _state);
22218  }
22219  if( st==1 )
22220  {
22221 
22222  /*
22223  * Hermite basis
22224  */
22225  for(i=0; i<=m/2-1; i++)
22226  {
22227  sy.ptr.p_double[i] = tmp.ptr.p_double[2*i];
22228  sd.ptr.p_double[i] = tmp.ptr.p_double[2*i+1];
22229  }
22230  spline1dbuildhermite(&sx, &sy, &sd, m/2, s, _state);
22231  }
22232  spline1dlintransx(s, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
22233  spline1dlintransy(s, sb-sa, sa, _state);
22234 
22235  /*
22236  * Scale absolute errors obtained from LSFitLinearW.
22237  * Relative error should be calculated separately
22238  * (because of shifting/scaling of the task)
22239  */
22240  rep->taskrcond = lrep.taskrcond;
22241  rep->rmserror = lrep.rmserror*(sb-sa);
22242  rep->avgerror = lrep.avgerror*(sb-sa);
22243  rep->maxerror = lrep.maxerror*(sb-sa);
22244  rep->avgrelerror = 0;
22245  relcnt = 0;
22246  for(i=0; i<=n-1; i++)
22247  {
22248  if( ae_fp_neq(yoriginal.ptr.p_double[i],0) )
22249  {
22250  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);
22251  relcnt = relcnt+1;
22252  }
22253  }
22254  if( relcnt!=0 )
22255  {
22256  rep->avgrelerror = rep->avgrelerror/relcnt;
22257  }
22258  ae_frame_leave(_state);
22259 }
22260 
22261 
22262 /*************************************************************************
22263 Internal fitting subroutine
22264 *************************************************************************/
22265 static void lsfit_lsfitlinearinternal(/* Real */ ae_vector* y,
22266  /* Real */ ae_vector* w,
22267  /* Real */ ae_matrix* fmatrix,
22268  ae_int_t n,
22269  ae_int_t m,
22270  ae_int_t* info,
22271  /* Real */ ae_vector* c,
22272  lsfitreport* rep,
22273  ae_state *_state)
22274 {
22275  ae_frame _frame_block;
22276  double threshold;
22277  ae_matrix ft;
22278  ae_matrix q;
22279  ae_matrix l;
22280  ae_matrix r;
22281  ae_vector b;
22282  ae_vector wmod;
22283  ae_vector tau;
22284  ae_vector nzeros;
22285  ae_vector s;
22286  ae_int_t i;
22287  ae_int_t j;
22288  double v;
22289  ae_vector sv;
22290  ae_matrix u;
22291  ae_matrix vt;
22292  ae_vector tmp;
22293  ae_vector utb;
22294  ae_vector sutb;
22295  ae_int_t relcnt;
22296 
22297  ae_frame_make(_state, &_frame_block);
22298  *info = 0;
22299  ae_vector_clear(c);
22300  _lsfitreport_clear(rep);
22301  ae_matrix_init(&ft, 0, 0, DT_REAL, _state, ae_true);
22302  ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
22303  ae_matrix_init(&l, 0, 0, DT_REAL, _state, ae_true);
22304  ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true);
22305  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
22306  ae_vector_init(&wmod, 0, DT_REAL, _state, ae_true);
22307  ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
22308  ae_vector_init(&nzeros, 0, DT_REAL, _state, ae_true);
22309  ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
22310  ae_vector_init(&sv, 0, DT_REAL, _state, ae_true);
22311  ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
22312  ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
22313  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
22314  ae_vector_init(&utb, 0, DT_REAL, _state, ae_true);
22315  ae_vector_init(&sutb, 0, DT_REAL, _state, ae_true);
22316 
22317  lsfit_clearreport(rep, _state);
22318  if( n<1||m<1 )
22319  {
22320  *info = -1;
22321  ae_frame_leave(_state);
22322  return;
22323  }
22324  *info = 1;
22325  threshold = ae_sqrt(ae_machineepsilon, _state);
22326 
22327  /*
22328  * Degenerate case, needs special handling
22329  */
22330  if( n<m )
22331  {
22332 
22333  /*
22334  * Create design matrix.
22335  */
22336  ae_matrix_set_length(&ft, n, m, _state);
22337  ae_vector_set_length(&b, n, _state);
22338  ae_vector_set_length(&wmod, n, _state);
22339  for(j=0; j<=n-1; j++)
22340  {
22341  v = w->ptr.p_double[j];
22342  ae_v_moved(&ft.ptr.pp_double[j][0], 1, &fmatrix->ptr.pp_double[j][0], 1, ae_v_len(0,m-1), v);
22343  b.ptr.p_double[j] = w->ptr.p_double[j]*y->ptr.p_double[j];
22344  wmod.ptr.p_double[j] = 1;
22345  }
22346 
22347  /*
22348  * LQ decomposition and reduction to M=N
22349  */
22350  ae_vector_set_length(c, m, _state);
22351  for(i=0; i<=m-1; i++)
22352  {
22353  c->ptr.p_double[i] = 0;
22354  }
22355  rep->taskrcond = 0;
22356  rmatrixlq(&ft, n, m, &tau, _state);
22357  rmatrixlqunpackq(&ft, n, m, &tau, n, &q, _state);
22358  rmatrixlqunpackl(&ft, n, m, &l, _state);
22359  lsfit_lsfitlinearinternal(&b, &wmod, &l, n, n, info, &tmp, rep, _state);
22360  if( *info<=0 )
22361  {
22362  ae_frame_leave(_state);
22363  return;
22364  }
22365  for(i=0; i<=n-1; i++)
22366  {
22367  v = tmp.ptr.p_double[i];
22368  ae_v_addd(&c->ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
22369  }
22370  ae_frame_leave(_state);
22371  return;
22372  }
22373 
22374  /*
22375  * N>=M. Generate design matrix and reduce to N=M using
22376  * QR decomposition.
22377  */
22378  ae_matrix_set_length(&ft, n, m, _state);
22379  ae_vector_set_length(&b, n, _state);
22380  for(j=0; j<=n-1; j++)
22381  {
22382  v = w->ptr.p_double[j];
22383  ae_v_moved(&ft.ptr.pp_double[j][0], 1, &fmatrix->ptr.pp_double[j][0], 1, ae_v_len(0,m-1), v);
22384  b.ptr.p_double[j] = w->ptr.p_double[j]*y->ptr.p_double[j];
22385  }
22386  rmatrixqr(&ft, n, m, &tau, _state);
22387  rmatrixqrunpackq(&ft, n, m, &tau, m, &q, _state);
22388  rmatrixqrunpackr(&ft, n, m, &r, _state);
22389  ae_vector_set_length(&tmp, m, _state);
22390  for(i=0; i<=m-1; i++)
22391  {
22392  tmp.ptr.p_double[i] = 0;
22393  }
22394  for(i=0; i<=n-1; i++)
22395  {
22396  v = b.ptr.p_double[i];
22397  ae_v_addd(&tmp.ptr.p_double[0], 1, &q.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
22398  }
22399  ae_vector_set_length(&b, m, _state);
22400  ae_v_move(&b.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
22401 
22402  /*
22403  * R contains reduced MxM design upper triangular matrix,
22404  * B contains reduced Mx1 right part.
22405  *
22406  * Determine system condition number and decide
22407  * should we use triangular solver (faster) or
22408  * SVD-based solver (more stable).
22409  *
22410  * We can use LU-based RCond estimator for this task.
22411  */
22412  rep->taskrcond = rmatrixlurcondinf(&r, m, _state);
22413  if( ae_fp_greater(rep->taskrcond,threshold) )
22414  {
22415 
22416  /*
22417  * use QR-based solver
22418  */
22419  ae_vector_set_length(c, m, _state);
22420  c->ptr.p_double[m-1] = b.ptr.p_double[m-1]/r.ptr.pp_double[m-1][m-1];
22421  for(i=m-2; i>=0; i--)
22422  {
22423  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));
22424  c->ptr.p_double[i] = (b.ptr.p_double[i]-v)/r.ptr.pp_double[i][i];
22425  }
22426  }
22427  else
22428  {
22429 
22430  /*
22431  * use SVD-based solver
22432  */
22433  if( !rmatrixsvd(&r, m, m, 1, 1, 2, &sv, &u, &vt, _state) )
22434  {
22435  *info = -4;
22436  ae_frame_leave(_state);
22437  return;
22438  }
22439  ae_vector_set_length(&utb, m, _state);
22440  ae_vector_set_length(&sutb, m, _state);
22441  for(i=0; i<=m-1; i++)
22442  {
22443  utb.ptr.p_double[i] = 0;
22444  }
22445  for(i=0; i<=m-1; i++)
22446  {
22447  v = b.ptr.p_double[i];
22448  ae_v_addd(&utb.ptr.p_double[0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
22449  }
22450  if( ae_fp_greater(sv.ptr.p_double[0],0) )
22451  {
22452  rep->taskrcond = sv.ptr.p_double[m-1]/sv.ptr.p_double[0];
22453  for(i=0; i<=m-1; i++)
22454  {
22455  if( ae_fp_greater(sv.ptr.p_double[i],threshold*sv.ptr.p_double[0]) )
22456  {
22457  sutb.ptr.p_double[i] = utb.ptr.p_double[i]/sv.ptr.p_double[i];
22458  }
22459  else
22460  {
22461  sutb.ptr.p_double[i] = 0;
22462  }
22463  }
22464  }
22465  else
22466  {
22467  rep->taskrcond = 0;
22468  for(i=0; i<=m-1; i++)
22469  {
22470  sutb.ptr.p_double[i] = 0;
22471  }
22472  }
22473  ae_vector_set_length(c, m, _state);
22474  for(i=0; i<=m-1; i++)
22475  {
22476  c->ptr.p_double[i] = 0;
22477  }
22478  for(i=0; i<=m-1; i++)
22479  {
22480  v = sutb.ptr.p_double[i];
22481  ae_v_addd(&c->ptr.p_double[0], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
22482  }
22483  }
22484 
22485  /*
22486  * calculate errors
22487  */
22488  rep->rmserror = 0;
22489  rep->avgerror = 0;
22490  rep->avgrelerror = 0;
22491  rep->maxerror = 0;
22492  relcnt = 0;
22493  for(i=0; i<=n-1; i++)
22494  {
22495  v = ae_v_dotproduct(&fmatrix->ptr.pp_double[i][0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1));
22496  rep->rmserror = rep->rmserror+ae_sqr(v-y->ptr.p_double[i], _state);
22497  rep->avgerror = rep->avgerror+ae_fabs(v-y->ptr.p_double[i], _state);
22498  if( ae_fp_neq(y->ptr.p_double[i],0) )
22499  {
22500  rep->avgrelerror = rep->avgrelerror+ae_fabs(v-y->ptr.p_double[i], _state)/ae_fabs(y->ptr.p_double[i], _state);
22501  relcnt = relcnt+1;
22502  }
22503  rep->maxerror = ae_maxreal(rep->maxerror, ae_fabs(v-y->ptr.p_double[i], _state), _state);
22504  }
22505  rep->rmserror = ae_sqrt(rep->rmserror/n, _state);
22506  rep->avgerror = rep->avgerror/n;
22507  if( relcnt!=0 )
22508  {
22509  rep->avgrelerror = rep->avgrelerror/relcnt;
22510  }
22511  ae_vector_set_length(&nzeros, n, _state);
22512  ae_vector_set_length(&s, m, _state);
22513  for(i=0; i<=m-1; i++)
22514  {
22515  s.ptr.p_double[i] = 0;
22516  }
22517  for(i=0; i<=n-1; i++)
22518  {
22519  for(j=0; j<=m-1; j++)
22520  {
22521  s.ptr.p_double[j] = s.ptr.p_double[j]+ae_sqr(fmatrix->ptr.pp_double[i][j], _state);
22522  }
22523  nzeros.ptr.p_double[i] = 0;
22524  }
22525  for(i=0; i<=m-1; i++)
22526  {
22527  if( ae_fp_neq(s.ptr.p_double[i],0) )
22528  {
22529  s.ptr.p_double[i] = ae_sqrt(1/s.ptr.p_double[i], _state);
22530  }
22531  else
22532  {
22533  s.ptr.p_double[i] = 1;
22534  }
22535  }
22536  lsfit_estimateerrors(fmatrix, &nzeros, y, w, c, &s, n, m, rep, &r, 1, _state);
22537  ae_frame_leave(_state);
22538 }
22539 
22540 
22541 /*************************************************************************
22542 Internal subroutine
22543 *************************************************************************/
22544 static void lsfit_lsfitclearrequestfields(lsfitstate* state,
22545  ae_state *_state)
22546 {
22547 
22548 
22549  state->needf = ae_false;
22550  state->needfg = ae_false;
22551  state->needfgh = ae_false;
22552  state->xupdated = ae_false;
22553 }
22554 
22555 
22556 /*************************************************************************
22557 Internal subroutine, calculates barycentric basis functions.
22558 Used for efficient simultaneous calculation of N basis functions.
22559 
22560  -- ALGLIB --
22561  Copyright 17.08.2009 by Bochkanov Sergey
22562 *************************************************************************/
22563 static void lsfit_barycentriccalcbasis(barycentricinterpolant* b,
22564  double t,
22565  /* Real */ ae_vector* y,
22566  ae_state *_state)
22567 {
22568  double s2;
22569  double s;
22570  double v;
22571  ae_int_t i;
22572  ae_int_t j;
22573 
22574 
22575 
22576  /*
22577  * special case: N=1
22578  */
22579  if( b->n==1 )
22580  {
22581  y->ptr.p_double[0] = 1;
22582  return;
22583  }
22584 
22585  /*
22586  * Here we assume that task is normalized, i.e.:
22587  * 1. abs(Y[i])<=1
22588  * 2. abs(W[i])<=1
22589  * 3. X[] is ordered
22590  *
22591  * First, we decide: should we use "safe" formula (guarded
22592  * against overflow) or fast one?
22593  */
22594  s = ae_fabs(t-b->x.ptr.p_double[0], _state);
22595  for(i=0; i<=b->n-1; i++)
22596  {
22597  v = b->x.ptr.p_double[i];
22598  if( ae_fp_eq(v,t) )
22599  {
22600  for(j=0; j<=b->n-1; j++)
22601  {
22602  y->ptr.p_double[j] = 0;
22603  }
22604  y->ptr.p_double[i] = 1;
22605  return;
22606  }
22607  v = ae_fabs(t-v, _state);
22608  if( ae_fp_less(v,s) )
22609  {
22610  s = v;
22611  }
22612  }
22613  s2 = 0;
22614  for(i=0; i<=b->n-1; i++)
22615  {
22616  v = s/(t-b->x.ptr.p_double[i]);
22617  v = v*b->w.ptr.p_double[i];
22618  y->ptr.p_double[i] = v;
22619  s2 = s2+v;
22620  }
22621  v = 1/s2;
22622  ae_v_muld(&y->ptr.p_double[0], 1, ae_v_len(0,b->n-1), v);
22623 }
22624 
22625 
22626 /*************************************************************************
22627 This is internal function for Chebyshev fitting.
22628 
22629 It assumes that input data are normalized:
22630 * X/XC belong to [-1,+1],
22631 * mean(Y)=0, stddev(Y)=1.
22632 
22633 It does not checks inputs for errors.
22634 
22635 This function is used to fit general (shifted) Chebyshev models, power
22636 basis models or barycentric models.
22637 
22638 INPUT PARAMETERS:
22639  X - points, array[0..N-1].
22640  Y - function values, array[0..N-1].
22641  W - weights, array[0..N-1]
22642  N - number of points, N>0.
22643  XC - points where polynomial values/derivatives are constrained,
22644  array[0..K-1].
22645  YC - values of constraints, array[0..K-1]
22646  DC - array[0..K-1], types of constraints:
22647  * DC[i]=0 means that P(XC[i])=YC[i]
22648  * DC[i]=1 means that P'(XC[i])=YC[i]
22649  K - number of constraints, 0<=K<M.
22650  K=0 means no constraints (XC/YC/DC are not used in such cases)
22651  M - number of basis functions (= polynomial_degree + 1), M>=1
22652 
22653 OUTPUT PARAMETERS:
22654  Info- same format as in LSFitLinearW() subroutine:
22655  * Info>0 task is solved
22656  * Info<=0 an error occurred:
22657  -4 means inconvergence of internal SVD
22658  -3 means inconsistent constraints
22659  C - interpolant in Chebyshev form; [-1,+1] is used as base interval
22660  Rep - report, same format as in LSFitLinearW() subroutine.
22661  Following fields are set:
22662  * RMSError rms error on the (X,Y).
22663  * AvgError average error on the (X,Y).
22664  * AvgRelError average relative error on the non-zero Y
22665  * MaxError maximum error
22666  NON-WEIGHTED ERRORS ARE CALCULATED
22667 
22668 IMPORTANT:
22669  this subroitine doesn't calculate task's condition number for K<>0.
22670 
22671  -- ALGLIB PROJECT --
22672  Copyright 10.12.2009 by Bochkanov Sergey
22673 *************************************************************************/
22674 static void lsfit_internalchebyshevfit(/* Real */ ae_vector* x,
22675  /* Real */ ae_vector* y,
22676  /* Real */ ae_vector* w,
22677  ae_int_t n,
22678  /* Real */ ae_vector* xc,
22679  /* Real */ ae_vector* yc,
22680  /* Integer */ ae_vector* dc,
22681  ae_int_t k,
22682  ae_int_t m,
22683  ae_int_t* info,
22684  /* Real */ ae_vector* c,
22685  lsfitreport* rep,
22686  ae_state *_state)
22687 {
22688  ae_frame _frame_block;
22689  ae_vector _xc;
22690  ae_vector _yc;
22691  ae_vector y2;
22692  ae_vector w2;
22693  ae_vector tmp;
22694  ae_vector tmp2;
22695  ae_vector tmpdiff;
22696  ae_vector bx;
22697  ae_vector by;
22698  ae_vector bw;
22699  ae_matrix fmatrix;
22700  ae_matrix cmatrix;
22701  ae_int_t i;
22702  ae_int_t j;
22703  double mx;
22704  double decay;
22705 
22706  ae_frame_make(_state, &_frame_block);
22707  ae_vector_init_copy(&_xc, xc, _state, ae_true);
22708  xc = &_xc;
22709  ae_vector_init_copy(&_yc, yc, _state, ae_true);
22710  yc = &_yc;
22711  *info = 0;
22712  ae_vector_clear(c);
22713  _lsfitreport_clear(rep);
22714  ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
22715  ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
22716  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
22717  ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
22718  ae_vector_init(&tmpdiff, 0, DT_REAL, _state, ae_true);
22719  ae_vector_init(&bx, 0, DT_REAL, _state, ae_true);
22720  ae_vector_init(&by, 0, DT_REAL, _state, ae_true);
22721  ae_vector_init(&bw, 0, DT_REAL, _state, ae_true);
22722  ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
22723  ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true);
22724 
22725  lsfit_clearreport(rep, _state);
22726 
22727  /*
22728  * weight decay for correct handling of task which becomes
22729  * degenerate after constraints are applied
22730  */
22731  decay = 10000*ae_machineepsilon;
22732 
22733  /*
22734  * allocate space, initialize/fill:
22735  * * FMatrix- values of basis functions at X[]
22736  * * CMatrix- values (derivatives) of basis functions at XC[]
22737  * * fill constraints matrix
22738  * * fill first N rows of design matrix with values
22739  * * fill next M rows of design matrix with regularizing term
22740  * * append M zeros to Y
22741  * * append M elements, mean(abs(W)) each, to W
22742  */
22743  ae_vector_set_length(&y2, n+m, _state);
22744  ae_vector_set_length(&w2, n+m, _state);
22745  ae_vector_set_length(&tmp, m, _state);
22746  ae_vector_set_length(&tmpdiff, m, _state);
22747  ae_matrix_set_length(&fmatrix, n+m, m, _state);
22748  if( k>0 )
22749  {
22750  ae_matrix_set_length(&cmatrix, k, m+1, _state);
22751  }
22752 
22753  /*
22754  * Fill design matrix, Y2, W2:
22755  * * first N rows with basis functions for original points
22756  * * next M rows with decay terms
22757  */
22758  for(i=0; i<=n-1; i++)
22759  {
22760 
22761  /*
22762  * prepare Ith row
22763  * use Tmp for calculations to avoid multidimensional arrays overhead
22764  */
22765  for(j=0; j<=m-1; j++)
22766  {
22767  if( j==0 )
22768  {
22769  tmp.ptr.p_double[j] = 1;
22770  }
22771  else
22772  {
22773  if( j==1 )
22774  {
22775  tmp.ptr.p_double[j] = x->ptr.p_double[i];
22776  }
22777  else
22778  {
22779  tmp.ptr.p_double[j] = 2*x->ptr.p_double[i]*tmp.ptr.p_double[j-1]-tmp.ptr.p_double[j-2];
22780  }
22781  }
22782  }
22783  ae_v_move(&fmatrix.ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
22784  }
22785  for(i=0; i<=m-1; i++)
22786  {
22787  for(j=0; j<=m-1; j++)
22788  {
22789  if( i==j )
22790  {
22791  fmatrix.ptr.pp_double[n+i][j] = decay;
22792  }
22793  else
22794  {
22795  fmatrix.ptr.pp_double[n+i][j] = 0;
22796  }
22797  }
22798  }
22799  ae_v_move(&y2.ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
22800  ae_v_move(&w2.ptr.p_double[0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,n-1));
22801  mx = 0;
22802  for(i=0; i<=n-1; i++)
22803  {
22804  mx = mx+ae_fabs(w->ptr.p_double[i], _state);
22805  }
22806  mx = mx/n;
22807  for(i=0; i<=m-1; i++)
22808  {
22809  y2.ptr.p_double[n+i] = 0;
22810  w2.ptr.p_double[n+i] = mx;
22811  }
22812 
22813  /*
22814  * fill constraints matrix
22815  */
22816  for(i=0; i<=k-1; i++)
22817  {
22818 
22819  /*
22820  * prepare Ith row
22821  * use Tmp for basis function values,
22822  * TmpDiff for basos function derivatives
22823  */
22824  for(j=0; j<=m-1; j++)
22825  {
22826  if( j==0 )
22827  {
22828  tmp.ptr.p_double[j] = 1;
22829  tmpdiff.ptr.p_double[j] = 0;
22830  }
22831  else
22832  {
22833  if( j==1 )
22834  {
22835  tmp.ptr.p_double[j] = xc->ptr.p_double[i];
22836  tmpdiff.ptr.p_double[j] = 1;
22837  }
22838  else
22839  {
22840  tmp.ptr.p_double[j] = 2*xc->ptr.p_double[i]*tmp.ptr.p_double[j-1]-tmp.ptr.p_double[j-2];
22841  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];
22842  }
22843  }
22844  }
22845  if( dc->ptr.p_int[i]==0 )
22846  {
22847  ae_v_move(&cmatrix.ptr.pp_double[i][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
22848  }
22849  if( dc->ptr.p_int[i]==1 )
22850  {
22851  ae_v_move(&cmatrix.ptr.pp_double[i][0], 1, &tmpdiff.ptr.p_double[0], 1, ae_v_len(0,m-1));
22852  }
22853  cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i];
22854  }
22855 
22856  /*
22857  * Solve constrained task
22858  */
22859  if( k>0 )
22860  {
22861 
22862  /*
22863  * solve using regularization
22864  */
22865  lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, c, rep, _state);
22866  }
22867  else
22868  {
22869 
22870  /*
22871  * no constraints, no regularization needed
22872  */
22873  lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, 0, info, c, rep, _state);
22874  }
22875  if( *info<0 )
22876  {
22877  ae_frame_leave(_state);
22878  return;
22879  }
22880  ae_frame_leave(_state);
22881 }
22882 
22883 
22884 /*************************************************************************
22885 Internal Floater-Hormann fitting subroutine for fixed D
22886 *************************************************************************/
22887 static void lsfit_barycentricfitwcfixedd(/* Real */ ae_vector* x,
22888  /* Real */ ae_vector* y,
22889  /* Real */ ae_vector* w,
22890  ae_int_t n,
22891  /* Real */ ae_vector* xc,
22892  /* Real */ ae_vector* yc,
22893  /* Integer */ ae_vector* dc,
22894  ae_int_t k,
22895  ae_int_t m,
22896  ae_int_t d,
22897  ae_int_t* info,
22898  barycentricinterpolant* b,
22899  barycentricfitreport* rep,
22900  ae_state *_state)
22901 {
22902  ae_frame _frame_block;
22903  ae_vector _x;
22904  ae_vector _y;
22905  ae_vector _w;
22906  ae_vector _xc;
22907  ae_vector _yc;
22908  ae_matrix fmatrix;
22909  ae_matrix cmatrix;
22910  ae_vector y2;
22911  ae_vector w2;
22912  ae_vector sx;
22913  ae_vector sy;
22914  ae_vector sbf;
22915  ae_vector xoriginal;
22916  ae_vector yoriginal;
22917  ae_vector tmp;
22918  lsfitreport lrep;
22919  double v0;
22920  double v1;
22921  double mx;
22922  barycentricinterpolant b2;
22923  ae_int_t i;
22924  ae_int_t j;
22925  ae_int_t relcnt;
22926  double xa;
22927  double xb;
22928  double sa;
22929  double sb;
22930  double decay;
22931 
22932  ae_frame_make(_state, &_frame_block);
22933  ae_vector_init_copy(&_x, x, _state, ae_true);
22934  x = &_x;
22935  ae_vector_init_copy(&_y, y, _state, ae_true);
22936  y = &_y;
22937  ae_vector_init_copy(&_w, w, _state, ae_true);
22938  w = &_w;
22939  ae_vector_init_copy(&_xc, xc, _state, ae_true);
22940  xc = &_xc;
22941  ae_vector_init_copy(&_yc, yc, _state, ae_true);
22942  yc = &_yc;
22943  *info = 0;
22944  _barycentricinterpolant_clear(b);
22945  _barycentricfitreport_clear(rep);
22946  ae_matrix_init(&fmatrix, 0, 0, DT_REAL, _state, ae_true);
22947  ae_matrix_init(&cmatrix, 0, 0, DT_REAL, _state, ae_true);
22948  ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
22949  ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
22950  ae_vector_init(&sx, 0, DT_REAL, _state, ae_true);
22951  ae_vector_init(&sy, 0, DT_REAL, _state, ae_true);
22952  ae_vector_init(&sbf, 0, DT_REAL, _state, ae_true);
22953  ae_vector_init(&xoriginal, 0, DT_REAL, _state, ae_true);
22954  ae_vector_init(&yoriginal, 0, DT_REAL, _state, ae_true);
22955  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
22956  _lsfitreport_init(&lrep, _state, ae_true);
22957  _barycentricinterpolant_init(&b2, _state, ae_true);
22958 
22959  if( ((n<1||m<2)||k<0)||k>=m )
22960  {
22961  *info = -1;
22962  ae_frame_leave(_state);
22963  return;
22964  }
22965  for(i=0; i<=k-1; i++)
22966  {
22967  *info = 0;
22968  if( dc->ptr.p_int[i]<0 )
22969  {
22970  *info = -1;
22971  }
22972  if( dc->ptr.p_int[i]>1 )
22973  {
22974  *info = -1;
22975  }
22976  if( *info<0 )
22977  {
22978  ae_frame_leave(_state);
22979  return;
22980  }
22981  }
22982 
22983  /*
22984  * weight decay for correct handling of task which becomes
22985  * degenerate after constraints are applied
22986  */
22987  decay = 10000*ae_machineepsilon;
22988 
22989  /*
22990  * Scale X, Y, XC, YC
22991  */
22992  lsfitscalexy(x, y, w, n, xc, yc, dc, k, &xa, &xb, &sa, &sb, &xoriginal, &yoriginal, _state);
22993 
22994  /*
22995  * allocate space, initialize:
22996  * * FMatrix- values of basis functions at X[]
22997  * * CMatrix- values (derivatives) of basis functions at XC[]
22998  */
22999  ae_vector_set_length(&y2, n+m, _state);
23000  ae_vector_set_length(&w2, n+m, _state);
23001  ae_matrix_set_length(&fmatrix, n+m, m, _state);
23002  if( k>0 )
23003  {
23004  ae_matrix_set_length(&cmatrix, k, m+1, _state);
23005  }
23006  ae_vector_set_length(&y2, n+m, _state);
23007  ae_vector_set_length(&w2, n+m, _state);
23008 
23009  /*
23010  * Prepare design and constraints matrices:
23011  * * fill constraints matrix
23012  * * fill first N rows of design matrix with values
23013  * * fill next M rows of design matrix with regularizing term
23014  * * append M zeros to Y
23015  * * append M elements, mean(abs(W)) each, to W
23016  */
23017  ae_vector_set_length(&sx, m, _state);
23018  ae_vector_set_length(&sy, m, _state);
23019  ae_vector_set_length(&sbf, m, _state);
23020  for(j=0; j<=m-1; j++)
23021  {
23022  sx.ptr.p_double[j] = (double)(2*j)/(double)(m-1)-1;
23023  }
23024  for(i=0; i<=m-1; i++)
23025  {
23026  sy.ptr.p_double[i] = 1;
23027  }
23028  barycentricbuildfloaterhormann(&sx, &sy, m, d, &b2, _state);
23029  mx = 0;
23030  for(i=0; i<=n-1; i++)
23031  {
23032  lsfit_barycentriccalcbasis(&b2, x->ptr.p_double[i], &sbf, _state);
23033  ae_v_move(&fmatrix.ptr.pp_double[i][0], 1, &sbf.ptr.p_double[0], 1, ae_v_len(0,m-1));
23034  y2.ptr.p_double[i] = y->ptr.p_double[i];
23035  w2.ptr.p_double[i] = w->ptr.p_double[i];
23036  mx = mx+ae_fabs(w->ptr.p_double[i], _state)/n;
23037  }
23038  for(i=0; i<=m-1; i++)
23039  {
23040  for(j=0; j<=m-1; j++)
23041  {
23042  if( i==j )
23043  {
23044  fmatrix.ptr.pp_double[n+i][j] = decay;
23045  }
23046  else
23047  {
23048  fmatrix.ptr.pp_double[n+i][j] = 0;
23049  }
23050  }
23051  y2.ptr.p_double[n+i] = 0;
23052  w2.ptr.p_double[n+i] = mx;
23053  }
23054  if( k>0 )
23055  {
23056  for(j=0; j<=m-1; j++)
23057  {
23058  for(i=0; i<=m-1; i++)
23059  {
23060  sy.ptr.p_double[i] = 0;
23061  }
23062  sy.ptr.p_double[j] = 1;
23063  barycentricbuildfloaterhormann(&sx, &sy, m, d, &b2, _state);
23064  for(i=0; i<=k-1; i++)
23065  {
23066  ae_assert(dc->ptr.p_int[i]>=0&&dc->ptr.p_int[i]<=1, "BarycentricFit: internal error!", _state);
23067  barycentricdiff1(&b2, xc->ptr.p_double[i], &v0, &v1, _state);
23068  if( dc->ptr.p_int[i]==0 )
23069  {
23070  cmatrix.ptr.pp_double[i][j] = v0;
23071  }
23072  if( dc->ptr.p_int[i]==1 )
23073  {
23074  cmatrix.ptr.pp_double[i][j] = v1;
23075  }
23076  }
23077  }
23078  for(i=0; i<=k-1; i++)
23079  {
23080  cmatrix.ptr.pp_double[i][m] = yc->ptr.p_double[i];
23081  }
23082  }
23083 
23084  /*
23085  * Solve constrained task
23086  */
23087  if( k>0 )
23088  {
23089 
23090  /*
23091  * solve using regularization
23092  */
23093  lsfitlinearwc(&y2, &w2, &fmatrix, &cmatrix, n+m, m, k, info, &tmp, &lrep, _state);
23094  }
23095  else
23096  {
23097 
23098  /*
23099  * no constraints, no regularization needed
23100  */
23101  lsfitlinearwc(y, w, &fmatrix, &cmatrix, n, m, k, info, &tmp, &lrep, _state);
23102  }
23103  if( *info<0 )
23104  {
23105  ae_frame_leave(_state);
23106  return;
23107  }
23108 
23109  /*
23110  * Generate interpolant and scale it
23111  */
23112  ae_v_move(&sy.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
23113  barycentricbuildfloaterhormann(&sx, &sy, m, d, b, _state);
23114  barycentriclintransx(b, 2/(xb-xa), -(xa+xb)/(xb-xa), _state);
23115  barycentriclintransy(b, sb-sa, sa, _state);
23116 
23117  /*
23118  * Scale absolute errors obtained from LSFitLinearW.
23119  * Relative error should be calculated separately
23120  * (because of shifting/scaling of the task)
23121  */
23122  rep->taskrcond = lrep.taskrcond;
23123  rep->rmserror = lrep.rmserror*(sb-sa);
23124  rep->avgerror = lrep.avgerror*(sb-sa);
23125  rep->maxerror = lrep.maxerror*(sb-sa);
23126  rep->avgrelerror = 0;
23127  relcnt = 0;
23128  for(i=0; i<=n-1; i++)
23129  {
23130  if( ae_fp_neq(yoriginal.ptr.p_double[i],0) )
23131  {
23132  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);
23133  relcnt = relcnt+1;
23134  }
23135  }
23136  if( relcnt!=0 )
23137  {
23138  rep->avgrelerror = rep->avgrelerror/relcnt;
23139  }
23140  ae_frame_leave(_state);
23141 }
23142 
23143 
23144 static void lsfit_clearreport(lsfitreport* rep, ae_state *_state)
23145 {
23146 
23147 
23148  rep->taskrcond = 0;
23149  rep->iterationscount = 0;
23150  rep->varidx = -1;
23151  rep->rmserror = 0;
23152  rep->avgerror = 0;
23153  rep->avgrelerror = 0;
23154  rep->maxerror = 0;
23155  rep->wrmserror = 0;
23156  rep->r2 = 0;
23157  ae_matrix_set_length(&rep->covpar, 0, 0, _state);
23158  ae_vector_set_length(&rep->errpar, 0, _state);
23159  ae_vector_set_length(&rep->errcurve, 0, _state);
23160  ae_vector_set_length(&rep->noise, 0, _state);
23161 }
23162 
23163 
23164 /*************************************************************************
23165 This internal function estimates covariance matrix and other error-related
23166 information for linear/nonlinear least squares model.
23167 
23168 It has a bit awkward interface, but it can be used for both linear and
23169 nonlinear problems.
23170 
23171 INPUT PARAMETERS:
23172  F1 - array[0..N-1,0..K-1]:
23173  * for linear problems - matrix of function values
23174  * for nonlinear problems - Jacobian matrix
23175  F0 - array[0..N-1]:
23176  * for linear problems - must be filled with zeros
23177  * for nonlinear problems - must store values of function being
23178  fitted
23179  Y - array[0..N-1]:
23180  * for linear and nonlinear problems - must store target values
23181  W - weights, array[0..N-1]:
23182  * for linear and nonlinear problems - weights
23183  X - array[0..K-1]:
23184  * for linear and nonlinear problems - current solution
23185  S - array[0..K-1]:
23186  * its components should be strictly positive
23187  * squared inverse of this diagonal matrix is used as damping
23188  factor for covariance matrix (linear and nonlinear problems)
23189  * for nonlinear problems, when scale of the variables is usually
23190  explicitly given by user, you may use scale vector for this
23191  parameter
23192  * for linear problems you may set this parameter to
23193  S=sqrt(1/diag(F'*F))
23194  * this parameter is automatically rescaled by this function,
23195  only relative magnitudes of its components (with respect to
23196  each other) matter.
23197  N - number of points, N>0.
23198  K - number of dimensions
23199  Rep - structure which is used to store results
23200  Z - additional matrix which, depending on ZKind, may contain some
23201  information used to accelerate calculations - or just can be
23202  temporary buffer:
23203  * for ZKind=0 Z contains no information, just temporary
23204  buffer which can be resized and used as needed
23205  * for ZKind=1 Z contains triangular matrix from QR
23206  decomposition of W*F1. This matrix can be used
23207  to speedup calculation of covariance matrix.
23208  It should not be changed by algorithm.
23209  ZKind- contents of Z
23210 
23211 OUTPUT PARAMETERS:
23212 
23213 * Rep.CovPar covariance matrix for parameters, array[K,K].
23214 * Rep.ErrPar errors in parameters, array[K],
23215  errpar = sqrt(diag(CovPar))
23216 * Rep.ErrCurve vector of fit errors - standard deviations of empirical
23217  best-fit curve from "ideal" best-fit curve built with
23218  infinite number of samples, array[N].
23219  errcurve = sqrt(diag(J*CovPar*J')),
23220  where J is Jacobian matrix.
23221 * Rep.Noise vector of per-point estimates of noise, array[N]
23222 * Rep.R2 coefficient of determination (non-weighted)
23223 
23224 Other fields of Rep are not changed.
23225 
23226 IMPORTANT: errors in parameters are calculated without taking into
23227  account boundary/linear constraints! Presence of constraints
23228  changes distribution of errors, but there is no easy way to
23229  account for constraints when you calculate covariance matrix.
23230 
23231 NOTE: noise in the data is estimated as follows:
23232  * for fitting without user-supplied weights all points are
23233  assumed to have same level of noise, which is estimated from
23234  the data
23235  * for fitting with user-supplied weights we assume that noise
23236  level in I-th point is inversely proportional to Ith weight.
23237  Coefficient of proportionality is estimated from the data.
23238 
23239 NOTE: we apply small amount of regularization when we invert squared
23240  Jacobian and calculate covariance matrix. It guarantees that
23241  algorithm won't divide by zero during inversion, but skews
23242  error estimates a bit (fractional error is about 10^-9).
23243 
23244  However, we believe that this difference is insignificant for
23245  all practical purposes except for the situation when you want
23246  to compare ALGLIB results with "reference" implementation up
23247  to the last significant digit.
23248 
23249  -- ALGLIB PROJECT --
23250  Copyright 10.12.2009 by Bochkanov Sergey
23251 *************************************************************************/
23252 static void lsfit_estimateerrors(/* Real */ ae_matrix* f1,
23253  /* Real */ ae_vector* f0,
23254  /* Real */ ae_vector* y,
23255  /* Real */ ae_vector* w,
23256  /* Real */ ae_vector* x,
23257  /* Real */ ae_vector* s,
23258  ae_int_t n,
23259  ae_int_t k,
23260  lsfitreport* rep,
23261  /* Real */ ae_matrix* z,
23262  ae_int_t zkind,
23263  ae_state *_state)
23264 {
23265  ae_frame _frame_block;
23266  ae_vector _s;
23267  ae_int_t i;
23268  ae_int_t j;
23269  ae_int_t j1;
23270  double v;
23271  double noisec;
23272  ae_int_t info;
23273  matinvreport invrep;
23274  ae_int_t nzcnt;
23275  double avg;
23276  double rss;
23277  double tss;
23278  double sz;
23279  double ss;
23280 
23281  ae_frame_make(_state, &_frame_block);
23282  ae_vector_init_copy(&_s, s, _state, ae_true);
23283  s = &_s;
23284  _matinvreport_init(&invrep, _state, ae_true);
23285 
23286 
23287  /*
23288  * Compute NZCnt - count of non-zero weights
23289  */
23290  nzcnt = 0;
23291  for(i=0; i<=n-1; i++)
23292  {
23293  if( ae_fp_neq(w->ptr.p_double[i],0) )
23294  {
23295  nzcnt = nzcnt+1;
23296  }
23297  }
23298 
23299  /*
23300  * Compute R2
23301  */
23302  if( nzcnt>0 )
23303  {
23304  avg = 0.0;
23305  for(i=0; i<=n-1; i++)
23306  {
23307  if( ae_fp_neq(w->ptr.p_double[i],0) )
23308  {
23309  avg = avg+y->ptr.p_double[i];
23310  }
23311  }
23312  avg = avg/nzcnt;
23313  rss = 0.0;
23314  tss = 0.0;
23315  for(i=0; i<=n-1; i++)
23316  {
23317  if( ae_fp_neq(w->ptr.p_double[i],0) )
23318  {
23319  v = ae_v_dotproduct(&f1->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,k-1));
23320  v = v+f0->ptr.p_double[i];
23321  rss = rss+ae_sqr(v-y->ptr.p_double[i], _state);
23322  tss = tss+ae_sqr(y->ptr.p_double[i]-avg, _state);
23323  }
23324  }
23325  if( ae_fp_neq(tss,0) )
23326  {
23327  rep->r2 = ae_maxreal(1.0-rss/tss, 0.0, _state);
23328  }
23329  else
23330  {
23331  rep->r2 = 1.0;
23332  }
23333  }
23334  else
23335  {
23336  rep->r2 = 0;
23337  }
23338 
23339  /*
23340  * Compute estimate of proportionality between noise in the data and weights:
23341  * NoiseC = mean(per-point-noise*per-point-weight)
23342  * Noise level (standard deviation) at each point is equal to NoiseC/W[I].
23343  */
23344  if( nzcnt>k )
23345  {
23346  noisec = 0.0;
23347  for(i=0; i<=n-1; i++)
23348  {
23349  if( ae_fp_neq(w->ptr.p_double[i],0) )
23350  {
23351  v = ae_v_dotproduct(&f1->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,k-1));
23352  v = v+f0->ptr.p_double[i];
23353  noisec = noisec+ae_sqr((v-y->ptr.p_double[i])*w->ptr.p_double[i], _state);
23354  }
23355  }
23356  noisec = ae_sqrt(noisec/(nzcnt-k), _state);
23357  }
23358  else
23359  {
23360  noisec = 0.0;
23361  }
23362 
23363  /*
23364  * Two branches on noise level:
23365  * * NoiseC>0 normal situation
23366  * * NoiseC=0 degenerate case CovPar is filled by zeros
23367  */
23368  rmatrixsetlengthatleast(&rep->covpar, k, k, _state);
23369  if( ae_fp_greater(noisec,0) )
23370  {
23371 
23372  /*
23373  * Normal situation: non-zero noise level
23374  */
23375  ae_assert(zkind==0||zkind==1, "LSFit: internal error in EstimateErrors() function", _state);
23376  if( zkind==0 )
23377  {
23378 
23379  /*
23380  * Z contains no additional information which can be used to speed up
23381  * calculations. We have to calculate covariance matrix on our own:
23382  * * Compute scaled Jacobian N*J, where N[i,i]=WCur[I]/NoiseC, store in Z
23383  * * Compute Z'*Z, store in CovPar
23384  * * Apply moderate regularization to CovPar and compute matrix inverse.
23385  * In case inverse failed, increase regularization parameter and try
23386  * again.
23387  */
23388  rmatrixsetlengthatleast(z, n, k, _state);
23389  for(i=0; i<=n-1; i++)
23390  {
23391  v = w->ptr.p_double[i]/noisec;
23392  ae_v_moved(&z->ptr.pp_double[i][0], 1, &f1->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
23393  }
23394 
23395  /*
23396  * Convert S to automatically scaled damped matrix:
23397  * * calculate SZ - sum of diagonal elements of Z'*Z
23398  * * calculate SS - sum of diagonal elements of S^(-2)
23399  * * overwrite S by (SZ/SS)*S^(-2)
23400  * * now S has approximately same magnitude as giagonal of Z'*Z
23401  */
23402  sz = 0;
23403  for(i=0; i<=n-1; i++)
23404  {
23405  for(j=0; j<=k-1; j++)
23406  {
23407  sz = sz+z->ptr.pp_double[i][j]*z->ptr.pp_double[i][j];
23408  }
23409  }
23410  if( ae_fp_eq(sz,0) )
23411  {
23412  sz = 1;
23413  }
23414  ss = 0;
23415  for(j=0; j<=k-1; j++)
23416  {
23417  ss = ss+1/ae_sqr(s->ptr.p_double[j], _state);
23418  }
23419  for(j=0; j<=k-1; j++)
23420  {
23421  s->ptr.p_double[j] = sz/ss/ae_sqr(s->ptr.p_double[j], _state);
23422  }
23423 
23424  /*
23425  * Calculate damped inverse inv(Z'*Z+S).
23426  * We increase damping factor V until Z'*Z become well-conditioned.
23427  */
23428  v = 1.0E3*ae_machineepsilon;
23429  do
23430  {
23431  rmatrixsyrk(k, n, 1.0, z, 0, 0, 2, 0.0, &rep->covpar, 0, 0, ae_true, _state);
23432  for(i=0; i<=k-1; i++)
23433  {
23434  rep->covpar.ptr.pp_double[i][i] = rep->covpar.ptr.pp_double[i][i]+v*s->ptr.p_double[i];
23435  }
23436  spdmatrixinverse(&rep->covpar, k, ae_true, &info, &invrep, _state);
23437  v = 10*v;
23438  }
23439  while(info<=0);
23440  for(i=0; i<=k-1; i++)
23441  {
23442  for(j=i+1; j<=k-1; j++)
23443  {
23444  rep->covpar.ptr.pp_double[j][i] = rep->covpar.ptr.pp_double[i][j];
23445  }
23446  }
23447  }
23448  if( zkind==1 )
23449  {
23450 
23451  /*
23452  * We can reuse additional information:
23453  * * Z contains R matrix from QR decomposition of W*F1
23454  * * After multiplication by 1/NoiseC we get Z_mod = N*F1, where diag(N)=w[i]/NoiseC
23455  * * Such triangular Z_mod is a Cholesky factor from decomposition of J'*N'*N*J.
23456  * Thus, we can calculate covariance matrix as inverse of the matrix given by
23457  * its Cholesky decomposition. It allow us to avoid time-consuming calculation
23458  * of J'*N'*N*J in CovPar - complexity is reduced from O(N*K^2) to O(K^3), which
23459  * is quite good because K is usually orders of magnitude smaller than N.
23460  *
23461  * First, convert S to automatically scaled damped matrix:
23462  * * calculate SZ - sum of magnitudes of diagonal elements of Z/NoiseC
23463  * * calculate SS - sum of diagonal elements of S^(-1)
23464  * * overwrite S by (SZ/SS)*S^(-1)
23465  * * now S has approximately same magnitude as giagonal of Z'*Z
23466  */
23467  sz = 0;
23468  for(j=0; j<=k-1; j++)
23469  {
23470  sz = sz+ae_fabs(z->ptr.pp_double[j][j]/noisec, _state);
23471  }
23472  if( ae_fp_eq(sz,0) )
23473  {
23474  sz = 1;
23475  }
23476  ss = 0;
23477  for(j=0; j<=k-1; j++)
23478  {
23479  ss = ss+1/s->ptr.p_double[j];
23480  }
23481  for(j=0; j<=k-1; j++)
23482  {
23483  s->ptr.p_double[j] = sz/ss/s->ptr.p_double[j];
23484  }
23485 
23486  /*
23487  * Calculate damped inverse of inv((Z+v*S)'*(Z+v*S))
23488  * We increase damping factor V until matrix become well-conditioned.
23489  */
23490  v = 1.0E3*ae_machineepsilon;
23491  do
23492  {
23493  for(i=0; i<=k-1; i++)
23494  {
23495  for(j=i; j<=k-1; j++)
23496  {
23497  rep->covpar.ptr.pp_double[i][j] = z->ptr.pp_double[i][j]/noisec;
23498  }
23499  rep->covpar.ptr.pp_double[i][i] = rep->covpar.ptr.pp_double[i][i]+v*s->ptr.p_double[i];
23500  }
23501  spdmatrixcholeskyinverse(&rep->covpar, k, ae_true, &info, &invrep, _state);
23502  v = 10*v;
23503  }
23504  while(info<=0);
23505  for(i=0; i<=k-1; i++)
23506  {
23507  for(j=i+1; j<=k-1; j++)
23508  {
23509  rep->covpar.ptr.pp_double[j][i] = rep->covpar.ptr.pp_double[i][j];
23510  }
23511  }
23512  }
23513  }
23514  else
23515  {
23516 
23517  /*
23518  * Degenerate situation: zero noise level, covariance matrix is zero.
23519  */
23520  for(i=0; i<=k-1; i++)
23521  {
23522  for(j=0; j<=k-1; j++)
23523  {
23524  rep->covpar.ptr.pp_double[j][i] = 0;
23525  }
23526  }
23527  }
23528 
23529  /*
23530  * Estimate erorrs in parameters, curve and per-point noise
23531  */
23532  rvectorsetlengthatleast(&rep->errpar, k, _state);
23533  rvectorsetlengthatleast(&rep->errcurve, n, _state);
23534  rvectorsetlengthatleast(&rep->noise, n, _state);
23535  for(i=0; i<=k-1; i++)
23536  {
23537  rep->errpar.ptr.p_double[i] = ae_sqrt(rep->covpar.ptr.pp_double[i][i], _state);
23538  }
23539  for(i=0; i<=n-1; i++)
23540  {
23541 
23542  /*
23543  * ErrCurve[I] is sqrt(P[i,i]) where P=J*CovPar*J'
23544  */
23545  v = 0.0;
23546  for(j=0; j<=k-1; j++)
23547  {
23548  for(j1=0; j1<=k-1; j1++)
23549  {
23550  v = v+f1->ptr.pp_double[i][j]*rep->covpar.ptr.pp_double[j][j1]*f1->ptr.pp_double[i][j1];
23551  }
23552  }
23553  rep->errcurve.ptr.p_double[i] = ae_sqrt(v, _state);
23554 
23555  /*
23556  * Noise[i] is filled using weights and current estimate of noise level
23557  */
23558  if( ae_fp_neq(w->ptr.p_double[i],0) )
23559  {
23560  rep->noise.ptr.p_double[i] = noisec/w->ptr.p_double[i];
23561  }
23562  else
23563  {
23564  rep->noise.ptr.p_double[i] = 0;
23565  }
23566  }
23567  ae_frame_leave(_state);
23568 }
23569 
23570 
23571 ae_bool _polynomialfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
23572 {
23573  polynomialfitreport *p = (polynomialfitreport*)_p;
23574  ae_touch_ptr((void*)p);
23575  return ae_true;
23576 }
23577 
23578 
23579 ae_bool _polynomialfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
23580 {
23581  polynomialfitreport *dst = (polynomialfitreport*)_dst;
23582  polynomialfitreport *src = (polynomialfitreport*)_src;
23583  dst->taskrcond = src->taskrcond;
23584  dst->rmserror = src->rmserror;
23585  dst->avgerror = src->avgerror;
23586  dst->avgrelerror = src->avgrelerror;
23587  dst->maxerror = src->maxerror;
23588  return ae_true;
23589 }
23590 
23591 
23592 void _polynomialfitreport_clear(void* _p)
23593 {
23594  polynomialfitreport *p = (polynomialfitreport*)_p;
23595  ae_touch_ptr((void*)p);
23596 }
23597 
23598 
23599 void _polynomialfitreport_destroy(void* _p)
23600 {
23601  polynomialfitreport *p = (polynomialfitreport*)_p;
23602  ae_touch_ptr((void*)p);
23603 }
23604 
23605 
23606 ae_bool _barycentricfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
23607 {
23608  barycentricfitreport *p = (barycentricfitreport*)_p;
23609  ae_touch_ptr((void*)p);
23610  return ae_true;
23611 }
23612 
23613 
23614 ae_bool _barycentricfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
23615 {
23616  barycentricfitreport *dst = (barycentricfitreport*)_dst;
23617  barycentricfitreport *src = (barycentricfitreport*)_src;
23618  dst->taskrcond = src->taskrcond;
23619  dst->dbest = src->dbest;
23620  dst->rmserror = src->rmserror;
23621  dst->avgerror = src->avgerror;
23622  dst->avgrelerror = src->avgrelerror;
23623  dst->maxerror = src->maxerror;
23624  return ae_true;
23625 }
23626 
23627 
23628 void _barycentricfitreport_clear(void* _p)
23629 {
23630  barycentricfitreport *p = (barycentricfitreport*)_p;
23631  ae_touch_ptr((void*)p);
23632 }
23633 
23634 
23635 void _barycentricfitreport_destroy(void* _p)
23636 {
23637  barycentricfitreport *p = (barycentricfitreport*)_p;
23638  ae_touch_ptr((void*)p);
23639 }
23640 
23641 
23642 ae_bool _spline1dfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
23643 {
23644  spline1dfitreport *p = (spline1dfitreport*)_p;
23645  ae_touch_ptr((void*)p);
23646  return ae_true;
23647 }
23648 
23649 
23650 ae_bool _spline1dfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
23651 {
23652  spline1dfitreport *dst = (spline1dfitreport*)_dst;
23653  spline1dfitreport *src = (spline1dfitreport*)_src;
23654  dst->taskrcond = src->taskrcond;
23655  dst->rmserror = src->rmserror;
23656  dst->avgerror = src->avgerror;
23657  dst->avgrelerror = src->avgrelerror;
23658  dst->maxerror = src->maxerror;
23659  return ae_true;
23660 }
23661 
23662 
23663 void _spline1dfitreport_clear(void* _p)
23664 {
23665  spline1dfitreport *p = (spline1dfitreport*)_p;
23666  ae_touch_ptr((void*)p);
23667 }
23668 
23669 
23670 void _spline1dfitreport_destroy(void* _p)
23671 {
23672  spline1dfitreport *p = (spline1dfitreport*)_p;
23673  ae_touch_ptr((void*)p);
23674 }
23675 
23676 
23677 ae_bool _lsfitreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
23678 {
23679  lsfitreport *p = (lsfitreport*)_p;
23680  ae_touch_ptr((void*)p);
23681  if( !ae_matrix_init(&p->covpar, 0, 0, DT_REAL, _state, make_automatic) )
23682  return ae_false;
23683  if( !ae_vector_init(&p->errpar, 0, DT_REAL, _state, make_automatic) )
23684  return ae_false;
23685  if( !ae_vector_init(&p->errcurve, 0, DT_REAL, _state, make_automatic) )
23686  return ae_false;
23687  if( !ae_vector_init(&p->noise, 0, DT_REAL, _state, make_automatic) )
23688  return ae_false;
23689  return ae_true;
23690 }
23691 
23692 
23693 ae_bool _lsfitreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
23694 {
23695  lsfitreport *dst = (lsfitreport*)_dst;
23696  lsfitreport *src = (lsfitreport*)_src;
23697  dst->taskrcond = src->taskrcond;
23698  dst->iterationscount = src->iterationscount;
23699  dst->varidx = src->varidx;
23700  dst->rmserror = src->rmserror;
23701  dst->avgerror = src->avgerror;
23702  dst->avgrelerror = src->avgrelerror;
23703  dst->maxerror = src->maxerror;
23704  dst->wrmserror = src->wrmserror;
23705  if( !ae_matrix_init_copy(&dst->covpar, &src->covpar, _state, make_automatic) )
23706  return ae_false;
23707  if( !ae_vector_init_copy(&dst->errpar, &src->errpar, _state, make_automatic) )
23708  return ae_false;
23709  if( !ae_vector_init_copy(&dst->errcurve, &src->errcurve, _state, make_automatic) )
23710  return ae_false;
23711  if( !ae_vector_init_copy(&dst->noise, &src->noise, _state, make_automatic) )
23712  return ae_false;
23713  dst->r2 = src->r2;
23714  return ae_true;
23715 }
23716 
23717 
23718 void _lsfitreport_clear(void* _p)
23719 {
23720  lsfitreport *p = (lsfitreport*)_p;
23721  ae_touch_ptr((void*)p);
23722  ae_matrix_clear(&p->covpar);
23723  ae_vector_clear(&p->errpar);
23724  ae_vector_clear(&p->errcurve);
23725  ae_vector_clear(&p->noise);
23726 }
23727 
23728 
23729 void _lsfitreport_destroy(void* _p)
23730 {
23731  lsfitreport *p = (lsfitreport*)_p;
23732  ae_touch_ptr((void*)p);
23733  ae_matrix_destroy(&p->covpar);
23734  ae_vector_destroy(&p->errpar);
23735  ae_vector_destroy(&p->errcurve);
23736  ae_vector_destroy(&p->noise);
23737 }
23738 
23739 
23740 ae_bool _lsfitstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
23741 {
23742  lsfitstate *p = (lsfitstate*)_p;
23743  ae_touch_ptr((void*)p);
23744  if( !ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic) )
23745  return ae_false;
23746  if( !ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic) )
23747  return ae_false;
23748  if( !ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic) )
23749  return ae_false;
23750  if( !ae_matrix_init(&p->taskx, 0, 0, DT_REAL, _state, make_automatic) )
23751  return ae_false;
23752  if( !ae_vector_init(&p->tasky, 0, DT_REAL, _state, make_automatic) )
23753  return ae_false;
23754  if( !ae_vector_init(&p->taskw, 0, DT_REAL, _state, make_automatic) )
23755  return ae_false;
23756  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
23757  return ae_false;
23758  if( !ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic) )
23759  return ae_false;
23760  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
23761  return ae_false;
23762  if( !ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic) )
23763  return ae_false;
23764  if( !ae_vector_init(&p->wcur, 0, DT_REAL, _state, make_automatic) )
23765  return ae_false;
23766  if( !ae_vector_init(&p->tmp, 0, DT_REAL, _state, make_automatic) )
23767  return ae_false;
23768  if( !ae_vector_init(&p->tmpf, 0, DT_REAL, _state, make_automatic) )
23769  return ae_false;
23770  if( !ae_matrix_init(&p->tmpjac, 0, 0, DT_REAL, _state, make_automatic) )
23771  return ae_false;
23772  if( !ae_matrix_init(&p->tmpjacw, 0, 0, DT_REAL, _state, make_automatic) )
23773  return ae_false;
23774  if( !_matinvreport_init(&p->invrep, _state, make_automatic) )
23775  return ae_false;
23776  if( !_lsfitreport_init(&p->rep, _state, make_automatic) )
23777  return ae_false;
23778  if( !_minlmstate_init(&p->optstate, _state, make_automatic) )
23779  return ae_false;
23780  if( !_minlmreport_init(&p->optrep, _state, make_automatic) )
23781  return ae_false;
23782  if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
23783  return ae_false;
23784  return ae_true;
23785 }
23786 
23787 
23788 ae_bool _lsfitstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
23789 {
23790  lsfitstate *dst = (lsfitstate*)_dst;
23791  lsfitstate *src = (lsfitstate*)_src;
23792  dst->optalgo = src->optalgo;
23793  dst->m = src->m;
23794  dst->k = src->k;
23795  dst->epsf = src->epsf;
23796  dst->epsx = src->epsx;
23797  dst->maxits = src->maxits;
23798  dst->stpmax = src->stpmax;
23799  dst->xrep = src->xrep;
23800  if( !ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic) )
23801  return ae_false;
23802  if( !ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic) )
23803  return ae_false;
23804  if( !ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic) )
23805  return ae_false;
23806  if( !ae_matrix_init_copy(&dst->taskx, &src->taskx, _state, make_automatic) )
23807  return ae_false;
23808  if( !ae_vector_init_copy(&dst->tasky, &src->tasky, _state, make_automatic) )
23809  return ae_false;
23810  dst->npoints = src->npoints;
23811  if( !ae_vector_init_copy(&dst->taskw, &src->taskw, _state, make_automatic) )
23812  return ae_false;
23813  dst->nweights = src->nweights;
23814  dst->wkind = src->wkind;
23815  dst->wits = src->wits;
23816  dst->diffstep = src->diffstep;
23817  dst->teststep = src->teststep;
23818  dst->xupdated = src->xupdated;
23819  dst->needf = src->needf;
23820  dst->needfg = src->needfg;
23821  dst->needfgh = src->needfgh;
23822  dst->pointindex = src->pointindex;
23823  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
23824  return ae_false;
23825  if( !ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic) )
23826  return ae_false;
23827  dst->f = src->f;
23828  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
23829  return ae_false;
23830  if( !ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic) )
23831  return ae_false;
23832  if( !ae_vector_init_copy(&dst->wcur, &src->wcur, _state, make_automatic) )
23833  return ae_false;
23834  if( !ae_vector_init_copy(&dst->tmp, &src->tmp, _state, make_automatic) )
23835  return ae_false;
23836  if( !ae_vector_init_copy(&dst->tmpf, &src->tmpf, _state, make_automatic) )
23837  return ae_false;
23838  if( !ae_matrix_init_copy(&dst->tmpjac, &src->tmpjac, _state, make_automatic) )
23839  return ae_false;
23840  if( !ae_matrix_init_copy(&dst->tmpjacw, &src->tmpjacw, _state, make_automatic) )
23841  return ae_false;
23842  dst->tmpnoise = src->tmpnoise;
23843  if( !_matinvreport_init_copy(&dst->invrep, &src->invrep, _state, make_automatic) )
23844  return ae_false;
23845  dst->repiterationscount = src->repiterationscount;
23846  dst->repterminationtype = src->repterminationtype;
23847  dst->repvaridx = src->repvaridx;
23848  dst->reprmserror = src->reprmserror;
23849  dst->repavgerror = src->repavgerror;
23850  dst->repavgrelerror = src->repavgrelerror;
23851  dst->repmaxerror = src->repmaxerror;
23852  dst->repwrmserror = src->repwrmserror;
23853  if( !_lsfitreport_init_copy(&dst->rep, &src->rep, _state, make_automatic) )
23854  return ae_false;
23855  if( !_minlmstate_init_copy(&dst->optstate, &src->optstate, _state, make_automatic) )
23856  return ae_false;
23857  if( !_minlmreport_init_copy(&dst->optrep, &src->optrep, _state, make_automatic) )
23858  return ae_false;
23859  dst->prevnpt = src->prevnpt;
23860  dst->prevalgo = src->prevalgo;
23861  if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
23862  return ae_false;
23863  return ae_true;
23864 }
23865 
23866 
23867 void _lsfitstate_clear(void* _p)
23868 {
23869  lsfitstate *p = (lsfitstate*)_p;
23870  ae_touch_ptr((void*)p);
23871  ae_vector_clear(&p->s);
23872  ae_vector_clear(&p->bndl);
23873  ae_vector_clear(&p->bndu);
23874  ae_matrix_clear(&p->taskx);
23875  ae_vector_clear(&p->tasky);
23876  ae_vector_clear(&p->taskw);
23877  ae_vector_clear(&p->x);
23878  ae_vector_clear(&p->c);
23879  ae_vector_clear(&p->g);
23880  ae_matrix_clear(&p->h);
23881  ae_vector_clear(&p->wcur);
23882  ae_vector_clear(&p->tmp);
23883  ae_vector_clear(&p->tmpf);
23884  ae_matrix_clear(&p->tmpjac);
23885  ae_matrix_clear(&p->tmpjacw);
23886  _matinvreport_clear(&p->invrep);
23887  _lsfitreport_clear(&p->rep);
23888  _minlmstate_clear(&p->optstate);
23889  _minlmreport_clear(&p->optrep);
23890  _rcommstate_clear(&p->rstate);
23891 }
23892 
23893 
23894 void _lsfitstate_destroy(void* _p)
23895 {
23896  lsfitstate *p = (lsfitstate*)_p;
23897  ae_touch_ptr((void*)p);
23898  ae_vector_destroy(&p->s);
23899  ae_vector_destroy(&p->bndl);
23900  ae_vector_destroy(&p->bndu);
23901  ae_matrix_destroy(&p->taskx);
23902  ae_vector_destroy(&p->tasky);
23903  ae_vector_destroy(&p->taskw);
23904  ae_vector_destroy(&p->x);
23905  ae_vector_destroy(&p->c);
23906  ae_vector_destroy(&p->g);
23907  ae_matrix_destroy(&p->h);
23908  ae_vector_destroy(&p->wcur);
23909  ae_vector_destroy(&p->tmp);
23910  ae_vector_destroy(&p->tmpf);
23911  ae_matrix_destroy(&p->tmpjac);
23912  ae_matrix_destroy(&p->tmpjacw);
23913  _matinvreport_destroy(&p->invrep);
23914  _lsfitreport_destroy(&p->rep);
23915  _minlmstate_destroy(&p->optstate);
23916  _minlmreport_destroy(&p->optrep);
23917  _rcommstate_destroy(&p->rstate);
23918 }
23919 
23920 
23921 
23922 
23923 /*************************************************************************
23924 This function builds non-periodic 2-dimensional parametric spline which
23925 starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]).
23926 
23927 INPUT PARAMETERS:
23928  XY - points, array[0..N-1,0..1].
23929  XY[I,0:1] corresponds to the Ith point.
23930  Order of points is important!
23931  N - points count, N>=5 for Akima splines, N>=2 for other types of
23932  splines.
23933  ST - spline type:
23934  * 0 Akima spline
23935  * 1 parabolically terminated Catmull-Rom spline (Tension=0)
23936  * 2 parabolically terminated cubic spline
23937  PT - parameterization type:
23938  * 0 uniform
23939  * 1 chord length
23940  * 2 centripetal
23941 
23942 OUTPUT PARAMETERS:
23943  P - parametric spline interpolant
23944 
23945 
23946 NOTES:
23947 * this function assumes that there all consequent points are distinct.
23948  I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
23949  However, non-consequent points may coincide, i.e. we can have (x0,y0)=
23950  =(x2,y2).
23951 
23952  -- ALGLIB PROJECT --
23953  Copyright 28.05.2010 by Bochkanov Sergey
23954 *************************************************************************/
23955 void pspline2build(/* Real */ ae_matrix* xy,
23956  ae_int_t n,
23957  ae_int_t st,
23958  ae_int_t pt,
23959  pspline2interpolant* p,
23960  ae_state *_state)
23961 {
23962  ae_frame _frame_block;
23963  ae_matrix _xy;
23964  ae_vector tmp;
23965 
23966  ae_frame_make(_state, &_frame_block);
23967  ae_matrix_init_copy(&_xy, xy, _state, ae_true);
23968  xy = &_xy;
23969  _pspline2interpolant_clear(p);
23970  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
23971 
23972  ae_assert(st>=0&&st<=2, "PSpline2Build: incorrect spline type!", _state);
23973  ae_assert(pt>=0&&pt<=2, "PSpline2Build: incorrect parameterization type!", _state);
23974  if( st==0 )
23975  {
23976  ae_assert(n>=5, "PSpline2Build: N<5 (minimum value for Akima splines)!", _state);
23977  }
23978  else
23979  {
23980  ae_assert(n>=2, "PSpline2Build: N<2!", _state);
23981  }
23982 
23983  /*
23984  * Prepare
23985  */
23986  p->n = n;
23987  p->periodic = ae_false;
23988  ae_vector_set_length(&tmp, n, _state);
23989 
23990  /*
23991  * Build parameterization, check that all parameters are distinct
23992  */
23993  pspline_pspline2par(xy, n, pt, &p->p, _state);
23994  ae_assert(aredistinct(&p->p, n, _state), "PSpline2Build: consequent points are too close!", _state);
23995 
23996  /*
23997  * Build splines
23998  */
23999  if( st==0 )
24000  {
24001  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
24002  spline1dbuildakima(&p->p, &tmp, n, &p->x, _state);
24003  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
24004  spline1dbuildakima(&p->p, &tmp, n, &p->y, _state);
24005  }
24006  if( st==1 )
24007  {
24008  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
24009  spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->x, _state);
24010  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
24011  spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->y, _state);
24012  }
24013  if( st==2 )
24014  {
24015  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
24016  spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->x, _state);
24017  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
24018  spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->y, _state);
24019  }
24020  ae_frame_leave(_state);
24021 }
24022 
24023 
24024 /*************************************************************************
24025 This function builds non-periodic 3-dimensional parametric spline which
24026 starts at (X[0],Y[0],Z[0]) and ends at (X[N-1],Y[N-1],Z[N-1]).
24027 
24028 Same as PSpline2Build() function, but for 3D, so we won't duplicate its
24029 description here.
24030 
24031  -- ALGLIB PROJECT --
24032  Copyright 28.05.2010 by Bochkanov Sergey
24033 *************************************************************************/
24034 void pspline3build(/* Real */ ae_matrix* xy,
24035  ae_int_t n,
24036  ae_int_t st,
24037  ae_int_t pt,
24038  pspline3interpolant* p,
24039  ae_state *_state)
24040 {
24041  ae_frame _frame_block;
24042  ae_matrix _xy;
24043  ae_vector tmp;
24044 
24045  ae_frame_make(_state, &_frame_block);
24046  ae_matrix_init_copy(&_xy, xy, _state, ae_true);
24047  xy = &_xy;
24048  _pspline3interpolant_clear(p);
24049  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
24050 
24051  ae_assert(st>=0&&st<=2, "PSpline3Build: incorrect spline type!", _state);
24052  ae_assert(pt>=0&&pt<=2, "PSpline3Build: incorrect parameterization type!", _state);
24053  if( st==0 )
24054  {
24055  ae_assert(n>=5, "PSpline3Build: N<5 (minimum value for Akima splines)!", _state);
24056  }
24057  else
24058  {
24059  ae_assert(n>=2, "PSpline3Build: N<2!", _state);
24060  }
24061 
24062  /*
24063  * Prepare
24064  */
24065  p->n = n;
24066  p->periodic = ae_false;
24067  ae_vector_set_length(&tmp, n, _state);
24068 
24069  /*
24070  * Build parameterization, check that all parameters are distinct
24071  */
24072  pspline_pspline3par(xy, n, pt, &p->p, _state);
24073  ae_assert(aredistinct(&p->p, n, _state), "PSpline3Build: consequent points are too close!", _state);
24074 
24075  /*
24076  * Build splines
24077  */
24078  if( st==0 )
24079  {
24080  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
24081  spline1dbuildakima(&p->p, &tmp, n, &p->x, _state);
24082  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
24083  spline1dbuildakima(&p->p, &tmp, n, &p->y, _state);
24084  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1));
24085  spline1dbuildakima(&p->p, &tmp, n, &p->z, _state);
24086  }
24087  if( st==1 )
24088  {
24089  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
24090  spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->x, _state);
24091  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
24092  spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->y, _state);
24093  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1));
24094  spline1dbuildcatmullrom(&p->p, &tmp, n, 0, 0.0, &p->z, _state);
24095  }
24096  if( st==2 )
24097  {
24098  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][0], xy->stride, ae_v_len(0,n-1));
24099  spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->x, _state);
24100  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][1], xy->stride, ae_v_len(0,n-1));
24101  spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->y, _state);
24102  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][2], xy->stride, ae_v_len(0,n-1));
24103  spline1dbuildcubic(&p->p, &tmp, n, 0, 0.0, 0, 0.0, &p->z, _state);
24104  }
24105  ae_frame_leave(_state);
24106 }
24107 
24108 
24109 /*************************************************************************
24110 This function builds periodic 2-dimensional parametric spline which
24111 starts at (X[0],Y[0]), goes through all points to (X[N-1],Y[N-1]) and then
24112 back to (X[0],Y[0]).
24113 
24114 INPUT PARAMETERS:
24115  XY - points, array[0..N-1,0..1].
24116  XY[I,0:1] corresponds to the Ith point.
24117  XY[N-1,0:1] must be different from XY[0,0:1].
24118  Order of points is important!
24119  N - points count, N>=3 for other types of splines.
24120  ST - spline type:
24121  * 1 Catmull-Rom spline (Tension=0) with cyclic boundary conditions
24122  * 2 cubic spline with cyclic boundary conditions
24123  PT - parameterization type:
24124  * 0 uniform
24125  * 1 chord length
24126  * 2 centripetal
24127 
24128 OUTPUT PARAMETERS:
24129  P - parametric spline interpolant
24130 
24131 
24132 NOTES:
24133 * this function assumes that there all consequent points are distinct.
24134  I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), (x2,y2)<>(x3,y3) and so on.
24135  However, non-consequent points may coincide, i.e. we can have (x0,y0)=
24136  =(x2,y2).
24137 * last point of sequence is NOT equal to the first point. You shouldn't
24138  make curve "explicitly periodic" by making them equal.
24139 
24140  -- ALGLIB PROJECT --
24141  Copyright 28.05.2010 by Bochkanov Sergey
24142 *************************************************************************/
24143 void pspline2buildperiodic(/* Real */ ae_matrix* xy,
24144  ae_int_t n,
24145  ae_int_t st,
24146  ae_int_t pt,
24147  pspline2interpolant* p,
24148  ae_state *_state)
24149 {
24150  ae_frame _frame_block;
24151  ae_matrix _xy;
24152  ae_matrix xyp;
24153  ae_vector tmp;
24154 
24155  ae_frame_make(_state, &_frame_block);
24156  ae_matrix_init_copy(&_xy, xy, _state, ae_true);
24157  xy = &_xy;
24158  _pspline2interpolant_clear(p);
24159  ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true);
24160  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
24161 
24162  ae_assert(st>=1&&st<=2, "PSpline2BuildPeriodic: incorrect spline type!", _state);
24163  ae_assert(pt>=0&&pt<=2, "PSpline2BuildPeriodic: incorrect parameterization type!", _state);
24164  ae_assert(n>=3, "PSpline2BuildPeriodic: N<3!", _state);
24165 
24166  /*
24167  * Prepare
24168  */
24169  p->n = n;
24170  p->periodic = ae_true;
24171  ae_vector_set_length(&tmp, n+1, _state);
24172  ae_matrix_set_length(&xyp, n+1, 2, _state);
24173  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));
24174  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));
24175  ae_v_move(&xyp.ptr.pp_double[n][0], 1, &xy->ptr.pp_double[0][0], 1, ae_v_len(0,1));
24176 
24177  /*
24178  * Build parameterization, check that all parameters are distinct
24179  */
24180  pspline_pspline2par(&xyp, n+1, pt, &p->p, _state);
24181  ae_assert(aredistinct(&p->p, n+1, _state), "PSpline2BuildPeriodic: consequent (or first and last) points are too close!", _state);
24182 
24183  /*
24184  * Build splines
24185  */
24186  if( st==1 )
24187  {
24188  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
24189  spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->x, _state);
24190  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
24191  spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->y, _state);
24192  }
24193  if( st==2 )
24194  {
24195  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
24196  spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->x, _state);
24197  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
24198  spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->y, _state);
24199  }
24200  ae_frame_leave(_state);
24201 }
24202 
24203 
24204 /*************************************************************************
24205 This function builds periodic 3-dimensional parametric spline which
24206 starts at (X[0],Y[0],Z[0]), goes through all points to (X[N-1],Y[N-1],Z[N-1])
24207 and then back to (X[0],Y[0],Z[0]).
24208 
24209 Same as PSpline2Build() function, but for 3D, so we won't duplicate its
24210 description here.
24211 
24212  -- ALGLIB PROJECT --
24213  Copyright 28.05.2010 by Bochkanov Sergey
24214 *************************************************************************/
24215 void pspline3buildperiodic(/* Real */ ae_matrix* xy,
24216  ae_int_t n,
24217  ae_int_t st,
24218  ae_int_t pt,
24219  pspline3interpolant* p,
24220  ae_state *_state)
24221 {
24222  ae_frame _frame_block;
24223  ae_matrix _xy;
24224  ae_matrix xyp;
24225  ae_vector tmp;
24226 
24227  ae_frame_make(_state, &_frame_block);
24228  ae_matrix_init_copy(&_xy, xy, _state, ae_true);
24229  xy = &_xy;
24230  _pspline3interpolant_clear(p);
24231  ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true);
24232  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
24233 
24234  ae_assert(st>=1&&st<=2, "PSpline3BuildPeriodic: incorrect spline type!", _state);
24235  ae_assert(pt>=0&&pt<=2, "PSpline3BuildPeriodic: incorrect parameterization type!", _state);
24236  ae_assert(n>=3, "PSpline3BuildPeriodic: N<3!", _state);
24237 
24238  /*
24239  * Prepare
24240  */
24241  p->n = n;
24242  p->periodic = ae_true;
24243  ae_vector_set_length(&tmp, n+1, _state);
24244  ae_matrix_set_length(&xyp, n+1, 3, _state);
24245  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));
24246  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));
24247  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));
24248  ae_v_move(&xyp.ptr.pp_double[n][0], 1, &xy->ptr.pp_double[0][0], 1, ae_v_len(0,2));
24249 
24250  /*
24251  * Build parameterization, check that all parameters are distinct
24252  */
24253  pspline_pspline3par(&xyp, n+1, pt, &p->p, _state);
24254  ae_assert(aredistinct(&p->p, n+1, _state), "PSplineBuild2Periodic: consequent (or first and last) points are too close!", _state);
24255 
24256  /*
24257  * Build splines
24258  */
24259  if( st==1 )
24260  {
24261  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
24262  spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->x, _state);
24263  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
24264  spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->y, _state);
24265  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][2], xyp.stride, ae_v_len(0,n));
24266  spline1dbuildcatmullrom(&p->p, &tmp, n+1, -1, 0.0, &p->z, _state);
24267  }
24268  if( st==2 )
24269  {
24270  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][0], xyp.stride, ae_v_len(0,n));
24271  spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->x, _state);
24272  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][1], xyp.stride, ae_v_len(0,n));
24273  spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->y, _state);
24274  ae_v_move(&tmp.ptr.p_double[0], 1, &xyp.ptr.pp_double[0][2], xyp.stride, ae_v_len(0,n));
24275  spline1dbuildcubic(&p->p, &tmp, n+1, -1, 0.0, -1, 0.0, &p->z, _state);
24276  }
24277  ae_frame_leave(_state);
24278 }
24279 
24280 
24281 /*************************************************************************
24282 This function returns vector of parameter values correspoding to points.
24283 
24284 I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and U=TValues(P) we
24285 have
24286  (X[0],Y[0]) = PSpline2Calc(P,U[0]),
24287  (X[1],Y[1]) = PSpline2Calc(P,U[1]),
24288  (X[2],Y[2]) = PSpline2Calc(P,U[2]),
24289  ...
24290 
24291 INPUT PARAMETERS:
24292  P - parametric spline interpolant
24293 
24294 OUTPUT PARAMETERS:
24295  N - array size
24296  T - array[0..N-1]
24297 
24298 
24299 NOTES:
24300 * for non-periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]=1
24301 * for periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]<1
24302 
24303  -- ALGLIB PROJECT --
24304  Copyright 28.05.2010 by Bochkanov Sergey
24305 *************************************************************************/
24306 void pspline2parametervalues(pspline2interpolant* p,
24307  ae_int_t* n,
24308  /* Real */ ae_vector* t,
24309  ae_state *_state)
24310 {
24311 
24312  *n = 0;
24313  ae_vector_clear(t);
24314 
24315  ae_assert(p->n>=2, "PSpline2ParameterValues: internal error!", _state);
24316  *n = p->n;
24317  ae_vector_set_length(t, *n, _state);
24318  ae_v_move(&t->ptr.p_double[0], 1, &p->p.ptr.p_double[0], 1, ae_v_len(0,*n-1));
24319  t->ptr.p_double[0] = 0;
24320  if( !p->periodic )
24321  {
24322  t->ptr.p_double[*n-1] = 1;
24323  }
24324 }
24325 
24326 
24327 /*************************************************************************
24328 This function returns vector of parameter values correspoding to points.
24329 
24330 Same as PSpline2ParameterValues(), but for 3D.
24331 
24332  -- ALGLIB PROJECT --
24333  Copyright 28.05.2010 by Bochkanov Sergey
24334 *************************************************************************/
24335 void pspline3parametervalues(pspline3interpolant* p,
24336  ae_int_t* n,
24337  /* Real */ ae_vector* t,
24338  ae_state *_state)
24339 {
24340 
24341  *n = 0;
24342  ae_vector_clear(t);
24343 
24344  ae_assert(p->n>=2, "PSpline3ParameterValues: internal error!", _state);
24345  *n = p->n;
24346  ae_vector_set_length(t, *n, _state);
24347  ae_v_move(&t->ptr.p_double[0], 1, &p->p.ptr.p_double[0], 1, ae_v_len(0,*n-1));
24348  t->ptr.p_double[0] = 0;
24349  if( !p->periodic )
24350  {
24351  t->ptr.p_double[*n-1] = 1;
24352  }
24353 }
24354 
24355 
24356 /*************************************************************************
24357 This function calculates the value of the parametric spline for a given
24358 value of parameter T
24359 
24360 INPUT PARAMETERS:
24361  P - parametric spline interpolant
24362  T - point:
24363  * T in [0,1] corresponds to interval spanned by points
24364  * for non-periodic splines T<0 (or T>1) correspond to parts of
24365  the curve before the first (after the last) point
24366  * for periodic splines T<0 (or T>1) are projected into [0,1]
24367  by making T=T-floor(T).
24368 
24369 OUTPUT PARAMETERS:
24370  X - X-position
24371  Y - Y-position
24372 
24373 
24374  -- ALGLIB PROJECT --
24375  Copyright 28.05.2010 by Bochkanov Sergey
24376 *************************************************************************/
24377 void pspline2calc(pspline2interpolant* p,
24378  double t,
24379  double* x,
24380  double* y,
24381  ae_state *_state)
24382 {
24383 
24384  *x = 0;
24385  *y = 0;
24386 
24387  if( p->periodic )
24388  {
24389  t = t-ae_ifloor(t, _state);
24390  }
24391  *x = spline1dcalc(&p->x, t, _state);
24392  *y = spline1dcalc(&p->y, t, _state);
24393 }
24394 
24395 
24396 /*************************************************************************
24397 This function calculates the value of the parametric spline for a given
24398 value of parameter T.
24399 
24400 INPUT PARAMETERS:
24401  P - parametric spline interpolant
24402  T - point:
24403  * T in [0,1] corresponds to interval spanned by points
24404  * for non-periodic splines T<0 (or T>1) correspond to parts of
24405  the curve before the first (after the last) point
24406  * for periodic splines T<0 (or T>1) are projected into [0,1]
24407  by making T=T-floor(T).
24408 
24409 OUTPUT PARAMETERS:
24410  X - X-position
24411  Y - Y-position
24412  Z - Z-position
24413 
24414 
24415  -- ALGLIB PROJECT --
24416  Copyright 28.05.2010 by Bochkanov Sergey
24417 *************************************************************************/
24418 void pspline3calc(pspline3interpolant* p,
24419  double t,
24420  double* x,
24421  double* y,
24422  double* z,
24423  ae_state *_state)
24424 {
24425 
24426  *x = 0;
24427  *y = 0;
24428  *z = 0;
24429 
24430  if( p->periodic )
24431  {
24432  t = t-ae_ifloor(t, _state);
24433  }
24434  *x = spline1dcalc(&p->x, t, _state);
24435  *y = spline1dcalc(&p->y, t, _state);
24436  *z = spline1dcalc(&p->z, t, _state);
24437 }
24438 
24439 
24440 /*************************************************************************
24441 This function calculates tangent vector for a given value of parameter T
24442 
24443 INPUT PARAMETERS:
24444  P - parametric spline interpolant
24445  T - point:
24446  * T in [0,1] corresponds to interval spanned by points
24447  * for non-periodic splines T<0 (or T>1) correspond to parts of
24448  the curve before the first (after the last) point
24449  * for periodic splines T<0 (or T>1) are projected into [0,1]
24450  by making T=T-floor(T).
24451 
24452 OUTPUT PARAMETERS:
24453  X - X-component of tangent vector (normalized)
24454  Y - Y-component of tangent vector (normalized)
24455 
24456 NOTE:
24457  X^2+Y^2 is either 1 (for non-zero tangent vector) or 0.
24458 
24459 
24460  -- ALGLIB PROJECT --
24461  Copyright 28.05.2010 by Bochkanov Sergey
24462 *************************************************************************/
24463 void pspline2tangent(pspline2interpolant* p,
24464  double t,
24465  double* x,
24466  double* y,
24467  ae_state *_state)
24468 {
24469  double v;
24470  double v0;
24471  double v1;
24472 
24473  *x = 0;
24474  *y = 0;
24475 
24476  if( p->periodic )
24477  {
24478  t = t-ae_ifloor(t, _state);
24479  }
24480  pspline2diff(p, t, &v0, x, &v1, y, _state);
24481  if( ae_fp_neq(*x,0)||ae_fp_neq(*y,0) )
24482  {
24483 
24484  /*
24485  * this code is a bit more complex than X^2+Y^2 to avoid
24486  * overflow for large values of X and Y.
24487  */
24488  v = safepythag2(*x, *y, _state);
24489  *x = *x/v;
24490  *y = *y/v;
24491  }
24492 }
24493 
24494 
24495 /*************************************************************************
24496 This function calculates tangent vector for a given value of parameter T
24497 
24498 INPUT PARAMETERS:
24499  P - parametric spline interpolant
24500  T - point:
24501  * T in [0,1] corresponds to interval spanned by points
24502  * for non-periodic splines T<0 (or T>1) correspond to parts of
24503  the curve before the first (after the last) point
24504  * for periodic splines T<0 (or T>1) are projected into [0,1]
24505  by making T=T-floor(T).
24506 
24507 OUTPUT PARAMETERS:
24508  X - X-component of tangent vector (normalized)
24509  Y - Y-component of tangent vector (normalized)
24510  Z - Z-component of tangent vector (normalized)
24511 
24512 NOTE:
24513  X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0.
24514 
24515 
24516  -- ALGLIB PROJECT --
24517  Copyright 28.05.2010 by Bochkanov Sergey
24518 *************************************************************************/
24519 void pspline3tangent(pspline3interpolant* p,
24520  double t,
24521  double* x,
24522  double* y,
24523  double* z,
24524  ae_state *_state)
24525 {
24526  double v;
24527  double v0;
24528  double v1;
24529  double v2;
24530 
24531  *x = 0;
24532  *y = 0;
24533  *z = 0;
24534 
24535  if( p->periodic )
24536  {
24537  t = t-ae_ifloor(t, _state);
24538  }
24539  pspline3diff(p, t, &v0, x, &v1, y, &v2, z, _state);
24540  if( (ae_fp_neq(*x,0)||ae_fp_neq(*y,0))||ae_fp_neq(*z,0) )
24541  {
24542  v = safepythag3(*x, *y, *z, _state);
24543  *x = *x/v;
24544  *y = *y/v;
24545  *z = *z/v;
24546  }
24547 }
24548 
24549 
24550 /*************************************************************************
24551 This function calculates derivative, i.e. it returns (dX/dT,dY/dT).
24552 
24553 INPUT PARAMETERS:
24554  P - parametric spline interpolant
24555  T - point:
24556  * T in [0,1] corresponds to interval spanned by points
24557  * for non-periodic splines T<0 (or T>1) correspond to parts of
24558  the curve before the first (after the last) point
24559  * for periodic splines T<0 (or T>1) are projected into [0,1]
24560  by making T=T-floor(T).
24561 
24562 OUTPUT PARAMETERS:
24563  X - X-value
24564  DX - X-derivative
24565  Y - Y-value
24566  DY - Y-derivative
24567 
24568 
24569  -- ALGLIB PROJECT --
24570  Copyright 28.05.2010 by Bochkanov Sergey
24571 *************************************************************************/
24572 void pspline2diff(pspline2interpolant* p,
24573  double t,
24574  double* x,
24575  double* dx,
24576  double* y,
24577  double* dy,
24578  ae_state *_state)
24579 {
24580  double d2s;
24581 
24582  *x = 0;
24583  *dx = 0;
24584  *y = 0;
24585  *dy = 0;
24586 
24587  if( p->periodic )
24588  {
24589  t = t-ae_ifloor(t, _state);
24590  }
24591  spline1ddiff(&p->x, t, x, dx, &d2s, _state);
24592  spline1ddiff(&p->y, t, y, dy, &d2s, _state);
24593 }
24594 
24595 
24596 /*************************************************************************
24597 This function calculates derivative, i.e. it returns (dX/dT,dY/dT,dZ/dT).
24598 
24599 INPUT PARAMETERS:
24600  P - parametric spline interpolant
24601  T - point:
24602  * T in [0,1] corresponds to interval spanned by points
24603  * for non-periodic splines T<0 (or T>1) correspond to parts of
24604  the curve before the first (after the last) point
24605  * for periodic splines T<0 (or T>1) are projected into [0,1]
24606  by making T=T-floor(T).
24607 
24608 OUTPUT PARAMETERS:
24609  X - X-value
24610  DX - X-derivative
24611  Y - Y-value
24612  DY - Y-derivative
24613  Z - Z-value
24614  DZ - Z-derivative
24615 
24616 
24617  -- ALGLIB PROJECT --
24618  Copyright 28.05.2010 by Bochkanov Sergey
24619 *************************************************************************/
24620 void pspline3diff(pspline3interpolant* p,
24621  double t,
24622  double* x,
24623  double* dx,
24624  double* y,
24625  double* dy,
24626  double* z,
24627  double* dz,
24628  ae_state *_state)
24629 {
24630  double d2s;
24631 
24632  *x = 0;
24633  *dx = 0;
24634  *y = 0;
24635  *dy = 0;
24636  *z = 0;
24637  *dz = 0;
24638 
24639  if( p->periodic )
24640  {
24641  t = t-ae_ifloor(t, _state);
24642  }
24643  spline1ddiff(&p->x, t, x, dx, &d2s, _state);
24644  spline1ddiff(&p->y, t, y, dy, &d2s, _state);
24645  spline1ddiff(&p->z, t, z, dz, &d2s, _state);
24646 }
24647 
24648 
24649 /*************************************************************************
24650 This function calculates first and second derivative with respect to T.
24651 
24652 INPUT PARAMETERS:
24653  P - parametric spline interpolant
24654  T - point:
24655  * T in [0,1] corresponds to interval spanned by points
24656  * for non-periodic splines T<0 (or T>1) correspond to parts of
24657  the curve before the first (after the last) point
24658  * for periodic splines T<0 (or T>1) are projected into [0,1]
24659  by making T=T-floor(T).
24660 
24661 OUTPUT PARAMETERS:
24662  X - X-value
24663  DX - derivative
24664  D2X - second derivative
24665  Y - Y-value
24666  DY - derivative
24667  D2Y - second derivative
24668 
24669 
24670  -- ALGLIB PROJECT --
24671  Copyright 28.05.2010 by Bochkanov Sergey
24672 *************************************************************************/
24673 void pspline2diff2(pspline2interpolant* p,
24674  double t,
24675  double* x,
24676  double* dx,
24677  double* d2x,
24678  double* y,
24679  double* dy,
24680  double* d2y,
24681  ae_state *_state)
24682 {
24683 
24684  *x = 0;
24685  *dx = 0;
24686  *d2x = 0;
24687  *y = 0;
24688  *dy = 0;
24689  *d2y = 0;
24690 
24691  if( p->periodic )
24692  {
24693  t = t-ae_ifloor(t, _state);
24694  }
24695  spline1ddiff(&p->x, t, x, dx, d2x, _state);
24696  spline1ddiff(&p->y, t, y, dy, d2y, _state);
24697 }
24698 
24699 
24700 /*************************************************************************
24701 This function calculates first and second derivative with respect to T.
24702 
24703 INPUT PARAMETERS:
24704  P - parametric spline interpolant
24705  T - point:
24706  * T in [0,1] corresponds to interval spanned by points
24707  * for non-periodic splines T<0 (or T>1) correspond to parts of
24708  the curve before the first (after the last) point
24709  * for periodic splines T<0 (or T>1) are projected into [0,1]
24710  by making T=T-floor(T).
24711 
24712 OUTPUT PARAMETERS:
24713  X - X-value
24714  DX - derivative
24715  D2X - second derivative
24716  Y - Y-value
24717  DY - derivative
24718  D2Y - second derivative
24719  Z - Z-value
24720  DZ - derivative
24721  D2Z - second derivative
24722 
24723 
24724  -- ALGLIB PROJECT --
24725  Copyright 28.05.2010 by Bochkanov Sergey
24726 *************************************************************************/
24727 void pspline3diff2(pspline3interpolant* p,
24728  double t,
24729  double* x,
24730  double* dx,
24731  double* d2x,
24732  double* y,
24733  double* dy,
24734  double* d2y,
24735  double* z,
24736  double* dz,
24737  double* d2z,
24738  ae_state *_state)
24739 {
24740 
24741  *x = 0;
24742  *dx = 0;
24743  *d2x = 0;
24744  *y = 0;
24745  *dy = 0;
24746  *d2y = 0;
24747  *z = 0;
24748  *dz = 0;
24749  *d2z = 0;
24750 
24751  if( p->periodic )
24752  {
24753  t = t-ae_ifloor(t, _state);
24754  }
24755  spline1ddiff(&p->x, t, x, dx, d2x, _state);
24756  spline1ddiff(&p->y, t, y, dy, d2y, _state);
24757  spline1ddiff(&p->z, t, z, dz, d2z, _state);
24758 }
24759 
24760 
24761 /*************************************************************************
24762 This function calculates arc length, i.e. length of curve between t=a
24763 and t=b.
24764 
24765 INPUT PARAMETERS:
24766  P - parametric spline interpolant
24767  A,B - parameter values corresponding to arc ends:
24768  * B>A will result in positive length returned
24769  * B<A will result in negative length returned
24770 
24771 RESULT:
24772  length of arc starting at T=A and ending at T=B.
24773 
24774 
24775  -- ALGLIB PROJECT --
24776  Copyright 30.05.2010 by Bochkanov Sergey
24777 *************************************************************************/
24778 double pspline2arclength(pspline2interpolant* p,
24779  double a,
24780  double b,
24781  ae_state *_state)
24782 {
24783  ae_frame _frame_block;
24784  autogkstate state;
24785  autogkreport rep;
24786  double sx;
24787  double dsx;
24788  double d2sx;
24789  double sy;
24790  double dsy;
24791  double d2sy;
24792  double result;
24793 
24794  ae_frame_make(_state, &_frame_block);
24795  _autogkstate_init(&state, _state, ae_true);
24796  _autogkreport_init(&rep, _state, ae_true);
24797 
24798  autogksmooth(a, b, &state, _state);
24799  while(autogkiteration(&state, _state))
24800  {
24801  spline1ddiff(&p->x, state.x, &sx, &dsx, &d2sx, _state);
24802  spline1ddiff(&p->y, state.x, &sy, &dsy, &d2sy, _state);
24803  state.f = safepythag2(dsx, dsy, _state);
24804  }
24805  autogkresults(&state, &result, &rep, _state);
24806  ae_assert(rep.terminationtype>0, "PSpline2ArcLength: internal error!", _state);
24807  ae_frame_leave(_state);
24808  return result;
24809 }
24810 
24811 
24812 /*************************************************************************
24813 This function calculates arc length, i.e. length of curve between t=a
24814 and t=b.
24815 
24816 INPUT PARAMETERS:
24817  P - parametric spline interpolant
24818  A,B - parameter values corresponding to arc ends:
24819  * B>A will result in positive length returned
24820  * B<A will result in negative length returned
24821 
24822 RESULT:
24823  length of arc starting at T=A and ending at T=B.
24824 
24825 
24826  -- ALGLIB PROJECT --
24827  Copyright 30.05.2010 by Bochkanov Sergey
24828 *************************************************************************/
24829 double pspline3arclength(pspline3interpolant* p,
24830  double a,
24831  double b,
24832  ae_state *_state)
24833 {
24834  ae_frame _frame_block;
24835  autogkstate state;
24836  autogkreport rep;
24837  double sx;
24838  double dsx;
24839  double d2sx;
24840  double sy;
24841  double dsy;
24842  double d2sy;
24843  double sz;
24844  double dsz;
24845  double d2sz;
24846  double result;
24847 
24848  ae_frame_make(_state, &_frame_block);
24849  _autogkstate_init(&state, _state, ae_true);
24850  _autogkreport_init(&rep, _state, ae_true);
24851 
24852  autogksmooth(a, b, &state, _state);
24853  while(autogkiteration(&state, _state))
24854  {
24855  spline1ddiff(&p->x, state.x, &sx, &dsx, &d2sx, _state);
24856  spline1ddiff(&p->y, state.x, &sy, &dsy, &d2sy, _state);
24857  spline1ddiff(&p->z, state.x, &sz, &dsz, &d2sz, _state);
24858  state.f = safepythag3(dsx, dsy, dsz, _state);
24859  }
24860  autogkresults(&state, &result, &rep, _state);
24861  ae_assert(rep.terminationtype>0, "PSpline3ArcLength: internal error!", _state);
24862  ae_frame_leave(_state);
24863  return result;
24864 }
24865 
24866 
24867 /*************************************************************************
24868 Builds non-periodic parameterization for 2-dimensional spline
24869 *************************************************************************/
24870 static void pspline_pspline2par(/* Real */ ae_matrix* xy,
24871  ae_int_t n,
24872  ae_int_t pt,
24873  /* Real */ ae_vector* p,
24874  ae_state *_state)
24875 {
24876  double v;
24877  ae_int_t i;
24878 
24879  ae_vector_clear(p);
24880 
24881  ae_assert(pt>=0&&pt<=2, "PSpline2Par: internal error!", _state);
24882 
24883  /*
24884  * Build parameterization:
24885  * * fill by non-normalized values
24886  * * normalize them so we have P[0]=0, P[N-1]=1.
24887  */
24888  ae_vector_set_length(p, n, _state);
24889  if( pt==0 )
24890  {
24891  for(i=0; i<=n-1; i++)
24892  {
24893  p->ptr.p_double[i] = i;
24894  }
24895  }
24896  if( pt==1 )
24897  {
24898  p->ptr.p_double[0] = 0;
24899  for(i=1; i<=n-1; i++)
24900  {
24901  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);
24902  }
24903  }
24904  if( pt==2 )
24905  {
24906  p->ptr.p_double[0] = 0;
24907  for(i=1; i<=n-1; i++)
24908  {
24909  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);
24910  }
24911  }
24912  v = 1/p->ptr.p_double[n-1];
24913  ae_v_muld(&p->ptr.p_double[0], 1, ae_v_len(0,n-1), v);
24914 }
24915 
24916 
24917 /*************************************************************************
24918 Builds non-periodic parameterization for 3-dimensional spline
24919 *************************************************************************/
24920 static void pspline_pspline3par(/* Real */ ae_matrix* xy,
24921  ae_int_t n,
24922  ae_int_t pt,
24923  /* Real */ ae_vector* p,
24924  ae_state *_state)
24925 {
24926  double v;
24927  ae_int_t i;
24928 
24929  ae_vector_clear(p);
24930 
24931  ae_assert(pt>=0&&pt<=2, "PSpline3Par: internal error!", _state);
24932 
24933  /*
24934  * Build parameterization:
24935  * * fill by non-normalized values
24936  * * normalize them so we have P[0]=0, P[N-1]=1.
24937  */
24938  ae_vector_set_length(p, n, _state);
24939  if( pt==0 )
24940  {
24941  for(i=0; i<=n-1; i++)
24942  {
24943  p->ptr.p_double[i] = i;
24944  }
24945  }
24946  if( pt==1 )
24947  {
24948  p->ptr.p_double[0] = 0;
24949  for(i=1; i<=n-1; i++)
24950  {
24951  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);
24952  }
24953  }
24954  if( pt==2 )
24955  {
24956  p->ptr.p_double[0] = 0;
24957  for(i=1; i<=n-1; i++)
24958  {
24959  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);
24960  }
24961  }
24962  v = 1/p->ptr.p_double[n-1];
24963  ae_v_muld(&p->ptr.p_double[0], 1, ae_v_len(0,n-1), v);
24964 }
24965 
24966 
24967 ae_bool _pspline2interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
24968 {
24969  pspline2interpolant *p = (pspline2interpolant*)_p;
24970  ae_touch_ptr((void*)p);
24971  if( !ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic) )
24972  return ae_false;
24973  if( !_spline1dinterpolant_init(&p->x, _state, make_automatic) )
24974  return ae_false;
24975  if( !_spline1dinterpolant_init(&p->y, _state, make_automatic) )
24976  return ae_false;
24977  return ae_true;
24978 }
24979 
24980 
24981 ae_bool _pspline2interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
24982 {
24983  pspline2interpolant *dst = (pspline2interpolant*)_dst;
24984  pspline2interpolant *src = (pspline2interpolant*)_src;
24985  dst->n = src->n;
24986  dst->periodic = src->periodic;
24987  if( !ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic) )
24988  return ae_false;
24989  if( !_spline1dinterpolant_init_copy(&dst->x, &src->x, _state, make_automatic) )
24990  return ae_false;
24991  if( !_spline1dinterpolant_init_copy(&dst->y, &src->y, _state, make_automatic) )
24992  return ae_false;
24993  return ae_true;
24994 }
24995 
24996 
24997 void _pspline2interpolant_clear(void* _p)
24998 {
24999  pspline2interpolant *p = (pspline2interpolant*)_p;
25000  ae_touch_ptr((void*)p);
25001  ae_vector_clear(&p->p);
25002  _spline1dinterpolant_clear(&p->x);
25003  _spline1dinterpolant_clear(&p->y);
25004 }
25005 
25006 
25007 void _pspline2interpolant_destroy(void* _p)
25008 {
25009  pspline2interpolant *p = (pspline2interpolant*)_p;
25010  ae_touch_ptr((void*)p);
25011  ae_vector_destroy(&p->p);
25012  _spline1dinterpolant_destroy(&p->x);
25013  _spline1dinterpolant_destroy(&p->y);
25014 }
25015 
25016 
25017 ae_bool _pspline3interpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
25018 {
25019  pspline3interpolant *p = (pspline3interpolant*)_p;
25020  ae_touch_ptr((void*)p);
25021  if( !ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic) )
25022  return ae_false;
25023  if( !_spline1dinterpolant_init(&p->x, _state, make_automatic) )
25024  return ae_false;
25025  if( !_spline1dinterpolant_init(&p->y, _state, make_automatic) )
25026  return ae_false;
25027  if( !_spline1dinterpolant_init(&p->z, _state, make_automatic) )
25028  return ae_false;
25029  return ae_true;
25030 }
25031 
25032 
25033 ae_bool _pspline3interpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
25034 {
25035  pspline3interpolant *dst = (pspline3interpolant*)_dst;
25036  pspline3interpolant *src = (pspline3interpolant*)_src;
25037  dst->n = src->n;
25038  dst->periodic = src->periodic;
25039  if( !ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic) )
25040  return ae_false;
25041  if( !_spline1dinterpolant_init_copy(&dst->x, &src->x, _state, make_automatic) )
25042  return ae_false;
25043  if( !_spline1dinterpolant_init_copy(&dst->y, &src->y, _state, make_automatic) )
25044  return ae_false;
25045  if( !_spline1dinterpolant_init_copy(&dst->z, &src->z, _state, make_automatic) )
25046  return ae_false;
25047  return ae_true;
25048 }
25049 
25050 
25051 void _pspline3interpolant_clear(void* _p)
25052 {
25053  pspline3interpolant *p = (pspline3interpolant*)_p;
25054  ae_touch_ptr((void*)p);
25055  ae_vector_clear(&p->p);
25056  _spline1dinterpolant_clear(&p->x);
25057  _spline1dinterpolant_clear(&p->y);
25058  _spline1dinterpolant_clear(&p->z);
25059 }
25060 
25061 
25062 void _pspline3interpolant_destroy(void* _p)
25063 {
25064  pspline3interpolant *p = (pspline3interpolant*)_p;
25065  ae_touch_ptr((void*)p);
25066  ae_vector_destroy(&p->p);
25067  _spline1dinterpolant_destroy(&p->x);
25068  _spline1dinterpolant_destroy(&p->y);
25069  _spline1dinterpolant_destroy(&p->z);
25070 }
25071 
25072 
25073 
25074 
25075 /*************************************************************************
25076 This function creates RBF model for a scalar (NY=1) or vector (NY>1)
25077 function in a NX-dimensional space (NX=2 or NX=3).
25078 
25079 Newly created model is empty. It can be used for interpolation right after
25080 creation, but it just returns zeros. You have to add points to the model,
25081 tune interpolation settings, and then call model construction function
25082 RBFBuildModel() which will update model according to your specification.
25083 
25084 USAGE:
25085 1. User creates model with RBFCreate()
25086 2. User adds dataset with RBFSetPoints() (points do NOT have to be on a
25087  regular grid)
25088 3. (OPTIONAL) User chooses polynomial term by calling:
25089  * RBFLinTerm() to set linear term
25090  * RBFConstTerm() to set constant term
25091  * RBFZeroTerm() to set zero term
25092  By default, linear term is used.
25093 4. User chooses specific RBF algorithm to use: either QNN (RBFSetAlgoQNN)
25094  or ML (RBFSetAlgoMultiLayer).
25095 5. User calls RBFBuildModel() function which rebuilds model according to
25096  the specification
25097 6. User may call RBFCalc() to calculate model value at the specified point,
25098  RBFGridCalc() to calculate model values at the points of the regular
25099  grid. User may extract model coefficients with RBFUnpack() call.
25100 
25101 INPUT PARAMETERS:
25102  NX - dimension of the space, NX=2 or NX=3
25103  NY - function dimension, NY>=1
25104 
25105 OUTPUT PARAMETERS:
25106  S - RBF model (initially equals to zero)
25107 
25108 NOTE 1: memory requirements. RBF models require amount of memory which is
25109  proportional to the number of data points. Memory is allocated
25110  during model construction, but most of this memory is freed after
25111  model coefficients are calculated.
25112 
25113  Some approximate estimates for N centers with default settings are
25114  given below:
25115  * about 250*N*(sizeof(double)+2*sizeof(int)) bytes of memory is
25116  needed during model construction stage.
25117  * about 15*N*sizeof(double) bytes is needed after model is built.
25118  For example, for N=100000 we may need 0.6 GB of memory to build
25119  model, but just about 0.012 GB to store it.
25120 
25121  -- ALGLIB --
25122  Copyright 13.12.2011 by Bochkanov Sergey
25123 *************************************************************************/
25124 void rbfcreate(ae_int_t nx, ae_int_t ny, rbfmodel* s, ae_state *_state)
25125 {
25126  ae_int_t i;
25127  ae_int_t j;
25128 
25129  _rbfmodel_clear(s);
25130 
25131  ae_assert(nx==2||nx==3, "RBFCreate: NX<>2 and NX<>3", _state);
25132  ae_assert(ny>=1, "RBFCreate: NY<1", _state);
25133  s->nx = nx;
25134  s->ny = ny;
25135  s->nl = 0;
25136  s->nc = 0;
25137  ae_matrix_set_length(&s->v, ny, rbf_mxnx+1, _state);
25138  for(i=0; i<=ny-1; i++)
25139  {
25140  for(j=0; j<=rbf_mxnx; j++)
25141  {
25142  s->v.ptr.pp_double[i][j] = 0;
25143  }
25144  }
25145  s->n = 0;
25146  s->rmax = 0;
25147  s->gridtype = 2;
25148  s->fixrad = ae_false;
25149  s->radvalue = 1;
25150  s->radzvalue = 5;
25151  s->aterm = 1;
25152  s->algorithmtype = 1;
25153 
25154  /*
25155  * stopping criteria
25156  */
25157  s->epsort = rbf_eps;
25158  s->epserr = rbf_eps;
25159  s->maxits = 0;
25160 }
25161 
25162 
25163 /*************************************************************************
25164 This function adds dataset.
25165 
25166 This function overrides results of the previous calls, i.e. multiple calls
25167 of this function will result in only the last set being added.
25168 
25169 INPUT PARAMETERS:
25170  S - RBF model, initialized by RBFCreate() call.
25171  XY - points, array[N,NX+NY]. One row corresponds to one point
25172  in the dataset. First NX elements are coordinates, next
25173  NY elements are function values. Array may be larger than
25174  specific, in this case only leading [N,NX+NY] elements
25175  will be used.
25176  N - number of points in the dataset
25177 
25178 After you've added dataset and (optionally) tuned algorithm settings you
25179 should call RBFBuildModel() in order to build a model for you.
25180 
25181 NOTE: this function has some serialization-related subtleties. We
25182  recommend you to study serialization examples from ALGLIB Reference
25183  Manual if you want to perform serialization of your models.
25184 
25185 
25186  -- ALGLIB --
25187  Copyright 13.12.2011 by Bochkanov Sergey
25188 *************************************************************************/
25189 void rbfsetpoints(rbfmodel* s,
25190  /* Real */ ae_matrix* xy,
25191  ae_int_t n,
25192  ae_state *_state)
25193 {
25194  ae_int_t i;
25195  ae_int_t j;
25196 
25197 
25198  ae_assert(n>0, "RBFSetPoints: N<0", _state);
25199  ae_assert(xy->rows>=n, "RBFSetPoints: Rows(XY)<N", _state);
25200  ae_assert(xy->cols>=s->nx+s->ny, "RBFSetPoints: Cols(XY)<NX+NY", _state);
25201  s->n = n;
25202  ae_matrix_set_length(&s->x, s->n, rbf_mxnx, _state);
25203  ae_matrix_set_length(&s->y, s->n, s->ny, _state);
25204  for(i=0; i<=s->n-1; i++)
25205  {
25206  for(j=0; j<=rbf_mxnx-1; j++)
25207  {
25208  s->x.ptr.pp_double[i][j] = 0;
25209  }
25210  for(j=0; j<=s->nx-1; j++)
25211  {
25212  s->x.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j];
25213  }
25214  for(j=0; j<=s->ny-1; j++)
25215  {
25216  s->y.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j+s->nx];
25217  }
25218  }
25219 }
25220 
25221 
25222 /*************************************************************************
25223 This function sets RBF interpolation algorithm. ALGLIB supports several
25224 RBF algorithms with different properties.
25225 
25226 This algorithm is called RBF-QNN and it is good for point sets with
25227 following properties:
25228 a) all points are distinct
25229 b) all points are well separated.
25230 c) points distribution is approximately uniform. There is no "contour
25231  lines", clusters of points, or other small-scale structures.
25232 
25233 Algorithm description:
25234 1) interpolation centers are allocated to data points
25235 2) interpolation radii are calculated as distances to the nearest centers
25236  times Q coefficient (where Q is a value from [0.75,1.50]).
25237 3) after performing (2) radii are transformed in order to avoid situation
25238  when single outlier has very large radius and influences many points
25239  across all dataset. Transformation has following form:
25240  new_r[i] = min(r[i],Z*median(r[]))
25241  where r[i] is I-th radius, median() is a median radius across entire
25242  dataset, Z is user-specified value which controls amount of deviation
25243  from median radius.
25244 
25245 When (a) is violated, we will be unable to build RBF model. When (b) or
25246 (c) are violated, model will be built, but interpolation quality will be
25247 low. See http://www.alglib.net/interpolation/ for more information on this
25248 subject.
25249 
25250 This algorithm is used by default.
25251 
25252 Additional Q parameter controls smoothness properties of the RBF basis:
25253 * Q<0.75 will give perfectly conditioned basis, but terrible smoothness
25254  properties (RBF interpolant will have sharp peaks around function values)
25255 * Q around 1.0 gives good balance between smoothness and condition number
25256 * Q>1.5 will lead to badly conditioned systems and slow convergence of the
25257  underlying linear solver (although smoothness will be very good)
25258 * Q>2.0 will effectively make optimizer useless because it won't converge
25259  within reasonable amount of iterations. It is possible to set such large
25260  Q, but it is advised not to do so.
25261 
25262 INPUT PARAMETERS:
25263  S - RBF model, initialized by RBFCreate() call
25264  Q - Q parameter, Q>0, recommended value - 1.0
25265  Z - Z parameter, Z>0, recommended value - 5.0
25266 
25267 NOTE: this function has some serialization-related subtleties. We
25268  recommend you to study serialization examples from ALGLIB Reference
25269  Manual if you want to perform serialization of your models.
25270 
25271 
25272  -- ALGLIB --
25273  Copyright 13.12.2011 by Bochkanov Sergey
25274 *************************************************************************/
25275 void rbfsetalgoqnn(rbfmodel* s, double q, double z, ae_state *_state)
25276 {
25277 
25278 
25279  ae_assert(ae_isfinite(q, _state), "RBFSetAlgoQNN: Q is infinite or NAN", _state);
25280  ae_assert(ae_fp_greater(q,0), "RBFSetAlgoQNN: Q<=0", _state);
25281  rbf_rbfgridpoints(s, _state);
25282  rbf_rbfradnn(s, q, z, _state);
25283  s->algorithmtype = 1;
25284 }
25285 
25286 
25287 /*************************************************************************
25288 This function sets RBF interpolation algorithm. ALGLIB supports several
25289 RBF algorithms with different properties.
25290 
25291 This algorithm is called RBF-ML. It builds multilayer RBF model, i.e.
25292 model with subsequently decreasing radii, which allows us to combine
25293 smoothness (due to large radii of the first layers) with exactness (due
25294 to small radii of the last layers) and fast convergence.
25295 
25296 Internally RBF-ML uses many different means of acceleration, from sparse
25297 matrices to KD-trees, which results in algorithm whose working time is
25298 roughly proportional to N*log(N)*Density*RBase^2*NLayers, where N is a
25299 number of points, Density is an average density if points per unit of the
25300 interpolation space, RBase is an initial radius, NLayers is a number of
25301 layers.
25302 
25303 RBF-ML is good for following kinds of interpolation problems:
25304 1. "exact" problems (perfect fit) with well separated points
25305 2. least squares problems with arbitrary distribution of points (algorithm
25306  gives perfect fit where it is possible, and resorts to least squares
25307  fit in the hard areas).
25308 3. noisy problems where we want to apply some controlled amount of
25309  smoothing.
25310 
25311 INPUT PARAMETERS:
25312  S - RBF model, initialized by RBFCreate() call
25313  RBase - RBase parameter, RBase>0
25314  NLayers - NLayers parameter, NLayers>0, recommended value to start
25315  with - about 5.
25316  LambdaV - regularization value, can be useful when solving problem
25317  in the least squares sense. Optimal lambda is problem-
25318  dependent and require trial and error. In our experience,
25319  good lambda can be as large as 0.1, and you can use 0.001
25320  as initial guess.
25321  Default value - 0.01, which is used when LambdaV is not
25322  given. You can specify zero value, but it is not
25323  recommended to do so.
25324 
25325 TUNING ALGORITHM
25326 
25327 In order to use this algorithm you have to choose three parameters:
25328 * initial radius RBase
25329 * number of layers in the model NLayers
25330 * regularization coefficient LambdaV
25331 
25332 Initial radius is easy to choose - you can pick any number several times
25333 larger than the average distance between points. Algorithm won't break
25334 down if you choose radius which is too large (model construction time will
25335 increase, but model will be built correctly).
25336 
25337 Choose such number of layers that RLast=RBase/2^(NLayers-1) (radius used
25338 by the last layer) will be smaller than the typical distance between
25339 points. In case model error is too large, you can increase number of
25340 layers. Having more layers will make model construction and evaluation
25341 proportionally slower, but it will allow you to have model which precisely
25342 fits your data. From the other side, if you want to suppress noise, you
25343 can DECREASE number of layers to make your model less flexible.
25344 
25345 Regularization coefficient LambdaV controls smoothness of the individual
25346 models built for each layer. We recommend you to use default value in case
25347 you don't want to tune this parameter, because having non-zero LambdaV
25348 accelerates and stabilizes internal iterative algorithm. In case you want
25349 to suppress noise you can use LambdaV as additional parameter (larger
25350 value = more smoothness) to tune.
25351 
25352 TYPICAL ERRORS
25353 
25354 1. Using initial radius which is too large. Memory requirements of the
25355  RBF-ML are roughly proportional to N*Density*RBase^2 (where Density is
25356  an average density of points per unit of the interpolation space). In
25357  the extreme case of the very large RBase we will need O(N^2) units of
25358  memory - and many layers in order to decrease radius to some reasonably
25359  small value.
25360 
25361 2. Using too small number of layers - RBF models with large radius are not
25362  flexible enough to reproduce small variations in the target function.
25363  You need many layers with different radii, from large to small, in
25364  order to have good model.
25365 
25366 3. Using initial radius which is too small. You will get model with
25367  "holes" in the areas which are too far away from interpolation centers.
25368  However, algorithm will work correctly (and quickly) in this case.
25369 
25370 4. Using too many layers - you will get too large and too slow model. This
25371  model will perfectly reproduce your function, but maybe you will be
25372  able to achieve similar results with less layers (and less memory).
25373 
25374  -- ALGLIB --
25375  Copyright 02.03.2012 by Bochkanov Sergey
25376 *************************************************************************/
25377 void rbfsetalgomultilayer(rbfmodel* s,
25378  double rbase,
25379  ae_int_t nlayers,
25380  double lambdav,
25381  ae_state *_state)
25382 {
25383 
25384 
25385  ae_assert(ae_isfinite(rbase, _state), "RBFSetAlgoMultiLayer: RBase is infinite or NaN", _state);
25386  ae_assert(ae_fp_greater(rbase,0), "RBFSetAlgoMultiLayer: RBase<=0", _state);
25387  ae_assert(nlayers>=0, "RBFSetAlgoMultiLayer: NLayers<0", _state);
25388  ae_assert(ae_isfinite(lambdav, _state), "RBFSetAlgoMultiLayer: LambdaV is infinite or NAN", _state);
25389  ae_assert(ae_fp_greater_eq(lambdav,0), "RBFSetAlgoMultiLayer: LambdaV<0", _state);
25390  s->radvalue = rbase;
25391  s->nlayers = nlayers;
25392  s->algorithmtype = 2;
25393  s->lambdav = lambdav;
25394 }
25395 
25396 
25397 /*************************************************************************
25398 This function sets linear term (model is a sum of radial basis functions
25399 plus linear polynomial). This function won't have effect until next call
25400 to RBFBuildModel().
25401 
25402 INPUT PARAMETERS:
25403  S - RBF model, initialized by RBFCreate() call
25404 
25405 NOTE: this function has some serialization-related subtleties. We
25406  recommend you to study serialization examples from ALGLIB Reference
25407  Manual if you want to perform serialization of your models.
25408 
25409  -- ALGLIB --
25410  Copyright 13.12.2011 by Bochkanov Sergey
25411 *************************************************************************/
25412 void rbfsetlinterm(rbfmodel* s, ae_state *_state)
25413 {
25414 
25415 
25416  s->aterm = 1;
25417 }
25418 
25419 
25420 /*************************************************************************
25421 This function sets constant term (model is a sum of radial basis functions
25422 plus constant). This function won't have effect until next call to
25423 RBFBuildModel().
25424 
25425 INPUT PARAMETERS:
25426  S - RBF model, initialized by RBFCreate() call
25427 
25428 NOTE: this function has some serialization-related subtleties. We
25429  recommend you to study serialization examples from ALGLIB Reference
25430  Manual if you want to perform serialization of your models.
25431 
25432  -- ALGLIB --
25433  Copyright 13.12.2011 by Bochkanov Sergey
25434 *************************************************************************/
25435 void rbfsetconstterm(rbfmodel* s, ae_state *_state)
25436 {
25437 
25438 
25439  s->aterm = 2;
25440 }
25441 
25442 
25443 /*************************************************************************
25444 This function sets zero term (model is a sum of radial basis functions
25445 without polynomial term). This function won't have effect until next call
25446 to RBFBuildModel().
25447 
25448 INPUT PARAMETERS:
25449  S - RBF model, initialized by RBFCreate() call
25450 
25451 NOTE: this function has some serialization-related subtleties. We
25452  recommend you to study serialization examples from ALGLIB Reference
25453  Manual if you want to perform serialization of your models.
25454 
25455  -- ALGLIB --
25456  Copyright 13.12.2011 by Bochkanov Sergey
25457 *************************************************************************/
25458 void rbfsetzeroterm(rbfmodel* s, ae_state *_state)
25459 {
25460 
25461 
25462  s->aterm = 3;
25463 }
25464 
25465 
25466 /*************************************************************************
25467 This function sets stopping criteria of the underlying linear solver.
25468 
25469 INPUT PARAMETERS:
25470  S - RBF model, initialized by RBFCreate() call
25471  EpsOrt - orthogonality stopping criterion, EpsOrt>=0. Algorithm will
25472  stop when ||A'*r||<=EpsOrt where A' is a transpose of the
25473  system matrix, r is a residual vector.
25474  Recommended value of EpsOrt is equal to 1E-6.
25475  This criterion will stop algorithm when we have "bad fit"
25476  situation, i.e. when we should stop in a point with large,
25477  nonzero residual.
25478  EpsErr - residual stopping criterion. Algorithm will stop when
25479  ||r||<=EpsErr*||b||, where r is a residual vector, b is a
25480  right part of the system (function values).
25481  Recommended value of EpsErr is equal to 1E-3 or 1E-6.
25482  This criterion will stop algorithm in a "good fit"
25483  situation when we have near-zero residual near the desired
25484  solution.
25485  MaxIts - this criterion will stop algorithm after MaxIts iterations.
25486  It should be used for debugging purposes only!
25487  Zero MaxIts means that no limit is placed on the number of
25488  iterations.
25489 
25490 We recommend to set moderate non-zero values EpsOrt and EpsErr
25491 simultaneously. Values equal to 10E-6 are good to start with. In case you
25492 need high performance and do not need high precision , you may decrease
25493 EpsErr down to 0.001. However, we do not recommend decreasing EpsOrt.
25494 
25495 As for MaxIts, we recommend to leave it zero unless you know what you do.
25496 
25497 NOTE: this function has some serialization-related subtleties. We
25498  recommend you to study serialization examples from ALGLIB Reference
25499  Manual if you want to perform serialization of your models.
25500 
25501  -- ALGLIB --
25502  Copyright 13.12.2011 by Bochkanov Sergey
25503 *************************************************************************/
25504 void rbfsetcond(rbfmodel* s,
25505  double epsort,
25506  double epserr,
25507  ae_int_t maxits,
25508  ae_state *_state)
25509 {
25510 
25511 
25512  ae_assert(ae_isfinite(epsort, _state)&&ae_fp_greater_eq(epsort,0), "RBFSetCond: EpsOrt is negative, INF or NAN", _state);
25513  ae_assert(ae_isfinite(epserr, _state)&&ae_fp_greater_eq(epserr,0), "RBFSetCond: EpsB is negative, INF or NAN", _state);
25514  ae_assert(maxits>=0, "RBFSetCond: MaxIts is negative", _state);
25515  if( (ae_fp_eq(epsort,0)&&ae_fp_eq(epserr,0))&&maxits==0 )
25516  {
25517  s->epsort = rbf_eps;
25518  s->epserr = rbf_eps;
25519  s->maxits = 0;
25520  }
25521  else
25522  {
25523  s->epsort = epsort;
25524  s->epserr = epserr;
25525  s->maxits = maxits;
25526  }
25527 }
25528 
25529 
25530 /*************************************************************************
25531 This function builds RBF model and returns report (contains some
25532 information which can be used for evaluation of the algorithm properties).
25533 
25534 Call to this function modifies RBF model by calculating its centers/radii/
25535 weights and saving them into RBFModel structure. Initially RBFModel
25536 contain zero coefficients, but after call to this function we will have
25537 coefficients which were calculated in order to fit our dataset.
25538 
25539 After you called this function you can call RBFCalc(), RBFGridCalc() and
25540 other model calculation functions.
25541 
25542 INPUT PARAMETERS:
25543  S - RBF model, initialized by RBFCreate() call
25544  Rep - report:
25545  * Rep.TerminationType:
25546  * -5 - non-distinct basis function centers were detected,
25547  interpolation aborted
25548  * -4 - nonconvergence of the internal SVD solver
25549  * 1 - successful termination
25550  Fields are used for debugging purposes:
25551  * Rep.IterationsCount - iterations count of the LSQR solver
25552  * Rep.NMV - number of matrix-vector products
25553  * Rep.ARows - rows count for the system matrix
25554  * Rep.ACols - columns count for the system matrix
25555  * Rep.ANNZ - number of significantly non-zero elements
25556  (elements above some algorithm-determined threshold)
25557 
25558 NOTE: failure to build model will leave current state of the structure
25559 unchanged.
25560 
25561  -- ALGLIB --
25562  Copyright 13.12.2011 by Bochkanov Sergey
25563 *************************************************************************/
25564 void rbfbuildmodel(rbfmodel* s, rbfreport* rep, ae_state *_state)
25565 {
25566  ae_frame _frame_block;
25567  kdtree tree;
25568  kdtree ctree;
25569  ae_vector dist;
25570  ae_vector xcx;
25571  ae_matrix a;
25572  ae_matrix v;
25573  ae_matrix omega;
25574  ae_vector y;
25575  ae_matrix residualy;
25576  ae_vector radius;
25577  ae_matrix xc;
25578  ae_vector mnx;
25579  ae_vector mxx;
25580  ae_vector edge;
25581  ae_vector mxsteps;
25582  ae_int_t nc;
25583  double rmax;
25584  ae_vector tags;
25585  ae_vector ctags;
25586  ae_int_t i;
25587  ae_int_t j;
25588  ae_int_t k;
25589  ae_int_t k2;
25590  ae_int_t snnz;
25591  ae_vector tmp0;
25592  ae_vector tmp1;
25593  ae_int_t layerscnt;
25594 
25595  ae_frame_make(_state, &_frame_block);
25596  _rbfreport_clear(rep);
25597  _kdtree_init(&tree, _state, ae_true);
25598  _kdtree_init(&ctree, _state, ae_true);
25599  ae_vector_init(&dist, 0, DT_REAL, _state, ae_true);
25600  ae_vector_init(&xcx, 0, DT_REAL, _state, ae_true);
25601  ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
25602  ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
25603  ae_matrix_init(&omega, 0, 0, DT_REAL, _state, ae_true);
25604  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
25605  ae_matrix_init(&residualy, 0, 0, DT_REAL, _state, ae_true);
25606  ae_vector_init(&radius, 0, DT_REAL, _state, ae_true);
25607  ae_matrix_init(&xc, 0, 0, DT_REAL, _state, ae_true);
25608  ae_vector_init(&mnx, 0, DT_REAL, _state, ae_true);
25609  ae_vector_init(&mxx, 0, DT_REAL, _state, ae_true);
25610  ae_vector_init(&edge, 0, DT_REAL, _state, ae_true);
25611  ae_vector_init(&mxsteps, 0, DT_INT, _state, ae_true);
25612  ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
25613  ae_vector_init(&ctags, 0, DT_INT, _state, ae_true);
25614  ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
25615  ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
25616 
25617  ae_assert(s->nx==2||s->nx==3, "RBFBuildModel: S.NX<>2 or S.NX<>3!", _state);
25618 
25619  /*
25620  * Quick exit when we have no points
25621  */
25622  if( s->n==0 )
25623  {
25624  rep->terminationtype = 1;
25625  rep->iterationscount = 0;
25626  rep->nmv = 0;
25627  rep->arows = 0;
25628  rep->acols = 0;
25629  kdtreebuildtagged(&s->xc, &tags, 0, rbf_mxnx, 0, 2, &s->tree, _state);
25630  ae_matrix_set_length(&s->xc, 0, 0, _state);
25631  ae_matrix_set_length(&s->wr, 0, 0, _state);
25632  s->nc = 0;
25633  s->rmax = 0;
25634  ae_matrix_set_length(&s->v, s->ny, rbf_mxnx+1, _state);
25635  for(i=0; i<=s->ny-1; i++)
25636  {
25637  for(j=0; j<=rbf_mxnx; j++)
25638  {
25639  s->v.ptr.pp_double[i][j] = 0;
25640  }
25641  }
25642  ae_frame_leave(_state);
25643  return;
25644  }
25645 
25646  /*
25647  * General case, N>0
25648  */
25649  rep->annz = 0;
25650  rep->iterationscount = 0;
25651  rep->nmv = 0;
25652  ae_vector_set_length(&xcx, rbf_mxnx, _state);
25653 
25654  /*
25655  * First model in a sequence - linear model.
25656  * Residuals from linear regression are stored in the ResidualY variable
25657  * (used later to build RBF models).
25658  */
25659  ae_matrix_set_length(&residualy, s->n, s->ny, _state);
25660  for(i=0; i<=s->n-1; i++)
25661  {
25662  for(j=0; j<=s->ny-1; j++)
25663  {
25664  residualy.ptr.pp_double[i][j] = s->y.ptr.pp_double[i][j];
25665  }
25666  }
25667  if( !rbf_buildlinearmodel(&s->x, &residualy, s->n, s->ny, s->aterm, &v, _state) )
25668  {
25669  rep->terminationtype = -5;
25670  ae_frame_leave(_state);
25671  return;
25672  }
25673 
25674  /*
25675  * Handle special case: multilayer model with NLayers=0.
25676  * Quick exit.
25677  */
25678  if( s->algorithmtype==2&&s->nlayers==0 )
25679  {
25680  rep->terminationtype = 1;
25681  rep->iterationscount = 0;
25682  rep->nmv = 0;
25683  rep->arows = 0;
25684  rep->acols = 0;
25685  kdtreebuildtagged(&s->xc, &tags, 0, rbf_mxnx, 0, 2, &s->tree, _state);
25686  ae_matrix_set_length(&s->xc, 0, 0, _state);
25687  ae_matrix_set_length(&s->wr, 0, 0, _state);
25688  s->nc = 0;
25689  s->rmax = 0;
25690  ae_matrix_set_length(&s->v, s->ny, rbf_mxnx+1, _state);
25691  for(i=0; i<=s->ny-1; i++)
25692  {
25693  for(j=0; j<=rbf_mxnx; j++)
25694  {
25695  s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j];
25696  }
25697  }
25698  ae_frame_leave(_state);
25699  return;
25700  }
25701 
25702  /*
25703  * Second model in a sequence - RBF term.
25704  *
25705  * NOTE: assignments below are not necessary, but without them
25706  * MSVC complains about unitialized variables.
25707  */
25708  nc = 0;
25709  rmax = 0;
25710  layerscnt = 0;
25711  if( s->algorithmtype==1 )
25712  {
25713 
25714  /*
25715  * Add RBF model.
25716  * This model uses local KD-trees to speed-up nearest neighbor searches.
25717  */
25718  if( s->gridtype==1 )
25719  {
25720  ae_vector_set_length(&mxx, s->nx, _state);
25721  ae_vector_set_length(&mnx, s->nx, _state);
25722  ae_vector_set_length(&mxsteps, s->nx, _state);
25723  ae_vector_set_length(&edge, s->nx, _state);
25724  for(i=0; i<=s->nx-1; i++)
25725  {
25726  mxx.ptr.p_double[i] = s->x.ptr.pp_double[0][i];
25727  mnx.ptr.p_double[i] = s->x.ptr.pp_double[0][i];
25728  }
25729  for(i=0; i<=s->n-1; i++)
25730  {
25731  for(j=0; j<=s->nx-1; j++)
25732  {
25733  if( ae_fp_less(mxx.ptr.p_double[j],s->x.ptr.pp_double[i][j]) )
25734  {
25735  mxx.ptr.p_double[j] = s->x.ptr.pp_double[i][j];
25736  }
25737  if( ae_fp_greater(mnx.ptr.p_double[j],s->x.ptr.pp_double[i][j]) )
25738  {
25739  mnx.ptr.p_double[j] = s->x.ptr.pp_double[i][j];
25740  }
25741  }
25742  }
25743  for(i=0; i<=s->nx-1; i++)
25744  {
25745  mxsteps.ptr.p_int[i] = ae_trunc((mxx.ptr.p_double[i]-mnx.ptr.p_double[i])/(2*s->h), _state)+1;
25746  edge.ptr.p_double[i] = (mxx.ptr.p_double[i]+mnx.ptr.p_double[i])/2-s->h*mxsteps.ptr.p_int[i];
25747  }
25748  nc = 1;
25749  for(i=0; i<=s->nx-1; i++)
25750  {
25751  mxsteps.ptr.p_int[i] = 2*mxsteps.ptr.p_int[i]+1;
25752  nc = nc*mxsteps.ptr.p_int[i];
25753  }
25754  ae_matrix_set_length(&xc, nc, rbf_mxnx, _state);
25755  if( s->nx==2 )
25756  {
25757  for(i=0; i<=mxsteps.ptr.p_int[0]-1; i++)
25758  {
25759  for(j=0; j<=mxsteps.ptr.p_int[1]-1; j++)
25760  {
25761  for(k2=0; k2<=rbf_mxnx-1; k2++)
25762  {
25763  xc.ptr.pp_double[i*mxsteps.ptr.p_int[1]+j][k2] = 0;
25764  }
25765  xc.ptr.pp_double[i*mxsteps.ptr.p_int[1]+j][0] = edge.ptr.p_double[0]+s->h*i;
25766  xc.ptr.pp_double[i*mxsteps.ptr.p_int[1]+j][1] = edge.ptr.p_double[1]+s->h*j;
25767  }
25768  }
25769  }
25770  if( s->nx==3 )
25771  {
25772  for(i=0; i<=mxsteps.ptr.p_int[0]-1; i++)
25773  {
25774  for(j=0; j<=mxsteps.ptr.p_int[1]-1; j++)
25775  {
25776  for(k=0; k<=mxsteps.ptr.p_int[2]-1; k++)
25777  {
25778  for(k2=0; k2<=rbf_mxnx-1; k2++)
25779  {
25780  xc.ptr.pp_double[i*mxsteps.ptr.p_int[1]+j][k2] = 0;
25781  }
25782  xc.ptr.pp_double[(i*mxsteps.ptr.p_int[1]+j)*mxsteps.ptr.p_int[2]+k][0] = edge.ptr.p_double[0]+s->h*i;
25783  xc.ptr.pp_double[(i*mxsteps.ptr.p_int[1]+j)*mxsteps.ptr.p_int[2]+k][1] = edge.ptr.p_double[1]+s->h*j;
25784  xc.ptr.pp_double[(i*mxsteps.ptr.p_int[1]+j)*mxsteps.ptr.p_int[2]+k][2] = edge.ptr.p_double[2]+s->h*k;
25785  }
25786  }
25787  }
25788  }
25789  }
25790  else
25791  {
25792  if( s->gridtype==2 )
25793  {
25794  nc = s->n;
25795  ae_matrix_set_length(&xc, nc, rbf_mxnx, _state);
25796  for(i=0; i<=nc-1; i++)
25797  {
25798  for(j=0; j<=rbf_mxnx-1; j++)
25799  {
25800  xc.ptr.pp_double[i][j] = s->x.ptr.pp_double[i][j];
25801  }
25802  }
25803  }
25804  else
25805  {
25806  if( s->gridtype==3 )
25807  {
25808  nc = s->nc;
25809  ae_matrix_set_length(&xc, nc, rbf_mxnx, _state);
25810  for(i=0; i<=nc-1; i++)
25811  {
25812  for(j=0; j<=rbf_mxnx-1; j++)
25813  {
25814  xc.ptr.pp_double[i][j] = s->xc.ptr.pp_double[i][j];
25815  }
25816  }
25817  }
25818  else
25819  {
25820  ae_assert(ae_false, "RBFBuildModel: either S.GridType<1 or S.GridType>3!", _state);
25821  }
25822  }
25823  }
25824  rmax = 0;
25825  ae_vector_set_length(&radius, nc, _state);
25826  ae_vector_set_length(&ctags, nc, _state);
25827  for(i=0; i<=nc-1; i++)
25828  {
25829  ctags.ptr.p_int[i] = i;
25830  }
25831  kdtreebuildtagged(&xc, &ctags, nc, rbf_mxnx, 0, 2, &ctree, _state);
25832  if( s->fixrad )
25833  {
25834 
25835  /*
25836  * Fixed radius
25837  */
25838  for(i=0; i<=nc-1; i++)
25839  {
25840  radius.ptr.p_double[i] = s->radvalue;
25841  }
25842  rmax = radius.ptr.p_double[0];
25843  }
25844  else
25845  {
25846 
25847  /*
25848  * Dynamic radius
25849  */
25850  if( nc==0 )
25851  {
25852  rmax = 1;
25853  }
25854  else
25855  {
25856  if( nc==1 )
25857  {
25858  radius.ptr.p_double[0] = s->radvalue;
25859  rmax = radius.ptr.p_double[0];
25860  }
25861  else
25862  {
25863 
25864  /*
25865  * NC>1, calculate radii using distances to nearest neigbors
25866  */
25867  for(i=0; i<=nc-1; i++)
25868  {
25869  for(j=0; j<=rbf_mxnx-1; j++)
25870  {
25871  xcx.ptr.p_double[j] = xc.ptr.pp_double[i][j];
25872  }
25873  if( kdtreequeryknn(&ctree, &xcx, 1, ae_false, _state)>0 )
25874  {
25875  kdtreequeryresultsdistances(&ctree, &dist, _state);
25876  radius.ptr.p_double[i] = s->radvalue*dist.ptr.p_double[0];
25877  }
25878  else
25879  {
25880 
25881  /*
25882  * No neighbors found (it will happen when we have only one center).
25883  * Initialize radius with default value.
25884  */
25885  radius.ptr.p_double[i] = 1.0;
25886  }
25887  }
25888 
25889  /*
25890  * Apply filtering
25891  */
25892  rvectorsetlengthatleast(&tmp0, nc, _state);
25893  for(i=0; i<=nc-1; i++)
25894  {
25895  tmp0.ptr.p_double[i] = radius.ptr.p_double[i];
25896  }
25897  tagsortfast(&tmp0, &tmp1, nc, _state);
25898  for(i=0; i<=nc-1; i++)
25899  {
25900  radius.ptr.p_double[i] = ae_minreal(radius.ptr.p_double[i], s->radzvalue*tmp0.ptr.p_double[nc/2], _state);
25901  }
25902 
25903  /*
25904  * Calculate RMax, check that all radii are non-zero
25905  */
25906  for(i=0; i<=nc-1; i++)
25907  {
25908  rmax = ae_maxreal(rmax, radius.ptr.p_double[i], _state);
25909  }
25910  for(i=0; i<=nc-1; i++)
25911  {
25912  if( ae_fp_eq(radius.ptr.p_double[i],0) )
25913  {
25914  rep->terminationtype = -5;
25915  ae_frame_leave(_state);
25916  return;
25917  }
25918  }
25919  }
25920  }
25921  }
25922  ivectorsetlengthatleast(&tags, s->n, _state);
25923  for(i=0; i<=s->n-1; i++)
25924  {
25925  tags.ptr.p_int[i] = i;
25926  }
25927  kdtreebuildtagged(&s->x, &tags, s->n, rbf_mxnx, 0, 2, &tree, _state);
25928  rbf_buildrbfmodellsqr(&s->x, &residualy, &xc, &radius, s->n, nc, s->ny, &tree, &ctree, s->epsort, s->epserr, s->maxits, &rep->annz, &snnz, &omega, &rep->terminationtype, &rep->iterationscount, &rep->nmv, _state);
25929  layerscnt = 1;
25930  }
25931  else
25932  {
25933  if( s->algorithmtype==2 )
25934  {
25935  rmax = s->radvalue;
25936  rbf_buildrbfmlayersmodellsqr(&s->x, &residualy, &xc, s->radvalue, &radius, s->n, &nc, s->ny, s->nlayers, &ctree, 1.0E-6, 1.0E-6, 50, s->lambdav, &rep->annz, &omega, &rep->terminationtype, &rep->iterationscount, &rep->nmv, _state);
25937  layerscnt = s->nlayers;
25938  }
25939  else
25940  {
25941  ae_assert(ae_false, "RBFBuildModel: internal error(AlgorithmType neither 1 nor 2)", _state);
25942  }
25943  }
25944  if( rep->terminationtype<=0 )
25945  {
25946  ae_frame_leave(_state);
25947  return;
25948  }
25949 
25950  /*
25951  * Model is built
25952  */
25953  s->nc = nc/layerscnt;
25954  s->rmax = rmax;
25955  s->nl = layerscnt;
25956  ae_matrix_set_length(&s->xc, s->nc, rbf_mxnx, _state);
25957  ae_matrix_set_length(&s->wr, s->nc, 1+s->nl*s->ny, _state);
25958  ae_matrix_set_length(&s->v, s->ny, rbf_mxnx+1, _state);
25959  for(i=0; i<=s->nc-1; i++)
25960  {
25961  for(j=0; j<=rbf_mxnx-1; j++)
25962  {
25963  s->xc.ptr.pp_double[i][j] = xc.ptr.pp_double[i][j];
25964  }
25965  }
25966  ivectorsetlengthatleast(&tags, s->nc, _state);
25967  for(i=0; i<=s->nc-1; i++)
25968  {
25969  tags.ptr.p_int[i] = i;
25970  }
25971  kdtreebuildtagged(&s->xc, &tags, s->nc, rbf_mxnx, 0, 2, &s->tree, _state);
25972  for(i=0; i<=s->nc-1; i++)
25973  {
25974  s->wr.ptr.pp_double[i][0] = radius.ptr.p_double[i];
25975  for(k=0; k<=layerscnt-1; k++)
25976  {
25977  for(j=0; j<=s->ny-1; j++)
25978  {
25979  s->wr.ptr.pp_double[i][1+k*s->ny+j] = omega.ptr.pp_double[k*s->nc+i][j];
25980  }
25981  }
25982  }
25983  for(i=0; i<=s->ny-1; i++)
25984  {
25985  for(j=0; j<=rbf_mxnx; j++)
25986  {
25987  s->v.ptr.pp_double[i][j] = v.ptr.pp_double[i][j];
25988  }
25989  }
25990  rep->terminationtype = 1;
25991  rep->arows = s->n;
25992  rep->acols = s->nc;
25993  ae_frame_leave(_state);
25994 }
25995 
25996 
25997 /*************************************************************************
25998 This function calculates values of the RBF model in the given point.
25999 
26000 This function should be used when we have NY=1 (scalar function) and NX=2
26001 (2-dimensional space). If you have 3-dimensional space, use RBFCalc3(). If
26002 you have general situation (NX-dimensional space, NY-dimensional function)
26003 you should use general, less efficient implementation RBFCalc().
26004 
26005 If you want to calculate function values many times, consider using
26006 RBFGridCalc2(), which is far more efficient than many subsequent calls to
26007 RBFCalc2().
26008 
26009 This function returns 0.0 when:
26010 * model is not initialized
26011 * NX<>2
26012  *NY<>1
26013 
26014 INPUT PARAMETERS:
26015  S - RBF model
26016  X0 - first coordinate, finite number
26017  X1 - second coordinate, finite number
26018 
26019 RESULT:
26020  value of the model or 0.0 (as defined above)
26021 
26022  -- ALGLIB --
26023  Copyright 13.12.2011 by Bochkanov Sergey
26024 *************************************************************************/
26025 double rbfcalc2(rbfmodel* s, double x0, double x1, ae_state *_state)
26026 {
26027  ae_int_t i;
26028  ae_int_t j;
26029  ae_int_t lx;
26030  ae_int_t tg;
26031  double d2;
26032  double t;
26033  double bfcur;
26034  double rcur;
26035  double result;
26036 
26037 
26038  ae_assert(ae_isfinite(x0, _state), "RBFCalc2: invalid value for X0 (X0 is Inf)!", _state);
26039  ae_assert(ae_isfinite(x1, _state), "RBFCalc2: invalid value for X1 (X1 is Inf)!", _state);
26040  if( s->ny!=1||s->nx!=2 )
26041  {
26042  result = 0;
26043  return result;
26044  }
26045  result = s->v.ptr.pp_double[0][0]*x0+s->v.ptr.pp_double[0][1]*x1+s->v.ptr.pp_double[0][rbf_mxnx];
26046  if( s->nc==0 )
26047  {
26048  return result;
26049  }
26050  rvectorsetlengthatleast(&s->calcbufxcx, rbf_mxnx, _state);
26051  for(i=0; i<=rbf_mxnx-1; i++)
26052  {
26053  s->calcbufxcx.ptr.p_double[i] = 0.0;
26054  }
26055  s->calcbufxcx.ptr.p_double[0] = x0;
26056  s->calcbufxcx.ptr.p_double[1] = x1;
26057  lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbf_rbffarradius, ae_true, _state);
26058  kdtreequeryresultsx(&s->tree, &s->calcbufx, _state);
26059  kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state);
26060  for(i=0; i<=lx-1; i++)
26061  {
26062  tg = s->calcbuftags.ptr.p_int[i];
26063  d2 = ae_sqr(x0-s->calcbufx.ptr.pp_double[i][0], _state)+ae_sqr(x1-s->calcbufx.ptr.pp_double[i][1], _state);
26064  rcur = s->wr.ptr.pp_double[tg][0];
26065  bfcur = ae_exp(-d2/(rcur*rcur), _state);
26066  for(j=0; j<=s->nl-1; j++)
26067  {
26068  result = result+bfcur*s->wr.ptr.pp_double[tg][1+j];
26069  rcur = 0.5*rcur;
26070  t = bfcur*bfcur;
26071  bfcur = t*t;
26072  }
26073  }
26074  return result;
26075 }
26076 
26077 
26078 /*************************************************************************
26079 This function calculates values of the RBF model in the given point.
26080 
26081 This function should be used when we have NY=1 (scalar function) and NX=3
26082 (3-dimensional space). If you have 2-dimensional space, use RBFCalc2(). If
26083 you have general situation (NX-dimensional space, NY-dimensional function)
26084 you should use general, less efficient implementation RBFCalc().
26085 
26086 This function returns 0.0 when:
26087 * model is not initialized
26088 * NX<>3
26089  *NY<>1
26090 
26091 INPUT PARAMETERS:
26092  S - RBF model
26093  X0 - first coordinate, finite number
26094  X1 - second coordinate, finite number
26095  X2 - third coordinate, finite number
26096 
26097 RESULT:
26098  value of the model or 0.0 (as defined above)
26099 
26100  -- ALGLIB --
26101  Copyright 13.12.2011 by Bochkanov Sergey
26102 *************************************************************************/
26103 double rbfcalc3(rbfmodel* s,
26104  double x0,
26105  double x1,
26106  double x2,
26107  ae_state *_state)
26108 {
26109  ae_int_t i;
26110  ae_int_t j;
26111  ae_int_t lx;
26112  ae_int_t tg;
26113  double t;
26114  double rcur;
26115  double bf;
26116  double result;
26117 
26118 
26119  ae_assert(ae_isfinite(x0, _state), "RBFCalc3: invalid value for X0 (X0 is Inf or NaN)!", _state);
26120  ae_assert(ae_isfinite(x1, _state), "RBFCalc3: invalid value for X1 (X1 is Inf or NaN)!", _state);
26121  ae_assert(ae_isfinite(x2, _state), "RBFCalc3: invalid value for X2 (X2 is Inf or NaN)!", _state);
26122  if( s->ny!=1||s->nx!=3 )
26123  {
26124  result = 0;
26125  return result;
26126  }
26127  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][rbf_mxnx];
26128  if( s->nc==0 )
26129  {
26130  return result;
26131  }
26132 
26133  /*
26134  * calculating value for F(X)
26135  */
26136  rvectorsetlengthatleast(&s->calcbufxcx, rbf_mxnx, _state);
26137  for(i=0; i<=rbf_mxnx-1; i++)
26138  {
26139  s->calcbufxcx.ptr.p_double[i] = 0.0;
26140  }
26141  s->calcbufxcx.ptr.p_double[0] = x0;
26142  s->calcbufxcx.ptr.p_double[1] = x1;
26143  s->calcbufxcx.ptr.p_double[2] = x2;
26144  lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbf_rbffarradius, ae_true, _state);
26145  kdtreequeryresultsx(&s->tree, &s->calcbufx, _state);
26146  kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state);
26147  for(i=0; i<=lx-1; i++)
26148  {
26149  tg = s->calcbuftags.ptr.p_int[i];
26150  rcur = s->wr.ptr.pp_double[tg][0];
26151  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);
26152  for(j=0; j<=s->nl-1; j++)
26153  {
26154  result = result+bf*s->wr.ptr.pp_double[tg][1+j];
26155  t = bf*bf;
26156  bf = t*t;
26157  }
26158  }
26159  return result;
26160 }
26161 
26162 
26163 /*************************************************************************
26164 This function calculates values of the RBF model at the given point.
26165 
26166 This is general function which can be used for arbitrary NX (dimension of
26167 the space of arguments) and NY (dimension of the function itself). However
26168 when you have NY=1 you may find more convenient to use RBFCalc2() or
26169 RBFCalc3().
26170 
26171 This function returns 0.0 when model is not initialized.
26172 
26173 INPUT PARAMETERS:
26174  S - RBF model
26175  X - coordinates, array[NX].
26176  X may have more than NX elements, in this case only
26177  leading NX will be used.
26178 
26179 OUTPUT PARAMETERS:
26180  Y - function value, array[NY]. Y is out-parameter and
26181  reallocated after call to this function. In case you want
26182  to reuse previously allocated Y, you may use RBFCalcBuf(),
26183  which reallocates Y only when it is too small.
26184 
26185  -- ALGLIB --
26186  Copyright 13.12.2011 by Bochkanov Sergey
26187 *************************************************************************/
26188 void rbfcalc(rbfmodel* s,
26189  /* Real */ ae_vector* x,
26190  /* Real */ ae_vector* y,
26191  ae_state *_state)
26192 {
26193 
26194  ae_vector_clear(y);
26195 
26196  ae_assert(x->cnt>=s->nx, "RBFCalc: Length(X)<NX", _state);
26197  ae_assert(isfinitevector(x, s->nx, _state), "RBFCalc: X contains infinite or NaN values", _state);
26198  rbfcalcbuf(s, x, y, _state);
26199 }
26200 
26201 
26202 /*************************************************************************
26203 This function calculates values of the RBF model at the given point.
26204 
26205 Same as RBFCalc(), but does not reallocate Y when in is large enough to
26206 store function values.
26207 
26208 INPUT PARAMETERS:
26209  S - RBF model
26210  X - coordinates, array[NX].
26211  X may have more than NX elements, in this case only
26212  leading NX will be used.
26213  Y - possibly preallocated array
26214 
26215 OUTPUT PARAMETERS:
26216  Y - function value, array[NY]. Y is not reallocated when it
26217  is larger than NY.
26218 
26219  -- ALGLIB --
26220  Copyright 13.12.2011 by Bochkanov Sergey
26221 *************************************************************************/
26222 void rbfcalcbuf(rbfmodel* s,
26223  /* Real */ ae_vector* x,
26224  /* Real */ ae_vector* y,
26225  ae_state *_state)
26226 {
26227  ae_int_t i;
26228  ae_int_t j;
26229  ae_int_t k;
26230  ae_int_t lx;
26231  ae_int_t tg;
26232  double t;
26233  double rcur;
26234  double bf;
26235 
26236 
26237  ae_assert(x->cnt>=s->nx, "RBFCalcBuf: Length(X)<NX", _state);
26238  ae_assert(isfinitevector(x, s->nx, _state), "RBFCalcBuf: X contains infinite or NaN values", _state);
26239  if( y->cnt<s->ny )
26240  {
26241  ae_vector_set_length(y, s->ny, _state);
26242  }
26243  for(i=0; i<=s->ny-1; i++)
26244  {
26245  y->ptr.p_double[i] = s->v.ptr.pp_double[i][rbf_mxnx];
26246  for(j=0; j<=s->nx-1; j++)
26247  {
26248  y->ptr.p_double[i] = y->ptr.p_double[i]+s->v.ptr.pp_double[i][j]*x->ptr.p_double[j];
26249  }
26250  }
26251  if( s->nc==0 )
26252  {
26253  return;
26254  }
26255  rvectorsetlengthatleast(&s->calcbufxcx, rbf_mxnx, _state);
26256  for(i=0; i<=rbf_mxnx-1; i++)
26257  {
26258  s->calcbufxcx.ptr.p_double[i] = 0.0;
26259  }
26260  for(i=0; i<=s->nx-1; i++)
26261  {
26262  s->calcbufxcx.ptr.p_double[i] = x->ptr.p_double[i];
26263  }
26264  lx = kdtreequeryrnn(&s->tree, &s->calcbufxcx, s->rmax*rbf_rbffarradius, ae_true, _state);
26265  kdtreequeryresultsx(&s->tree, &s->calcbufx, _state);
26266  kdtreequeryresultstags(&s->tree, &s->calcbuftags, _state);
26267  for(i=0; i<=s->ny-1; i++)
26268  {
26269  for(j=0; j<=lx-1; j++)
26270  {
26271  tg = s->calcbuftags.ptr.p_int[j];
26272  rcur = s->wr.ptr.pp_double[tg][0];
26273  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);
26274  for(k=0; k<=s->nl-1; k++)
26275  {
26276  y->ptr.p_double[i] = y->ptr.p_double[i]+bf*s->wr.ptr.pp_double[tg][1+k*s->ny+i];
26277  t = bf*bf;
26278  bf = t*t;
26279  }
26280  }
26281  }
26282 }
26283 
26284 
26285 /*************************************************************************
26286 This function calculates values of the RBF model at the regular grid.
26287 
26288 Grid have N0*N1 points, with Point[I,J] = (X0[I], X1[J])
26289 
26290 This function returns 0.0 when:
26291 * model is not initialized
26292 * NX<>2
26293  *NY<>1
26294 
26295 INPUT PARAMETERS:
26296  S - RBF model
26297  X0 - array of grid nodes, first coordinates, array[N0]
26298  N0 - grid size (number of nodes) in the first dimension
26299  X1 - array of grid nodes, second coordinates, array[N1]
26300  N1 - grid size (number of nodes) in the second dimension
26301 
26302 OUTPUT PARAMETERS:
26303  Y - function values, array[N0,N1]. Y is out-variable and
26304  is reallocated by this function.
26305 
26306  -- ALGLIB --
26307  Copyright 13.12.2011 by Bochkanov Sergey
26308 *************************************************************************/
26309 void rbfgridcalc2(rbfmodel* s,
26310  /* Real */ ae_vector* x0,
26311  ae_int_t n0,
26312  /* Real */ ae_vector* x1,
26313  ae_int_t n1,
26314  /* Real */ ae_matrix* y,
26315  ae_state *_state)
26316 {
26317  ae_frame _frame_block;
26318  ae_vector cpx0;
26319  ae_vector cpx1;
26320  ae_vector p01;
26321  ae_vector p11;
26322  ae_vector p2;
26323  double rlimit;
26324  double xcnorm2;
26325  ae_int_t hp01;
26326  double hcpx0;
26327  double xc0;
26328  double xc1;
26329  double omega;
26330  double radius;
26331  ae_int_t i;
26332  ae_int_t j;
26333  ae_int_t k;
26334  ae_int_t d;
26335  ae_int_t i00;
26336  ae_int_t i01;
26337  ae_int_t i10;
26338  ae_int_t i11;
26339 
26340  ae_frame_make(_state, &_frame_block);
26341  ae_matrix_clear(y);
26342  ae_vector_init(&cpx0, 0, DT_REAL, _state, ae_true);
26343  ae_vector_init(&cpx1, 0, DT_REAL, _state, ae_true);
26344  ae_vector_init(&p01, 0, DT_INT, _state, ae_true);
26345  ae_vector_init(&p11, 0, DT_INT, _state, ae_true);
26346  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
26347 
26348  ae_assert(n0>0, "RBFGridCalc2: invalid value for N0 (N0<=0)!", _state);
26349  ae_assert(n1>0, "RBFGridCalc2: invalid value for N1 (N1<=0)!", _state);
26350  ae_assert(x0->cnt>=n0, "RBFGridCalc2: Length(X0)<N0", _state);
26351  ae_assert(x1->cnt>=n1, "RBFGridCalc2: Length(X1)<N1", _state);
26352  ae_assert(isfinitevector(x0, n0, _state), "RBFGridCalc2: X0 contains infinite or NaN values!", _state);
26353  ae_assert(isfinitevector(x1, n1, _state), "RBFGridCalc2: X1 contains infinite or NaN values!", _state);
26354  ae_matrix_set_length(y, n0, n1, _state);
26355  for(i=0; i<=n0-1; i++)
26356  {
26357  for(j=0; j<=n1-1; j++)
26358  {
26359  y->ptr.pp_double[i][j] = 0;
26360  }
26361  }
26362  if( (s->ny!=1||s->nx!=2)||s->nc==0 )
26363  {
26364  ae_frame_leave(_state);
26365  return;
26366  }
26367 
26368  /*
26369  *create and sort arrays
26370  */
26371  ae_vector_set_length(&cpx0, n0, _state);
26372  for(i=0; i<=n0-1; i++)
26373  {
26374  cpx0.ptr.p_double[i] = x0->ptr.p_double[i];
26375  }
26376  tagsort(&cpx0, n0, &p01, &p2, _state);
26377  ae_vector_set_length(&cpx1, n1, _state);
26378  for(i=0; i<=n1-1; i++)
26379  {
26380  cpx1.ptr.p_double[i] = x1->ptr.p_double[i];
26381  }
26382  tagsort(&cpx1, n1, &p11, &p2, _state);
26383 
26384  /*
26385  *calculate function's value
26386  */
26387  for(i=0; i<=s->nc-1; i++)
26388  {
26389  radius = s->wr.ptr.pp_double[i][0];
26390  for(d=0; d<=s->nl-1; d++)
26391  {
26392  omega = s->wr.ptr.pp_double[i][1+d];
26393  rlimit = radius*rbf_rbffarradius;
26394 
26395  /*
26396  *search lower and upper indexes
26397  */
26398  i00 = lowerbound(&cpx0, n0, s->xc.ptr.pp_double[i][0]-rlimit, _state);
26399  i01 = upperbound(&cpx0, n0, s->xc.ptr.pp_double[i][0]+rlimit, _state);
26400  i10 = lowerbound(&cpx1, n1, s->xc.ptr.pp_double[i][1]-rlimit, _state);
26401  i11 = upperbound(&cpx1, n1, s->xc.ptr.pp_double[i][1]+rlimit, _state);
26402  xc0 = s->xc.ptr.pp_double[i][0];
26403  xc1 = s->xc.ptr.pp_double[i][1];
26404  for(j=i00; j<=i01-1; j++)
26405  {
26406  hcpx0 = cpx0.ptr.p_double[j];
26407  hp01 = p01.ptr.p_int[j];
26408  for(k=i10; k<=i11-1; k++)
26409  {
26410  xcnorm2 = ae_sqr(hcpx0-xc0, _state)+ae_sqr(cpx1.ptr.p_double[k]-xc1, _state);
26411  if( ae_fp_less_eq(xcnorm2,rlimit*rlimit) )
26412  {
26413  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;
26414  }
26415  }
26416  }
26417  radius = 0.5*radius;
26418  }
26419  }
26420 
26421  /*
26422  *add linear term
26423  */
26424  for(i=0; i<=n0-1; i++)
26425  {
26426  for(j=0; j<=n1-1; j++)
26427  {
26428  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][rbf_mxnx];
26429  }
26430  }
26431  ae_frame_leave(_state);
26432 }
26433 
26434 
26435 /*************************************************************************
26436 This function "unpacks" RBF model by extracting its coefficients.
26437 
26438 INPUT PARAMETERS:
26439  S - RBF model
26440 
26441 OUTPUT PARAMETERS:
26442  NX - dimensionality of argument
26443  NY - dimensionality of the target function
26444  XWR - model information, array[NC,NX+NY+1].
26445  One row of the array corresponds to one basis function:
26446  * first NX columns - coordinates of the center
26447  * next NY columns - weights, one per dimension of the
26448  function being modelled
26449  * last column - radius, same for all dimensions of
26450  the function being modelled
26451  NC - number of the centers
26452  V - polynomial term , array[NY,NX+1]. One row per one
26453  dimension of the function being modelled. First NX
26454  elements are linear coefficients, V[NX] is equal to the
26455  constant part.
26456 
26457  -- ALGLIB --
26458  Copyright 13.12.2011 by Bochkanov Sergey
26459 *************************************************************************/
26460 void rbfunpack(rbfmodel* s,
26461  ae_int_t* nx,
26462  ae_int_t* ny,
26463  /* Real */ ae_matrix* xwr,
26464  ae_int_t* nc,
26465  /* Real */ ae_matrix* v,
26466  ae_state *_state)
26467 {
26468  ae_int_t i;
26469  ae_int_t j;
26470  double rcur;
26471 
26472  *nx = 0;
26473  *ny = 0;
26474  ae_matrix_clear(xwr);
26475  *nc = 0;
26476  ae_matrix_clear(v);
26477 
26478  *nx = s->nx;
26479  *ny = s->ny;
26480  *nc = s->nc;
26481 
26482  /*
26483  * Fill V
26484  */
26485  ae_matrix_set_length(v, s->ny, s->nx+1, _state);
26486  for(i=0; i<=s->ny-1; i++)
26487  {
26488  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));
26489  v->ptr.pp_double[i][s->nx] = s->v.ptr.pp_double[i][rbf_mxnx];
26490  }
26491 
26492  /*
26493  * Fill XWR and V
26494  */
26495  if( *nc*s->nl>0 )
26496  {
26497  ae_matrix_set_length(xwr, s->nc*s->nl, s->nx+s->ny+1, _state);
26498  for(i=0; i<=s->nc-1; i++)
26499  {
26500  rcur = s->wr.ptr.pp_double[i][0];
26501  for(j=0; j<=s->nl-1; j++)
26502  {
26503  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));
26504  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));
26505  xwr->ptr.pp_double[i*s->nl+j][s->nx+s->ny] = rcur;
26506  rcur = 0.5*rcur;
26507  }
26508  }
26509  }
26510 }
26511 
26512 
26513 /*************************************************************************
26514 Serializer: allocation
26515 
26516  -- ALGLIB --
26517  Copyright 02.02.2012 by Bochkanov Sergey
26518 *************************************************************************/
26519 void rbfalloc(ae_serializer* s, rbfmodel* model, ae_state *_state)
26520 {
26521 
26522 
26523 
26524  /*
26525  * Header
26526  */
26527  ae_serializer_alloc_entry(s);
26528  ae_serializer_alloc_entry(s);
26529 
26530  /*
26531  * Data
26532  */
26533  ae_serializer_alloc_entry(s);
26534  ae_serializer_alloc_entry(s);
26535  ae_serializer_alloc_entry(s);
26536  ae_serializer_alloc_entry(s);
26537  kdtreealloc(s, &model->tree, _state);
26538  allocrealmatrix(s, &model->xc, -1, -1, _state);
26539  allocrealmatrix(s, &model->wr, -1, -1, _state);
26540  ae_serializer_alloc_entry(s);
26541  allocrealmatrix(s, &model->v, -1, -1, _state);
26542 }
26543 
26544 
26545 /*************************************************************************
26546 Serializer: serialization
26547 
26548  -- ALGLIB --
26549  Copyright 02.02.2012 by Bochkanov Sergey
26550 *************************************************************************/
26551 void rbfserialize(ae_serializer* s, rbfmodel* model, ae_state *_state)
26552 {
26553 
26554 
26555 
26556  /*
26557  * Header
26558  */
26559  ae_serializer_serialize_int(s, getrbfserializationcode(_state), _state);
26560  ae_serializer_serialize_int(s, rbf_rbffirstversion, _state);
26561 
26562  /*
26563  * Data
26564  */
26565  ae_serializer_serialize_int(s, model->nx, _state);
26566  ae_serializer_serialize_int(s, model->ny, _state);
26567  ae_serializer_serialize_int(s, model->nc, _state);
26568  ae_serializer_serialize_int(s, model->nl, _state);
26569  kdtreeserialize(s, &model->tree, _state);
26570  serializerealmatrix(s, &model->xc, -1, -1, _state);
26571  serializerealmatrix(s, &model->wr, -1, -1, _state);
26572  ae_serializer_serialize_double(s, model->rmax, _state);
26573  serializerealmatrix(s, &model->v, -1, -1, _state);
26574 }
26575 
26576 
26577 /*************************************************************************
26578 Serializer: unserialization
26579 
26580  -- ALGLIB --
26581  Copyright 02.02.2012 by Bochkanov Sergey
26582 *************************************************************************/
26583 void rbfunserialize(ae_serializer* s, rbfmodel* model, ae_state *_state)
26584 {
26585  ae_int_t i0;
26586  ae_int_t i1;
26587  ae_int_t nx;
26588  ae_int_t ny;
26589 
26590  _rbfmodel_clear(model);
26591 
26592 
26593  /*
26594  * Header
26595  */
26596  ae_serializer_unserialize_int(s, &i0, _state);
26597  ae_assert(i0==getrbfserializationcode(_state), "RBFUnserialize: stream header corrupted", _state);
26598  ae_serializer_unserialize_int(s, &i1, _state);
26599  ae_assert(i1==rbf_rbffirstversion, "RBFUnserialize: stream header corrupted", _state);
26600 
26601  /*
26602  * Unserialize primary model parameters, initialize model.
26603  *
26604  * It is necessary to call RBFCreate() because some internal fields
26605  * which are NOT unserialized will need initialization.
26606  */
26607  ae_serializer_unserialize_int(s, &nx, _state);
26608  ae_serializer_unserialize_int(s, &ny, _state);
26609  rbfcreate(nx, ny, model, _state);
26610  ae_serializer_unserialize_int(s, &model->nc, _state);
26611  ae_serializer_unserialize_int(s, &model->nl, _state);
26612  kdtreeunserialize(s, &model->tree, _state);
26613  unserializerealmatrix(s, &model->xc, _state);
26614  unserializerealmatrix(s, &model->wr, _state);
26615  ae_serializer_unserialize_double(s, &model->rmax, _state);
26616  unserializerealmatrix(s, &model->v, _state);
26617 }
26618 
26619 
26620 /*************************************************************************
26621 This function changes centers allocation algorithm to one which allocates
26622 centers exactly at the dataset points (one input point = one center). This
26623 function won't have effect until next call to RBFBuildModel().
26624 
26625 INPUT PARAMETERS:
26626  S - RBF model, initialized by RBFCreate() call
26627 
26628 NOTE: this function has some serialization-related subtleties. We
26629  recommend you to study serialization examples from ALGLIB Reference
26630  Manual if you want to perform serialization of your models.
26631 
26632  -- ALGLIB --
26633  Copyright 13.12.2011 by Bochkanov Sergey
26634 *************************************************************************/
26635 static void rbf_rbfgridpoints(rbfmodel* s, ae_state *_state)
26636 {
26637 
26638 
26639  s->gridtype = 2;
26640 }
26641 
26642 
26643 /*************************************************************************
26644 This function changes radii calculation algorithm to one which makes
26645 radius for I-th node equal to R[i]=DistNN[i]*Q, where:
26646 * R[i] is a radius calculated by the algorithm
26647 * DistNN[i] is distance from I-th center to its nearest neighbor center
26648 * Q is a scale parameter, which should be within [0.75,1.50], with
26649  recommended value equal to 1.0
26650 * after performing radii calculation, radii are transformed in order to
26651  avoid situation when single outlier has very large radius and influences
26652  many points across entire dataset. Transformation has following form:
26653  new_r[i] = min(r[i],Z*median(r[]))
26654  where r[i] is I-th radius, median() is a median radius across entire
26655  dataset, Z is user-specified value which controls amount of deviation
26656  from median radius.
26657 
26658 This function won't have effect until next call to RBFBuildModel().
26659 
26660 The idea behind this algorithm is to choose radii corresponding to basis
26661 functions is such way that I-th radius is approximately equal to distance
26662 from I-th center to its nearest neighbor. In this case interactions with
26663 distant points will be insignificant, and we will get well conditioned
26664 basis.
26665 
26666 Properties of this basis depend on the value of Q:
26667 * Q<0.75 will give perfectly conditioned basis, but terrible smoothness
26668  properties (RBF interpolant will have sharp peaks around function values)
26669 * Q>1.5 will lead to badly conditioned systems and slow convergence of the
26670  underlying linear solver (although smoothness will be very good)
26671 * Q around 1.0 gives good balance between smoothness and condition number
26672 
26673 
26674 INPUT PARAMETERS:
26675  S - RBF model, initialized by RBFCreate() call
26676  Q - radius coefficient, Q>0
26677  Z - z-parameter, Z>0
26678 
26679 Default value of Q is equal to 1.0
26680 Default value of Z is equal to 5.0
26681 
26682 NOTE: this function has some serialization-related subtleties. We
26683  recommend you to study serialization examples from ALGLIB Reference
26684  Manual if you want to perform serialization of your models.
26685 
26686  -- ALGLIB --
26687  Copyright 13.12.2011 by Bochkanov Sergey
26688 *************************************************************************/
26689 static void rbf_rbfradnn(rbfmodel* s,
26690  double q,
26691  double z,
26692  ae_state *_state)
26693 {
26694 
26695 
26696  ae_assert(ae_isfinite(q, _state)&&ae_fp_greater(q,0), "RBFRadNN: Q<=0, infinite or NAN", _state);
26697  ae_assert(ae_isfinite(z, _state)&&ae_fp_greater(z,0), "RBFRadNN: Z<=0, infinite or NAN", _state);
26698  s->fixrad = ae_false;
26699  s->radvalue = q;
26700  s->radzvalue = z;
26701 }
26702 
26703 
26704 static ae_bool rbf_buildlinearmodel(/* Real */ ae_matrix* x,
26705  /* Real */ ae_matrix* y,
26706  ae_int_t n,
26707  ae_int_t ny,
26708  ae_int_t modeltype,
26709  /* Real */ ae_matrix* v,
26710  ae_state *_state)
26711 {
26712  ae_frame _frame_block;
26713  ae_vector tmpy;
26714  ae_matrix a;
26715  double scaling;
26716  ae_vector shifting;
26717  double mn;
26718  double mx;
26719  ae_vector c;
26720  lsfitreport rep;
26721  ae_int_t i;
26722  ae_int_t j;
26723  ae_int_t k;
26724  ae_int_t info;
26725  ae_bool result;
26726 
26727  ae_frame_make(_state, &_frame_block);
26728  ae_matrix_clear(v);
26729  ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
26730  ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
26731  ae_vector_init(&shifting, 0, DT_REAL, _state, ae_true);
26732  ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
26733  _lsfitreport_init(&rep, _state, ae_true);
26734 
26735  ae_assert(n>=0, "BuildLinearModel: N<0", _state);
26736  ae_assert(ny>0, "BuildLinearModel: NY<=0", _state);
26737 
26738  /*
26739  * Handle degenerate case (N=0)
26740  */
26741  result = ae_true;
26742  ae_matrix_set_length(v, ny, rbf_mxnx+1, _state);
26743  if( n==0 )
26744  {
26745  for(j=0; j<=rbf_mxnx; j++)
26746  {
26747  for(i=0; i<=ny-1; i++)
26748  {
26749  v->ptr.pp_double[i][j] = 0;
26750  }
26751  }
26752  ae_frame_leave(_state);
26753  return result;
26754  }
26755 
26756  /*
26757  * Allocate temporaries
26758  */
26759  ae_vector_set_length(&tmpy, n, _state);
26760 
26761  /*
26762  * General linear model.
26763  */
26764  if( modeltype==1 )
26765  {
26766 
26767  /*
26768  * Calculate scaling/shifting, transform variables, prepare LLS problem
26769  */
26770  ae_matrix_set_length(&a, n, rbf_mxnx+1, _state);
26771  ae_vector_set_length(&shifting, rbf_mxnx, _state);
26772  scaling = 0;
26773  for(i=0; i<=rbf_mxnx-1; i++)
26774  {
26775  mn = x->ptr.pp_double[0][i];
26776  mx = mn;
26777  for(j=1; j<=n-1; j++)
26778  {
26779  if( ae_fp_greater(mn,x->ptr.pp_double[j][i]) )
26780  {
26781  mn = x->ptr.pp_double[j][i];
26782  }
26783  if( ae_fp_less(mx,x->ptr.pp_double[j][i]) )
26784  {
26785  mx = x->ptr.pp_double[j][i];
26786  }
26787  }
26788  scaling = ae_maxreal(scaling, mx-mn, _state);
26789  shifting.ptr.p_double[i] = 0.5*(mx+mn);
26790  }
26791  if( ae_fp_eq(scaling,0) )
26792  {
26793  scaling = 1;
26794  }
26795  else
26796  {
26797  scaling = 0.5*scaling;
26798  }
26799  for(i=0; i<=n-1; i++)
26800  {
26801  for(j=0; j<=rbf_mxnx-1; j++)
26802  {
26803  a.ptr.pp_double[i][j] = (x->ptr.pp_double[i][j]-shifting.ptr.p_double[j])/scaling;
26804  }
26805  }
26806  for(i=0; i<=n-1; i++)
26807  {
26808  a.ptr.pp_double[i][rbf_mxnx] = 1;
26809  }
26810 
26811  /*
26812  * Solve linear system in transformed variables, make backward
26813  */
26814  for(i=0; i<=ny-1; i++)
26815  {
26816  for(j=0; j<=n-1; j++)
26817  {
26818  tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i];
26819  }
26820  lsfitlinear(&tmpy, &a, n, rbf_mxnx+1, &info, &c, &rep, _state);
26821  if( info<=0 )
26822  {
26823  result = ae_false;
26824  ae_frame_leave(_state);
26825  return result;
26826  }
26827  for(j=0; j<=rbf_mxnx-1; j++)
26828  {
26829  v->ptr.pp_double[i][j] = c.ptr.p_double[j]/scaling;
26830  }
26831  v->ptr.pp_double[i][rbf_mxnx] = c.ptr.p_double[rbf_mxnx];
26832  for(j=0; j<=rbf_mxnx-1; j++)
26833  {
26834  v->ptr.pp_double[i][rbf_mxnx] = v->ptr.pp_double[i][rbf_mxnx]-shifting.ptr.p_double[j]*v->ptr.pp_double[i][j];
26835  }
26836  for(j=0; j<=n-1; j++)
26837  {
26838  for(k=0; k<=rbf_mxnx-1; k++)
26839  {
26840  y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-x->ptr.pp_double[j][k]*v->ptr.pp_double[i][k];
26841  }
26842  y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][rbf_mxnx];
26843  }
26844  }
26845  ae_frame_leave(_state);
26846  return result;
26847  }
26848 
26849  /*
26850  * Constant model, very simple
26851  */
26852  if( modeltype==2 )
26853  {
26854  for(i=0; i<=ny-1; i++)
26855  {
26856  for(j=0; j<=rbf_mxnx; j++)
26857  {
26858  v->ptr.pp_double[i][j] = 0;
26859  }
26860  for(j=0; j<=n-1; j++)
26861  {
26862  v->ptr.pp_double[i][rbf_mxnx] = v->ptr.pp_double[i][rbf_mxnx]+y->ptr.pp_double[j][i];
26863  }
26864  if( n>0 )
26865  {
26866  v->ptr.pp_double[i][rbf_mxnx] = v->ptr.pp_double[i][rbf_mxnx]/n;
26867  }
26868  for(j=0; j<=n-1; j++)
26869  {
26870  y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-v->ptr.pp_double[i][rbf_mxnx];
26871  }
26872  }
26873  ae_frame_leave(_state);
26874  return result;
26875  }
26876 
26877  /*
26878  * Zero model
26879  */
26880  ae_assert(modeltype==3, "BuildLinearModel: unknown model type", _state);
26881  for(i=0; i<=ny-1; i++)
26882  {
26883  for(j=0; j<=rbf_mxnx; j++)
26884  {
26885  v->ptr.pp_double[i][j] = 0;
26886  }
26887  }
26888  ae_frame_leave(_state);
26889  return result;
26890 }
26891 
26892 
26893 static void rbf_buildrbfmodellsqr(/* Real */ ae_matrix* x,
26894  /* Real */ ae_matrix* y,
26895  /* Real */ ae_matrix* xc,
26896  /* Real */ ae_vector* r,
26897  ae_int_t n,
26898  ae_int_t nc,
26899  ae_int_t ny,
26900  kdtree* pointstree,
26901  kdtree* centerstree,
26902  double epsort,
26903  double epserr,
26904  ae_int_t maxits,
26905  ae_int_t* gnnz,
26906  ae_int_t* snnz,
26907  /* Real */ ae_matrix* w,
26908  ae_int_t* info,
26909  ae_int_t* iterationscount,
26910  ae_int_t* nmv,
26911  ae_state *_state)
26912 {
26913  ae_frame _frame_block;
26914  linlsqrstate state;
26915  linlsqrreport lsqrrep;
26916  sparsematrix spg;
26917  sparsematrix sps;
26918  ae_vector nearcenterscnt;
26919  ae_vector nearpointscnt;
26920  ae_vector skipnearpointscnt;
26921  ae_vector farpointscnt;
26922  ae_int_t maxnearcenterscnt;
26923  ae_int_t maxnearpointscnt;
26924  ae_int_t maxfarpointscnt;
26925  ae_int_t sumnearcenterscnt;
26926  ae_int_t sumnearpointscnt;
26927  ae_int_t sumfarpointscnt;
26928  double maxrad;
26929  ae_vector pointstags;
26930  ae_vector centerstags;
26931  ae_matrix nearpoints;
26932  ae_matrix nearcenters;
26933  ae_matrix farpoints;
26934  ae_int_t tmpi;
26935  ae_int_t pointscnt;
26936  ae_int_t centerscnt;
26937  ae_vector xcx;
26938  ae_vector tmpy;
26939  ae_vector tc;
26940  ae_vector g;
26941  ae_vector c;
26942  ae_int_t i;
26943  ae_int_t j;
26944  ae_int_t k;
26945  ae_int_t sind;
26946  ae_matrix a;
26947  double vv;
26948  double vx;
26949  double vy;
26950  double vz;
26951  double vr;
26952  double gnorm2;
26953  ae_vector tmp0;
26954  ae_vector tmp1;
26955  ae_vector tmp2;
26956  double fx;
26957  ae_matrix xx;
26958  ae_matrix cx;
26959  double mrad;
26960 
26961  ae_frame_make(_state, &_frame_block);
26962  *gnnz = 0;
26963  *snnz = 0;
26964  ae_matrix_clear(w);
26965  *info = 0;
26966  *iterationscount = 0;
26967  *nmv = 0;
26968  _linlsqrstate_init(&state, _state, ae_true);
26969  _linlsqrreport_init(&lsqrrep, _state, ae_true);
26970  _sparsematrix_init(&spg, _state, ae_true);
26971  _sparsematrix_init(&sps, _state, ae_true);
26972  ae_vector_init(&nearcenterscnt, 0, DT_INT, _state, ae_true);
26973  ae_vector_init(&nearpointscnt, 0, DT_INT, _state, ae_true);
26974  ae_vector_init(&skipnearpointscnt, 0, DT_INT, _state, ae_true);
26975  ae_vector_init(&farpointscnt, 0, DT_INT, _state, ae_true);
26976  ae_vector_init(&pointstags, 0, DT_INT, _state, ae_true);
26977  ae_vector_init(&centerstags, 0, DT_INT, _state, ae_true);
26978  ae_matrix_init(&nearpoints, 0, 0, DT_REAL, _state, ae_true);
26979  ae_matrix_init(&nearcenters, 0, 0, DT_REAL, _state, ae_true);
26980  ae_matrix_init(&farpoints, 0, 0, DT_REAL, _state, ae_true);
26981  ae_vector_init(&xcx, 0, DT_REAL, _state, ae_true);
26982  ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
26983  ae_vector_init(&tc, 0, DT_REAL, _state, ae_true);
26984  ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
26985  ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
26986  ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
26987  ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
26988  ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
26989  ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
26990  ae_matrix_init(&xx, 0, 0, DT_REAL, _state, ae_true);
26991  ae_matrix_init(&cx, 0, 0, DT_REAL, _state, ae_true);
26992 
26993 
26994  /*
26995  * Handle special cases: NC=0
26996  */
26997  if( nc==0 )
26998  {
26999  *info = 1;
27000  *iterationscount = 0;
27001  *nmv = 0;
27002  ae_frame_leave(_state);
27003  return;
27004  }
27005 
27006  /*
27007  * Prepare for general case, NC>0
27008  */
27009  ae_vector_set_length(&xcx, rbf_mxnx, _state);
27010  ae_vector_set_length(&pointstags, n, _state);
27011  ae_vector_set_length(&centerstags, nc, _state);
27012  *info = -1;
27013  *iterationscount = 0;
27014  *nmv = 0;
27015 
27016  /*
27017  * This block prepares quantities used to compute approximate cardinal basis functions (ACBFs):
27018  * * NearCentersCnt[] - array[NC], whose elements store number of near centers used to build ACBF
27019  * * NearPointsCnt[] - array[NC], number of near points used to build ACBF
27020  * * FarPointsCnt[] - array[NC], number of far points (ones where ACBF is nonzero)
27021  * * MaxNearCentersCnt - max(NearCentersCnt)
27022  * * MaxNearPointsCnt - max(NearPointsCnt)
27023  * * SumNearCentersCnt - sum(NearCentersCnt)
27024  * * SumNearPointsCnt - sum(NearPointsCnt)
27025  * * SumFarPointsCnt - sum(FarPointsCnt)
27026  */
27027  ae_vector_set_length(&nearcenterscnt, nc, _state);
27028  ae_vector_set_length(&nearpointscnt, nc, _state);
27029  ae_vector_set_length(&skipnearpointscnt, nc, _state);
27030  ae_vector_set_length(&farpointscnt, nc, _state);
27031  maxnearcenterscnt = 0;
27032  maxnearpointscnt = 0;
27033  maxfarpointscnt = 0;
27034  sumnearcenterscnt = 0;
27035  sumnearpointscnt = 0;
27036  sumfarpointscnt = 0;
27037  for(i=0; i<=nc-1; i++)
27038  {
27039  for(j=0; j<=rbf_mxnx-1; j++)
27040  {
27041  xcx.ptr.p_double[j] = xc->ptr.pp_double[i][j];
27042  }
27043 
27044  /*
27045  * Determine number of near centers and maximum radius of near centers
27046  */
27047  nearcenterscnt.ptr.p_int[i] = kdtreequeryrnn(centerstree, &xcx, r->ptr.p_double[i]*rbf_rbfnearradius, ae_true, _state);
27048  kdtreequeryresultstags(centerstree, &centerstags, _state);
27049  maxrad = 0;
27050  for(j=0; j<=nearcenterscnt.ptr.p_int[i]-1; j++)
27051  {
27052  maxrad = ae_maxreal(maxrad, ae_fabs(r->ptr.p_double[centerstags.ptr.p_int[j]], _state), _state);
27053  }
27054 
27055  /*
27056  * Determine number of near points (ones which used to build ACBF)
27057  * and skipped points (the most near points which are NOT used to build ACBF
27058  * and are NOT included in the near points count
27059  */
27060  skipnearpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, 0.1*r->ptr.p_double[i], ae_true, _state);
27061  nearpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, (r->ptr.p_double[i]+maxrad)*rbf_rbfnearradius, ae_true, _state)-skipnearpointscnt.ptr.p_int[i];
27062  ae_assert(nearpointscnt.ptr.p_int[i]>=0, "BuildRBFModelLSQR: internal error", _state);
27063 
27064  /*
27065  * Determine number of far points
27066  */
27067  farpointscnt.ptr.p_int[i] = kdtreequeryrnn(pointstree, &xcx, ae_maxreal(r->ptr.p_double[i]*rbf_rbfnearradius+maxrad*rbf_rbffarradius, r->ptr.p_double[i]*rbf_rbffarradius, _state), ae_true, _state);
27068 
27069  /*
27070  * calculate sum and max, make some basic checks
27071  */
27072  ae_assert(nearcenterscnt.ptr.p_int[i]>0, "BuildRBFModelLSQR: internal error", _state);
27073  maxnearcenterscnt = ae_maxint(maxnearcenterscnt, nearcenterscnt.ptr.p_int[i], _state);
27074  maxnearpointscnt = ae_maxint(maxnearpointscnt, nearpointscnt.ptr.p_int[i], _state);
27075  maxfarpointscnt = ae_maxint(maxfarpointscnt, farpointscnt.ptr.p_int[i], _state);
27076  sumnearcenterscnt = sumnearcenterscnt+nearcenterscnt.ptr.p_int[i];
27077  sumnearpointscnt = sumnearpointscnt+nearpointscnt.ptr.p_int[i];
27078  sumfarpointscnt = sumfarpointscnt+farpointscnt.ptr.p_int[i];
27079  }
27080  *snnz = sumnearcenterscnt;
27081  *gnnz = sumfarpointscnt;
27082  ae_assert(maxnearcenterscnt>0, "BuildRBFModelLSQR: internal error", _state);
27083 
27084  /*
27085  * Allocate temporaries.
27086  *
27087  * NOTE: we want to avoid allocation of zero-size arrays, so we
27088  * use max(desired_size,1) instead of desired_size when performing
27089  * memory allocation.
27090  */
27091  ae_matrix_set_length(&a, maxnearpointscnt+maxnearcenterscnt, maxnearcenterscnt, _state);
27092  ae_vector_set_length(&tmpy, maxnearpointscnt+maxnearcenterscnt, _state);
27093  ae_vector_set_length(&g, maxnearcenterscnt, _state);
27094  ae_vector_set_length(&c, maxnearcenterscnt, _state);
27095  ae_matrix_set_length(&nearcenters, maxnearcenterscnt, rbf_mxnx, _state);
27096  ae_matrix_set_length(&nearpoints, ae_maxint(maxnearpointscnt, 1, _state), rbf_mxnx, _state);
27097  ae_matrix_set_length(&farpoints, ae_maxint(maxfarpointscnt, 1, _state), rbf_mxnx, _state);
27098 
27099  /*
27100  * fill matrix SpG
27101  */
27102  sparsecreate(n, nc, *gnnz, &spg, _state);
27103  sparsecreate(nc, nc, *snnz, &sps, _state);
27104  for(i=0; i<=nc-1; i++)
27105  {
27106  centerscnt = nearcenterscnt.ptr.p_int[i];
27107 
27108  /*
27109  * main center
27110  */
27111  for(j=0; j<=rbf_mxnx-1; j++)
27112  {
27113  xcx.ptr.p_double[j] = xc->ptr.pp_double[i][j];
27114  }
27115 
27116  /*
27117  * center's tree
27118  */
27119  tmpi = kdtreequeryknn(centerstree, &xcx, centerscnt, ae_true, _state);
27120  ae_assert(tmpi==centerscnt, "BuildRBFModelLSQR: internal error", _state);
27121  kdtreequeryresultsx(centerstree, &cx, _state);
27122  kdtreequeryresultstags(centerstree, &centerstags, _state);
27123 
27124  /*
27125  * point's tree
27126  */
27127  mrad = 0;
27128  for(j=0; j<=centerscnt-1; j++)
27129  {
27130  mrad = ae_maxreal(mrad, r->ptr.p_double[centerstags.ptr.p_int[j]], _state);
27131  }
27132 
27133  /*
27134  * we need to be sure that 'CTree' contains
27135  * at least one side center
27136  */
27137  sparseset(&sps, i, i, 1, _state);
27138  c.ptr.p_double[0] = 1.0;
27139  for(j=1; j<=centerscnt-1; j++)
27140  {
27141  c.ptr.p_double[j] = 0.0;
27142  }
27143  if( centerscnt>1&&nearpointscnt.ptr.p_int[i]>0 )
27144  {
27145 
27146  /*
27147  * first KDTree request for points
27148  */
27149  pointscnt = nearpointscnt.ptr.p_int[i];
27150  tmpi = kdtreequeryknn(pointstree, &xcx, skipnearpointscnt.ptr.p_int[i]+nearpointscnt.ptr.p_int[i], ae_true, _state);
27151  ae_assert(tmpi==skipnearpointscnt.ptr.p_int[i]+nearpointscnt.ptr.p_int[i], "BuildRBFModelLSQR: internal error", _state);
27152  kdtreequeryresultsx(pointstree, &xx, _state);
27153  sind = skipnearpointscnt.ptr.p_int[i];
27154  for(j=0; j<=pointscnt-1; j++)
27155  {
27156  vx = xx.ptr.pp_double[sind+j][0];
27157  vy = xx.ptr.pp_double[sind+j][1];
27158  vz = xx.ptr.pp_double[sind+j][2];
27159  for(k=0; k<=centerscnt-1; k++)
27160  {
27161  vr = 0.0;
27162  vv = vx-cx.ptr.pp_double[k][0];
27163  vr = vr+vv*vv;
27164  vv = vy-cx.ptr.pp_double[k][1];
27165  vr = vr+vv*vv;
27166  vv = vz-cx.ptr.pp_double[k][2];
27167  vr = vr+vv*vv;
27168  vv = r->ptr.p_double[centerstags.ptr.p_int[k]];
27169  a.ptr.pp_double[j][k] = ae_exp(-vr/(vv*vv), _state);
27170  }
27171  }
27172  for(j=0; j<=centerscnt-1; j++)
27173  {
27174  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);
27175  }
27176 
27177  /*
27178  * calculate the problem
27179  */
27180  gnorm2 = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
27181  for(j=0; j<=pointscnt-1; j++)
27182  {
27183  vv = ae_v_dotproduct(&a.ptr.pp_double[j][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
27184  vv = vv/gnorm2;
27185  tmpy.ptr.p_double[j] = -vv;
27186  ae_v_subd(&a.ptr.pp_double[j][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv);
27187  }
27188  for(j=pointscnt; j<=pointscnt+centerscnt-1; j++)
27189  {
27190  for(k=0; k<=centerscnt-1; k++)
27191  {
27192  a.ptr.pp_double[j][k] = 0.0;
27193  }
27194  a.ptr.pp_double[j][j-pointscnt] = 1.0E-6;
27195  tmpy.ptr.p_double[j] = 0.0;
27196  }
27197  fblssolvels(&a, &tmpy, pointscnt+centerscnt, centerscnt, &tmp0, &tmp1, &tmp2, _state);
27198  ae_v_move(&c.ptr.p_double[0], 1, &tmpy.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
27199  vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1));
27200  vv = vv/gnorm2;
27201  ae_v_subd(&c.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv);
27202  vv = 1/gnorm2;
27203  ae_v_addd(&c.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,centerscnt-1), vv);
27204  for(j=0; j<=centerscnt-1; j++)
27205  {
27206  sparseset(&sps, i, centerstags.ptr.p_int[j], c.ptr.p_double[j], _state);
27207  }
27208  }
27209 
27210  /*
27211  * second KDTree request for points
27212  */
27213  pointscnt = farpointscnt.ptr.p_int[i];
27214  tmpi = kdtreequeryknn(pointstree, &xcx, pointscnt, ae_true, _state);
27215  ae_assert(tmpi==pointscnt, "BuildRBFModelLSQR: internal error", _state);
27216  kdtreequeryresultsx(pointstree, &xx, _state);
27217  kdtreequeryresultstags(pointstree, &pointstags, _state);
27218 
27219  /*
27220  *fill SpG matrix
27221  */
27222  for(j=0; j<=pointscnt-1; j++)
27223  {
27224  fx = 0;
27225  vx = xx.ptr.pp_double[j][0];
27226  vy = xx.ptr.pp_double[j][1];
27227  vz = xx.ptr.pp_double[j][2];
27228  for(k=0; k<=centerscnt-1; k++)
27229  {
27230  vr = 0.0;
27231  vv = vx-cx.ptr.pp_double[k][0];
27232  vr = vr+vv*vv;
27233  vv = vy-cx.ptr.pp_double[k][1];
27234  vr = vr+vv*vv;
27235  vv = vz-cx.ptr.pp_double[k][2];
27236  vr = vr+vv*vv;
27237  vv = r->ptr.p_double[centerstags.ptr.p_int[k]];
27238  vv = vv*vv;
27239  fx = fx+c.ptr.p_double[k]*ae_exp(-vr/vv, _state);
27240  }
27241  sparseset(&spg, pointstags.ptr.p_int[j], i, fx, _state);
27242  }
27243  }
27244  sparseconverttocrs(&spg, _state);
27245  sparseconverttocrs(&sps, _state);
27246 
27247  /*
27248  * solve by LSQR method
27249  */
27250  ae_vector_set_length(&tmpy, n, _state);
27251  ae_vector_set_length(&tc, nc, _state);
27252  ae_matrix_set_length(w, nc, ny, _state);
27253  linlsqrcreate(n, nc, &state, _state);
27254  linlsqrsetcond(&state, epsort, epserr, maxits, _state);
27255  for(i=0; i<=ny-1; i++)
27256  {
27257  for(j=0; j<=n-1; j++)
27258  {
27259  tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i];
27260  }
27261  linlsqrsolvesparse(&state, &spg, &tmpy, _state);
27262  linlsqrresults(&state, &c, &lsqrrep, _state);
27263  if( lsqrrep.terminationtype<=0 )
27264  {
27265  *info = -4;
27266  ae_frame_leave(_state);
27267  return;
27268  }
27269  sparsemtv(&sps, &c, &tc, _state);
27270  for(j=0; j<=nc-1; j++)
27271  {
27272  w->ptr.pp_double[j][i] = tc.ptr.p_double[j];
27273  }
27274  *iterationscount = *iterationscount+lsqrrep.iterationscount;
27275  *nmv = *nmv+lsqrrep.nmv;
27276  }
27277  *info = 1;
27278  ae_frame_leave(_state);
27279 }
27280 
27281 
27282 static void rbf_buildrbfmlayersmodellsqr(/* Real */ ae_matrix* x,
27283  /* Real */ ae_matrix* y,
27284  /* Real */ ae_matrix* xc,
27285  double rval,
27286  /* Real */ ae_vector* r,
27287  ae_int_t n,
27288  ae_int_t* nc,
27289  ae_int_t ny,
27290  ae_int_t nlayers,
27291  kdtree* centerstree,
27292  double epsort,
27293  double epserr,
27294  ae_int_t maxits,
27295  double lambdav,
27296  ae_int_t* annz,
27297  /* Real */ ae_matrix* w,
27298  ae_int_t* info,
27299  ae_int_t* iterationscount,
27300  ae_int_t* nmv,
27301  ae_state *_state)
27302 {
27303  ae_frame _frame_block;
27304  linlsqrstate state;
27305  linlsqrreport lsqrrep;
27306  sparsematrix spa;
27307  double anorm;
27308  ae_vector omega;
27309  ae_vector xx;
27310  ae_vector tmpy;
27311  ae_matrix cx;
27312  double yval;
27313  ae_int_t nec;
27314  ae_vector centerstags;
27315  ae_int_t layer;
27316  ae_int_t i;
27317  ae_int_t j;
27318  ae_int_t k;
27319  double v;
27320  double rmaxbefore;
27321  double rmaxafter;
27322 
27323  ae_frame_make(_state, &_frame_block);
27324  ae_matrix_clear(xc);
27325  ae_vector_clear(r);
27326  *nc = 0;
27327  *annz = 0;
27328  ae_matrix_clear(w);
27329  *info = 0;
27330  *iterationscount = 0;
27331  *nmv = 0;
27332  _linlsqrstate_init(&state, _state, ae_true);
27333  _linlsqrreport_init(&lsqrrep, _state, ae_true);
27334  _sparsematrix_init(&spa, _state, ae_true);
27335  ae_vector_init(&omega, 0, DT_REAL, _state, ae_true);
27336  ae_vector_init(&xx, 0, DT_REAL, _state, ae_true);
27337  ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
27338  ae_matrix_init(&cx, 0, 0, DT_REAL, _state, ae_true);
27339  ae_vector_init(&centerstags, 0, DT_INT, _state, ae_true);
27340 
27341  ae_assert(nlayers>=0, "BuildRBFMLayersModelLSQR: invalid argument(NLayers<0)", _state);
27342  ae_assert(n>=0, "BuildRBFMLayersModelLSQR: invalid argument(N<0)", _state);
27343  ae_assert(rbf_mxnx>0&&rbf_mxnx<=3, "BuildRBFMLayersModelLSQR: internal error(invalid global const MxNX: either MxNX<=0 or MxNX>3)", _state);
27344  *annz = 0;
27345  if( n==0||nlayers==0 )
27346  {
27347  *info = 1;
27348  *iterationscount = 0;
27349  *nmv = 0;
27350  ae_frame_leave(_state);
27351  return;
27352  }
27353  *nc = n*nlayers;
27354  ae_vector_set_length(&xx, rbf_mxnx, _state);
27355  ae_vector_set_length(&centerstags, n, _state);
27356  ae_matrix_set_length(xc, *nc, rbf_mxnx, _state);
27357  ae_vector_set_length(r, *nc, _state);
27358  for(i=0; i<=*nc-1; i++)
27359  {
27360  for(j=0; j<=rbf_mxnx-1; j++)
27361  {
27362  xc->ptr.pp_double[i][j] = x->ptr.pp_double[i%n][j];
27363  }
27364  }
27365  for(i=0; i<=*nc-1; i++)
27366  {
27367  r->ptr.p_double[i] = rval/ae_pow(2, i/n, _state);
27368  }
27369  for(i=0; i<=n-1; i++)
27370  {
27371  centerstags.ptr.p_int[i] = i;
27372  }
27373  kdtreebuildtagged(xc, &centerstags, n, rbf_mxnx, 0, 2, centerstree, _state);
27374  ae_vector_set_length(&omega, n, _state);
27375  ae_vector_set_length(&tmpy, n, _state);
27376  ae_matrix_set_length(w, *nc, ny, _state);
27377  *info = -1;
27378  *iterationscount = 0;
27379  *nmv = 0;
27380  linlsqrcreate(n, n, &state, _state);
27381  linlsqrsetcond(&state, epsort, epserr, maxits, _state);
27382  linlsqrsetlambdai(&state, 1.0E-6, _state);
27383 
27384  /*
27385  * calculate number of non-zero elements for sparse matrix
27386  */
27387  for(i=0; i<=n-1; i++)
27388  {
27389  for(j=0; j<=rbf_mxnx-1; j++)
27390  {
27391  xx.ptr.p_double[j] = x->ptr.pp_double[i][j];
27392  }
27393  *annz = *annz+kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[0]*rbf_rbfmlradius, ae_true, _state);
27394  }
27395  for(layer=0; layer<=nlayers-1; layer++)
27396  {
27397 
27398  /*
27399  * Fill sparse matrix, calculate norm(A)
27400  */
27401  anorm = 0.0;
27402  sparsecreate(n, n, *annz, &spa, _state);
27403  for(i=0; i<=n-1; i++)
27404  {
27405  for(j=0; j<=rbf_mxnx-1; j++)
27406  {
27407  xx.ptr.p_double[j] = x->ptr.pp_double[i][j];
27408  }
27409  nec = kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[layer*n]*rbf_rbfmlradius, ae_true, _state);
27410  kdtreequeryresultsx(centerstree, &cx, _state);
27411  kdtreequeryresultstags(centerstree, &centerstags, _state);
27412  for(j=0; j<=nec-1; j++)
27413  {
27414  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);
27415  sparseset(&spa, i, centerstags.ptr.p_int[j], v, _state);
27416  anorm = anorm+ae_sqr(v, _state);
27417  }
27418  }
27419  anorm = ae_sqrt(anorm, _state);
27420  sparseconverttocrs(&spa, _state);
27421 
27422  /*
27423  * Calculate maximum residual before adding new layer.
27424  * This value is not used by algorithm, the only purpose is to make debugging easier.
27425  */
27426  rmaxbefore = 0.0;
27427  for(j=0; j<=n-1; j++)
27428  {
27429  for(i=0; i<=ny-1; i++)
27430  {
27431  rmaxbefore = ae_maxreal(rmaxbefore, ae_fabs(y->ptr.pp_double[j][i], _state), _state);
27432  }
27433  }
27434 
27435  /*
27436  * Process NY dimensions of the target function
27437  */
27438  for(i=0; i<=ny-1; i++)
27439  {
27440  for(j=0; j<=n-1; j++)
27441  {
27442  tmpy.ptr.p_double[j] = y->ptr.pp_double[j][i];
27443  }
27444 
27445  /*
27446  * calculate Omega for current layer
27447  */
27448  linlsqrsetlambdai(&state, lambdav*anorm/n, _state);
27449  linlsqrsolvesparse(&state, &spa, &tmpy, _state);
27450  linlsqrresults(&state, &omega, &lsqrrep, _state);
27451  if( lsqrrep.terminationtype<=0 )
27452  {
27453  *info = -4;
27454  ae_frame_leave(_state);
27455  return;
27456  }
27457 
27458  /*
27459  * calculate error for current layer
27460  */
27461  for(j=0; j<=n-1; j++)
27462  {
27463  yval = 0;
27464  for(k=0; k<=rbf_mxnx-1; k++)
27465  {
27466  xx.ptr.p_double[k] = x->ptr.pp_double[j][k];
27467  }
27468  nec = kdtreequeryrnn(centerstree, &xx, r->ptr.p_double[layer*n]*rbf_rbffarradius, ae_true, _state);
27469  kdtreequeryresultsx(centerstree, &cx, _state);
27470  kdtreequeryresultstags(centerstree, &centerstags, _state);
27471  for(k=0; k<=nec-1; k++)
27472  {
27473  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);
27474  }
27475  y->ptr.pp_double[j][i] = y->ptr.pp_double[j][i]-yval;
27476  }
27477 
27478  /*
27479  * write Omega in out parameter W
27480  */
27481  for(j=0; j<=n-1; j++)
27482  {
27483  w->ptr.pp_double[layer*n+j][i] = omega.ptr.p_double[j];
27484  }
27485  *iterationscount = *iterationscount+lsqrrep.iterationscount;
27486  *nmv = *nmv+lsqrrep.nmv;
27487  }
27488 
27489  /*
27490  * Calculate maximum residual before adding new layer.
27491  * This value is not used by algorithm, the only purpose is to make debugging easier.
27492  */
27493  rmaxafter = 0.0;
27494  for(j=0; j<=n-1; j++)
27495  {
27496  for(i=0; i<=ny-1; i++)
27497  {
27498  rmaxafter = ae_maxreal(rmaxafter, ae_fabs(y->ptr.pp_double[j][i], _state), _state);
27499  }
27500  }
27501  }
27502  *info = 1;
27503  ae_frame_leave(_state);
27504 }
27505 
27506 
27507 ae_bool _rbfmodel_init(void* _p, ae_state *_state, ae_bool make_automatic)
27508 {
27509  rbfmodel *p = (rbfmodel*)_p;
27510  ae_touch_ptr((void*)p);
27511  if( !_kdtree_init(&p->tree, _state, make_automatic) )
27512  return ae_false;
27513  if( !ae_matrix_init(&p->xc, 0, 0, DT_REAL, _state, make_automatic) )
27514  return ae_false;
27515  if( !ae_matrix_init(&p->wr, 0, 0, DT_REAL, _state, make_automatic) )
27516  return ae_false;
27517  if( !ae_matrix_init(&p->v, 0, 0, DT_REAL, _state, make_automatic) )
27518  return ae_false;
27519  if( !ae_matrix_init(&p->x, 0, 0, DT_REAL, _state, make_automatic) )
27520  return ae_false;
27521  if( !ae_matrix_init(&p->y, 0, 0, DT_REAL, _state, make_automatic) )
27522  return ae_false;
27523  if( !ae_vector_init(&p->calcbufxcx, 0, DT_REAL, _state, make_automatic) )
27524  return ae_false;
27525  if( !ae_matrix_init(&p->calcbufx, 0, 0, DT_REAL, _state, make_automatic) )
27526  return ae_false;
27527  if( !ae_vector_init(&p->calcbuftags, 0, DT_INT, _state, make_automatic) )
27528  return ae_false;
27529  return ae_true;
27530 }
27531 
27532 
27533 ae_bool _rbfmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27534 {
27535  rbfmodel *dst = (rbfmodel*)_dst;
27536  rbfmodel *src = (rbfmodel*)_src;
27537  dst->ny = src->ny;
27538  dst->nx = src->nx;
27539  dst->nc = src->nc;
27540  dst->nl = src->nl;
27541  if( !_kdtree_init_copy(&dst->tree, &src->tree, _state, make_automatic) )
27542  return ae_false;
27543  if( !ae_matrix_init_copy(&dst->xc, &src->xc, _state, make_automatic) )
27544  return ae_false;
27545  if( !ae_matrix_init_copy(&dst->wr, &src->wr, _state, make_automatic) )
27546  return ae_false;
27547  dst->rmax = src->rmax;
27548  if( !ae_matrix_init_copy(&dst->v, &src->v, _state, make_automatic) )
27549  return ae_false;
27550  dst->gridtype = src->gridtype;
27551  dst->fixrad = src->fixrad;
27552  dst->lambdav = src->lambdav;
27553  dst->radvalue = src->radvalue;
27554  dst->radzvalue = src->radzvalue;
27555  dst->nlayers = src->nlayers;
27556  dst->aterm = src->aterm;
27557  dst->algorithmtype = src->algorithmtype;
27558  dst->epsort = src->epsort;
27559  dst->epserr = src->epserr;
27560  dst->maxits = src->maxits;
27561  dst->h = src->h;
27562  dst->n = src->n;
27563  if( !ae_matrix_init_copy(&dst->x, &src->x, _state, make_automatic) )
27564  return ae_false;
27565  if( !ae_matrix_init_copy(&dst->y, &src->y, _state, make_automatic) )
27566  return ae_false;
27567  if( !ae_vector_init_copy(&dst->calcbufxcx, &src->calcbufxcx, _state, make_automatic) )
27568  return ae_false;
27569  if( !ae_matrix_init_copy(&dst->calcbufx, &src->calcbufx, _state, make_automatic) )
27570  return ae_false;
27571  if( !ae_vector_init_copy(&dst->calcbuftags, &src->calcbuftags, _state, make_automatic) )
27572  return ae_false;
27573  return ae_true;
27574 }
27575 
27576 
27577 void _rbfmodel_clear(void* _p)
27578 {
27579  rbfmodel *p = (rbfmodel*)_p;
27580  ae_touch_ptr((void*)p);
27581  _kdtree_clear(&p->tree);
27582  ae_matrix_clear(&p->xc);
27583  ae_matrix_clear(&p->wr);
27584  ae_matrix_clear(&p->v);
27585  ae_matrix_clear(&p->x);
27586  ae_matrix_clear(&p->y);
27587  ae_vector_clear(&p->calcbufxcx);
27588  ae_matrix_clear(&p->calcbufx);
27589  ae_vector_clear(&p->calcbuftags);
27590 }
27591 
27592 
27593 void _rbfmodel_destroy(void* _p)
27594 {
27595  rbfmodel *p = (rbfmodel*)_p;
27596  ae_touch_ptr((void*)p);
27597  _kdtree_destroy(&p->tree);
27598  ae_matrix_destroy(&p->xc);
27599  ae_matrix_destroy(&p->wr);
27600  ae_matrix_destroy(&p->v);
27601  ae_matrix_destroy(&p->x);
27602  ae_matrix_destroy(&p->y);
27603  ae_vector_destroy(&p->calcbufxcx);
27604  ae_matrix_destroy(&p->calcbufx);
27605  ae_vector_destroy(&p->calcbuftags);
27606 }
27607 
27608 
27609 ae_bool _rbfreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
27610 {
27611  rbfreport *p = (rbfreport*)_p;
27612  ae_touch_ptr((void*)p);
27613  return ae_true;
27614 }
27615 
27616 
27617 ae_bool _rbfreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27618 {
27619  rbfreport *dst = (rbfreport*)_dst;
27620  rbfreport *src = (rbfreport*)_src;
27621  dst->arows = src->arows;
27622  dst->acols = src->acols;
27623  dst->annz = src->annz;
27624  dst->iterationscount = src->iterationscount;
27625  dst->nmv = src->nmv;
27626  dst->terminationtype = src->terminationtype;
27627  return ae_true;
27628 }
27629 
27630 
27631 void _rbfreport_clear(void* _p)
27632 {
27633  rbfreport *p = (rbfreport*)_p;
27634  ae_touch_ptr((void*)p);
27635 }
27636 
27637 
27638 void _rbfreport_destroy(void* _p)
27639 {
27640  rbfreport *p = (rbfreport*)_p;
27641  ae_touch_ptr((void*)p);
27642 }
27643 
27644 
27645 
27646 
27647 /*************************************************************************
27648 This subroutine calculates the value of the bilinear or bicubic spline at
27649 the given point X.
27650 
27651 Input parameters:
27652  C - coefficients table.
27653  Built by BuildBilinearSpline or BuildBicubicSpline.
27654  X, Y- point
27655 
27656 Result:
27657  S(x,y)
27658 
27659  -- ALGLIB PROJECT --
27660  Copyright 05.07.2007 by Bochkanov Sergey
27661 *************************************************************************/
27662 double spline2dcalc(spline2dinterpolant* c,
27663  double x,
27664  double y,
27665  ae_state *_state)
27666 {
27667  double v;
27668  double vx;
27669  double vy;
27670  double vxy;
27671  double result;
27672 
27673 
27674  ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalc: incorrect C (incorrect parameter C.SType)", _state);
27675  ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalc: X or Y contains NaN or Infinite value", _state);
27676  if( c->d!=1 )
27677  {
27678  result = 0;
27679  return result;
27680  }
27681  spline2ddiff(c, x, y, &v, &vx, &vy, &vxy, _state);
27682  result = v;
27683  return result;
27684 }
27685 
27686 
27687 /*************************************************************************
27688 This subroutine calculates the value of the bilinear or bicubic spline at
27689 the given point X and its derivatives.
27690 
27691 Input parameters:
27692  C - spline interpolant.
27693  X, Y- point
27694 
27695 Output parameters:
27696  F - S(x,y)
27697  FX - dS(x,y)/dX
27698  FY - dS(x,y)/dY
27699  FXY - d2S(x,y)/dXdY
27700 
27701  -- ALGLIB PROJECT --
27702  Copyright 05.07.2007 by Bochkanov Sergey
27703 *************************************************************************/
27704 void spline2ddiff(spline2dinterpolant* c,
27705  double x,
27706  double y,
27707  double* f,
27708  double* fx,
27709  double* fy,
27710  double* fxy,
27711  ae_state *_state)
27712 {
27713  double t;
27714  double dt;
27715  double u;
27716  double du;
27717  ae_int_t ix;
27718  ae_int_t iy;
27719  ae_int_t l;
27720  ae_int_t r;
27721  ae_int_t h;
27722  ae_int_t s1;
27723  ae_int_t s2;
27724  ae_int_t s3;
27725  ae_int_t s4;
27726  ae_int_t sfx;
27727  ae_int_t sfy;
27728  ae_int_t sfxy;
27729  double y1;
27730  double y2;
27731  double y3;
27732  double y4;
27733  double v;
27734  double t0;
27735  double t1;
27736  double t2;
27737  double t3;
27738  double u0;
27739  double u1;
27740  double u2;
27741  double u3;
27742 
27743  *f = 0;
27744  *fx = 0;
27745  *fy = 0;
27746  *fxy = 0;
27747 
27748  ae_assert(c->stype==-1||c->stype==-3, "Spline2DDiff: incorrect C (incorrect parameter C.SType)", _state);
27749  ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DDiff: X or Y contains NaN or Infinite value", _state);
27750 
27751  /*
27752  * Prepare F, dF/dX, dF/dY, d2F/dXdY
27753  */
27754  *f = 0;
27755  *fx = 0;
27756  *fy = 0;
27757  *fxy = 0;
27758  if( c->d!=1 )
27759  {
27760  return;
27761  }
27762 
27763  /*
27764  * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
27765  */
27766  l = 0;
27767  r = c->n-1;
27768  while(l!=r-1)
27769  {
27770  h = (l+r)/2;
27771  if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
27772  {
27773  r = h;
27774  }
27775  else
27776  {
27777  l = h;
27778  }
27779  }
27780  t = (x-c->x.ptr.p_double[l])/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
27781  dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
27782  ix = l;
27783 
27784  /*
27785  * Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included)
27786  */
27787  l = 0;
27788  r = c->m-1;
27789  while(l!=r-1)
27790  {
27791  h = (l+r)/2;
27792  if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
27793  {
27794  r = h;
27795  }
27796  else
27797  {
27798  l = h;
27799  }
27800  }
27801  u = (y-c->y.ptr.p_double[l])/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
27802  du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
27803  iy = l;
27804 
27805  /*
27806  * Bilinear interpolation
27807  */
27808  if( c->stype==-1 )
27809  {
27810  y1 = c->f.ptr.p_double[c->n*iy+ix];
27811  y2 = c->f.ptr.p_double[c->n*iy+(ix+1)];
27812  y3 = c->f.ptr.p_double[c->n*(iy+1)+(ix+1)];
27813  y4 = c->f.ptr.p_double[c->n*(iy+1)+ix];
27814  *f = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
27815  *fx = (-(1-u)*y1+(1-u)*y2+u*y3-u*y4)*dt;
27816  *fy = (-(1-t)*y1-t*y2+t*y3+(1-t)*y4)*du;
27817  *fxy = (y1-y2+y3-y4)*du*dt;
27818  return;
27819  }
27820 
27821  /*
27822  * Bicubic interpolation
27823  */
27824  if( c->stype==-3 )
27825  {
27826 
27827  /*
27828  * Prepare info
27829  */
27830  t0 = 1;
27831  t1 = t;
27832  t2 = ae_sqr(t, _state);
27833  t3 = t*t2;
27834  u0 = 1;
27835  u1 = u;
27836  u2 = ae_sqr(u, _state);
27837  u3 = u*u2;
27838  sfx = c->n*c->m;
27839  sfy = 2*c->n*c->m;
27840  sfxy = 3*c->n*c->m;
27841  s1 = c->n*iy+ix;
27842  s2 = c->n*iy+(ix+1);
27843  s3 = c->n*(iy+1)+(ix+1);
27844  s4 = c->n*(iy+1)+ix;
27845 
27846  /*
27847  * Calculate
27848  */
27849  v = c->f.ptr.p_double[s1];
27850  *f = *f+v*t0*u0;
27851  v = c->f.ptr.p_double[sfy+s1]/du;
27852  *f = *f+v*t0*u1;
27853  *fy = *fy+v*t0*u0*du;
27854  v = -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;
27855  *f = *f+v*t0*u2;
27856  *fy = *fy+2*v*t0*u1*du;
27857  v = 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;
27858  *f = *f+v*t0*u3;
27859  *fy = *fy+3*v*t0*u2*du;
27860  v = c->f.ptr.p_double[sfx+s1]/dt;
27861  *f = *f+v*t1*u0;
27862  *fx = *fx+v*t0*u0*dt;
27863  v = c->f.ptr.p_double[sfxy+s1]/(dt*du);
27864  *f = *f+v*t1*u1;
27865  *fx = *fx+v*t0*u1*dt;
27866  *fy = *fy+v*t1*u0*du;
27867  *fxy = *fxy+v*t0*u0*dt*du;
27868  v = -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);
27869  *f = *f+v*t1*u2;
27870  *fx = *fx+v*t0*u2*dt;
27871  *fy = *fy+2*v*t1*u1*du;
27872  *fxy = *fxy+2*v*t0*u1*dt*du;
27873  v = 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);
27874  *f = *f+v*t1*u3;
27875  *fx = *fx+v*t0*u3*dt;
27876  *fy = *fy+3*v*t1*u2*du;
27877  *fxy = *fxy+3*v*t0*u2*dt*du;
27878  v = -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;
27879  *f = *f+v*t2*u0;
27880  *fx = *fx+2*v*t1*u0*dt;
27881  v = -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);
27882  *f = *f+v*t2*u1;
27883  *fx = *fx+2*v*t1*u1*dt;
27884  *fy = *fy+v*t2*u0*du;
27885  *fxy = *fxy+2*v*t1*u0*dt*du;
27886  v = 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);
27887  *f = *f+v*t2*u2;
27888  *fx = *fx+2*v*t1*u2*dt;
27889  *fy = *fy+2*v*t2*u1*du;
27890  *fxy = *fxy+4*v*t1*u1*dt*du;
27891  v = -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);
27892  *f = *f+v*t2*u3;
27893  *fx = *fx+2*v*t1*u3*dt;
27894  *fy = *fy+3*v*t2*u2*du;
27895  *fxy = *fxy+6*v*t1*u2*dt*du;
27896  v = 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;
27897  *f = *f+v*t3*u0;
27898  *fx = *fx+3*v*t2*u0*dt;
27899  v = 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);
27900  *f = *f+v*t3*u1;
27901  *fx = *fx+3*v*t2*u1*dt;
27902  *fy = *fy+v*t3*u0*du;
27903  *fxy = *fxy+3*v*t2*u0*dt*du;
27904  v = -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);
27905  *f = *f+v*t3*u2;
27906  *fx = *fx+3*v*t2*u2*dt;
27907  *fy = *fy+2*v*t3*u1*du;
27908  *fxy = *fxy+6*v*t2*u1*dt*du;
27909  v = 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);
27910  *f = *f+v*t3*u3;
27911  *fx = *fx+3*v*t2*u3*dt;
27912  *fy = *fy+3*v*t3*u2*du;
27913  *fxy = *fxy+9*v*t2*u2*dt*du;
27914  return;
27915  }
27916 }
27917 
27918 
27919 /*************************************************************************
27920 This subroutine performs linear transformation of the spline argument.
27921 
27922 Input parameters:
27923  C - spline interpolant
27924  AX, BX - transformation coefficients: x = A*t + B
27925  AY, BY - transformation coefficients: y = A*u + B
27926 Result:
27927  C - transformed spline
27928 
27929  -- ALGLIB PROJECT --
27930  Copyright 30.06.2007 by Bochkanov Sergey
27931 *************************************************************************/
27932 void spline2dlintransxy(spline2dinterpolant* c,
27933  double ax,
27934  double bx,
27935  double ay,
27936  double by,
27937  ae_state *_state)
27938 {
27939  ae_frame _frame_block;
27940  ae_vector x;
27941  ae_vector y;
27942  ae_vector f;
27943  ae_vector v;
27944  ae_int_t i;
27945  ae_int_t j;
27946  ae_int_t k;
27947 
27948  ae_frame_make(_state, &_frame_block);
27949  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
27950  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
27951  ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
27952  ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
27953 
27954  ae_assert(c->stype==-3||c->stype==-1, "Spline2DLinTransXY: incorrect C (incorrect parameter C.SType)", _state);
27955  ae_assert(ae_isfinite(ax, _state), "Spline2DLinTransXY: AX is infinite or NaN", _state);
27956  ae_assert(ae_isfinite(bx, _state), "Spline2DLinTransXY: BX is infinite or NaN", _state);
27957  ae_assert(ae_isfinite(ay, _state), "Spline2DLinTransXY: AY is infinite or NaN", _state);
27958  ae_assert(ae_isfinite(by, _state), "Spline2DLinTransXY: BY is infinite or NaN", _state);
27959  ae_vector_set_length(&x, c->n, _state);
27960  ae_vector_set_length(&y, c->m, _state);
27961  ae_vector_set_length(&f, c->m*c->n*c->d, _state);
27962  for(j=0; j<=c->n-1; j++)
27963  {
27964  x.ptr.p_double[j] = c->x.ptr.p_double[j];
27965  }
27966  for(i=0; i<=c->m-1; i++)
27967  {
27968  y.ptr.p_double[i] = c->y.ptr.p_double[i];
27969  }
27970  for(i=0; i<=c->m-1; i++)
27971  {
27972  for(j=0; j<=c->n-1; j++)
27973  {
27974  for(k=0; k<=c->d-1; k++)
27975  {
27976  f.ptr.p_double[c->d*(i*c->n+j)+k] = c->f.ptr.p_double[c->d*(i*c->n+j)+k];
27977  }
27978  }
27979  }
27980 
27981  /*
27982  * Handle different combinations of AX/AY
27983  */
27984  if( ae_fp_eq(ax,0)&&ae_fp_neq(ay,0) )
27985  {
27986  for(i=0; i<=c->m-1; i++)
27987  {
27988  spline2dcalcvbuf(c, bx, y.ptr.p_double[i], &v, _state);
27989  y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay;
27990  for(j=0; j<=c->n-1; j++)
27991  {
27992  for(k=0; k<=c->d-1; k++)
27993  {
27994  f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k];
27995  }
27996  }
27997  }
27998  }
27999  if( ae_fp_neq(ax,0)&&ae_fp_eq(ay,0) )
28000  {
28001  for(j=0; j<=c->n-1; j++)
28002  {
28003  spline2dcalcvbuf(c, x.ptr.p_double[j], by, &v, _state);
28004  x.ptr.p_double[j] = (x.ptr.p_double[j]-bx)/ax;
28005  for(i=0; i<=c->m-1; i++)
28006  {
28007  for(k=0; k<=c->d-1; k++)
28008  {
28009  f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k];
28010  }
28011  }
28012  }
28013  }
28014  if( ae_fp_neq(ax,0)&&ae_fp_neq(ay,0) )
28015  {
28016  for(j=0; j<=c->n-1; j++)
28017  {
28018  x.ptr.p_double[j] = (x.ptr.p_double[j]-bx)/ax;
28019  }
28020  for(i=0; i<=c->m-1; i++)
28021  {
28022  y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay;
28023  }
28024  }
28025  if( ae_fp_eq(ax,0)&&ae_fp_eq(ay,0) )
28026  {
28027  spline2dcalcvbuf(c, bx, by, &v, _state);
28028  for(i=0; i<=c->m-1; i++)
28029  {
28030  for(j=0; j<=c->n-1; j++)
28031  {
28032  for(k=0; k<=c->d-1; k++)
28033  {
28034  f.ptr.p_double[c->d*(i*c->n+j)+k] = v.ptr.p_double[k];
28035  }
28036  }
28037  }
28038  }
28039 
28040  /*
28041  * Rebuild spline
28042  */
28043  if( c->stype==-3 )
28044  {
28045  spline2dbuildbicubicv(&x, c->n, &y, c->m, &f, c->d, c, _state);
28046  }
28047  if( c->stype==-1 )
28048  {
28049  spline2dbuildbilinearv(&x, c->n, &y, c->m, &f, c->d, c, _state);
28050  }
28051  ae_frame_leave(_state);
28052 }
28053 
28054 
28055 /*************************************************************************
28056 This subroutine performs linear transformation of the spline.
28057 
28058 Input parameters:
28059  C - spline interpolant.
28060  A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B
28061 
28062 Output parameters:
28063  C - transformed spline
28064 
28065  -- ALGLIB PROJECT --
28066  Copyright 30.06.2007 by Bochkanov Sergey
28067 *************************************************************************/
28068 void spline2dlintransf(spline2dinterpolant* c,
28069  double a,
28070  double b,
28071  ae_state *_state)
28072 {
28073  ae_frame _frame_block;
28074  ae_vector x;
28075  ae_vector y;
28076  ae_vector f;
28077  ae_int_t i;
28078  ae_int_t j;
28079 
28080  ae_frame_make(_state, &_frame_block);
28081  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
28082  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
28083  ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
28084 
28085  ae_assert(c->stype==-3||c->stype==-1, "Spline2DLinTransF: incorrect C (incorrect parameter C.SType)", _state);
28086  ae_vector_set_length(&x, c->n, _state);
28087  ae_vector_set_length(&y, c->m, _state);
28088  ae_vector_set_length(&f, c->m*c->n*c->d, _state);
28089  for(j=0; j<=c->n-1; j++)
28090  {
28091  x.ptr.p_double[j] = c->x.ptr.p_double[j];
28092  }
28093  for(i=0; i<=c->m-1; i++)
28094  {
28095  y.ptr.p_double[i] = c->y.ptr.p_double[i];
28096  }
28097  for(i=0; i<=c->m*c->n*c->d-1; i++)
28098  {
28099  f.ptr.p_double[i] = a*c->f.ptr.p_double[i]+b;
28100  }
28101  if( c->stype==-3 )
28102  {
28103  spline2dbuildbicubicv(&x, c->n, &y, c->m, &f, c->d, c, _state);
28104  }
28105  if( c->stype==-1 )
28106  {
28107  spline2dbuildbilinearv(&x, c->n, &y, c->m, &f, c->d, c, _state);
28108  }
28109  ae_frame_leave(_state);
28110 }
28111 
28112 
28113 /*************************************************************************
28114 This subroutine makes the copy of the spline model.
28115 
28116 Input parameters:
28117  C - spline interpolant
28118 
28119 Output parameters:
28120  CC - spline copy
28121 
28122  -- ALGLIB PROJECT --
28123  Copyright 29.06.2007 by Bochkanov Sergey
28124 *************************************************************************/
28125 void spline2dcopy(spline2dinterpolant* c,
28126  spline2dinterpolant* cc,
28127  ae_state *_state)
28128 {
28129  ae_int_t tblsize;
28130 
28131  _spline2dinterpolant_clear(cc);
28132 
28133  ae_assert(c->k==1||c->k==3, "Spline2DCopy: incorrect C (incorrect parameter C.K)", _state);
28134  cc->k = c->k;
28135  cc->n = c->n;
28136  cc->m = c->m;
28137  cc->d = c->d;
28138  cc->stype = c->stype;
28139  tblsize = -1;
28140  if( c->stype==-3 )
28141  {
28142  tblsize = 4*c->n*c->m*c->d;
28143  }
28144  if( c->stype==-1 )
28145  {
28146  tblsize = c->n*c->m*c->d;
28147  }
28148  ae_assert(tblsize>0, "Spline2DCopy: internal error", _state);
28149  ae_vector_set_length(&cc->x, cc->n, _state);
28150  ae_vector_set_length(&cc->y, cc->m, _state);
28151  ae_vector_set_length(&cc->f, tblsize, _state);
28152  ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1));
28153  ae_v_move(&cc->y.ptr.p_double[0], 1, &c->y.ptr.p_double[0], 1, ae_v_len(0,cc->m-1));
28154  ae_v_move(&cc->f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,tblsize-1));
28155 }
28156 
28157 
28158 /*************************************************************************
28159 Bicubic spline resampling
28160 
28161 Input parameters:
28162  A - function values at the old grid,
28163  array[0..OldHeight-1, 0..OldWidth-1]
28164  OldHeight - old grid height, OldHeight>1
28165  OldWidth - old grid width, OldWidth>1
28166  NewHeight - new grid height, NewHeight>1
28167  NewWidth - new grid width, NewWidth>1
28168 
28169 Output parameters:
28170  B - function values at the new grid,
28171  array[0..NewHeight-1, 0..NewWidth-1]
28172 
28173  -- ALGLIB routine --
28174  15 May, 2007
28175  Copyright by Bochkanov Sergey
28176 *************************************************************************/
28177 void spline2dresamplebicubic(/* Real */ ae_matrix* a,
28178  ae_int_t oldheight,
28179  ae_int_t oldwidth,
28180  /* Real */ ae_matrix* b,
28181  ae_int_t newheight,
28182  ae_int_t newwidth,
28183  ae_state *_state)
28184 {
28185  ae_frame _frame_block;
28186  ae_matrix buf;
28187  ae_vector x;
28188  ae_vector y;
28189  spline1dinterpolant c;
28190  ae_int_t mw;
28191  ae_int_t mh;
28192  ae_int_t i;
28193  ae_int_t j;
28194 
28195  ae_frame_make(_state, &_frame_block);
28196  ae_matrix_clear(b);
28197  ae_matrix_init(&buf, 0, 0, DT_REAL, _state, ae_true);
28198  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
28199  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
28200  _spline1dinterpolant_init(&c, _state, ae_true);
28201 
28202  ae_assert(oldwidth>1&&oldheight>1, "Spline2DResampleBicubic: width/height less than 1", _state);
28203  ae_assert(newwidth>1&&newheight>1, "Spline2DResampleBicubic: width/height less than 1", _state);
28204 
28205  /*
28206  * Prepare
28207  */
28208  mw = ae_maxint(oldwidth, newwidth, _state);
28209  mh = ae_maxint(oldheight, newheight, _state);
28210  ae_matrix_set_length(b, newheight, newwidth, _state);
28211  ae_matrix_set_length(&buf, oldheight, newwidth, _state);
28212  ae_vector_set_length(&x, ae_maxint(mw, mh, _state), _state);
28213  ae_vector_set_length(&y, ae_maxint(mw, mh, _state), _state);
28214 
28215  /*
28216  * Horizontal interpolation
28217  */
28218  for(i=0; i<=oldheight-1; i++)
28219  {
28220 
28221  /*
28222  * Fill X, Y
28223  */
28224  for(j=0; j<=oldwidth-1; j++)
28225  {
28226  x.ptr.p_double[j] = (double)j/(double)(oldwidth-1);
28227  y.ptr.p_double[j] = a->ptr.pp_double[i][j];
28228  }
28229 
28230  /*
28231  * Interpolate and place result into temporary matrix
28232  */
28233  spline1dbuildcubic(&x, &y, oldwidth, 0, 0.0, 0, 0.0, &c, _state);
28234  for(j=0; j<=newwidth-1; j++)
28235  {
28236  buf.ptr.pp_double[i][j] = spline1dcalc(&c, (double)j/(double)(newwidth-1), _state);
28237  }
28238  }
28239 
28240  /*
28241  * Vertical interpolation
28242  */
28243  for(j=0; j<=newwidth-1; j++)
28244  {
28245 
28246  /*
28247  * Fill X, Y
28248  */
28249  for(i=0; i<=oldheight-1; i++)
28250  {
28251  x.ptr.p_double[i] = (double)i/(double)(oldheight-1);
28252  y.ptr.p_double[i] = buf.ptr.pp_double[i][j];
28253  }
28254 
28255  /*
28256  * Interpolate and place result into B
28257  */
28258  spline1dbuildcubic(&x, &y, oldheight, 0, 0.0, 0, 0.0, &c, _state);
28259  for(i=0; i<=newheight-1; i++)
28260  {
28261  b->ptr.pp_double[i][j] = spline1dcalc(&c, (double)i/(double)(newheight-1), _state);
28262  }
28263  }
28264  ae_frame_leave(_state);
28265 }
28266 
28267 
28268 /*************************************************************************
28269 Bilinear spline resampling
28270 
28271 Input parameters:
28272  A - function values at the old grid,
28273  array[0..OldHeight-1, 0..OldWidth-1]
28274  OldHeight - old grid height, OldHeight>1
28275  OldWidth - old grid width, OldWidth>1
28276  NewHeight - new grid height, NewHeight>1
28277  NewWidth - new grid width, NewWidth>1
28278 
28279 Output parameters:
28280  B - function values at the new grid,
28281  array[0..NewHeight-1, 0..NewWidth-1]
28282 
28283  -- ALGLIB routine --
28284  09.07.2007
28285  Copyright by Bochkanov Sergey
28286 *************************************************************************/
28287 void spline2dresamplebilinear(/* Real */ ae_matrix* a,
28288  ae_int_t oldheight,
28289  ae_int_t oldwidth,
28290  /* Real */ ae_matrix* b,
28291  ae_int_t newheight,
28292  ae_int_t newwidth,
28293  ae_state *_state)
28294 {
28295  ae_int_t l;
28296  ae_int_t c;
28297  double t;
28298  double u;
28299  ae_int_t i;
28300  ae_int_t j;
28301 
28302  ae_matrix_clear(b);
28303 
28304  ae_assert(oldwidth>1&&oldheight>1, "Spline2DResampleBilinear: width/height less than 1", _state);
28305  ae_assert(newwidth>1&&newheight>1, "Spline2DResampleBilinear: width/height less than 1", _state);
28306  ae_matrix_set_length(b, newheight, newwidth, _state);
28307  for(i=0; i<=newheight-1; i++)
28308  {
28309  for(j=0; j<=newwidth-1; j++)
28310  {
28311  l = i*(oldheight-1)/(newheight-1);
28312  if( l==oldheight-1 )
28313  {
28314  l = oldheight-2;
28315  }
28316  u = (double)i/(double)(newheight-1)*(oldheight-1)-l;
28317  c = j*(oldwidth-1)/(newwidth-1);
28318  if( c==oldwidth-1 )
28319  {
28320  c = oldwidth-2;
28321  }
28322  t = (double)(j*(oldwidth-1))/(double)(newwidth-1)-c;
28323  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];
28324  }
28325  }
28326 }
28327 
28328 
28329 /*************************************************************************
28330 This subroutine builds bilinear vector-valued spline.
28331 
28332 Input parameters:
28333  X - spline abscissas, array[0..N-1]
28334  Y - spline ordinates, array[0..M-1]
28335  F - function values, array[0..M*N*D-1]:
28336  * first D elements store D values at (X[0],Y[0])
28337  * next D elements store D values at (X[1],Y[0])
28338  * general form - D function values at (X[i],Y[j]) are stored
28339  at F[D*(J*N+I)...D*(J*N+I)+D-1].
28340  M,N - grid size, M>=2, N>=2
28341  D - vector dimension, D>=1
28342 
28343 Output parameters:
28344  C - spline interpolant
28345 
28346  -- ALGLIB PROJECT --
28347  Copyright 16.04.2012 by Bochkanov Sergey
28348 *************************************************************************/
28349 void spline2dbuildbilinearv(/* Real */ ae_vector* x,
28350  ae_int_t n,
28351  /* Real */ ae_vector* y,
28352  ae_int_t m,
28353  /* Real */ ae_vector* f,
28354  ae_int_t d,
28355  spline2dinterpolant* c,
28356  ae_state *_state)
28357 {
28358  double t;
28359  ae_int_t i;
28360  ae_int_t j;
28361  ae_int_t k;
28362  ae_int_t i0;
28363 
28364  _spline2dinterpolant_clear(c);
28365 
28366  ae_assert(n>=2, "Spline2DBuildBilinearV: N is less then 2", _state);
28367  ae_assert(m>=2, "Spline2DBuildBilinearV: M is less then 2", _state);
28368  ae_assert(d>=1, "Spline2DBuildBilinearV: invalid argument D (D<1)", _state);
28369  ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBilinearV: length of X or Y is too short (Length(X/Y)<N/M)", _state);
28370  ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBilinearV: X or Y contains NaN or Infinite value", _state);
28371  k = n*m*d;
28372  ae_assert(f->cnt>=k, "Spline2DBuildBilinearV: length of F is too short (Length(F)<N*M*D)", _state);
28373  ae_assert(isfinitevector(f, k, _state), "Spline2DBuildBilinearV: F contains NaN or Infinite value", _state);
28374 
28375  /*
28376  * Fill interpolant
28377  */
28378  c->k = 1;
28379  c->n = n;
28380  c->m = m;
28381  c->d = d;
28382  c->stype = -1;
28383  ae_vector_set_length(&c->x, c->n, _state);
28384  ae_vector_set_length(&c->y, c->m, _state);
28385  ae_vector_set_length(&c->f, k, _state);
28386  for(i=0; i<=c->n-1; i++)
28387  {
28388  c->x.ptr.p_double[i] = x->ptr.p_double[i];
28389  }
28390  for(i=0; i<=c->m-1; i++)
28391  {
28392  c->y.ptr.p_double[i] = y->ptr.p_double[i];
28393  }
28394  for(i=0; i<=k-1; i++)
28395  {
28396  c->f.ptr.p_double[i] = f->ptr.p_double[i];
28397  }
28398 
28399  /*
28400  * Sort points
28401  */
28402  for(j=0; j<=c->n-1; j++)
28403  {
28404  k = j;
28405  for(i=j+1; i<=c->n-1; i++)
28406  {
28407  if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
28408  {
28409  k = i;
28410  }
28411  }
28412  if( k!=j )
28413  {
28414  for(i=0; i<=c->m-1; i++)
28415  {
28416  for(i0=0; i0<=c->d-1; i0++)
28417  {
28418  t = c->f.ptr.p_double[c->d*(i*c->n+j)+i0];
28419  c->f.ptr.p_double[c->d*(i*c->n+j)+i0] = c->f.ptr.p_double[c->d*(i*c->n+k)+i0];
28420  c->f.ptr.p_double[c->d*(i*c->n+k)+i0] = t;
28421  }
28422  }
28423  t = c->x.ptr.p_double[j];
28424  c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
28425  c->x.ptr.p_double[k] = t;
28426  }
28427  }
28428  for(i=0; i<=c->m-1; i++)
28429  {
28430  k = i;
28431  for(j=i+1; j<=c->m-1; j++)
28432  {
28433  if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
28434  {
28435  k = j;
28436  }
28437  }
28438  if( k!=i )
28439  {
28440  for(j=0; j<=c->n-1; j++)
28441  {
28442  for(i0=0; i0<=c->d-1; i0++)
28443  {
28444  t = c->f.ptr.p_double[c->d*(i*c->n+j)+i0];
28445  c->f.ptr.p_double[c->d*(i*c->n+j)+i0] = c->f.ptr.p_double[c->d*(k*c->n+j)+i0];
28446  c->f.ptr.p_double[c->d*(k*c->n+j)+i0] = t;
28447  }
28448  }
28449  t = c->y.ptr.p_double[i];
28450  c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
28451  c->y.ptr.p_double[k] = t;
28452  }
28453  }
28454 }
28455 
28456 
28457 /*************************************************************************
28458 This subroutine builds bicubic vector-valued spline.
28459 
28460 Input parameters:
28461  X - spline abscissas, array[0..N-1]
28462  Y - spline ordinates, array[0..M-1]
28463  F - function values, array[0..M*N*D-1]:
28464  * first D elements store D values at (X[0],Y[0])
28465  * next D elements store D values at (X[1],Y[0])
28466  * general form - D function values at (X[i],Y[j]) are stored
28467  at F[D*(J*N+I)...D*(J*N+I)+D-1].
28468  M,N - grid size, M>=2, N>=2
28469  D - vector dimension, D>=1
28470 
28471 Output parameters:
28472  C - spline interpolant
28473 
28474  -- ALGLIB PROJECT --
28475  Copyright 16.04.2012 by Bochkanov Sergey
28476 *************************************************************************/
28477 void spline2dbuildbicubicv(/* Real */ ae_vector* x,
28478  ae_int_t n,
28479  /* Real */ ae_vector* y,
28480  ae_int_t m,
28481  /* Real */ ae_vector* f,
28482  ae_int_t d,
28483  spline2dinterpolant* c,
28484  ae_state *_state)
28485 {
28486  ae_frame _frame_block;
28487  ae_vector _f;
28488  ae_matrix tf;
28489  ae_matrix dx;
28490  ae_matrix dy;
28491  ae_matrix dxy;
28492  double t;
28493  ae_int_t i;
28494  ae_int_t j;
28495  ae_int_t k;
28496  ae_int_t di;
28497 
28498  ae_frame_make(_state, &_frame_block);
28499  ae_vector_init_copy(&_f, f, _state, ae_true);
28500  f = &_f;
28501  _spline2dinterpolant_clear(c);
28502  ae_matrix_init(&tf, 0, 0, DT_REAL, _state, ae_true);
28503  ae_matrix_init(&dx, 0, 0, DT_REAL, _state, ae_true);
28504  ae_matrix_init(&dy, 0, 0, DT_REAL, _state, ae_true);
28505  ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true);
28506 
28507  ae_assert(n>=2, "Spline2DBuildBicubicV: N is less than 2", _state);
28508  ae_assert(m>=2, "Spline2DBuildBicubicV: M is less than 2", _state);
28509  ae_assert(d>=1, "Spline2DBuildBicubicV: invalid argument D (D<1)", _state);
28510  ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBicubicV: length of X or Y is too short (Length(X/Y)<N/M)", _state);
28511  ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBicubicV: X or Y contains NaN or Infinite value", _state);
28512  k = n*m*d;
28513  ae_assert(f->cnt>=k, "Spline2DBuildBicubicV: length of F is too short (Length(F)<N*M*D)", _state);
28514  ae_assert(isfinitevector(f, k, _state), "Spline2DBuildBicubicV: F contains NaN or Infinite value", _state);
28515 
28516  /*
28517  * Fill interpolant:
28518  * F[0]...F[N*M*D-1]:
28519  * f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on...
28520  * F[N*M*D]...F[2*N*M*D-1]:
28521  * df(i,j)/dx table.
28522  * F[2*N*M*D]...F[3*N*M*D-1]:
28523  * df(i,j)/dy table.
28524  * F[3*N*M*D]...F[4*N*M*D-1]:
28525  * d2f(i,j)/dxdy table.
28526  */
28527  c->k = 3;
28528  c->d = d;
28529  c->n = n;
28530  c->m = m;
28531  c->stype = -3;
28532  k = 4*k;
28533  ae_vector_set_length(&c->x, c->n, _state);
28534  ae_vector_set_length(&c->y, c->m, _state);
28535  ae_vector_set_length(&c->f, k, _state);
28536  ae_matrix_set_length(&tf, c->m, c->n, _state);
28537  for(i=0; i<=c->n-1; i++)
28538  {
28539  c->x.ptr.p_double[i] = x->ptr.p_double[i];
28540  }
28541  for(i=0; i<=c->m-1; i++)
28542  {
28543  c->y.ptr.p_double[i] = y->ptr.p_double[i];
28544  }
28545 
28546  /*
28547  * Sort points
28548  */
28549  for(j=0; j<=c->n-1; j++)
28550  {
28551  k = j;
28552  for(i=j+1; i<=c->n-1; i++)
28553  {
28554  if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
28555  {
28556  k = i;
28557  }
28558  }
28559  if( k!=j )
28560  {
28561  for(i=0; i<=c->m-1; i++)
28562  {
28563  for(di=0; di<=c->d-1; di++)
28564  {
28565  t = f->ptr.p_double[c->d*(i*c->n+j)+di];
28566  f->ptr.p_double[c->d*(i*c->n+j)+di] = f->ptr.p_double[c->d*(i*c->n+k)+di];
28567  f->ptr.p_double[c->d*(i*c->n+k)+di] = t;
28568  }
28569  }
28570  t = c->x.ptr.p_double[j];
28571  c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
28572  c->x.ptr.p_double[k] = t;
28573  }
28574  }
28575  for(i=0; i<=c->m-1; i++)
28576  {
28577  k = i;
28578  for(j=i+1; j<=c->m-1; j++)
28579  {
28580  if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
28581  {
28582  k = j;
28583  }
28584  }
28585  if( k!=i )
28586  {
28587  for(j=0; j<=c->n-1; j++)
28588  {
28589  for(di=0; di<=c->d-1; di++)
28590  {
28591  t = f->ptr.p_double[c->d*(i*c->n+j)+di];
28592  f->ptr.p_double[c->d*(i*c->n+j)+di] = f->ptr.p_double[c->d*(k*c->n+j)+di];
28593  f->ptr.p_double[c->d*(k*c->n+j)+di] = t;
28594  }
28595  }
28596  t = c->y.ptr.p_double[i];
28597  c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
28598  c->y.ptr.p_double[k] = t;
28599  }
28600  }
28601  for(di=0; di<=c->d-1; di++)
28602  {
28603  for(i=0; i<=c->m-1; i++)
28604  {
28605  for(j=0; j<=c->n-1; j++)
28606  {
28607  tf.ptr.pp_double[i][j] = f->ptr.p_double[c->d*(i*c->n+j)+di];
28608  }
28609  }
28610  spline2d_bicubiccalcderivatives(&tf, &c->x, &c->y, c->m, c->n, &dx, &dy, &dxy, _state);
28611  for(i=0; i<=c->m-1; i++)
28612  {
28613  for(j=0; j<=c->n-1; j++)
28614  {
28615  k = c->d*(i*c->n+j)+di;
28616  c->f.ptr.p_double[k] = tf.ptr.pp_double[i][j];
28617  c->f.ptr.p_double[c->n*c->m*c->d+k] = dx.ptr.pp_double[i][j];
28618  c->f.ptr.p_double[2*c->n*c->m*c->d+k] = dy.ptr.pp_double[i][j];
28619  c->f.ptr.p_double[3*c->n*c->m*c->d+k] = dxy.ptr.pp_double[i][j];
28620  }
28621  }
28622  }
28623  ae_frame_leave(_state);
28624 }
28625 
28626 
28627 /*************************************************************************
28628 This subroutine calculates bilinear or bicubic vector-valued spline at the
28629 given point (X,Y).
28630 
28631 INPUT PARAMETERS:
28632  C - spline interpolant.
28633  X, Y- point
28634  F - output buffer, possibly preallocated array. In case array size
28635  is large enough to store result, it is not reallocated. Array
28636  which is too short will be reallocated
28637 
28638 OUTPUT PARAMETERS:
28639  F - array[D] (or larger) which stores function values
28640 
28641  -- ALGLIB PROJECT --
28642  Copyright 16.04.2012 by Bochkanov Sergey
28643 *************************************************************************/
28644 void spline2dcalcvbuf(spline2dinterpolant* c,
28645  double x,
28646  double y,
28647  /* Real */ ae_vector* f,
28648  ae_state *_state)
28649 {
28650  double t;
28651  double dt;
28652  double u;
28653  double du;
28654  ae_int_t ix;
28655  ae_int_t iy;
28656  ae_int_t l;
28657  ae_int_t r;
28658  ae_int_t h;
28659  ae_int_t s1;
28660  ae_int_t s2;
28661  ae_int_t s3;
28662  ae_int_t s4;
28663  ae_int_t sfx;
28664  ae_int_t sfy;
28665  ae_int_t sfxy;
28666  double y1;
28667  double y2;
28668  double y3;
28669  double y4;
28670  double v;
28671  double t0;
28672  double t1;
28673  double t2;
28674  double t3;
28675  double u0;
28676  double u1;
28677  double u2;
28678  double u3;
28679  ae_int_t i;
28680 
28681 
28682  ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcVBuf: incorrect C (incorrect parameter C.SType)", _state);
28683  ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcVBuf: either X=NaN/Infinite or Y=NaN/Infinite", _state);
28684  rvectorsetlengthatleast(f, c->d, _state);
28685 
28686  /*
28687  * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
28688  */
28689  l = 0;
28690  r = c->n-1;
28691  while(l!=r-1)
28692  {
28693  h = (l+r)/2;
28694  if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
28695  {
28696  r = h;
28697  }
28698  else
28699  {
28700  l = h;
28701  }
28702  }
28703  t = (x-c->x.ptr.p_double[l])/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
28704  dt = 1.0/(c->x.ptr.p_double[l+1]-c->x.ptr.p_double[l]);
28705  ix = l;
28706 
28707  /*
28708  * Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included)
28709  */
28710  l = 0;
28711  r = c->m-1;
28712  while(l!=r-1)
28713  {
28714  h = (l+r)/2;
28715  if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
28716  {
28717  r = h;
28718  }
28719  else
28720  {
28721  l = h;
28722  }
28723  }
28724  u = (y-c->y.ptr.p_double[l])/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
28725  du = 1.0/(c->y.ptr.p_double[l+1]-c->y.ptr.p_double[l]);
28726  iy = l;
28727 
28728  /*
28729  * Bilinear interpolation
28730  */
28731  if( c->stype==-1 )
28732  {
28733  for(i=0; i<=c->d-1; i++)
28734  {
28735  y1 = c->f.ptr.p_double[c->d*(c->n*iy+ix)+i];
28736  y2 = c->f.ptr.p_double[c->d*(c->n*iy+(ix+1))+i];
28737  y3 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+(ix+1))+i];
28738  y4 = c->f.ptr.p_double[c->d*(c->n*(iy+1)+ix)+i];
28739  f->ptr.p_double[i] = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
28740  }
28741  return;
28742  }
28743 
28744  /*
28745  * Bicubic interpolation
28746  */
28747  if( c->stype==-3 )
28748  {
28749 
28750  /*
28751  * Prepare info
28752  */
28753  t0 = 1;
28754  t1 = t;
28755  t2 = ae_sqr(t, _state);
28756  t3 = t*t2;
28757  u0 = 1;
28758  u1 = u;
28759  u2 = ae_sqr(u, _state);
28760  u3 = u*u2;
28761  sfx = c->n*c->m*c->d;
28762  sfy = 2*c->n*c->m*c->d;
28763  sfxy = 3*c->n*c->m*c->d;
28764  for(i=0; i<=c->d-1; i++)
28765  {
28766 
28767  /*
28768  * Prepare F, dF/dX, dF/dY, d2F/dXdY
28769  */
28770  f->ptr.p_double[i] = 0;
28771  s1 = c->d*(c->n*iy+ix)+i;
28772  s2 = c->d*(c->n*iy+(ix+1))+i;
28773  s3 = c->d*(c->n*(iy+1)+(ix+1))+i;
28774  s4 = c->d*(c->n*(iy+1)+ix)+i;
28775 
28776  /*
28777  * Calculate
28778  */
28779  v = c->f.ptr.p_double[s1];
28780  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t0*u0;
28781  v = c->f.ptr.p_double[sfy+s1]/du;
28782  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t0*u1;
28783  v = -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;
28784  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t0*u2;
28785  v = 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;
28786  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t0*u3;
28787  v = c->f.ptr.p_double[sfx+s1]/dt;
28788  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t1*u0;
28789  v = c->f.ptr.p_double[sfxy+s1]/(dt*du);
28790  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t1*u1;
28791  v = -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);
28792  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t1*u2;
28793  v = 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);
28794  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t1*u3;
28795  v = -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;
28796  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t2*u0;
28797  v = -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);
28798  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t2*u1;
28799  v = 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);
28800  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t2*u2;
28801  v = -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);
28802  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t2*u3;
28803  v = 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;
28804  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t3*u0;
28805  v = 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);
28806  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t3*u1;
28807  v = -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);
28808  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t3*u2;
28809  v = 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);
28810  f->ptr.p_double[i] = f->ptr.p_double[i]+v*t3*u3;
28811  }
28812  return;
28813  }
28814 }
28815 
28816 
28817 /*************************************************************************
28818 This subroutine calculates bilinear or bicubic vector-valued spline at the
28819 given point (X,Y).
28820 
28821 INPUT PARAMETERS:
28822  C - spline interpolant.
28823  X, Y- point
28824 
28825 OUTPUT PARAMETERS:
28826  F - array[D] which stores function values. F is out-parameter and
28827  it is reallocated after call to this function. In case you
28828  want to reuse previously allocated F, you may use
28829  Spline2DCalcVBuf(), which reallocates F only when it is too
28830  small.
28831 
28832  -- ALGLIB PROJECT --
28833  Copyright 16.04.2012 by Bochkanov Sergey
28834 *************************************************************************/
28835 void spline2dcalcv(spline2dinterpolant* c,
28836  double x,
28837  double y,
28838  /* Real */ ae_vector* f,
28839  ae_state *_state)
28840 {
28841 
28842  ae_vector_clear(f);
28843 
28844  ae_assert(c->stype==-1||c->stype==-3, "Spline2DCalcV: incorrect C (incorrect parameter C.SType)", _state);
28845  ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline2DCalcV: either X=NaN/Infinite or Y=NaN/Infinite", _state);
28846  ae_vector_set_length(f, c->d, _state);
28847  spline2dcalcvbuf(c, x, y, f, _state);
28848 }
28849 
28850 
28851 /*************************************************************************
28852 This subroutine unpacks two-dimensional spline into the coefficients table
28853 
28854 Input parameters:
28855  C - spline interpolant.
28856 
28857 Result:
28858  M, N- grid size (x-axis and y-axis)
28859  D - number of components
28860  Tbl - coefficients table, unpacked format,
28861  D - components: [0..(N-1)*(M-1)*D-1, 0..19].
28862  For T=0..D-1 (component index), I = 0...N-2 (x index),
28863  J=0..M-2 (y index):
28864  K := T + I*D + J*D*(N-1)
28865 
28866  K-th row stores decomposition for T-th component of the
28867  vector-valued function
28868 
28869  Tbl[K,0] = X[i]
28870  Tbl[K,1] = X[i+1]
28871  Tbl[K,2] = Y[j]
28872  Tbl[K,3] = Y[j+1]
28873  Tbl[K,4] = C00
28874  Tbl[K,5] = C01
28875  Tbl[K,6] = C02
28876  Tbl[K,7] = C03
28877  Tbl[K,8] = C10
28878  Tbl[K,9] = C11
28879  ...
28880  Tbl[K,19] = C33
28881  On each grid square spline is equals to:
28882  S(x) = SUM(c[i,j]*(t^i)*(u^j), i=0..3, j=0..3)
28883  t = x-x[j]
28884  u = y-y[i]
28885 
28886  -- ALGLIB PROJECT --
28887  Copyright 16.04.2012 by Bochkanov Sergey
28888 *************************************************************************/
28889 void spline2dunpackv(spline2dinterpolant* c,
28890  ae_int_t* m,
28891  ae_int_t* n,
28892  ae_int_t* d,
28893  /* Real */ ae_matrix* tbl,
28894  ae_state *_state)
28895 {
28896  ae_int_t k;
28897  ae_int_t p;
28898  ae_int_t ci;
28899  ae_int_t cj;
28900  ae_int_t s1;
28901  ae_int_t s2;
28902  ae_int_t s3;
28903  ae_int_t s4;
28904  ae_int_t sfx;
28905  ae_int_t sfy;
28906  ae_int_t sfxy;
28907  double y1;
28908  double y2;
28909  double y3;
28910  double y4;
28911  double dt;
28912  double du;
28913  ae_int_t i;
28914  ae_int_t j;
28915  ae_int_t k0;
28916 
28917  *m = 0;
28918  *n = 0;
28919  *d = 0;
28920  ae_matrix_clear(tbl);
28921 
28922  ae_assert(c->stype==-3||c->stype==-1, "Spline2DUnpackV: incorrect C (incorrect parameter C.SType)", _state);
28923  *n = c->n;
28924  *m = c->m;
28925  *d = c->d;
28926  ae_matrix_set_length(tbl, (*n-1)*(*m-1)*(*d), 20, _state);
28927  sfx = *n*(*m)*(*d);
28928  sfy = 2*(*n)*(*m)*(*d);
28929  sfxy = 3*(*n)*(*m)*(*d);
28930  for(i=0; i<=*m-2; i++)
28931  {
28932  for(j=0; j<=*n-2; j++)
28933  {
28934  for(k=0; k<=*d-1; k++)
28935  {
28936  p = *d*(i*(*n-1)+j)+k;
28937  tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[j];
28938  tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[j+1];
28939  tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[i];
28940  tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[i+1];
28941  dt = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]);
28942  du = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]);
28943 
28944  /*
28945  * Bilinear interpolation
28946  */
28947  if( c->stype==-1 )
28948  {
28949  for(k0=4; k0<=19; k0++)
28950  {
28951  tbl->ptr.pp_double[p][k0] = 0;
28952  }
28953  y1 = c->f.ptr.p_double[*d*(*n*i+j)+k];
28954  y2 = c->f.ptr.p_double[*d*(*n*i+(j+1))+k];
28955  y3 = c->f.ptr.p_double[*d*(*n*(i+1)+(j+1))+k];
28956  y4 = c->f.ptr.p_double[*d*(*n*(i+1)+j)+k];
28957  tbl->ptr.pp_double[p][4] = y1;
28958  tbl->ptr.pp_double[p][4+1*4+0] = y2-y1;
28959  tbl->ptr.pp_double[p][4+0*4+1] = y4-y1;
28960  tbl->ptr.pp_double[p][4+1*4+1] = y3-y2-y4+y1;
28961  }
28962 
28963  /*
28964  * Bicubic interpolation
28965  */
28966  if( c->stype==-3 )
28967  {
28968  s1 = *d*(*n*i+j)+k;
28969  s2 = *d*(*n*i+(j+1))+k;
28970  s3 = *d*(*n*(i+1)+(j+1))+k;
28971  s4 = *d*(*n*(i+1)+j)+k;
28972  tbl->ptr.pp_double[p][4+0*4+0] = c->f.ptr.p_double[s1];
28973  tbl->ptr.pp_double[p][4+0*4+1] = c->f.ptr.p_double[sfy+s1]/du;
28974  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;
28975  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;
28976  tbl->ptr.pp_double[p][4+1*4+0] = c->f.ptr.p_double[sfx+s1]/dt;
28977  tbl->ptr.pp_double[p][4+1*4+1] = c->f.ptr.p_double[sfxy+s1]/(dt*du);
28978  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);
28979  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);
28980  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;
28981  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);
28982  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);
28983  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);
28984  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;
28985  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);
28986  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);
28987  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);
28988  }
28989 
28990  /*
28991  * Rescale Cij
28992  */
28993  for(ci=0; ci<=3; ci++)
28994  {
28995  for(cj=0; cj<=3; cj++)
28996  {
28997  tbl->ptr.pp_double[p][4+ci*4+cj] = tbl->ptr.pp_double[p][4+ci*4+cj]*ae_pow(dt, ci, _state)*ae_pow(du, cj, _state);
28998  }
28999  }
29000  }
29001  }
29002  }
29003 }
29004 
29005 
29006 /*************************************************************************
29007 This subroutine was deprecated in ALGLIB 3.6.0
29008 
29009 We recommend you to switch to Spline2DBuildBilinearV(), which is more
29010 flexible and accepts its arguments in more convenient order.
29011 
29012  -- ALGLIB PROJECT --
29013  Copyright 05.07.2007 by Bochkanov Sergey
29014 *************************************************************************/
29015 void spline2dbuildbilinear(/* Real */ ae_vector* x,
29016  /* Real */ ae_vector* y,
29017  /* Real */ ae_matrix* f,
29018  ae_int_t m,
29019  ae_int_t n,
29020  spline2dinterpolant* c,
29021  ae_state *_state)
29022 {
29023  double t;
29024  ae_int_t i;
29025  ae_int_t j;
29026  ae_int_t k;
29027 
29028  _spline2dinterpolant_clear(c);
29029 
29030  ae_assert(n>=2, "Spline2DBuildBilinear: N<2", _state);
29031  ae_assert(m>=2, "Spline2DBuildBilinear: M<2", _state);
29032  ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBilinear: length of X or Y is too short (Length(X/Y)<N/M)", _state);
29033  ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBilinear: X or Y contains NaN or Infinite value", _state);
29034  ae_assert(f->rows>=m&&f->cols>=n, "Spline2DBuildBilinear: size of F is too small (rows(F)<M or cols(F)<N)", _state);
29035  ae_assert(apservisfinitematrix(f, m, n, _state), "Spline2DBuildBilinear: F contains NaN or Infinite value", _state);
29036 
29037  /*
29038  * Fill interpolant
29039  */
29040  c->k = 1;
29041  c->n = n;
29042  c->m = m;
29043  c->d = 1;
29044  c->stype = -1;
29045  ae_vector_set_length(&c->x, c->n, _state);
29046  ae_vector_set_length(&c->y, c->m, _state);
29047  ae_vector_set_length(&c->f, c->n*c->m, _state);
29048  for(i=0; i<=c->n-1; i++)
29049  {
29050  c->x.ptr.p_double[i] = x->ptr.p_double[i];
29051  }
29052  for(i=0; i<=c->m-1; i++)
29053  {
29054  c->y.ptr.p_double[i] = y->ptr.p_double[i];
29055  }
29056  for(i=0; i<=c->m-1; i++)
29057  {
29058  for(j=0; j<=c->n-1; j++)
29059  {
29060  c->f.ptr.p_double[i*c->n+j] = f->ptr.pp_double[i][j];
29061  }
29062  }
29063 
29064  /*
29065  * Sort points
29066  */
29067  for(j=0; j<=c->n-1; j++)
29068  {
29069  k = j;
29070  for(i=j+1; i<=c->n-1; i++)
29071  {
29072  if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
29073  {
29074  k = i;
29075  }
29076  }
29077  if( k!=j )
29078  {
29079  for(i=0; i<=c->m-1; i++)
29080  {
29081  t = c->f.ptr.p_double[i*c->n+j];
29082  c->f.ptr.p_double[i*c->n+j] = c->f.ptr.p_double[i*c->n+k];
29083  c->f.ptr.p_double[i*c->n+k] = t;
29084  }
29085  t = c->x.ptr.p_double[j];
29086  c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
29087  c->x.ptr.p_double[k] = t;
29088  }
29089  }
29090  for(i=0; i<=c->m-1; i++)
29091  {
29092  k = i;
29093  for(j=i+1; j<=c->m-1; j++)
29094  {
29095  if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
29096  {
29097  k = j;
29098  }
29099  }
29100  if( k!=i )
29101  {
29102  for(j=0; j<=c->n-1; j++)
29103  {
29104  t = c->f.ptr.p_double[i*c->n+j];
29105  c->f.ptr.p_double[i*c->n+j] = c->f.ptr.p_double[k*c->n+j];
29106  c->f.ptr.p_double[k*c->n+j] = t;
29107  }
29108  t = c->y.ptr.p_double[i];
29109  c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
29110  c->y.ptr.p_double[k] = t;
29111  }
29112  }
29113 }
29114 
29115 
29116 /*************************************************************************
29117 This subroutine was deprecated in ALGLIB 3.6.0
29118 
29119 We recommend you to switch to Spline2DBuildBicubicV(), which is more
29120 flexible and accepts its arguments in more convenient order.
29121 
29122  -- ALGLIB PROJECT --
29123  Copyright 05.07.2007 by Bochkanov Sergey
29124 *************************************************************************/
29125 void spline2dbuildbicubic(/* Real */ ae_vector* x,
29126  /* Real */ ae_vector* y,
29127  /* Real */ ae_matrix* f,
29128  ae_int_t m,
29129  ae_int_t n,
29130  spline2dinterpolant* c,
29131  ae_state *_state)
29132 {
29133  ae_frame _frame_block;
29134  ae_matrix _f;
29135  ae_int_t sfx;
29136  ae_int_t sfy;
29137  ae_int_t sfxy;
29138  ae_matrix dx;
29139  ae_matrix dy;
29140  ae_matrix dxy;
29141  double t;
29142  ae_int_t i;
29143  ae_int_t j;
29144  ae_int_t k;
29145 
29146  ae_frame_make(_state, &_frame_block);
29147  ae_matrix_init_copy(&_f, f, _state, ae_true);
29148  f = &_f;
29149  _spline2dinterpolant_clear(c);
29150  ae_matrix_init(&dx, 0, 0, DT_REAL, _state, ae_true);
29151  ae_matrix_init(&dy, 0, 0, DT_REAL, _state, ae_true);
29152  ae_matrix_init(&dxy, 0, 0, DT_REAL, _state, ae_true);
29153 
29154  ae_assert(n>=2, "Spline2DBuildBicubicSpline: N<2", _state);
29155  ae_assert(m>=2, "Spline2DBuildBicubicSpline: M<2", _state);
29156  ae_assert(x->cnt>=n&&y->cnt>=m, "Spline2DBuildBicubic: length of X or Y is too short (Length(X/Y)<N/M)", _state);
29157  ae_assert(isfinitevector(x, n, _state)&&isfinitevector(y, m, _state), "Spline2DBuildBicubic: X or Y contains NaN or Infinite value", _state);
29158  ae_assert(f->rows>=m&&f->cols>=n, "Spline2DBuildBicubic: size of F is too small (rows(F)<M or cols(F)<N)", _state);
29159  ae_assert(apservisfinitematrix(f, m, n, _state), "Spline2DBuildBicubic: F contains NaN or Infinite value", _state);
29160 
29161  /*
29162  * Fill interpolant:
29163  * F[0]...F[N*M-1]:
29164  * f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on...
29165  * F[N*M]...F[2*N*M-1]:
29166  * df(i,j)/dx table.
29167  * F[2*N*M]...F[3*N*M-1]:
29168  * df(i,j)/dy table.
29169  * F[3*N*M]...F[4*N*M-1]:
29170  * d2f(i,j)/dxdy table.
29171  */
29172  c->k = 3;
29173  c->d = 1;
29174  c->n = n;
29175  c->m = m;
29176  c->stype = -3;
29177  sfx = c->n*c->m;
29178  sfy = 2*c->n*c->m;
29179  sfxy = 3*c->n*c->m;
29180  ae_vector_set_length(&c->x, c->n, _state);
29181  ae_vector_set_length(&c->y, c->m, _state);
29182  ae_vector_set_length(&c->f, 4*c->n*c->m, _state);
29183  for(i=0; i<=c->n-1; i++)
29184  {
29185  c->x.ptr.p_double[i] = x->ptr.p_double[i];
29186  }
29187  for(i=0; i<=c->m-1; i++)
29188  {
29189  c->y.ptr.p_double[i] = y->ptr.p_double[i];
29190  }
29191 
29192  /*
29193  * Sort points
29194  */
29195  for(j=0; j<=c->n-1; j++)
29196  {
29197  k = j;
29198  for(i=j+1; i<=c->n-1; i++)
29199  {
29200  if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
29201  {
29202  k = i;
29203  }
29204  }
29205  if( k!=j )
29206  {
29207  for(i=0; i<=c->m-1; i++)
29208  {
29209  t = f->ptr.pp_double[i][j];
29210  f->ptr.pp_double[i][j] = f->ptr.pp_double[i][k];
29211  f->ptr.pp_double[i][k] = t;
29212  }
29213  t = c->x.ptr.p_double[j];
29214  c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
29215  c->x.ptr.p_double[k] = t;
29216  }
29217  }
29218  for(i=0; i<=c->m-1; i++)
29219  {
29220  k = i;
29221  for(j=i+1; j<=c->m-1; j++)
29222  {
29223  if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
29224  {
29225  k = j;
29226  }
29227  }
29228  if( k!=i )
29229  {
29230  for(j=0; j<=c->n-1; j++)
29231  {
29232  t = f->ptr.pp_double[i][j];
29233  f->ptr.pp_double[i][j] = f->ptr.pp_double[k][j];
29234  f->ptr.pp_double[k][j] = t;
29235  }
29236  t = c->y.ptr.p_double[i];
29237  c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
29238  c->y.ptr.p_double[k] = t;
29239  }
29240  }
29241  spline2d_bicubiccalcderivatives(f, &c->x, &c->y, c->m, c->n, &dx, &dy, &dxy, _state);
29242  for(i=0; i<=c->m-1; i++)
29243  {
29244  for(j=0; j<=c->n-1; j++)
29245  {
29246  k = i*c->n+j;
29247  c->f.ptr.p_double[k] = f->ptr.pp_double[i][j];
29248  c->f.ptr.p_double[sfx+k] = dx.ptr.pp_double[i][j];
29249  c->f.ptr.p_double[sfy+k] = dy.ptr.pp_double[i][j];
29250  c->f.ptr.p_double[sfxy+k] = dxy.ptr.pp_double[i][j];
29251  }
29252  }
29253  ae_frame_leave(_state);
29254 }
29255 
29256 
29257 /*************************************************************************
29258 This subroutine was deprecated in ALGLIB 3.6.0
29259 
29260 We recommend you to switch to Spline2DUnpackV(), which is more flexible
29261 and accepts its arguments in more convenient order.
29262 
29263  -- ALGLIB PROJECT --
29264  Copyright 29.06.2007 by Bochkanov Sergey
29265 *************************************************************************/
29266 void spline2dunpack(spline2dinterpolant* c,
29267  ae_int_t* m,
29268  ae_int_t* n,
29269  /* Real */ ae_matrix* tbl,
29270  ae_state *_state)
29271 {
29272  ae_int_t k;
29273  ae_int_t p;
29274  ae_int_t ci;
29275  ae_int_t cj;
29276  ae_int_t s1;
29277  ae_int_t s2;
29278  ae_int_t s3;
29279  ae_int_t s4;
29280  ae_int_t sfx;
29281  ae_int_t sfy;
29282  ae_int_t sfxy;
29283  double y1;
29284  double y2;
29285  double y3;
29286  double y4;
29287  double dt;
29288  double du;
29289  ae_int_t i;
29290  ae_int_t j;
29291 
29292  *m = 0;
29293  *n = 0;
29294  ae_matrix_clear(tbl);
29295 
29296  ae_assert(c->stype==-3||c->stype==-1, "Spline2DUnpack: incorrect C (incorrect parameter C.SType)", _state);
29297  if( c->d!=1 )
29298  {
29299  *n = 0;
29300  *m = 0;
29301  return;
29302  }
29303  *n = c->n;
29304  *m = c->m;
29305  ae_matrix_set_length(tbl, (*n-1)*(*m-1), 20, _state);
29306  sfx = *n*(*m);
29307  sfy = 2*(*n)*(*m);
29308  sfxy = 3*(*n)*(*m);
29309 
29310  /*
29311  * Fill
29312  */
29313  for(i=0; i<=*m-2; i++)
29314  {
29315  for(j=0; j<=*n-2; j++)
29316  {
29317  p = i*(*n-1)+j;
29318  tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[j];
29319  tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[j+1];
29320  tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[i];
29321  tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[i+1];
29322  dt = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]);
29323  du = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]);
29324 
29325  /*
29326  * Bilinear interpolation
29327  */
29328  if( c->stype==-1 )
29329  {
29330  for(k=4; k<=19; k++)
29331  {
29332  tbl->ptr.pp_double[p][k] = 0;
29333  }
29334  y1 = c->f.ptr.p_double[*n*i+j];
29335  y2 = c->f.ptr.p_double[*n*i+(j+1)];
29336  y3 = c->f.ptr.p_double[*n*(i+1)+(j+1)];
29337  y4 = c->f.ptr.p_double[*n*(i+1)+j];
29338  tbl->ptr.pp_double[p][4] = y1;
29339  tbl->ptr.pp_double[p][4+1*4+0] = y2-y1;
29340  tbl->ptr.pp_double[p][4+0*4+1] = y4-y1;
29341  tbl->ptr.pp_double[p][4+1*4+1] = y3-y2-y4+y1;
29342  }
29343 
29344  /*
29345  * Bicubic interpolation
29346  */
29347  if( c->stype==-3 )
29348  {
29349  s1 = *n*i+j;
29350  s2 = *n*i+(j+1);
29351  s3 = *n*(i+1)+(j+1);
29352  s4 = *n*(i+1)+j;
29353  tbl->ptr.pp_double[p][4+0*4+0] = c->f.ptr.p_double[s1];
29354  tbl->ptr.pp_double[p][4+0*4+1] = c->f.ptr.p_double[sfy+s1]/du;
29355  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;
29356  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;
29357  tbl->ptr.pp_double[p][4+1*4+0] = c->f.ptr.p_double[sfx+s1]/dt;
29358  tbl->ptr.pp_double[p][4+1*4+1] = c->f.ptr.p_double[sfxy+s1]/(dt*du);
29359  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);
29360  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);
29361  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;
29362  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);
29363  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);
29364  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);
29365  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;
29366  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);
29367  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);
29368  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);
29369  }
29370 
29371  /*
29372  * Rescale Cij
29373  */
29374  for(ci=0; ci<=3; ci++)
29375  {
29376  for(cj=0; cj<=3; cj++)
29377  {
29378  tbl->ptr.pp_double[p][4+ci*4+cj] = tbl->ptr.pp_double[p][4+ci*4+cj]*ae_pow(dt, ci, _state)*ae_pow(du, cj, _state);
29379  }
29380  }
29381  }
29382  }
29383 }
29384 
29385 
29386 /*************************************************************************
29387 Internal subroutine.
29388 Calculation of the first derivatives and the cross-derivative.
29389 *************************************************************************/
29390 static void spline2d_bicubiccalcderivatives(/* Real */ ae_matrix* a,
29391  /* Real */ ae_vector* x,
29392  /* Real */ ae_vector* y,
29393  ae_int_t m,
29394  ae_int_t n,
29395  /* Real */ ae_matrix* dx,
29396  /* Real */ ae_matrix* dy,
29397  /* Real */ ae_matrix* dxy,
29398  ae_state *_state)
29399 {
29400  ae_frame _frame_block;
29401  ae_int_t i;
29402  ae_int_t j;
29403  ae_vector xt;
29404  ae_vector ft;
29405  double s;
29406  double ds;
29407  double d2s;
29408  spline1dinterpolant c;
29409 
29410  ae_frame_make(_state, &_frame_block);
29411  ae_matrix_clear(dx);
29412  ae_matrix_clear(dy);
29413  ae_matrix_clear(dxy);
29414  ae_vector_init(&xt, 0, DT_REAL, _state, ae_true);
29415  ae_vector_init(&ft, 0, DT_REAL, _state, ae_true);
29416  _spline1dinterpolant_init(&c, _state, ae_true);
29417 
29418  ae_matrix_set_length(dx, m, n, _state);
29419  ae_matrix_set_length(dy, m, n, _state);
29420  ae_matrix_set_length(dxy, m, n, _state);
29421 
29422  /*
29423  * dF/dX
29424  */
29425  ae_vector_set_length(&xt, n, _state);
29426  ae_vector_set_length(&ft, n, _state);
29427  for(i=0; i<=m-1; i++)
29428  {
29429  for(j=0; j<=n-1; j++)
29430  {
29431  xt.ptr.p_double[j] = x->ptr.p_double[j];
29432  ft.ptr.p_double[j] = a->ptr.pp_double[i][j];
29433  }
29434  spline1dbuildcubic(&xt, &ft, n, 0, 0.0, 0, 0.0, &c, _state);
29435  for(j=0; j<=n-1; j++)
29436  {
29437  spline1ddiff(&c, x->ptr.p_double[j], &s, &ds, &d2s, _state);
29438  dx->ptr.pp_double[i][j] = ds;
29439  }
29440  }
29441 
29442  /*
29443  * dF/dY
29444  */
29445  ae_vector_set_length(&xt, m, _state);
29446  ae_vector_set_length(&ft, m, _state);
29447  for(j=0; j<=n-1; j++)
29448  {
29449  for(i=0; i<=m-1; i++)
29450  {
29451  xt.ptr.p_double[i] = y->ptr.p_double[i];
29452  ft.ptr.p_double[i] = a->ptr.pp_double[i][j];
29453  }
29454  spline1dbuildcubic(&xt, &ft, m, 0, 0.0, 0, 0.0, &c, _state);
29455  for(i=0; i<=m-1; i++)
29456  {
29457  spline1ddiff(&c, y->ptr.p_double[i], &s, &ds, &d2s, _state);
29458  dy->ptr.pp_double[i][j] = ds;
29459  }
29460  }
29461 
29462  /*
29463  * d2F/dXdY
29464  */
29465  ae_vector_set_length(&xt, n, _state);
29466  ae_vector_set_length(&ft, n, _state);
29467  for(i=0; i<=m-1; i++)
29468  {
29469  for(j=0; j<=n-1; j++)
29470  {
29471  xt.ptr.p_double[j] = x->ptr.p_double[j];
29472  ft.ptr.p_double[j] = dy->ptr.pp_double[i][j];
29473  }
29474  spline1dbuildcubic(&xt, &ft, n, 0, 0.0, 0, 0.0, &c, _state);
29475  for(j=0; j<=n-1; j++)
29476  {
29477  spline1ddiff(&c, x->ptr.p_double[j], &s, &ds, &d2s, _state);
29478  dxy->ptr.pp_double[i][j] = ds;
29479  }
29480  }
29481  ae_frame_leave(_state);
29482 }
29483 
29484 
29485 ae_bool _spline2dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
29486 {
29487  spline2dinterpolant *p = (spline2dinterpolant*)_p;
29488  ae_touch_ptr((void*)p);
29489  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
29490  return ae_false;
29491  if( !ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic) )
29492  return ae_false;
29493  if( !ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic) )
29494  return ae_false;
29495  return ae_true;
29496 }
29497 
29498 
29499 ae_bool _spline2dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29500 {
29501  spline2dinterpolant *dst = (spline2dinterpolant*)_dst;
29502  spline2dinterpolant *src = (spline2dinterpolant*)_src;
29503  dst->k = src->k;
29504  dst->stype = src->stype;
29505  dst->n = src->n;
29506  dst->m = src->m;
29507  dst->d = src->d;
29508  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
29509  return ae_false;
29510  if( !ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic) )
29511  return ae_false;
29512  if( !ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic) )
29513  return ae_false;
29514  return ae_true;
29515 }
29516 
29517 
29518 void _spline2dinterpolant_clear(void* _p)
29519 {
29520  spline2dinterpolant *p = (spline2dinterpolant*)_p;
29521  ae_touch_ptr((void*)p);
29522  ae_vector_clear(&p->x);
29523  ae_vector_clear(&p->y);
29524  ae_vector_clear(&p->f);
29525 }
29526 
29527 
29528 void _spline2dinterpolant_destroy(void* _p)
29529 {
29530  spline2dinterpolant *p = (spline2dinterpolant*)_p;
29531  ae_touch_ptr((void*)p);
29532  ae_vector_destroy(&p->x);
29533  ae_vector_destroy(&p->y);
29534  ae_vector_destroy(&p->f);
29535 }
29536 
29537 
29538 
29539 
29540 /*************************************************************************
29541 This subroutine calculates the value of the trilinear or tricubic spline at
29542 the given point (X,Y,Z).
29543 
29544 INPUT PARAMETERS:
29545  C - coefficients table.
29546  Built by BuildBilinearSpline or BuildBicubicSpline.
29547  X, Y,
29548  Z - point
29549 
29550 Result:
29551  S(x,y,z)
29552 
29553  -- ALGLIB PROJECT --
29554  Copyright 26.04.2012 by Bochkanov Sergey
29555 *************************************************************************/
29556 double spline3dcalc(spline3dinterpolant* c,
29557  double x,
29558  double y,
29559  double z,
29560  ae_state *_state)
29561 {
29562  double v;
29563  double vx;
29564  double vy;
29565  double vxy;
29566  double result;
29567 
29568 
29569  ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalc: incorrect C (incorrect parameter C.SType)", _state);
29570  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);
29571  if( c->d!=1 )
29572  {
29573  result = 0;
29574  return result;
29575  }
29576  spline3d_spline3ddiff(c, x, y, z, &v, &vx, &vy, &vxy, _state);
29577  result = v;
29578  return result;
29579 }
29580 
29581 
29582 /*************************************************************************
29583 This subroutine performs linear transformation of the spline argument.
29584 
29585 INPUT PARAMETERS:
29586  C - spline interpolant
29587  AX, BX - transformation coefficients: x = A*u + B
29588  AY, BY - transformation coefficients: y = A*v + B
29589  AZ, BZ - transformation coefficients: z = A*w + B
29590 
29591 OUTPUT PARAMETERS:
29592  C - transformed spline
29593 
29594  -- ALGLIB PROJECT --
29595  Copyright 26.04.2012 by Bochkanov Sergey
29596 *************************************************************************/
29597 void spline3dlintransxyz(spline3dinterpolant* c,
29598  double ax,
29599  double bx,
29600  double ay,
29601  double by,
29602  double az,
29603  double bz,
29604  ae_state *_state)
29605 {
29606  ae_frame _frame_block;
29607  ae_vector x;
29608  ae_vector y;
29609  ae_vector z;
29610  ae_vector f;
29611  ae_vector v;
29612  ae_int_t i;
29613  ae_int_t j;
29614  ae_int_t k;
29615  ae_int_t di;
29616 
29617  ae_frame_make(_state, &_frame_block);
29618  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
29619  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
29620  ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
29621  ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
29622  ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
29623 
29624  ae_assert(c->stype==-3||c->stype==-1, "Spline3DLinTransXYZ: incorrect C (incorrect parameter C.SType)", _state);
29625  ae_vector_set_length(&x, c->n, _state);
29626  ae_vector_set_length(&y, c->m, _state);
29627  ae_vector_set_length(&z, c->l, _state);
29628  ae_vector_set_length(&f, c->m*c->n*c->l*c->d, _state);
29629  for(j=0; j<=c->n-1; j++)
29630  {
29631  x.ptr.p_double[j] = c->x.ptr.p_double[j];
29632  }
29633  for(i=0; i<=c->m-1; i++)
29634  {
29635  y.ptr.p_double[i] = c->y.ptr.p_double[i];
29636  }
29637  for(i=0; i<=c->l-1; i++)
29638  {
29639  z.ptr.p_double[i] = c->z.ptr.p_double[i];
29640  }
29641 
29642  /*
29643  * Handle different combinations of zero/nonzero AX/AY/AZ
29644  */
29645  if( (ae_fp_neq(ax,0)&&ae_fp_neq(ay,0))&&ae_fp_neq(az,0) )
29646  {
29647  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));
29648  }
29649  if( (ae_fp_eq(ax,0)&&ae_fp_neq(ay,0))&&ae_fp_neq(az,0) )
29650  {
29651  for(i=0; i<=c->m-1; i++)
29652  {
29653  for(j=0; j<=c->l-1; j++)
29654  {
29655  spline3dcalcv(c, bx, y.ptr.p_double[i], z.ptr.p_double[j], &v, _state);
29656  for(k=0; k<=c->n-1; k++)
29657  {
29658  for(di=0; di<=c->d-1; di++)
29659  {
29660  f.ptr.p_double[c->d*(c->n*(c->m*j+i)+k)+di] = v.ptr.p_double[di];
29661  }
29662  }
29663  }
29664  }
29665  ax = 1;
29666  bx = 0;
29667  }
29668  if( (ae_fp_neq(ax,0)&&ae_fp_eq(ay,0))&&ae_fp_neq(az,0) )
29669  {
29670  for(i=0; i<=c->n-1; i++)
29671  {
29672  for(j=0; j<=c->l-1; j++)
29673  {
29674  spline3dcalcv(c, x.ptr.p_double[i], by, z.ptr.p_double[j], &v, _state);
29675  for(k=0; k<=c->m-1; k++)
29676  {
29677  for(di=0; di<=c->d-1; di++)
29678  {
29679  f.ptr.p_double[c->d*(c->n*(c->m*j+k)+i)+di] = v.ptr.p_double[di];
29680  }
29681  }
29682  }
29683  }
29684  ay = 1;
29685  by = 0;
29686  }
29687  if( (ae_fp_neq(ax,0)&&ae_fp_neq(ay,0))&&ae_fp_eq(az,0) )
29688  {
29689  for(i=0; i<=c->n-1; i++)
29690  {
29691  for(j=0; j<=c->m-1; j++)
29692  {
29693  spline3dcalcv(c, x.ptr.p_double[i], y.ptr.p_double[j], bz, &v, _state);
29694  for(k=0; k<=c->l-1; k++)
29695  {
29696  for(di=0; di<=c->d-1; di++)
29697  {
29698  f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di];
29699  }
29700  }
29701  }
29702  }
29703  az = 1;
29704  bz = 0;
29705  }
29706  if( (ae_fp_eq(ax,0)&&ae_fp_eq(ay,0))&&ae_fp_neq(az,0) )
29707  {
29708  for(i=0; i<=c->l-1; i++)
29709  {
29710  spline3dcalcv(c, bx, by, z.ptr.p_double[i], &v, _state);
29711  for(k=0; k<=c->m-1; k++)
29712  {
29713  for(j=0; j<=c->n-1; j++)
29714  {
29715  for(di=0; di<=c->d-1; di++)
29716  {
29717  f.ptr.p_double[c->d*(c->n*(c->m*i+k)+j)+di] = v.ptr.p_double[di];
29718  }
29719  }
29720  }
29721  }
29722  ax = 1;
29723  bx = 0;
29724  ay = 1;
29725  by = 0;
29726  }
29727  if( (ae_fp_eq(ax,0)&&ae_fp_neq(ay,0))&&ae_fp_eq(az,0) )
29728  {
29729  for(i=0; i<=c->m-1; i++)
29730  {
29731  spline3dcalcv(c, bx, y.ptr.p_double[i], bz, &v, _state);
29732  for(k=0; k<=c->l-1; k++)
29733  {
29734  for(j=0; j<=c->n-1; j++)
29735  {
29736  for(di=0; di<=c->d-1; di++)
29737  {
29738  f.ptr.p_double[c->d*(c->n*(c->m*k+i)+j)+di] = v.ptr.p_double[di];
29739  }
29740  }
29741  }
29742  }
29743  ax = 1;
29744  bx = 0;
29745  az = 1;
29746  bz = 0;
29747  }
29748  if( (ae_fp_neq(ax,0)&&ae_fp_eq(ay,0))&&ae_fp_eq(az,0) )
29749  {
29750  for(i=0; i<=c->n-1; i++)
29751  {
29752  spline3dcalcv(c, x.ptr.p_double[i], by, bz, &v, _state);
29753  for(k=0; k<=c->l-1; k++)
29754  {
29755  for(j=0; j<=c->m-1; j++)
29756  {
29757  for(di=0; di<=c->d-1; di++)
29758  {
29759  f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di];
29760  }
29761  }
29762  }
29763  }
29764  ay = 1;
29765  by = 0;
29766  az = 1;
29767  bz = 0;
29768  }
29769  if( (ae_fp_eq(ax,0)&&ae_fp_eq(ay,0))&&ae_fp_eq(az,0) )
29770  {
29771  spline3dcalcv(c, bx, by, bz, &v, _state);
29772  for(k=0; k<=c->l-1; k++)
29773  {
29774  for(j=0; j<=c->m-1; j++)
29775  {
29776  for(i=0; i<=c->n-1; i++)
29777  {
29778  for(di=0; di<=c->d-1; di++)
29779  {
29780  f.ptr.p_double[c->d*(c->n*(c->m*k+j)+i)+di] = v.ptr.p_double[di];
29781  }
29782  }
29783  }
29784  }
29785  ax = 1;
29786  bx = 0;
29787  ay = 1;
29788  by = 0;
29789  az = 1;
29790  bz = 0;
29791  }
29792 
29793  /*
29794  * General case: AX<>0, AY<>0, AZ<>0
29795  * Unpack, scale and pack again.
29796  */
29797  for(i=0; i<=c->n-1; i++)
29798  {
29799  x.ptr.p_double[i] = (x.ptr.p_double[i]-bx)/ax;
29800  }
29801  for(i=0; i<=c->m-1; i++)
29802  {
29803  y.ptr.p_double[i] = (y.ptr.p_double[i]-by)/ay;
29804  }
29805  for(i=0; i<=c->l-1; i++)
29806  {
29807  z.ptr.p_double[i] = (z.ptr.p_double[i]-bz)/az;
29808  }
29809  if( c->stype==-1 )
29810  {
29811  spline3dbuildtrilinearv(&x, c->n, &y, c->m, &z, c->l, &f, c->d, c, _state);
29812  }
29813  ae_frame_leave(_state);
29814 }
29815 
29816 
29817 /*************************************************************************
29818 This subroutine performs linear transformation of the spline.
29819 
29820 INPUT PARAMETERS:
29821  C - spline interpolant.
29822  A, B- transformation coefficients: S2(x,y) = A*S(x,y,z) + B
29823 
29824 OUTPUT PARAMETERS:
29825  C - transformed spline
29826 
29827  -- ALGLIB PROJECT --
29828  Copyright 26.04.2012 by Bochkanov Sergey
29829 *************************************************************************/
29830 void spline3dlintransf(spline3dinterpolant* c,
29831  double a,
29832  double b,
29833  ae_state *_state)
29834 {
29835  ae_frame _frame_block;
29836  ae_vector x;
29837  ae_vector y;
29838  ae_vector z;
29839  ae_vector f;
29840  ae_int_t i;
29841  ae_int_t j;
29842 
29843  ae_frame_make(_state, &_frame_block);
29844  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
29845  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
29846  ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
29847  ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
29848 
29849  ae_assert(c->stype==-3||c->stype==-1, "Spline3DLinTransF: incorrect C (incorrect parameter C.SType)", _state);
29850  ae_vector_set_length(&x, c->n, _state);
29851  ae_vector_set_length(&y, c->m, _state);
29852  ae_vector_set_length(&z, c->l, _state);
29853  ae_vector_set_length(&f, c->m*c->n*c->l*c->d, _state);
29854  for(j=0; j<=c->n-1; j++)
29855  {
29856  x.ptr.p_double[j] = c->x.ptr.p_double[j];
29857  }
29858  for(i=0; i<=c->m-1; i++)
29859  {
29860  y.ptr.p_double[i] = c->y.ptr.p_double[i];
29861  }
29862  for(i=0; i<=c->l-1; i++)
29863  {
29864  z.ptr.p_double[i] = c->z.ptr.p_double[i];
29865  }
29866  for(i=0; i<=c->m*c->n*c->l*c->d-1; i++)
29867  {
29868  f.ptr.p_double[i] = a*c->f.ptr.p_double[i]+b;
29869  }
29870  if( c->stype==-1 )
29871  {
29872  spline3dbuildtrilinearv(&x, c->n, &y, c->m, &z, c->l, &f, c->d, c, _state);
29873  }
29874  ae_frame_leave(_state);
29875 }
29876 
29877 
29878 /*************************************************************************
29879 This subroutine makes the copy of the spline model.
29880 
29881 INPUT PARAMETERS:
29882  C - spline interpolant
29883 
29884 OUTPUT PARAMETERS:
29885  CC - spline copy
29886 
29887  -- ALGLIB PROJECT --
29888  Copyright 26.04.2012 by Bochkanov Sergey
29889 *************************************************************************/
29890 void spline3dcopy(spline3dinterpolant* c,
29891  spline3dinterpolant* cc,
29892  ae_state *_state)
29893 {
29894  ae_int_t tblsize;
29895 
29896  _spline3dinterpolant_clear(cc);
29897 
29898  ae_assert(c->k==1||c->k==3, "Spline3DCopy: incorrect C (incorrect parameter C.K)", _state);
29899  cc->k = c->k;
29900  cc->n = c->n;
29901  cc->m = c->m;
29902  cc->l = c->l;
29903  cc->d = c->d;
29904  tblsize = c->n*c->m*c->l*c->d;
29905  cc->stype = c->stype;
29906  ae_vector_set_length(&cc->x, cc->n, _state);
29907  ae_vector_set_length(&cc->y, cc->m, _state);
29908  ae_vector_set_length(&cc->z, cc->l, _state);
29909  ae_vector_set_length(&cc->f, tblsize, _state);
29910  ae_v_move(&cc->x.ptr.p_double[0], 1, &c->x.ptr.p_double[0], 1, ae_v_len(0,cc->n-1));
29911  ae_v_move(&cc->y.ptr.p_double[0], 1, &c->y.ptr.p_double[0], 1, ae_v_len(0,cc->m-1));
29912  ae_v_move(&cc->z.ptr.p_double[0], 1, &c->z.ptr.p_double[0], 1, ae_v_len(0,cc->l-1));
29913  ae_v_move(&cc->f.ptr.p_double[0], 1, &c->f.ptr.p_double[0], 1, ae_v_len(0,tblsize-1));
29914 }
29915 
29916 
29917 /*************************************************************************
29918 Trilinear spline resampling
29919 
29920 INPUT PARAMETERS:
29921  A - array[0..OldXCount*OldYCount*OldZCount-1], function
29922  values at the old grid, :
29923  A[0] x=0,y=0,z=0
29924  A[1] x=1,y=0,z=0
29925  A[..] ...
29926  A[..] x=oldxcount-1,y=0,z=0
29927  A[..] x=0,y=1,z=0
29928  A[..] ...
29929  ...
29930  OldZCount - old Z-count, OldZCount>1
29931  OldYCount - old Y-count, OldYCount>1
29932  OldXCount - old X-count, OldXCount>1
29933  NewZCount - new Z-count, NewZCount>1
29934  NewYCount - new Y-count, NewYCount>1
29935  NewXCount - new X-count, NewXCount>1
29936 
29937 OUTPUT PARAMETERS:
29938  B - array[0..NewXCount*NewYCount*NewZCount-1], function
29939  values at the new grid:
29940  B[0] x=0,y=0,z=0
29941  B[1] x=1,y=0,z=0
29942  B[..] ...
29943  B[..] x=newxcount-1,y=0,z=0
29944  B[..] x=0,y=1,z=0
29945  B[..] ...
29946  ...
29947 
29948  -- ALGLIB routine --
29949  26.04.2012
29950  Copyright by Bochkanov Sergey
29951 *************************************************************************/
29952 void spline3dresampletrilinear(/* Real */ ae_vector* a,
29953  ae_int_t oldzcount,
29954  ae_int_t oldycount,
29955  ae_int_t oldxcount,
29956  ae_int_t newzcount,
29957  ae_int_t newycount,
29958  ae_int_t newxcount,
29959  /* Real */ ae_vector* b,
29960  ae_state *_state)
29961 {
29962  double xd;
29963  double yd;
29964  double zd;
29965  double c0;
29966  double c1;
29967  double c2;
29968  double c3;
29969  ae_int_t ix;
29970  ae_int_t iy;
29971  ae_int_t iz;
29972  ae_int_t i;
29973  ae_int_t j;
29974  ae_int_t k;
29975 
29976  ae_vector_clear(b);
29977 
29978  ae_assert((oldycount>1&&oldzcount>1)&&oldxcount>1, "Spline3DResampleTrilinear: length/width/height less than 1", _state);
29979  ae_assert((newycount>1&&newzcount>1)&&newxcount>1, "Spline3DResampleTrilinear: length/width/height less than 1", _state);
29980  ae_assert(a->cnt>=oldycount*oldzcount*oldxcount, "Spline3DResampleTrilinear: length/width/height less than 1", _state);
29981  ae_vector_set_length(b, newxcount*newycount*newzcount, _state);
29982  for(i=0; i<=newxcount-1; i++)
29983  {
29984  for(j=0; j<=newycount-1; j++)
29985  {
29986  for(k=0; k<=newzcount-1; k++)
29987  {
29988  ix = i*(oldxcount-1)/(newxcount-1);
29989  if( ix==oldxcount-1 )
29990  {
29991  ix = oldxcount-2;
29992  }
29993  xd = (double)(i*(oldxcount-1))/(double)(newxcount-1)-ix;
29994  iy = j*(oldycount-1)/(newycount-1);
29995  if( iy==oldycount-1 )
29996  {
29997  iy = oldycount-2;
29998  }
29999  yd = (double)(j*(oldycount-1))/(double)(newycount-1)-iy;
30000  iz = k*(oldzcount-1)/(newzcount-1);
30001  if( iz==oldzcount-1 )
30002  {
30003  iz = oldzcount-2;
30004  }
30005  zd = (double)(k*(oldzcount-1))/(double)(newzcount-1)-iz;
30006  c0 = a->ptr.p_double[oldxcount*(oldycount*iz+iy)+ix]*(1-xd)+a->ptr.p_double[oldxcount*(oldycount*iz+iy)+(ix+1)]*xd;
30007  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;
30008  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;
30009  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;
30010  c0 = c0*(1-yd)+c1*yd;
30011  c1 = c2*(1-yd)+c3*yd;
30012  b->ptr.p_double[newxcount*(newycount*k+j)+i] = c0*(1-zd)+c1*zd;
30013  }
30014  }
30015  }
30016 }
30017 
30018 
30019 /*************************************************************************
30020 This subroutine builds trilinear vector-valued spline.
30021 
30022 INPUT PARAMETERS:
30023  X - spline abscissas, array[0..N-1]
30024  Y - spline ordinates, array[0..M-1]
30025  Z - spline applicates, array[0..L-1]
30026  F - function values, array[0..M*N*L*D-1]:
30027  * first D elements store D values at (X[0],Y[0],Z[0])
30028  * next D elements store D values at (X[1],Y[0],Z[0])
30029  * next D elements store D values at (X[2],Y[0],Z[0])
30030  * ...
30031  * next D elements store D values at (X[0],Y[1],Z[0])
30032  * next D elements store D values at (X[1],Y[1],Z[0])
30033  * next D elements store D values at (X[2],Y[1],Z[0])
30034  * ...
30035  * next D elements store D values at (X[0],Y[0],Z[1])
30036  * next D elements store D values at (X[1],Y[0],Z[1])
30037  * next D elements store D values at (X[2],Y[0],Z[1])
30038  * ...
30039  * general form - D function values at (X[i],Y[j]) are stored
30040  at F[D*(N*(M*K+J)+I)...D*(N*(M*K+J)+I)+D-1].
30041  M,N,
30042  L - grid size, M>=2, N>=2, L>=2
30043  D - vector dimension, D>=1
30044 
30045 OUTPUT PARAMETERS:
30046  C - spline interpolant
30047 
30048  -- ALGLIB PROJECT --
30049  Copyright 26.04.2012 by Bochkanov Sergey
30050 *************************************************************************/
30051 void spline3dbuildtrilinearv(/* Real */ ae_vector* x,
30052  ae_int_t n,
30053  /* Real */ ae_vector* y,
30054  ae_int_t m,
30055  /* Real */ ae_vector* z,
30056  ae_int_t l,
30057  /* Real */ ae_vector* f,
30058  ae_int_t d,
30059  spline3dinterpolant* c,
30060  ae_state *_state)
30061 {
30062  double t;
30063  ae_int_t tblsize;
30064  ae_int_t i;
30065  ae_int_t j;
30066  ae_int_t k;
30067  ae_int_t i0;
30068  ae_int_t j0;
30069 
30070  _spline3dinterpolant_clear(c);
30071 
30072  ae_assert(m>=2, "Spline3DBuildTrilinearV: M<2", _state);
30073  ae_assert(n>=2, "Spline3DBuildTrilinearV: N<2", _state);
30074  ae_assert(l>=2, "Spline3DBuildTrilinearV: L<2", _state);
30075  ae_assert(d>=1, "Spline3DBuildTrilinearV: D<1", _state);
30076  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);
30077  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);
30078  tblsize = n*m*l*d;
30079  ae_assert(f->cnt>=tblsize, "Spline3DBuildTrilinearV: length of F is too short (Length(F)<N*M*L*D)", _state);
30080  ae_assert(isfinitevector(f, tblsize, _state), "Spline3DBuildTrilinearV: F contains NaN or Infinite value", _state);
30081 
30082  /*
30083  * Fill interpolant
30084  */
30085  c->k = 1;
30086  c->n = n;
30087  c->m = m;
30088  c->l = l;
30089  c->d = d;
30090  c->stype = -1;
30091  ae_vector_set_length(&c->x, c->n, _state);
30092  ae_vector_set_length(&c->y, c->m, _state);
30093  ae_vector_set_length(&c->z, c->l, _state);
30094  ae_vector_set_length(&c->f, tblsize, _state);
30095  for(i=0; i<=c->n-1; i++)
30096  {
30097  c->x.ptr.p_double[i] = x->ptr.p_double[i];
30098  }
30099  for(i=0; i<=c->m-1; i++)
30100  {
30101  c->y.ptr.p_double[i] = y->ptr.p_double[i];
30102  }
30103  for(i=0; i<=c->l-1; i++)
30104  {
30105  c->z.ptr.p_double[i] = z->ptr.p_double[i];
30106  }
30107  for(i=0; i<=tblsize-1; i++)
30108  {
30109  c->f.ptr.p_double[i] = f->ptr.p_double[i];
30110  }
30111 
30112  /*
30113  * Sort points:
30114  * * sort x;
30115  * * sort y;
30116  * * sort z.
30117  */
30118  for(j=0; j<=c->n-1; j++)
30119  {
30120  k = j;
30121  for(i=j+1; i<=c->n-1; i++)
30122  {
30123  if( ae_fp_less(c->x.ptr.p_double[i],c->x.ptr.p_double[k]) )
30124  {
30125  k = i;
30126  }
30127  }
30128  if( k!=j )
30129  {
30130  for(i=0; i<=c->m-1; i++)
30131  {
30132  for(j0=0; j0<=c->l-1; j0++)
30133  {
30134  for(i0=0; i0<=c->d-1; i0++)
30135  {
30136  t = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0];
30137  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];
30138  c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+k)+i0] = t;
30139  }
30140  }
30141  }
30142  t = c->x.ptr.p_double[j];
30143  c->x.ptr.p_double[j] = c->x.ptr.p_double[k];
30144  c->x.ptr.p_double[k] = t;
30145  }
30146  }
30147  for(i=0; i<=c->m-1; i++)
30148  {
30149  k = i;
30150  for(j=i+1; j<=c->m-1; j++)
30151  {
30152  if( ae_fp_less(c->y.ptr.p_double[j],c->y.ptr.p_double[k]) )
30153  {
30154  k = j;
30155  }
30156  }
30157  if( k!=i )
30158  {
30159  for(j=0; j<=c->n-1; j++)
30160  {
30161  for(j0=0; j0<=c->l-1; j0++)
30162  {
30163  for(i0=0; i0<=c->d-1; i0++)
30164  {
30165  t = c->f.ptr.p_double[c->d*(c->n*(c->m*j0+i)+j)+i0];
30166  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];
30167  c->f.ptr.p_double[c->d*(c->n*(c->m*j0+k)+j)+i0] = t;
30168  }
30169  }
30170  }
30171  t = c->y.ptr.p_double[i];
30172  c->y.ptr.p_double[i] = c->y.ptr.p_double[k];
30173  c->y.ptr.p_double[k] = t;
30174  }
30175  }
30176  for(k=0; k<=c->l-1; k++)
30177  {
30178  i = k;
30179  for(j=i+1; j<=c->l-1; j++)
30180  {
30181  if( ae_fp_less(c->z.ptr.p_double[j],c->z.ptr.p_double[i]) )
30182  {
30183  i = j;
30184  }
30185  }
30186  if( i!=k )
30187  {
30188  for(j=0; j<=c->m-1; j++)
30189  {
30190  for(j0=0; j0<=c->n-1; j0++)
30191  {
30192  for(i0=0; i0<=c->d-1; i0++)
30193  {
30194  t = c->f.ptr.p_double[c->d*(c->n*(c->m*k+j)+j0)+i0];
30195  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];
30196  c->f.ptr.p_double[c->d*(c->n*(c->m*i+j)+j0)+i0] = t;
30197  }
30198  }
30199  }
30200  t = c->z.ptr.p_double[k];
30201  c->z.ptr.p_double[k] = c->z.ptr.p_double[i];
30202  c->z.ptr.p_double[i] = t;
30203  }
30204  }
30205 }
30206 
30207 
30208 /*************************************************************************
30209 This subroutine calculates bilinear or bicubic vector-valued spline at the
30210 given point (X,Y,Z).
30211 
30212 INPUT PARAMETERS:
30213  C - spline interpolant.
30214  X, Y,
30215  Z - point
30216  F - output buffer, possibly preallocated array. In case array size
30217  is large enough to store result, it is not reallocated. Array
30218  which is too short will be reallocated
30219 
30220 OUTPUT PARAMETERS:
30221  F - array[D] (or larger) which stores function values
30222 
30223  -- ALGLIB PROJECT --
30224  Copyright 26.04.2012 by Bochkanov Sergey
30225 *************************************************************************/
30226 void spline3dcalcvbuf(spline3dinterpolant* c,
30227  double x,
30228  double y,
30229  double z,
30230  /* Real */ ae_vector* f,
30231  ae_state *_state)
30232 {
30233  double xd;
30234  double yd;
30235  double zd;
30236  double c0;
30237  double c1;
30238  double c2;
30239  double c3;
30240  ae_int_t ix;
30241  ae_int_t iy;
30242  ae_int_t iz;
30243  ae_int_t l;
30244  ae_int_t r;
30245  ae_int_t h;
30246  ae_int_t i;
30247 
30248 
30249  ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalcVBuf: incorrect C (incorrect parameter C.SType)", _state);
30250  ae_assert((ae_isfinite(x, _state)&&ae_isfinite(y, _state))&&ae_isfinite(z, _state), "Spline3DCalcVBuf: X, Y or Z contains NaN/Infinite", _state);
30251  rvectorsetlengthatleast(f, c->d, _state);
30252 
30253  /*
30254  * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
30255  */
30256  l = 0;
30257  r = c->n-1;
30258  while(l!=r-1)
30259  {
30260  h = (l+r)/2;
30261  if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
30262  {
30263  r = h;
30264  }
30265  else
30266  {
30267  l = h;
30268  }
30269  }
30270  ix = l;
30271 
30272  /*
30273  * Binary search in the [ y[0], ..., y[n-2] ] (y[n-1] is not included)
30274  */
30275  l = 0;
30276  r = c->m-1;
30277  while(l!=r-1)
30278  {
30279  h = (l+r)/2;
30280  if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
30281  {
30282  r = h;
30283  }
30284  else
30285  {
30286  l = h;
30287  }
30288  }
30289  iy = l;
30290 
30291  /*
30292  * Binary search in the [ z[0], ..., z[n-2] ] (z[n-1] is not included)
30293  */
30294  l = 0;
30295  r = c->l-1;
30296  while(l!=r-1)
30297  {
30298  h = (l+r)/2;
30299  if( ae_fp_greater_eq(c->z.ptr.p_double[h],z) )
30300  {
30301  r = h;
30302  }
30303  else
30304  {
30305  l = h;
30306  }
30307  }
30308  iz = l;
30309  xd = (x-c->x.ptr.p_double[ix])/(c->x.ptr.p_double[ix+1]-c->x.ptr.p_double[ix]);
30310  yd = (y-c->y.ptr.p_double[iy])/(c->y.ptr.p_double[iy+1]-c->y.ptr.p_double[iy]);
30311  zd = (z-c->z.ptr.p_double[iz])/(c->z.ptr.p_double[iz+1]-c->z.ptr.p_double[iz]);
30312  for(i=0; i<=c->d-1; i++)
30313  {
30314 
30315  /*
30316  * Trilinear interpolation
30317  */
30318  if( c->stype==-1 )
30319  {
30320  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;
30321  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;
30322  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;
30323  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;
30324  c0 = c0*(1-yd)+c1*yd;
30325  c1 = c2*(1-yd)+c3*yd;
30326  f->ptr.p_double[i] = c0*(1-zd)+c1*zd;
30327  }
30328  }
30329 }
30330 
30331 
30332 /*************************************************************************
30333 This subroutine calculates trilinear or tricubic vector-valued spline at the
30334 given point (X,Y,Z).
30335 
30336 INPUT PARAMETERS:
30337  C - spline interpolant.
30338  X, Y,
30339  Z - point
30340 
30341 OUTPUT PARAMETERS:
30342  F - array[D] which stores function values. F is out-parameter and
30343  it is reallocated after call to this function. In case you
30344  want to reuse previously allocated F, you may use
30345  Spline2DCalcVBuf(), which reallocates F only when it is too
30346  small.
30347 
30348  -- ALGLIB PROJECT --
30349  Copyright 26.04.2012 by Bochkanov Sergey
30350 *************************************************************************/
30351 void spline3dcalcv(spline3dinterpolant* c,
30352  double x,
30353  double y,
30354  double z,
30355  /* Real */ ae_vector* f,
30356  ae_state *_state)
30357 {
30358 
30359  ae_vector_clear(f);
30360 
30361  ae_assert(c->stype==-1||c->stype==-3, "Spline3DCalcV: incorrect C (incorrect parameter C.SType)", _state);
30362  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);
30363  ae_vector_set_length(f, c->d, _state);
30364  spline3dcalcvbuf(c, x, y, z, f, _state);
30365 }
30366 
30367 
30368 /*************************************************************************
30369 This subroutine unpacks tri-dimensional spline into the coefficients table
30370 
30371 INPUT PARAMETERS:
30372  C - spline interpolant.
30373 
30374 Result:
30375  N - grid size (X)
30376  M - grid size (Y)
30377  L - grid size (Z)
30378  D - number of components
30379  SType- spline type. Currently, only one spline type is supported:
30380  trilinear spline, as indicated by SType=1.
30381  Tbl - spline coefficients: [0..(N-1)*(M-1)*(L-1)*D-1, 0..13].
30382  For T=0..D-1 (component index), I = 0...N-2 (x index),
30383  J=0..M-2 (y index), K=0..L-2 (z index):
30384  Q := T + I*D + J*D*(N-1) + K*D*(N-1)*(M-1),
30385 
30386  Q-th row stores decomposition for T-th component of the
30387  vector-valued function
30388 
30389  Tbl[Q,0] = X[i]
30390  Tbl[Q,1] = X[i+1]
30391  Tbl[Q,2] = Y[j]
30392  Tbl[Q,3] = Y[j+1]
30393  Tbl[Q,4] = Z[k]
30394  Tbl[Q,5] = Z[k+1]
30395 
30396  Tbl[Q,6] = C000
30397  Tbl[Q,7] = C100
30398  Tbl[Q,8] = C010
30399  Tbl[Q,9] = C110
30400  Tbl[Q,10]= C001
30401  Tbl[Q,11]= C101
30402  Tbl[Q,12]= C011
30403  Tbl[Q,13]= C111
30404  On each grid square spline is equals to:
30405  S(x) = SUM(c[i,j,k]*(x^i)*(y^j)*(z^k), i=0..1, j=0..1, k=0..1)
30406  t = x-x[j]
30407  u = y-y[i]
30408  v = z-z[k]
30409 
30410  NOTE: format of Tbl is given for SType=1. Future versions of
30411  ALGLIB can use different formats for different values of
30412  SType.
30413 
30414  -- ALGLIB PROJECT --
30415  Copyright 26.04.2012 by Bochkanov Sergey
30416 *************************************************************************/
30417 void spline3dunpackv(spline3dinterpolant* c,
30418  ae_int_t* n,
30419  ae_int_t* m,
30420  ae_int_t* l,
30421  ae_int_t* d,
30422  ae_int_t* stype,
30423  /* Real */ ae_matrix* tbl,
30424  ae_state *_state)
30425 {
30426  ae_int_t p;
30427  ae_int_t ci;
30428  ae_int_t cj;
30429  ae_int_t ck;
30430  double du;
30431  double dv;
30432  double dw;
30433  ae_int_t i;
30434  ae_int_t j;
30435  ae_int_t k;
30436  ae_int_t di;
30437  ae_int_t i0;
30438 
30439  *n = 0;
30440  *m = 0;
30441  *l = 0;
30442  *d = 0;
30443  *stype = 0;
30444  ae_matrix_clear(tbl);
30445 
30446  ae_assert(c->stype==-1, "Spline3DUnpackV: incorrect C (incorrect parameter C.SType)", _state);
30447  *n = c->n;
30448  *m = c->m;
30449  *l = c->l;
30450  *d = c->d;
30451  *stype = ae_iabs(c->stype, _state);
30452  ae_matrix_set_length(tbl, (*n-1)*(*m-1)*(*l-1)*(*d), 14, _state);
30453 
30454  /*
30455  * Fill
30456  */
30457  for(i=0; i<=*n-2; i++)
30458  {
30459  for(j=0; j<=*m-2; j++)
30460  {
30461  for(k=0; k<=*l-2; k++)
30462  {
30463  for(di=0; di<=*d-1; di++)
30464  {
30465  p = *d*((*n-1)*((*m-1)*k+j)+i)+di;
30466  tbl->ptr.pp_double[p][0] = c->x.ptr.p_double[i];
30467  tbl->ptr.pp_double[p][1] = c->x.ptr.p_double[i+1];
30468  tbl->ptr.pp_double[p][2] = c->y.ptr.p_double[j];
30469  tbl->ptr.pp_double[p][3] = c->y.ptr.p_double[j+1];
30470  tbl->ptr.pp_double[p][4] = c->z.ptr.p_double[k];
30471  tbl->ptr.pp_double[p][5] = c->z.ptr.p_double[k+1];
30472  du = 1/(tbl->ptr.pp_double[p][1]-tbl->ptr.pp_double[p][0]);
30473  dv = 1/(tbl->ptr.pp_double[p][3]-tbl->ptr.pp_double[p][2]);
30474  dw = 1/(tbl->ptr.pp_double[p][5]-tbl->ptr.pp_double[p][4]);
30475 
30476  /*
30477  * Trilinear interpolation
30478  */
30479  if( c->stype==-1 )
30480  {
30481  for(i0=6; i0<=13; i0++)
30482  {
30483  tbl->ptr.pp_double[p][i0] = 0;
30484  }
30485  tbl->ptr.pp_double[p][6+2*(2*0+0)+0] = c->f.ptr.p_double[*d*(*n*(*m*k+j)+i)+di];
30486  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];
30487  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];
30488  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];
30489  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];
30490  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];
30491  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];
30492  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];
30493  }
30494 
30495  /*
30496  * Rescale Cij
30497  */
30498  for(ci=0; ci<=1; ci++)
30499  {
30500  for(cj=0; cj<=1; cj++)
30501  {
30502  for(ck=0; ck<=1; ck++)
30503  {
30504  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, ci, _state)*ae_pow(dv, cj, _state)*ae_pow(dw, ck, _state);
30505  }
30506  }
30507  }
30508  }
30509  }
30510  }
30511  }
30512 }
30513 
30514 
30515 /*************************************************************************
30516 This subroutine calculates the value of the trilinear(or tricubic;possible
30517 will be later) spline at the given point X(and its derivatives; possible
30518 will be later).
30519 
30520 INPUT PARAMETERS:
30521  C - spline interpolant.
30522  X, Y, Z - point
30523 
30524 OUTPUT PARAMETERS:
30525  F - S(x,y,z)
30526  FX - dS(x,y,z)/dX
30527  FY - dS(x,y,z)/dY
30528  FXY - d2S(x,y,z)/dXdY
30529 
30530  -- ALGLIB PROJECT --
30531  Copyright 26.04.2012 by Bochkanov Sergey
30532 *************************************************************************/
30533 static void spline3d_spline3ddiff(spline3dinterpolant* c,
30534  double x,
30535  double y,
30536  double z,
30537  double* f,
30538  double* fx,
30539  double* fy,
30540  double* fxy,
30541  ae_state *_state)
30542 {
30543  double xd;
30544  double yd;
30545  double zd;
30546  double c0;
30547  double c1;
30548  double c2;
30549  double c3;
30550  ae_int_t ix;
30551  ae_int_t iy;
30552  ae_int_t iz;
30553  ae_int_t l;
30554  ae_int_t r;
30555  ae_int_t h;
30556 
30557  *f = 0;
30558  *fx = 0;
30559  *fy = 0;
30560  *fxy = 0;
30561 
30562  ae_assert(c->stype==-1||c->stype==-3, "Spline3DDiff: incorrect C (incorrect parameter C.SType)", _state);
30563  ae_assert(ae_isfinite(x, _state)&&ae_isfinite(y, _state), "Spline3DDiff: X or Y contains NaN or Infinite value", _state);
30564 
30565  /*
30566  * Prepare F, dF/dX, dF/dY, d2F/dXdY
30567  */
30568  *f = 0;
30569  *fx = 0;
30570  *fy = 0;
30571  *fxy = 0;
30572  if( c->d!=1 )
30573  {
30574  return;
30575  }
30576 
30577  /*
30578  * Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
30579  */
30580  l = 0;
30581  r = c->n-1;
30582  while(l!=r-1)
30583  {
30584  h = (l+r)/2;
30585  if( ae_fp_greater_eq(c->x.ptr.p_double[h],x) )
30586  {
30587  r = h;
30588  }
30589  else
30590  {
30591  l = h;
30592  }
30593  }
30594  ix = l;
30595 
30596  /*
30597  * Binary search in the [ y[0], ..., y[n-2] ] (y[n-1] is not included)
30598  */
30599  l = 0;
30600  r = c->m-1;
30601  while(l!=r-1)
30602  {
30603  h = (l+r)/2;
30604  if( ae_fp_greater_eq(c->y.ptr.p_double[h],y) )
30605  {
30606  r = h;
30607  }
30608  else
30609  {
30610  l = h;
30611  }
30612  }
30613  iy = l;
30614 
30615  /*
30616  * Binary search in the [ z[0], ..., z[n-2] ] (z[n-1] is not included)
30617  */
30618  l = 0;
30619  r = c->l-1;
30620  while(l!=r-1)
30621  {
30622  h = (l+r)/2;
30623  if( ae_fp_greater_eq(c->z.ptr.p_double[h],z) )
30624  {
30625  r = h;
30626  }
30627  else
30628  {
30629  l = h;
30630  }
30631  }
30632  iz = l;
30633  xd = (x-c->x.ptr.p_double[ix])/(c->x.ptr.p_double[ix+1]-c->x.ptr.p_double[ix]);
30634  yd = (y-c->y.ptr.p_double[iy])/(c->y.ptr.p_double[iy+1]-c->y.ptr.p_double[iy]);
30635  zd = (z-c->z.ptr.p_double[iz])/(c->z.ptr.p_double[iz+1]-c->z.ptr.p_double[iz]);
30636 
30637  /*
30638  * Trilinear interpolation
30639  */
30640  if( c->stype==-1 )
30641  {
30642  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;
30643  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;
30644  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;
30645  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;
30646  c0 = c0*(1-yd)+c1*yd;
30647  c1 = c2*(1-yd)+c3*yd;
30648  *f = c0*(1-zd)+c1*zd;
30649  }
30650 }
30651 
30652 
30653 ae_bool _spline3dinterpolant_init(void* _p, ae_state *_state, ae_bool make_automatic)
30654 {
30655  spline3dinterpolant *p = (spline3dinterpolant*)_p;
30656  ae_touch_ptr((void*)p);
30657  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
30658  return ae_false;
30659  if( !ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic) )
30660  return ae_false;
30661  if( !ae_vector_init(&p->z, 0, DT_REAL, _state, make_automatic) )
30662  return ae_false;
30663  if( !ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic) )
30664  return ae_false;
30665  return ae_true;
30666 }
30667 
30668 
30669 ae_bool _spline3dinterpolant_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
30670 {
30671  spline3dinterpolant *dst = (spline3dinterpolant*)_dst;
30672  spline3dinterpolant *src = (spline3dinterpolant*)_src;
30673  dst->k = src->k;
30674  dst->stype = src->stype;
30675  dst->n = src->n;
30676  dst->m = src->m;
30677  dst->l = src->l;
30678  dst->d = src->d;
30679  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
30680  return ae_false;
30681  if( !ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic) )
30682  return ae_false;
30683  if( !ae_vector_init_copy(&dst->z, &src->z, _state, make_automatic) )
30684  return ae_false;
30685  if( !ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic) )
30686  return ae_false;
30687  return ae_true;
30688 }
30689 
30690 
30691 void _spline3dinterpolant_clear(void* _p)
30692 {
30693  spline3dinterpolant *p = (spline3dinterpolant*)_p;
30694  ae_touch_ptr((void*)p);
30695  ae_vector_clear(&p->x);
30696  ae_vector_clear(&p->y);
30697  ae_vector_clear(&p->z);
30698  ae_vector_clear(&p->f);
30699 }
30700 
30701 
30702 void _spline3dinterpolant_destroy(void* _p)
30703 {
30704  spline3dinterpolant *p = (spline3dinterpolant*)_p;
30705  ae_touch_ptr((void*)p);
30706  ae_vector_destroy(&p->x);
30707  ae_vector_destroy(&p->y);
30708  ae_vector_destroy(&p->z);
30709  ae_vector_destroy(&p->f);
30710 }
30711 
30712 
30713 
30714 }
30715 
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)
void polynomialpow2bar(const real_1d_array &a, const ae_int_t n, const double c, const double s, barycentricinterpolant &p)
_barycentricinterpolant_owner & operator=(const _barycentricinterpolant_owner &rhs)
void spline3dunpackv(spline3dinterpolant *c, ae_int_t *n, ae_int_t *m, ae_int_t *l, ae_int_t *d, ae_int_t *stype, ae_matrix *tbl, ae_state *_state)
struct alglib_impl::ae_state ae_state
ae_bool _lsfitreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
_rbfreport_owner & operator=(const _rbfreport_owner &rhs)
double xi
rbfmodel & operator=(const rbfmodel &rhs)
void _spline1dinterpolant_clear(void *_p)
ae_bool ae_fp_greater_eq(double v1, double v2)
Definition: ap.cpp:1351
void pspline2calc(const pspline2interpolant &p, const double t, double &x, double &y)
void pspline2calc(pspline2interpolant *p, double t, double *x, double *y, ae_state *_state)
double pspline3arclength(const pspline3interpolant &p, const double a, const double b)
#define yc
void spline1dfitcubic(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t m, ae_int_t *info, spline1dinterpolant *s, spline1dfitreport *rep, ae_state *_state)
void ae_serializer_init(ae_serializer *serializer)
Definition: ap.cpp:3393
_pspline2interpolant_owner & operator=(const _pspline2interpolant_owner &rhs)
void spline2ddiff(spline2dinterpolant *c, double x, double y, double *f, double *fx, double *fy, double *fxy, ae_state *_state)
void idwbuildnoisy(ae_matrix *xy, ae_int_t n, ae_int_t nx, ae_int_t d, ae_int_t nq, ae_int_t nw, idwinterpolant *z, ae_state *_state)
ae_bool _rbfmodel_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void pspline3build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p)
void spline1dconvcubic(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t boundltype, double boundl, ae_int_t boundrtype, double boundr, ae_vector *x2, ae_int_t n2, ae_vector *y2, ae_state *_state)
void lsfitsetbc(lsfitstate *state, ae_vector *bndl, ae_vector *bndu, ae_state *_state)
void barycentricunpack(const barycentricinterpolant &b, ae_int_t &n, real_1d_array &x, real_1d_array &y, real_1d_array &w)
void barycentricfitfloaterhormann(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t m, ae_int_t *info, barycentricinterpolant *b, barycentricfitreport *rep, ae_state *_state)
void ae_v_moved(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4425
ae_bool _spline2dinterpolant_init(void *_p, ae_state *_state, ae_bool make_automatic)
idwinterpolant & operator=(const idwinterpolant &rhs)
double spline1dintegrate(const spline1dinterpolant &c, const double x)
void polynomialbuildcheb1(double a, double b, ae_vector *y, ae_int_t n, barycentricinterpolant *p, ae_state *_state)
double ae_sin(double x, ae_state *state)
Definition: ap.cpp:1630
void spline1dlintransx(const spline1dinterpolant &c, const double a, const double b)
void spline3dbuildtrilinearv(ae_vector *x, ae_int_t n, ae_vector *y, ae_int_t m, ae_vector *z, ae_int_t l, ae_vector *f, ae_int_t d, spline3dinterpolant *c, ae_state *_state)
alglib_impl::barycentricinterpolant * p_struct
void apperiodicmap(double *x, double a, double b, double *k, ae_state *_state)
ae_int_t ae_serializer_get_alloc_size(ae_serializer *serializer)
Definition: ap.cpp:3416
void barycentricbuildfloaterhormann(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, const ae_int_t d, barycentricinterpolant &b)
void spline1dlintransx(spline1dinterpolant *c, double a, double b, ae_state *_state)
void ae_serializer_sstart_str(ae_serializer *serializer, std::string *buf)
Definition: ap.cpp:3447
void rbfsetalgoqnn(const rbfmodel &s, const double q, const double z)
double pspline3arclength(pspline3interpolant *p, double a, double b, ae_state *_state)
ae_int_t & iterationscount
void ae_v_muld(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
Definition: ap.cpp:4538
void barycentriclintransx(const barycentricinterpolant &b, const double ca, const double cb)
barycentricinterpolant & operator=(const barycentricinterpolant &rhs)
double ae_fabs(double x, ae_state *state)
Definition: ap.cpp:1520
void lsfitcreatef(ae_matrix *x, ae_vector *y, ae_vector *c, ae_int_t n, ae_int_t m, ae_int_t k, double diffstep, lsfitstate *state, ae_state *_state)
void lsfitsetbc(const lsfitstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
_lsfitreport_owner & operator=(const _lsfitreport_owner &rhs)
double ae_tan(double x, ae_state *state)
Definition: ap.cpp:1640
void spline1dbuildmonotone(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c)
void barycentricbuildxyw(ae_vector *x, ae_vector *y, ae_vector *w, ae_int_t n, barycentricinterpolant *b, ae_state *_state)
doublereal * c
doublereal * g
double ae_pow(double x, double y, ae_state *state)
Definition: ap.cpp:1684
void spline1dconvdiffcubic(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t boundltype, double boundl, ae_int_t boundrtype, double boundr, ae_vector *x2, ae_int_t n2, ae_vector *y2, ae_vector *d2, ae_state *_state)
void lsfitresults(lsfitstate *state, ae_int_t *info, ae_vector *c, lsfitreport *rep, ae_state *_state)
void barycentricbuildfloaterhormann(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t d, barycentricinterpolant *b, ae_state *_state)
#define ae_false
Definition: ap.h:196
double rbfcalc2(const rbfmodel &s, const double x0, const double x1)
double pspline2arclength(pspline2interpolant *p, double a, double b, ae_state *_state)
void * ae_malloc(size_t size, ae_state *state)
Definition: ap.cpp:222
ae_int_t stride
Definition: ap.h:446
void heapsortdpoints(ae_vector *x, ae_vector *y, ae_vector *d, ae_int_t n, ae_state *_state)
double rho
void lsfitcreatewfgh(ae_matrix *x, ae_vector *y, ae_vector *w, ae_vector *c, ae_int_t n, ae_int_t m, ae_int_t k, lsfitstate *state, ae_state *_state)
void rbfcalc(rbfmodel *s, ae_vector *x, ae_vector *y, ae_state *_state)
double beta(const double a, const double b)
ae_bool _spline2dinterpolant_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void kdtreequeryresultsdistances(const kdtree &kdt, real_1d_array &r)
doublereal * grad
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)
void ne(Image< double > &op1, const Image< double > &op2)
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)
union alglib_impl::ae_matrix::@12 ptr
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)
ae_bool _spline1dfitreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
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)
void spline1dfithermite(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t m, ae_int_t *info, spline1dinterpolant *s, spline1dfitreport *rep, ae_state *_state)
void barycentricdiff1(const barycentricinterpolant &b, const double t, double &f, double &df)
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)
void barycentriclintransy(const barycentricinterpolant &b, const double ca, const double cb)
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)
void rbfserialize(rbfmodel &obj, std::string &s_out)
void _barycentricfitreport_clear(void *_p)
void ae_frame_make(ae_state *state, ae_frame *tmp)
Definition: ap.cpp:402
static double * y
ae_bool aredistinct(ae_vector *x, ae_int_t n, ae_state *_state)
double rbfcalc2(rbfmodel *s, double x0, double x1, ae_state *_state)
ae_bool _idwinterpolant_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void lsfitlinearw(ae_vector *y, ae_vector *w, ae_matrix *fmatrix, ae_int_t n, ae_int_t m, ae_int_t *info, ae_vector *c, lsfitreport *rep, ae_state *_state)
_barycentricfitreport_owner & operator=(const _barycentricfitreport_owner &rhs)
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)
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)
void polynomialfit(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t m, ae_int_t *info, barycentricinterpolant *p, polynomialfitreport *rep, ae_state *_state)
ae_bool _spline3dinterpolant_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void pspline3diff(const pspline3interpolant &p, const double t, double &x, double &dx, double &y, double &dy, double &z, double &dz)
void rbfsetconstterm(rbfmodel *s, ae_state *_state)
void lsfitsetscale(const lsfitstate &state, const real_1d_array &s)
alglib_impl::barycentricfitreport * c_ptr()
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)
void _spline1dinterpolant_destroy(void *_p)
void lsfitsetxrep(const lsfitstate &state, const bool needxrep)
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)
void spline1dbuildmonotone(ae_vector *x, ae_vector *y, ae_int_t n, spline1dinterpolant *c, ae_state *_state)
void idwbuildnoisy(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const ae_int_t d, const ae_int_t nq, const ae_int_t nw, idwinterpolant &z)
void kdtreequeryresultstags(const kdtree &kdt, integer_1d_array &tags)
_rbfmodel_owner & operator=(const _rbfmodel_owner &rhs)
void spline2dlintransf(spline2dinterpolant *c, double a, double b, ae_state *_state)
void tagsortfastr(ae_vector *a, ae_vector *b, ae_vector *bufa, ae_vector *bufb, ae_int_t n, ae_state *_state)
void polynomialbar2cheb(const barycentricinterpolant &p, const double a, const double b, real_1d_array &t)
ae_int_t ae_sign(double x, ae_state *state)
Definition: ap.cpp:1540
void kdtreebuildtagged(const real_2d_array &xy, const integer_1d_array &tags, const ae_int_t n, const ae_int_t nx, const ae_int_t ny, const ae_int_t normtype, kdtree &kdt)
Definition: alglibmisc.cpp:662
ae_bool _lsfitreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void rbfbuildmodel(const rbfmodel &s, rbfreport &rep)
void ae_serializer_ustart_str(ae_serializer *serializer, const std::string *buf)
Definition: ap.cpp:3457
void pspline2build(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p)
void rbfcreate(const ae_int_t nx, const ae_int_t ny, rbfmodel &s)
void spline1dbuildcubic(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t boundltype, double boundl, ae_int_t boundrtype, double boundr, spline1dinterpolant *c, ae_state *_state)
ae_int_t bisectmethod(double pa, double ma, double pb, double mb, double a, double b, double *x, ae_state *_state)
void pspline2diff(const pspline2interpolant &p, const double t, double &x, double &dx, double &y, double &dy)
void spline3dlintransxyz(const spline3dinterpolant &c, const double ax, const double bx, const double ay, const double by, const double az, const double bz)
doublereal * w
void spline2dcopy(const spline2dinterpolant &c, spline2dinterpolant &cc)
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)
ae_int_t kdtreequeryknn(const kdtree &kdt, const real_1d_array &x, const ae_int_t k, const bool selfmatch)
Definition: alglibmisc.cpp:764
void lsfitcreatefg(ae_matrix *x, ae_vector *y, ae_vector *c, ae_int_t n, ae_int_t m, ae_int_t k, ae_bool cheapfg, lsfitstate *state, ae_state *_state)
void barycentriccopy(barycentricinterpolant *b, barycentricinterpolant *b2, ae_state *_state)
void spline3dcalcv(spline3dinterpolant *c, double x, double y, double z, ae_vector *f, ae_state *_state)
double * p_double
Definition: ap.h:437
void pspline3diff(pspline3interpolant *p, double t, double *x, double *dx, double *y, double *dy, double *z, double *dz, ae_state *_state)
void _spline2dinterpolant_clear(void *_p)
pspline2interpolant & operator=(const pspline2interpolant &rhs)
void _polynomialfitreport_clear(void *_p)
void spline1drootsandextrema(spline1dinterpolant *c, ae_vector *r, ae_int_t *nr, ae_bool *dr, ae_vector *e, ae_vector *et, ae_int_t *ne, ae_bool *de, ae_state *_state)
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)
real_2d_array covpar
alglib_impl::polynomialfitreport * p_struct
void ae_serializer_stop(ae_serializer *serializer)
Definition: ap.cpp:3599
void spline2dbuildbilinearv(ae_vector *x, ae_int_t n, ae_vector *y, ae_int_t m, ae_vector *f, ae_int_t d, spline2dinterpolant *c, ae_state *_state)
void _idwinterpolant_clear(void *_p)
void pspline3calc(const pspline3interpolant &p, const double t, double &x, double &y, double &z)
void ae_state_clear(ae_state *state)
Definition: ap.cpp:373
double spline2dcalc(const spline2dinterpolant &c, const double x, const double y)
const alglib_impl::ae_matrix * c_ptr() const
Definition: ap.cpp:6463
rbfreport & operator=(const rbfreport &rhs)
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)
ae_bool ae_fp_eq(double v1, double v2)
Definition: ap.cpp:1313
void barycentriclintransx(barycentricinterpolant *b, double ca, double cb, ae_state *_state)
void spline1dbuildlinear(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c)
void barycentricdiff2(barycentricinterpolant *b, double t, double *f, double *df, double *d2f, ae_state *_state)
ae_bool _spline1dinterpolant_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
double polynomialcalccheb1(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t)
cmache_1 eps
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)
double * gamma
alglib_impl::spline2dinterpolant * p_struct
void pspline2tangent(pspline2interpolant *p, double t, double *x, double *y, ae_state *_state)
spline1dinterpolant & operator=(const spline1dinterpolant &rhs)
double * di
void lsfitsetgradientcheck(const lsfitstate &state, const double teststep)
double ae_cos(double x, ae_state *state)
Definition: ap.cpp:1635
ae_bool ae_matrix_init_copy(ae_matrix *dst, ae_matrix *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:801
ae_bool ae_matrix_init(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:756
void spline2dresamplebicubic(ae_matrix *a, ae_int_t oldheight, ae_int_t oldwidth, ae_matrix *b, ae_int_t newheight, ae_int_t newwidth, ae_state *_state)
void pspline3parametervalues(pspline3interpolant *p, ae_int_t *n, ae_vector *t, ae_state *_state)
doublereal * x
void ae_matrix_destroy(ae_matrix *dst)
Definition: ap.cpp:909
bool lsfititeration(const lsfitstate &state)
double v_nan
Definition: ap.h:355
#define i
#define ae_pi
Definition: ap.h:828
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)
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
lsfitreport & operator=(const lsfitreport &rhs)
void spline1dfitpenalizedw(ae_vector *x, ae_vector *y, ae_vector *w, ae_int_t n, ae_int_t m, double rho, ae_int_t *info, spline1dinterpolant *s, spline1dfitreport *rep, ae_state *_state)
void spline3dresampletrilinear(ae_vector *a, ae_int_t oldzcount, ae_int_t oldycount, ae_int_t oldxcount, ae_int_t newzcount, ae_int_t newycount, ae_int_t newxcount, ae_vector *b, ae_state *_state)
ae_bool _kdtree_init(void *_p, ae_state *_state, ae_bool make_automatic)
doublereal * d
void polynomialcheb2bar(ae_vector *t, ae_int_t n, double a, double b, barycentricinterpolant *p, ae_state *_state)
double ** hess
void ae_serializer_clear(ae_serializer *serializer)
Definition: ap.cpp:3400
void lsfitcreatewf(ae_matrix *x, ae_vector *y, ae_vector *w, ae_vector *c, ae_int_t n, ae_int_t m, ae_int_t k, double diffstep, lsfitstate *state, ae_state *_state)
ae_bool _idwinterpolant_init(void *_p, ae_state *_state, ae_bool make_automatic)
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)
ae_bool _kdtree_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void spline2dunpackv(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, ae_int_t &d, real_2d_array &tbl)
void rbfsetalgomultilayer(const rbfmodel &s, const double rbase, const ae_int_t nlayers, const double lambdav)
void lsfitsetstpmax(lsfitstate *state, double stpmax, ae_state *_state)
void barycentricfitfloaterhormannwc(ae_vector *x, ae_vector *y, ae_vector *w, ae_int_t n, ae_vector *xc, ae_vector *yc, ae_vector *dc, ae_int_t k, ae_int_t m, ae_int_t *info, barycentricinterpolant *b, barycentricfitreport *rep, ae_state *_state)
void threshold(double *phi, unsigned long nvox, double limit)
Definition: lib_vwk.cpp:524
void lsfitlinearc(ae_vector *y, ae_matrix *fmatrix, ae_matrix *cmatrix, ae_int_t n, ae_int_t m, ae_int_t k, ae_int_t *info, ae_vector *c, lsfitreport *rep, ae_state *_state)
void spline2dbuildbicubic(ae_vector *x, ae_vector *y, ae_matrix *f, ae_int_t m, ae_int_t n, spline2dinterpolant *c, ae_state *_state)
void barycentricdiff1(barycentricinterpolant *b, double t, double *f, double *df, ae_state *_state)
double vv
lsfitstate & operator=(const lsfitstate &rhs)
ae_bool _barycentricinterpolant_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
spline1dfitreport & operator=(const spline1dfitreport &rhs)
alglib_impl::barycentricfitreport * p_struct
void spline1dconvdiffinternal(ae_vector *xold, ae_vector *yold, ae_vector *dold, ae_int_t n, ae_vector *x2, ae_int_t n2, ae_vector *y, ae_bool needy, ae_vector *d1, ae_bool needd1, ae_vector *d2, ae_bool needd2, ae_state *_state)
alglib_impl::pspline3interpolant * c_ptr()
void spline1dbuildakima(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, spline1dinterpolant &c)
ae_bool _pspline3interpolant_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void _barycentricinterpolant_destroy(void *_p)
glob_log first
void lsfitsetcond(lsfitstate *state, double epsf, double epsx, ae_int_t maxits, ae_state *_state)
real_1d_array errpar
ae_int_t ae_v_len(ae_int_t a, ae_int_t b)
Definition: ap.cpp:4562
void rbfcalcbuf(rbfmodel *s, ae_vector *x, ae_vector *y, ae_state *_state)
void ae_vector_destroy(ae_vector *dst)
Definition: ap.cpp:707
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)
ae_bool _pspline2interpolant_init(void *_p, ae_state *_state, ae_bool make_automatic)
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)
void rbfalloc(ae_serializer *s, rbfmodel *model, ae_state *_state)
doublereal * b
void polynomialbuild(const real_1d_array &x, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p)
double polynomialcalccheb2(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t)
void pspline2parametervalues(pspline2interpolant *p, ae_int_t *n, ae_vector *t, ae_state *_state)
double v1
void tagsort(ae_vector *a, ae_int_t n, ae_vector *p1, ae_vector *p2, ae_state *_state)
ae_bool _polynomialfitreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
void spline2dcopy(spline2dinterpolant *c, spline2dinterpolant *cc, ae_state *_state)
void spline1dlintransy(const spline1dinterpolant &c, const double a, const double b)
real_1d_array g
void lsfitsetcond(const lsfitstate &state, const double epsf, const double epsx, const ae_int_t maxits)
void _idwinterpolant_destroy(void *_p)
void rbfgridcalc2(rbfmodel *s, ae_vector *x0, ae_int_t n0, ae_vector *x1, ae_int_t n1, ae_matrix *y, ae_state *_state)
#define x0
void rbfsetpoints(rbfmodel *s, ae_matrix *xy, ae_int_t n, ae_state *_state)
double polynomialcalccheb1(double a, double b, ae_vector *f, ae_int_t n, double t, ae_state *_state)
double barycentriccalc(const barycentricinterpolant &b, const double t)
void lsfitfit(lsfitstate &state, void(*func)(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr), void(*rep)(const real_1d_array &c, double func, void *ptr), void *ptr)
void lsfitsetxrep(lsfitstate *state, ae_bool needxrep, ae_state *_state)
polynomialfitreport & operator=(const polynomialfitreport &rhs)
void spline2dbuildbilinear(ae_vector *x, ae_vector *y, ae_matrix *f, ae_int_t m, ae_int_t n, spline2dinterpolant *c, ae_state *_state)
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)
void ae_v_move(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4371
alglib_impl::pspline3interpolant * p_struct
alglib_impl::rbfreport * p_struct
viol type
_spline3dinterpolant_owner & operator=(const _spline3dinterpolant_owner &rhs)
alglib_impl::spline3dinterpolant * c_ptr()
void polynomialbuildcheb1(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p)
void spline2dunpackv(spline2dinterpolant *c, ae_int_t *m, ae_int_t *n, ae_int_t *d, ae_matrix *tbl, ae_state *_state)
real_1d_array noise
double idwcalc(idwinterpolant *z, ae_vector *x, ae_state *_state)
double pspline2arclength(const pspline2interpolant &p, const double a, const double b)
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)
alglib_impl::lsfitreport * p_struct
ae_bool ae_isinf(double x, ae_state *state)
Definition: ap.cpp:1505
int in
double * f
void ae_vector_clear(ae_vector *dst)
Definition: ap.cpp:692
alglib_impl::rbfmodel * c_ptr()
ae_int_t length() const
Definition: ap.cpp:5882
void spline3dcalcv(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f)
alglib_impl::lsfitreport * c_ptr()
void spline1dunpack(const spline1dinterpolant &c, ae_int_t &n, real_2d_array &tbl)
void spline1dfitpenalized(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t m, double rho, ae_int_t *info, spline1dinterpolant *s, spline1dfitreport *rep, ae_state *_state)
ae_bool ae_fp_less(double v1, double v2)
Definition: ap.cpp:1327
_spline1dinterpolant_owner & operator=(const _spline1dinterpolant_owner &rhs)
void spline1dconvdiff2cubic(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t boundltype, double boundl, ae_int_t boundrtype, double boundr, ae_vector *x2, ae_int_t n2, ae_vector *y2, ae_vector *d2, ae_vector *dd2, ae_state *_state)
double spline1dcalc(const spline1dinterpolant &c, const double x)
void idwbuildmodifiedshepardr(ae_matrix *xy, ae_int_t n, ae_int_t nx, double r, idwinterpolant *z, ae_state *_state)
alglib_impl::lsfitstate * c_ptr()
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)
ae_bool _polynomialfitreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
ae_bool _spline1dinterpolant_init(void *_p, ae_state *_state, ae_bool make_automatic)
void pspline2diff2(pspline2interpolant *p, double t, double *x, double *dx, double *d2x, double *y, double *dy, double *d2y, ae_state *_state)
void spline3dcalcvbuf(spline3dinterpolant *c, double x, double y, double z, ae_vector *f, ae_state *_state)
ae_int_t ae_iceil(double x, ae_state *state)
Definition: ap.cpp:1562
void pspline3parametervalues(const pspline3interpolant &p, ae_int_t &n, real_1d_array &t)
void lsfitlinearwc(ae_vector *y, ae_vector *w, ae_matrix *fmatrix, ae_matrix *cmatrix, ae_int_t n, ae_int_t m, ae_int_t k, ae_int_t *info, ae_vector *c, lsfitreport *rep, ae_state *_state)
ae_int_t kdtreequeryrnn(const kdtree &kdt, const real_1d_array &x, const double r, const bool selfmatch)
Definition: alglibmisc.cpp:856
ae_bool _densesolverlsreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
Definition: solvers.cpp:5613
void polynomialcheb2bar(const real_1d_array &t, const ae_int_t n, const double a, const double b, barycentricinterpolant &p)
void _rbfmodel_clear(void *_p)
pspline3interpolant & operator=(const pspline3interpolant &rhs)
alglib_impl::barycentricinterpolant * c_ptr()
void _pspline3interpolant_clear(void *_p)
ae_bool _barycentricfitreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
double dx
void spline2dlintransxy(spline2dinterpolant *c, double ax, double bx, double ay, double by, ae_state *_state)
alglib_impl::spline1dinterpolant * c_ptr()
#define ae_bool
Definition: ap.h:194
void spline1dfithermitewc(ae_vector *x, ae_vector *y, ae_vector *w, ae_int_t n, ae_vector *xc, ae_vector *yc, ae_vector *dc, ae_int_t k, ae_int_t m, ae_int_t *info, spline1dinterpolant *s, spline1dfitreport *rep, ae_state *_state)
ae_bool ae_fp_neq(double v1, double v2)
Definition: ap.cpp:1321
ae_bool ae_isnan(double x, ae_state *state)
Definition: ap.cpp:1500
real_1d_array errcurve
ae_bool isfinitevector(ae_vector *x, ae_int_t n, ae_state *_state)
void pspline3diff2(pspline3interpolant *p, double t, double *x, double *dx, double *d2x, double *y, double *dy, double *d2y, double *z, double *dz, double *d2z, ae_state *_state)
void rvectorsetlengthatleast(ae_vector *x, ae_int_t n, ae_state *_state)
void spline1dbuildhermite(const real_1d_array &x, const real_1d_array &y, const real_1d_array &d, const ae_int_t n, spline1dinterpolant &c)
double z
void spline1ddiff(spline1dinterpolant *c, double x, double *s, double *ds, double *d2s, ae_state *_state)
__host__ __device__ float length(float2 v)
void polynomialbar2pow(barycentricinterpolant *p, double c, double s, ae_vector *a, ae_state *_state)
ae_bool _spline1dfitreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
_pspline3interpolant_owner & operator=(const _pspline3interpolant_owner &rhs)
void ae_touch_ptr(void *p)
Definition: ap.cpp:294
_lsfitstate_owner & operator=(const _lsfitstate_owner &rhs)
void polynomialbar2cheb(barycentricinterpolant *p, double a, double b, ae_vector *t, ae_state *_state)
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)
void polynomialfitwc(ae_vector *x, ae_vector *y, ae_vector *w, ae_int_t n, ae_vector *xc, ae_vector *yc, ae_vector *dc, ae_int_t k, ae_int_t m, ae_int_t *info, barycentricinterpolant *p, polynomialfitreport *rep, ae_state *_state)
double ae_maxreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1577
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)
ae_error_type
Definition: ap.h:201
void rbfcalc(const rbfmodel &s, const real_1d_array &x, real_1d_array &y)
void _kdtree_clear(void *_p)
alglib_impl::idwinterpolant * p_struct
void barycentriclintransy(barycentricinterpolant *b, double ca, double cb, ae_state *_state)
void spline2dlintransxy(const spline2dinterpolant &c, const double ax, const double bx, const double ay, const double by)
ae_bool ae_vector_set_length(ae_vector *dst, ae_int_t newsize, ae_state *state)
Definition: ap.cpp:658
void polynomialpow2bar(ae_vector *a, ae_int_t n, double c, double s, barycentricinterpolant *p, ae_state *_state)
void pspline3calc(pspline3interpolant *p, double t, double *x, double *y, double *z, ae_state *_state)
void _pspline2interpolant_clear(void *_p)
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)
ae_bool _rbfmodel_init(void *_p, ae_state *_state, ae_bool make_automatic)
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)
void rbfsetalgomultilayer(rbfmodel *s, double rbase, ae_int_t nlayers, double lambdav, ae_state *_state)
void spline1dbuildakima(ae_vector *x, ae_vector *y, ae_int_t n, spline1dinterpolant *c, ae_state *_state)
void spline1dbuildhermite(ae_vector *x, ae_vector *y, ae_vector *d, ae_int_t n, spline1dinterpolant *c, ae_state *_state)
void spline1dgriddiff2cubic(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t boundltype, double boundl, ae_int_t boundrtype, double boundr, ae_vector *d1, ae_vector *d2, ae_state *_state)
void spline3dlintransf(spline3dinterpolant *c, double a, double b, ae_state *_state)
alglib_impl::pspline2interpolant * c_ptr()
alglib_impl::spline1dfitreport * c_ptr()
void lsfitcreatewfg(ae_matrix *x, ae_vector *y, ae_vector *w, ae_vector *c, ae_int_t n, ae_int_t m, ae_int_t k, ae_bool cheapfg, lsfitstate *state, ae_state *_state)
double ae_log(double x, ae_state *state)
Definition: ap.cpp:1679
void spline1dcopy(spline1dinterpolant *c, spline1dinterpolant *cc, ae_state *_state)
void _rbfreport_clear(void *_p)
struct alglib_impl::ae_vector ae_vector
const alglib_impl::ae_vector * c_ptr() const
Definition: ap.cpp:5907
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)
real_1d_array x
double * d0
void _lsfitreport_clear(void *_p)
#define j
double ae_minreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1582
void rbfbuildmodel(rbfmodel *s, rbfreport *rep, ae_state *_state)
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)
double polynomialcalceqdist(const double a, const double b, const real_1d_array &f, const ae_int_t n, const double t)
real_1d_array c
void polynomialbuildeqdist(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p)
void _barycentricinterpolant_clear(void *_p)
int m
void spline2dunpack(spline2dinterpolant *c, ae_int_t *m, ae_int_t *n, ae_matrix *tbl, ae_state *_state)
double spline1dcalc(spline1dinterpolant *c, double x, ae_state *_state)
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)
double polynomialcalccheb2(double a, double b, ae_vector *f, ae_int_t n, double t, ae_state *_state)
void _spline3dinterpolant_clear(void *_p)
void generatereflection(ae_vector *x, ae_int_t n, double *tau, ae_state *_state)
void spline2dresamplebilinear(ae_matrix *a, ae_int_t oldheight, ae_int_t oldwidth, ae_matrix *b, ae_int_t newheight, ae_int_t newwidth, ae_state *_state)
struct alglib_impl::ae_matrix ae_matrix
alglib_impl::spline1dinterpolant * p_struct
void spline3dlintransf(const spline3dinterpolant &c, const double a, const double b)
void rbfsetzeroterm(const rbfmodel &s)
void _spline1dfitreport_clear(void *_p)
double spline3dcalc(spline3dinterpolant *c, double x, double y, double z, ae_state *_state)
alglib_impl::spline3dinterpolant * p_struct
double ** pp_double
Definition: ap.h:455
void error(char *s)
Definition: tools.cpp:107
void _kdtree_destroy(void *_p)
void spline1dlintransy(spline1dinterpolant *c, double a, double b, ae_state *_state)
void ae_state_init(ae_state *state)
Definition: ap.cpp:309
double spline1dintegrate(spline1dinterpolant *c, double x, ae_state *_state)
double ae_sqrt(double x, ae_state *state)
Definition: ap.cpp:1535
void ae_assert(ae_bool cond, const char *msg, ae_state *state)
Definition: ap.cpp:1227
union alglib_impl::ae_vector::@11 ptr
void pspline3tangent(pspline3interpolant *p, double t, double *x, double *y, double *z, ae_state *_state)
ae_int_t rows() const
Definition: ap.cpp:6419
void rmatrixsolvels(const real_2d_array &a, const ae_int_t nrows, const ae_int_t ncols, const real_1d_array &b, const double threshold, ae_int_t &info, densesolverlsreport &rep, real_1d_array &x)
Definition: solvers.cpp:1119
void rbfsetpoints(const rbfmodel &s, const real_2d_array &xy, const ae_int_t n)
void rbfsetalgoqnn(rbfmodel *s, double q, double z, ae_state *_state)
double spline2dcalc(spline2dinterpolant *c, double x, double y, ae_state *_state)
void lsfitsetgradientcheck(lsfitstate *state, double teststep, ae_state *_state)
ae_bool _barycentricinterpolant_init(void *_p, ae_state *_state, ae_bool make_automatic)
void ae_serializer_alloc_start(ae_serializer *serializer)
Definition: ap.cpp:3404
const char *volatile error_msg
Definition: ap.h:389
void spline2dlintransf(const spline2dinterpolant &c, const double a, const double b)
void rbfcreate(ae_int_t nx, ae_int_t ny, rbfmodel *s, ae_state *_state)
void pspline2buildperiodic(ae_matrix *xy, ae_int_t n, ae_int_t st, ae_int_t pt, pspline2interpolant *p, ae_state *_state)
ae_bool _rbfreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void idwbuildmodifiedshepard(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const ae_int_t d, const ae_int_t nq, const ae_int_t nw, idwinterpolant &z)
void ivectorsetlengthatleast(ae_vector *x, ae_int_t n, ae_state *_state)
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)
#define ae_machineepsilon
Definition: ap.h:825
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)
void spline3dlintransxyz(spline3dinterpolant *c, double ax, double bx, double ay, double by, double az, double bz, ae_state *_state)
void rbfunserialize(std::string &s_in, rbfmodel &obj)
ae_bool _lsfitstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
_idwinterpolant_owner & operator=(const _idwinterpolant_owner &rhs)
void polynomialbuildcheb2(double a, double b, ae_vector *y, ae_int_t n, barycentricinterpolant *p, ae_state *_state)
double ae_exp(double x, ae_state *state)
Definition: ap.cpp:1689
spline3dinterpolant & operator=(const spline3dinterpolant &rhs)
void _lsfitstate_clear(void *_p)
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)
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)
barycentricfitreport & operator=(const barycentricfitreport &rhs)
alglib_impl::polynomialfitreport * c_ptr()
void pspline2buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline2interpolant &p)
void polynomialbuildeqdist(double a, double b, ae_vector *y, ae_int_t n, barycentricinterpolant *p, ae_state *_state)
void polynomialbar2pow(const barycentricinterpolant &p, const double c, const double s, real_1d_array &a)
spline2dinterpolant & operator=(const spline2dinterpolant &rhs)
void kdtreequeryresultsxy(const kdtree &kdt, real_2d_array &xy)
alglib_impl::idwinterpolant * c_ptr()
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)
double polynomialcalceqdist(double a, double b, ae_vector *f, ae_int_t n, double t, ae_state *_state)
ptrdiff_t ae_int_t
Definition: ap.h:186
void spline1ddiff(const spline1dinterpolant &c, const double x, double &s, double &ds, double &d2s)
doublereal * u
void spline2ddiff(const spline2dinterpolant &c, const double x, const double y, double &f, double &fx, double &fy, double &fxy)
void ae_v_subd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4533
ae_bool ae_vector_init(ae_vector *dst, ae_int_t size, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:580
void pspline3buildperiodic(const real_2d_array &xy, const ae_int_t n, const ae_int_t st, const ae_int_t pt, pspline3interpolant &p)
void spline2dcalcv(spline2dinterpolant *c, double x, double y, ae_vector *f, ae_state *_state)
_spline2dinterpolant_owner & operator=(const _spline2dinterpolant_owner &rhs)
ae_int_t ae_maxint(ae_int_t m1, ae_int_t m2, ae_state *state)
Definition: ap.cpp:1567
void rbfcalcbuf(const rbfmodel &s, const real_1d_array &x, real_1d_array &y)
ae_bool ae_isfinite(double x, ae_state *state)
Definition: ap.cpp:1495
double ae_sqr(double x, ae_state *state)
Definition: ap.cpp:1530
double rmatrixtrrcondinf(const real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit)
Definition: linalg.cpp:3258
#define INF
Definition: svm.cpp:43
void rbfserialize(ae_serializer *s, rbfmodel *model, ae_state *_state)
void solvecubicpolinom(double pa, double ma, double pb, double mb, double a, double b, double *x0, double *x1, double *x2, double *ex0, double *ex1, ae_int_t *nr, ae_int_t *ne, ae_vector *tempdata, ae_state *_state)
void(* obj)()
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)
constexpr int K
float r2
alglib_impl::lsfitstate * p_struct
ae_bool _pspline2interpolant_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
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)
void spline1dgriddiffcubic(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t boundltype, double boundl, ae_int_t boundrtype, double boundr, ae_vector *d, ae_state *_state)
void pspline2tangent(const pspline2interpolant &p, const double t, double &x, double &y)
void lsfitcreatefgh(ae_matrix *x, ae_vector *y, ae_vector *c, ae_int_t n, ae_int_t m, ae_int_t k, lsfitstate *state, ae_state *_state)
ae_int_t * p_int
Definition: ap.h:436
void rbfunserialize(ae_serializer *s, rbfmodel *model, ae_state *_state)
void idwbuildmodifiedshepardr(const real_2d_array &xy, const ae_int_t n, const ae_int_t nx, const double r, idwinterpolant &z)
void spline1dbuildcatmullrom(ae_vector *x, ae_vector *y, ae_int_t n, ae_int_t boundtype, double tension, spline1dinterpolant *c, ae_state *_state)
void polynomialbuild(ae_vector *x, ae_vector *y, ae_int_t n, barycentricinterpolant *p, ae_state *_state)
void solvepolinom2(double p0, double m0, double p1, double m1, double *x0, double *x1, ae_int_t *nr, ae_state *_state)
void tagsortfasti(ae_vector *a, ae_vector *b, ae_vector *bufa, ae_vector *bufb, ae_int_t n, ae_state *_state)
void pspline3build(ae_matrix *xy, ae_int_t n, ae_int_t st, ae_int_t pt, pspline3interpolant *p, ae_state *_state)
void rbfsetlinterm(rbfmodel *s, ae_state *_state)
void pspline2diff(pspline2interpolant *p, double t, double *x, double *dx, double *y, double *dy, ae_state *_state)
double spline3dcalc(const spline3dinterpolant &c, const double x, const double y, const double z)
ae_bool ae_vector_init_copy(ae_vector *dst, ae_vector *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:614
double barycentriccalc(barycentricinterpolant *b, double t, ae_state *_state)
void spline1dfitcubicwc(ae_vector *x, ae_vector *y, ae_vector *w, ae_int_t n, ae_vector *xc, ae_vector *yc, ae_vector *dc, ae_int_t k, ae_int_t m, ae_int_t *info, spline1dinterpolant *s, spline1dfitreport *rep, ae_state *_state)
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)
double rbfcalc3(rbfmodel *s, double x0, double x1, double x2, ae_state *_state)
void rbfsetconstterm(const rbfmodel &s)
_spline1dfitreport_owner & operator=(const _spline1dfitreport_owner &rhs)
ae_bool ae_fp_less_eq(double v1, double v2)
Definition: ap.cpp:1335
ae_int_t ae_round(double x, ae_state *state)
Definition: ap.cpp:1547
double idwcalc(const idwinterpolant &z, const real_1d_array &x)
alglib_impl::pspline2interpolant * p_struct
ae_bool _pspline3interpolant_init(void *_p, ae_state *_state, ae_bool make_automatic)
void spline2dunpack(const spline2dinterpolant &c, ae_int_t &m, ae_int_t &n, real_2d_array &tbl)
alglib_impl::ae_int_t ae_int_t
Definition: ap.h:889
double epsilon
alglib_impl::rbfreport * c_ptr()
void ae_frame_leave(ae_state *state)
Definition: ap.cpp:415
alglib_impl::rbfmodel * p_struct
void spline1dunpack(spline1dinterpolant *c, ae_int_t *n, ae_matrix *tbl, ae_state *_state)
void idwbuildmodifiedshepard(ae_matrix *xy, ae_int_t n, ae_int_t nx, ae_int_t d, ae_int_t nq, ae_int_t nw, idwinterpolant *z, ae_state *_state)
void ae_matrix_clear(ae_matrix *dst)
Definition: ap.cpp:891
#define ae_true
Definition: ap.h:195
ae_bool lsfititeration(lsfitstate *state, ae_state *_state)
void rbfunpack(rbfmodel *s, ae_int_t *nx, ae_int_t *ny, ae_matrix *xwr, ae_int_t *nc, ae_matrix *v, ae_state *_state)
int * n
void spline1dbuildlinear(ae_vector *x, ae_vector *y, ae_int_t n, spline1dinterpolant *c, ae_state *_state)
ae_int_t cols() const
Definition: ap.cpp:6426
void barycentricbuildxyw(const real_1d_array &x, const real_1d_array &y, const real_1d_array &w, const ae_int_t n, barycentricinterpolant &b)
ae_bool ae_fp_greater(double v1, double v2)
Definition: ap.cpp:1343
void spline2dcalcvbuf(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f)
void spline2dcalcvbuf(spline2dinterpolant *c, double x, double y, ae_vector *f, ae_state *_state)
alglib_impl::spline2dinterpolant * c_ptr()
ae_int_t cnt
Definition: ap.h:429
ae_bool ae_matrix_set_length(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_state *state)
Definition: ap.cpp:854
doublereal * a
void pspline3buildperiodic(ae_matrix *xy, ae_int_t n, ae_int_t st, ae_int_t pt, pspline3interpolant *p, ae_state *_state)
ae_bool _rbfreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
void lsfitsetstpmax(const lsfitstate &state, const double stpmax)
void lsfitsetscale(lsfitstate *state, ae_vector *s, ae_state *_state)
void spline2dbuildbicubicv(ae_vector *x, ae_int_t n, ae_vector *y, ae_int_t m, ae_vector *f, ae_int_t d, spline2dinterpolant *c, ae_state *_state)
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)
ae_bool _spline3dinterpolant_init(void *_p, ae_state *_state, ae_bool make_automatic)
double rbfcalc3(const rbfmodel &s, const double x0, const double x1, const double x2)
_polynomialfitreport_owner & operator=(const _polynomialfitreport_owner &rhs)
void pspline3tangent(const pspline3interpolant &p, const double t, double &x, double &y, double &z)
void pspline2build(ae_matrix *xy, ae_int_t n, ae_int_t st, ae_int_t pt, pspline2interpolant *p, ae_state *_state)
#define ae_minrealnumber
Definition: ap.h:827
void spline2dcalcv(const spline2dinterpolant &c, const double x, const double y, real_1d_array &f)
ae_int_t & iterationscount
alglib_impl::spline1dfitreport * p_struct
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)
void pspline2diff2(const pspline2interpolant &p, const double t, double &x, double &dx, double &d2x, double &y, double &dy, double &d2y)
ae_int_t ae_minint(ae_int_t m1, ae_int_t m2, ae_state *state)
Definition: ap.cpp:1572
void barycentricunpack(barycentricinterpolant *b, ae_int_t *n, ae_vector *x, ae_vector *y, ae_vector *w, ae_state *_state)
ae_bool _lsfitstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
void ae_free(void *p)
Definition: ap.cpp:237
void pspline2parametervalues(const pspline2interpolant &p, ae_int_t &n, real_1d_array &t)
void lsfitlinear(ae_vector *y, ae_matrix *fmatrix, ae_int_t n, ae_int_t m, ae_int_t *info, ae_vector *c, lsfitreport *rep, ae_state *_state)
void polynomialbuildcheb2(const double a, const double b, const real_1d_array &y, const ae_int_t n, barycentricinterpolant &p)
double * delta
real_2d_array h
ae_int_t & terminationtype
void barycentricdiff2(const barycentricinterpolant &b, const double t, double &f, double &df, double &d2f)
double ae_v_dotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n)
Definition: ap.cpp:4344
void rbfsetzeroterm(rbfmodel *s, ae_state *_state)
ae_bool _barycentricfitreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void rbfsetlinterm(const rbfmodel &s)
void lsfitresults(const lsfitstate &state, ae_int_t &info, real_1d_array &c, lsfitreport &rep)
void spline3dcalcvbuf(const spline3dinterpolant &c, const double x, const double y, const double z, real_1d_array &f)
#define xc