1 #include "stdafx.h"
2 #include <sstream>
3 #include <math.h>
4 
5 #include "alglibmisc.h"
6 #include "alglibinternal.h"
7 #include "linalg.h"
8 #include "statistics.h"
9 #include "dataanalysis.h"
10 #include "specialfunctions.h"
11 #include "solvers.h"
12 #include "optimization.h"
13 #include "diffequations.h"
14 #include "fasttransforms.h"
15 #include "integration.h"
16 #include "interpolation.h"
17 
18 #if AE_OS==AE_WINDOWS
19 #include <windows.h>
20 #elif AE_OS==AE_POSIX
21 #include <pthread.h>
22 #endif
23 
24 using namespace alglib;
25 
26 const char *fmt_str     = "%-29s %s\n";
27 const char *fmt_speedup = "%-25s %5.1fx\n";
28 
29 //
30 // Flag variables
31 //
32 bool issue505_passed = true;
33 bool issue478_passed = true;
34 bool issue528_passed = true;
35 bool issue591_passed = true;
36 bool issue594_passed = true;
37 bool issue764_passed = true;
38 bool issue813_passed = true;
39 bool issue824_passed = true;
40 
41 //
42 // Service datatypes
43 //
44 typedef struct
45 {
46     alglib_impl::ae_complex cval;
47     double rval;
48     alglib_impl::ae_int_t ival;
49     ae_bool bval;
50     alglib_impl::ae_vector i1val;
51 } innerrec;
52 
53 
54 typedef struct
55 {
56     ae_bool bval;
57     innerrec recval;
58     alglib_impl::ae_shared_pool pool;
59 } seedrec;
60 
_innerrec_init(void * _p,alglib_impl::ae_state * _state,ae_bool make_automatic)61 void _innerrec_init(void* _p, alglib_impl::ae_state *_state, ae_bool make_automatic)
62 {
63     innerrec *p = (innerrec*)_p;
64     alglib_impl::ae_touch_ptr((void*)p);
65     alglib_impl::ae_vector_init(&p->i1val, 0, alglib_impl::DT_INT, _state, make_automatic);
66 }
67 
68 
_innerrec_init_copy(void * _dst,void * _src,alglib_impl::ae_state * _state,ae_bool make_automatic)69 void _innerrec_init_copy(void* _dst, void* _src, alglib_impl::ae_state *_state, ae_bool make_automatic)
70 {
71     innerrec *dst = (innerrec*)_dst;
72     innerrec *src = (innerrec*)_src;
73     dst->cval = src->cval;
74     dst->rval = src->rval;
75     dst->ival = src->ival;
76     dst->bval = src->bval;
77     alglib_impl::ae_vector_init_copy(&dst->i1val, &src->i1val, _state, make_automatic);
78 }
79 
80 
_innerrec_clear(void * _p)81 void _innerrec_clear(void* _p)
82 {
83     innerrec *p = (innerrec*)_p;
84     alglib_impl::ae_touch_ptr((void*)p);
85     alglib_impl::ae_vector_clear(&p->i1val);
86 }
87 
88 
_innerrec_destroy(void * _p)89 void _innerrec_destroy(void* _p)
90 {
91     innerrec *p = (innerrec*)_p;
92     alglib_impl::ae_touch_ptr((void*)p);
93     alglib_impl::ae_vector_destroy(&p->i1val);
94 }
95 
96 
_seedrec_init(void * _p,alglib_impl::ae_state * _state,ae_bool make_automatic)97 void _seedrec_init(void* _p, alglib_impl::ae_state *_state, ae_bool make_automatic)
98 {
99     seedrec *p = (seedrec*)_p;
100     alglib_impl::ae_touch_ptr((void*)p);
101     _innerrec_init(&p->recval, _state, make_automatic);
102     alglib_impl::ae_shared_pool_init(&p->pool, _state, make_automatic);
103 }
104 
105 
_seedrec_init_copy(void * _dst,void * _src,alglib_impl::ae_state * _state,ae_bool make_automatic)106 void _seedrec_init_copy(void* _dst, void* _src, alglib_impl::ae_state *_state, ae_bool make_automatic)
107 {
108     seedrec *dst = (seedrec*)_dst;
109     seedrec *src = (seedrec*)_src;
110     dst->bval = src->bval;
111     _innerrec_init_copy(&dst->recval, &src->recval, _state, make_automatic);
112     alglib_impl::ae_shared_pool_init_copy(&dst->pool, &src->pool, _state, make_automatic);
113 }
114 
115 
_seedrec_clear(void * _p)116 void _seedrec_clear(void* _p)
117 {
118     seedrec *p = (seedrec*)_p;
119     alglib_impl::ae_touch_ptr((void*)p);
120     _innerrec_clear(&p->recval);
121     alglib_impl::ae_shared_pool_clear(&p->pool);
122 }
123 
124 
_seedrec_destroy(void * _p)125 void _seedrec_destroy(void* _p)
126 {
127     seedrec *p = (seedrec*)_p;
128     alglib_impl::ae_touch_ptr((void*)p);
129     _innerrec_destroy(&p->recval);
130     alglib_impl::ae_shared_pool_destroy(&p->pool);
131 }
132 
func505_grad(const real_1d_array & x,double & func,real_1d_array & grad,void * ptr)133 void func505_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr)
134 {
135     double x0 = *((double*)ptr);
136 
137     //
138     // This block assigns zero vector to gradient. Because gradient is a proxy vector
139     // (vector which uses another object as storage), sizes of gradient and vector being
140     // assigned must be equal. In this case data are copied in the memory linked with
141     // proxy.
142     //
143     // Early versions of ALGLIB failed to handle such assignment (it discrupted link
144     // between proxy vector and actual gradient stored in the internals of ALGLIB).
145     //
146     real_1d_array z = "[0]";
147     grad = "[0]";
148     grad = z;
149 
150     //
151     // This block tries to perform operations which are forbidden for proxy vector:
152     // * assign vector of non-matching size
153     // * change length of the vector
154     // Correct implementation must throw an exception without breaking a link between
155     // proxy object and actual vector.
156     //
157     z = "[0,1]";
158     try
159     {
160         grad = "[0,1]";
161         issue505_passed = false;
162     }
163     catch(...) {}
164     try
165     {
166         grad = z;
167         issue505_passed = false;
168     }
169     catch(...) {}
170     try
171     {
172         grad.setlength(10);
173         issue505_passed = false;
174     }
175     catch(...) {}
176     try
177     {
178         grad.setlength(1);
179         issue505_passed = false;
180     }
181     catch(...) {}
182 
183     //
184     // This block actually calculates function/gradient
185     //
186     func = pow(x[0]-x0,4);
187     grad[0] = 4*pow(x[0]-x0,3);
188 }
189 
func505_vec(const real_1d_array & x,real_1d_array & fi,void * ptr)190 void  func505_vec(const real_1d_array &x, real_1d_array &fi, void *ptr)
191 {
192     double x0 = *((double*)ptr);
193     fi[0] = x[0]-x0;
194     fi[1] = pow(x[0]-x0,2);
195 }
196 
func505_jac(const real_1d_array & x,real_1d_array & fi,real_2d_array & jac,void * ptr)197 void  func505_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
198 {
199     double x0 = *((double*)ptr);
200 
201     //
202     // This block assigns zero matrix to Jacobian. Because Jacobian is a proxy matrix
203     // (matrix which uses another object as storage), sizes of Jacobian and matrix being
204     // assigned must be equal. In this case data are copied in the memory linked with
205     // proxy.
206     //
207     // Early versions of ALGLIB failed to handle such assignment (it discrupted link
208     // between proxy and actual matrix stored in the internals of ALGLIB).
209     //
210     real_2d_array z = "[[0],[0]]";
211     jac = "[[0],[0]]";
212     jac = z;
213 
214     //
215     // This block tries to perform operations which are forbidden for proxy vector:
216     // * assign vector of non-matching size
217     // * change length of the vector
218     // Correct implementation must throw an exception without breaking a link between
219     // proxy object and actual vector.
220     //
221     try
222     {
223         jac = "[[0]]";
224         issue505_passed = false;
225     }
226     catch(...) {}
227     try
228     {
229         jac = "[[0,0],[1,1]]";
230         issue505_passed = false;
231     }
232     catch(...) {}
233     try
234     {
235         z = "[[0,1]]";
236         jac = z;
237         issue505_passed = false;
238     }
239     catch(...) {}
240     try
241     {
242         jac.setlength(10,6);
243         issue505_passed = false;
244     }
245     catch(...) {}
246     try
247     {
248         jac.setlength(2,1);
249         issue505_passed = false;
250     }
251     catch(...) {}
252 
253     //
254     // This block actually calculates function/gradient
255     //
256     fi[0] = x[0]-x0;
257     fi[1] = pow(x[0]-x0,2);
258     jac[0][0] = 1.0;
259     jac[1][0] = 2*(x[0]-x0);
260 }
261 
issue813_callback(const alglib::real_1d_array &,alglib::real_1d_array &,void *)262 void issue813_callback(const alglib::real_1d_array&, alglib::real_1d_array&, void*)
263 {
264     throw 0;
265 }
266 
issue824_callback_i(const alglib::real_1d_array &,double &,void *)267 void issue824_callback_i(const alglib::real_1d_array&, double&, void*)
268 {
269     throw (int*)(NULL);
270 }
271 
issue824_callback_d(const alglib::real_1d_array &,double &,void *)272 void issue824_callback_d(const alglib::real_1d_array&, double&, void*)
273 {
274     throw (double*)(NULL);
275 }
276 
file_put_contents(const char * filename,const char * contents)277 void file_put_contents(const char *filename, const char *contents)
278 {
279     FILE *f = fopen(filename, "wb");
280     if( f==NULL )
281         throw alglib::ap_error("file_put_contents: failed opening file");
282     if( fwrite((void*)contents, 1, strlen(contents), f)!=strlen(contents) )
283         throw alglib::ap_error("file_put_contents: failed writing to file");
284     fclose(f);
285 }
286 
287 #if AE_OS==AE_WINDOWS
288 struct async_rbf_record
289 {
290     alglib::rbfmodel  *p_model;
291     alglib::rbfreport *p_report;
292     bool thread_finished;
293 };
async_build_rbf_model(LPVOID T)294 DWORD WINAPI async_build_rbf_model(LPVOID T)
295 {
296     async_rbf_record *p = (async_rbf_record*)T;
297     alglib::rbfbuildmodel(*(p->p_model), *(p->p_report));
298     p->thread_finished = true;
299     return 0;
300 }
301 #elif AE_OS==AE_POSIX
302 struct async_rbf_record
303 {
304     alglib::rbfmodel  *p_model;
305     alglib::rbfreport *p_report;
306     bool thread_finished;
307 };
async_build_rbf_model(void * T)308 void* async_build_rbf_model(void *T)
309 {
310     async_rbf_record *p = (async_rbf_record*)T;
311     alglib::rbfbuildmodel(*(p->p_model), *(p->p_report));
312     p->thread_finished = true;
313     return NULL;
314 }
315 #endif
316 
main()317 int main()
318 {
319     //
320     // Report system properties
321     //
322     printf("System:\n");
323 #ifdef AE_HPC
324     printf("* cores count                %3ld\n", (long)alglib_impl::ae_cores_count());
325 #else
326     printf("* cores count                %3ld\n", (long)1);
327 #endif
328 
329     //
330     // Check status of allocation counter
331     //
332 #ifdef AE_USE_ALLOC_COUNTER
333     printf("Allocation counter activated...\n");
334     alglib_impl::_use_alloc_counter = ae_true;
335     if( alglib_impl::_alloc_counter!=0 )
336     {
337         printf("FAILURE: alloc_counter is non-zero on start!\n");
338         return 1;
339     }
340     {
341         alglib::real_1d_array x;
342         x.setlength(1);
343         if( alglib_impl::_alloc_counter==0 )
344             printf(":::: WARNING: ALLOC_COUNTER IS INACTIVE!!! ::::: \n");
345     }
346     if( alglib_impl::_alloc_counter!=0 )
347     {
348         printf("FAILURE: alloc_counter does not decrease!\n");
349         return 1;
350     }
351 #else
352     printf("No alloc counter.\nSome tests are skipped.\n");
353 #endif
354 
355     //
356     // Testing basic functionality
357     //
358     printf("Basic functions:\n");
359     {
360         //
361         // Testing 1D array functionality
362         //
363         bool passed = true;
364         try
365         {
366             //
367             // 1D boolean
368             //
369             // Default constructor, string constructor, copy constructor, assignment constructors:
370             // * test that array sizes as reported by length match to what was specified
371             // * test item-by-item access
372             // * test to_string()
373             // * test that modification of the copied array does not change original
374             // * test that setlength() changes length
375             // * test setcontent/getcontent
376             // * test getcontent(), operator() and operator[] on constant arrays
377             //   (in this case distinct implementation is used which must be tested separately)
378             //
379             alglib::boolean_1d_array arr_0, arr_1("[]"), arr_2("[true,false,true]"), arr_3(arr_2), arr_4, arr_5;
380             arr_4 = arr_2;
381             arr_5 = "[true,true,false]";
382             passed = passed && (arr_0.length()==0);
383             passed = passed && (arr_1.length()==0);
384             passed = passed && (arr_2.length()==3);
385             passed = passed && (arr_3.length()==3);
386             passed = passed && (arr_2[0]==arr_2(0)) && (arr_2[1]==arr_2(1)) && (arr_2[2]==arr_2(2));
387             passed = passed &&  arr_2[0] && !arr_2[1] &&  arr_2[2];
388             passed = passed &&  arr_3[0] && !arr_3[1] &&  arr_3[2];
389             passed = passed &&  arr_4[0] && !arr_4[1] &&  arr_4[2];
390             passed = passed &&  arr_5[0] &&  arr_5[1] && !arr_5[2];
391             passed = passed && (arr_2.tostring()=="[true,false,true]");
392             passed = passed && (arr_3.tostring()=="[true,false,true]");
393             passed = passed && (arr_4.tostring()=="[true,false,true]");
394             passed = passed && (arr_5.tostring()=="[true,true,false]");
395             arr_2[0] = false;
396             passed = passed && !arr_2[0] && arr_3[0] && arr_4[0];
397             arr_5.setlength(99);
398             passed = passed && (arr_5.length()==99);
399 
400             // setcontent/getcontent
401             bool a0[] = {true, false, true, false, false};
402             bool a0_mod  = false;
403             bool a0_orig = true;
404             bool *p6;
405             alglib::boolean_1d_array arr_6;
406             arr_6.setcontent(5, a0);
407             passed = passed && (arr_6[0]==a0[0]) && (arr_6[1]==a0[1]) && (arr_6[2]==a0[2]) && (arr_6[3]==a0[3]) && (arr_6[4]==a0[4]);
408             p6 = arr_6.getcontent();
409             passed = passed && (p6!=a0);
410             passed = passed && (p6[0]==a0[0]) && (p6[1]==a0[1]) && (p6[2]==a0[2]) && (p6[3]==a0[3]) && (p6[4]==a0[4]);
411             a0[0] = a0_mod;
412             passed = passed && (arr_6[0]!=a0[0]);
413             a0[0] = a0_orig;
414 
415             // operations on constant arrays
416             {
417                 const alglib::boolean_1d_array &ac = arr_6;
418                 passed = passed && (ac[0]==a0[0]) && (ac[1]==a0[1]) && (ac[2]==a0[2]) && (ac[3]==a0[3]) && (ac[4]==a0[4]);
419                 passed = passed && (ac(0)==a0[0]) && (ac(1)==a0[1]) && (ac(2)==a0[2]) && (ac(3)==a0[3]) && (ac(4)==a0[4]);
420                 const bool *p = ac.getcontent();
421                 passed = passed && (p[0]==a0[0]) && (p[1]==a0[1]) && (p[2]==a0[2]) && (p[3]==a0[3]) && (p[4]==a0[4]);
422             }
423 
424             //
425             // Operations with proxy arrays:
426             // * changes in target are propagated to proxy and vice versa
427             // * assignments where proxy is source create new independent copy
428             // * assignments to proxy are checked (their size must match to that of the target)
429             // * incorrect assignments or attempts to change length must generate exception
430             // * attempts to call setlength() must fail even when new size match original size
431             //   of the array
432             //
433             alglib::boolean_1d_array targt, acopy;
434             targt = "[true,false,false,true]";
435             alglib::boolean_1d_array proxy(targt.c_ptr());
436             acopy = proxy;
437             passed = passed &&  targt[0] && !targt[1] && !targt[2] &&  targt[3];
438             passed = passed &&  proxy[0] && !proxy[1] && !proxy[2] &&  proxy[3];
439             passed = passed &&  acopy[0] && !acopy[1] && !acopy[2] &&  acopy[3];
440 
441             targt[0] = false;
442             passed = passed && !targt[0] && !proxy[0] && acopy[0];
443             proxy[0] = true;
444             passed = passed &&  targt[0] &&  proxy[0] && acopy[0];
445 
446             acopy = "[false,true,true,true]";
447             proxy = acopy;
448             passed = passed && !targt[0] &&  targt[1] &&  targt[2] &&  targt[3];
449             passed = passed && !proxy[0] &&  proxy[1] &&  proxy[2] &&  proxy[3];
450             proxy = "[true,false,true,true]";
451             passed = passed &&  targt[0] && !targt[1] &&  targt[2] &&  targt[3];
452             passed = passed &&  proxy[0] && !proxy[1] &&  proxy[2] &&  proxy[3];
453 
454             try
455             {
456                 acopy = "[false,true,true]";
457                 proxy = acopy;
458                 passed = false;
459             }
460             catch(alglib::ap_error e)
461             { }
462             catch(...)
463             { passed = false; }
464 
465             try
466             {
467                 proxy = "[true,true,true]";
468                 passed = false;
469             }
470             catch(alglib::ap_error e)
471             { }
472             catch(...)
473             { passed = false; }
474 
475             try
476             {
477                 proxy.setlength(100);
478                 passed = false;
479             }
480             catch(alglib::ap_error e)
481             { }
482             catch(...)
483             { passed = false; }
484 
485             try
486             {
487                 proxy.setlength(proxy.length());
488                 passed = false;
489             }
490             catch(alglib::ap_error e)
491             { }
492             catch(...)
493             { passed = false; }
494         }
495         catch(...)
496         { passed = false; }
497         try
498         {
499             //
500             // 1D integer
501             //
502             // Default constructor, string constructor, copy constructor, assignment constructors:
503             // * test that array sizes as reported by length match to what was specified
504             // * test item-by-item access
505             // * test to_string()
506             // * test that modification of the copied array does not change original
507             // * test that setlength() changes length
508             //
509             const char *s1 = "[2,3,-1]";
510             const char *s2 = "[5,4,3]";
511             const char *s3 = "[6,7,3,-4]";
512             const char *s4 = "[9,5,-12,-0]";
513             const char *s5 = "[1,7,2,1]";
514             const char *s6 = "[7,7,7]";
515             int v10 =  2, v11 =  3, v12 = -1, v10_mod = 9;
516             int v20 =  5, v21 =  4, v22 =  3;
517             int v30 =  6, v31 =  7, v32 =  3, v33 = -4, v30_mod = -6;
518             int v40 =  9, v41 =  5, v42 =-12, v43 = 0;
519             int v50 =  1, v51 =  7, v52 =  2, v53 = 1;
520 
521             alglib::integer_1d_array arr_0, arr_1("[]"), arr_2(s1), arr_3(arr_2), arr_4, arr_5;
522             arr_4 = arr_2;
523             arr_5 = s2;
524             passed = passed && (arr_0.length()==0);
525             passed = passed && (arr_1.length()==0);
526             passed = passed && (arr_2.length()==3);
527             passed = passed && (arr_3.length()==3);
528             passed = passed && (arr_2[0]==arr_2(0)) && (arr_2[1]==arr_2(1)) && (arr_2[2]==arr_2(2));
529             passed = passed && (arr_2[0]==v10) && (arr_2[1]==v11) && (arr_2[2]==v12);
530             passed = passed && (arr_3[0]==v10) && (arr_3[1]==v11) && (arr_3[2]==v12);
531             passed = passed && (arr_4[0]==v10) && (arr_4[1]==v11) && (arr_4[2]==v12);
532             passed = passed && (arr_5[0]==v20) && (arr_5[1]==v21) && (arr_5[2]==v22);
533             passed = passed && (arr_2.tostring()==s1);
534             passed = passed && (arr_3.tostring()==s1);
535             passed = passed && (arr_4.tostring()==s1);
536             passed = passed && (arr_5.tostring()==s2);
537             arr_2[0] = v10_mod;
538             passed = passed && (arr_2[0]==v10_mod) && (arr_3[0]==v10) && (arr_4[0]==v10);
539             arr_5.setlength(99);
540             passed = passed && (arr_5.length()==99);
541 
542             // setcontent/getcontent
543             alglib::ae_int_t a0[] =   {2, 3, 1, 9, 2};
544             alglib::ae_int_t a0_mod  = 7;
545             alglib::ae_int_t a0_orig = 2;
546             alglib::ae_int_t *p6;
547             alglib::integer_1d_array arr_6;
548             arr_6.setcontent(5, a0);
549             passed = passed && (arr_6[0]==a0[0]) && (arr_6[1]==a0[1]) && (arr_6[2]==a0[2]) && (arr_6[3]==a0[3]) && (arr_6[4]==a0[4]);
550             p6 = arr_6.getcontent();
551             passed = passed && (p6!=a0);
552             passed = passed && (p6[0]==a0[0]) && (p6[1]==a0[1]) && (p6[2]==a0[2]) && (p6[3]==a0[3]) && (p6[4]==a0[4]);
553             a0[0] = a0_mod;
554             passed = passed && (arr_6[0]!=a0[0]);
555             a0[0] = a0_orig;
556 
557             // operations on constant arrays
558             {
559                 const alglib::integer_1d_array &ac = arr_6;
560                 passed = passed && (ac[0]==a0[0]) && (ac[1]==a0[1]) && (ac[2]==a0[2]) && (ac[3]==a0[3]) && (ac[4]==a0[4]);
561                 passed = passed && (ac(0)==a0[0]) && (ac(1)==a0[1]) && (ac(2)==a0[2]) && (ac(3)==a0[3]) && (ac(4)==a0[4]);
562                 const alglib::ae_int_t *p = ac.getcontent();
563                 passed = passed && (p[0]==a0[0]) && (p[1]==a0[1]) && (p[2]==a0[2]) && (p[3]==a0[3]) && (p[4]==a0[4]);
564             }
565 
566             //
567             // Operations with proxy arrays:
568             // * changes in target are propagated to proxy and vice versa
569             // * assignments where proxy is source create new independent copy
570             // * assignments to proxy are checked (their size must match to that of the target)
571             // * incorrect assignments or attempts to change length must generate exception
572             // * attempts to call setlength() must fail even when new size match original size
573             //   of the array
574             //
575             alglib::integer_1d_array targt, acopy;
576             targt = s3;
577             alglib::integer_1d_array proxy(targt.c_ptr());
578             acopy = proxy;
579             passed = passed && (targt[0]==v30) && (targt[1]==v31) && (targt[2]==v32) && (targt[3]==v33);
580             passed = passed && (proxy[0]==v30) && (proxy[1]==v31) && (proxy[2]==v32) && (proxy[3]==v33);
581             passed = passed && (acopy[0]==v30) && (acopy[1]==v31) && (acopy[2]==v32) && (acopy[3]==v33);
582 
583             targt[0] = v30_mod;
584             passed = passed && (targt[0]==v30_mod) && (proxy[0]==v30_mod) && (acopy[0]==v30);
585             proxy[0] = v30;
586             passed = passed && (targt[0]==v30)     && (proxy[0]==v30)     && (acopy[0]==v30);
587 
588             acopy = s4;
589             proxy = acopy;
590             passed = passed && (targt[0]==v40) && (targt[1]==v41) && (targt[2]==v42) && (targt[3]==v43);
591             passed = passed && (proxy[0]==v40) && (proxy[1]==v41) && (proxy[2]==v42) && (proxy[3]==v43);
592             proxy = s5;
593             passed = passed && (targt[0]==v50) && (targt[1]==v51) && (targt[2]==v52) && (targt[3]==v53);
594             passed = passed && (proxy[0]==v50) && (proxy[1]==v51) && (proxy[2]==v52) && (proxy[3]==v53);
595 
596             try
597             {
598                 acopy = s6;
599                 proxy = acopy;
600                 passed = false;
601             }
602             catch(alglib::ap_error e)
603             { }
604             catch(...)
605             { passed = false; }
606 
607             try
608             {
609                 proxy = s6;
610                 passed = false;
611             }
612             catch(alglib::ap_error e)
613             { }
614             catch(...)
615             { passed = false; }
616 
617             try
618             {
619                 proxy.setlength(100);
620                 passed = false;
621             }
622             catch(alglib::ap_error e)
623             { }
624             catch(...)
625             { passed = false; }
626 
627             try
628             {
629                 proxy.setlength(proxy.length());
630                 passed = false;
631             }
632             catch(alglib::ap_error e)
633             { }
634             catch(...)
635             { passed = false; }
636         }
637         catch(...)
638         { passed = false; }
639         try
640         {
641             //
642             // 1D real
643             //
644             // Default constructor, string constructor, copy constructor, assignment constructors:
645             // * test that array sizes as reported by length match to what was specified
646             // * test item-by-item access
647             // * test to_string()
648             // * test that modification of the copied array does not change original
649             // * test that setlength() changes length
650             //
651             const char *s1     = "[2,3.5,-2.5E-1]";
652             const char *s1_fmt = "[2.00,3.50,-0.25]";
653             const char *s2     = "[5,4,3.126]";
654             const char *s2_fmt = "[5.00,4.00,3.13]";
655             const char *s3 = "[6,7,3,-4E2]";
656             const char *s4 = "[9,5,-12,-0.01]";
657             const char *s5 = "[1,7,2,1]";
658             const char *s6 = "[7,7,7]";
659             const int dps = 2;
660             const double v10 =  2, v11 =  3.5, v12 = -0.25, v10_mod = 9;
661             const double v20 =  5, v21 =  4, v22 =  3.126;
662             const double v30 =  6, v31 =  7, v32 =  3, v33 = -400, v30_mod = -6;
663             const double v40 =  9, v41 =  5, v42 =-12, v43 = -0.01;
664             const double v50 =  1, v51 =  7, v52 =  2, v53 = 1;
665 
666             alglib::real_1d_array arr_0, arr_1("[]"), arr_2(s1), arr_3(arr_2), arr_4, arr_5;
667             arr_4 = arr_2;
668             arr_5 = s2;
669             passed = passed && (arr_0.length()==0);
670             passed = passed && (arr_1.length()==0);
671             passed = passed && (arr_2.length()==3);
672             passed = passed && (arr_3.length()==3);
673             passed = passed && (arr_2[0]==arr_2(0)) && (arr_2[1]==arr_2(1)) && (arr_2[2]==arr_2(2));
674             passed = passed && (arr_2[0]==v10) && (arr_2[1]==v11) && (arr_2[2]==v12);
675             passed = passed && (arr_3[0]==v10) && (arr_3[1]==v11) && (arr_3[2]==v12);
676             passed = passed && (arr_4[0]==v10) && (arr_4[1]==v11) && (arr_4[2]==v12);
677             passed = passed && (arr_5[0]==v20) && (arr_5[1]==v21) && (arr_5[2]==v22);
678             passed = passed && (arr_2.tostring(dps)==s1_fmt);
679             passed = passed && (arr_3.tostring(dps)==s1_fmt);
680             passed = passed && (arr_4.tostring(dps)==s1_fmt);
681             passed = passed && (arr_5.tostring(dps)==s2_fmt);
682             arr_2[0] = v10_mod;
683             passed = passed && (arr_2[0]==v10_mod) && (arr_3[0]==v10) && (arr_4[0]==v10);
684             arr_5.setlength(99);
685             passed = passed && (arr_5.length()==99);
686 
687             // setcontent/getcontent
688             double a0[] =   {2, 3.5, 1, 9.125, 2};
689             double a0_mod  = 7;
690             double a0_orig = 2;
691             double *p6;
692             alglib::real_1d_array arr_6;
693             arr_6.setcontent(5, a0);
694             passed = passed && (arr_6[0]==a0[0]) && (arr_6[1]==a0[1]) && (arr_6[2]==a0[2]) && (arr_6[3]==a0[3]) && (arr_6[4]==a0[4]);
695             p6 = arr_6.getcontent();
696             passed = passed && (p6!=a0);
697             passed = passed && (p6[0]==a0[0]) && (p6[1]==a0[1]) && (p6[2]==a0[2]) && (p6[3]==a0[3]) && (p6[4]==a0[4]);
698             a0[0] = a0_mod;
699             passed = passed && (arr_6[0]!=a0[0]);
700             a0[0] = a0_orig;
701 
702             // operations on constant arrays
703             {
704                 const alglib::real_1d_array &ac = arr_6;
705                 passed = passed && (ac[0]==a0[0]) && (ac[1]==a0[1]) && (ac[2]==a0[2]) && (ac[3]==a0[3]) && (ac[4]==a0[4]);
706                 passed = passed && (ac(0)==a0[0]) && (ac(1)==a0[1]) && (ac(2)==a0[2]) && (ac(3)==a0[3]) && (ac(4)==a0[4]);
707                 const double *p = ac.getcontent();
708                 passed = passed && (p[0]==a0[0]) && (p[1]==a0[1]) && (p[2]==a0[2]) && (p[3]==a0[3]) && (p[4]==a0[4]);
709             }
710 
711             //
712             // Operations with proxy arrays attached via attach_to(ae_vector*):
713             // * changes in target are propagated to proxy and vice versa
714             // * assignments where proxy is source create new independent copy
715             // * assignments to proxy are checked (their size must match to that of the target)
716             // * incorrect assignments or attempts to change length must generate exception
717             // * attempts to call setlength() must fail even when new size match original size
718             //   of the array
719             //
720             {
721                 alglib::real_1d_array targt, acopy;
722                 targt = s3;
723                 alglib::real_1d_array proxy(targt.c_ptr());
724                 acopy = proxy;
725                 passed = passed && (targt[0]==v30) && (targt[1]==v31) && (targt[2]==v32) && (targt[3]==v33);
726                 passed = passed && (proxy[0]==v30) && (proxy[1]==v31) && (proxy[2]==v32) && (proxy[3]==v33);
727                 passed = passed && (acopy[0]==v30) && (acopy[1]==v31) && (acopy[2]==v32) && (acopy[3]==v33);
728 
729                 targt[0] = v30_mod;
730                 passed = passed && (targt[0]==v30_mod) && (proxy[0]==v30_mod) && (acopy[0]==v30);
731                 proxy[0] = v30;
732                 passed = passed && (targt[0]==v30)     && (proxy[0]==v30)     && (acopy[0]==v30);
733 
734                 acopy = s4;
735                 proxy = acopy;
736                 passed = passed && (targt[0]==v40) && (targt[1]==v41) && (targt[2]==v42) && (targt[3]==v43);
737                 passed = passed && (proxy[0]==v40) && (proxy[1]==v41) && (proxy[2]==v42) && (proxy[3]==v43);
738                 proxy = s5;
739                 passed = passed && (targt[0]==v50) && (targt[1]==v51) && (targt[2]==v52) && (targt[3]==v53);
740                 passed = passed && (proxy[0]==v50) && (proxy[1]==v51) && (proxy[2]==v52) && (proxy[3]==v53);
741 
742                 try
743                 {
744                     acopy = s6;
745                     proxy = acopy;
746                     passed = false;
747                 }
748                 catch(alglib::ap_error e)
749                 { }
750                 catch(...)
751                 { passed = false; }
752 
753                 try
754                 {
755                     proxy = s6;
756                     passed = false;
757                 }
758                 catch(alglib::ap_error e)
759                 { }
760                 catch(...)
761                 { passed = false; }
762 
763                 try
764                 {
765                     proxy.setlength(100);
766                     passed = false;
767                 }
768                 catch(alglib::ap_error e)
769                 { }
770                 catch(...)
771                 { passed = false; }
772 
773                 try
774                 {
775                     proxy.setlength(proxy.length());
776                     passed = false;
777                 }
778                 catch(alglib::ap_error e)
779                 { }
780                 catch(...)
781                 { passed = false; }
782             }
783 
784             //
785             // >>> Unique for real_1d_array >>>
786             //
787             // Operations with proxy arrays attached via attach_to(double*):
788             // * changes in target are propagated to proxy and vice versa
789             // * assignments where proxy is source create new independent copy
790             // * assignments to proxy are checked (their size must match to that of the target)
791             // * incorrect assignments or attempts to change length must generate exception
792             // * attempts to call setlength() must fail even when new size match original size
793             //   of the array
794             //
795             {
796                 alglib::real_1d_array proxy, acopy;
797                 double targt[] = {v30, v31, v32, v33};
798                 proxy.attach_to_ptr(4, targt);
799                 acopy = proxy;
800                 passed = passed && (targt[0]==v30) && (targt[1]==v31) && (targt[2]==v32) && (targt[3]==v33);
801                 passed = passed && (proxy[0]==v30) && (proxy[1]==v31) && (proxy[2]==v32) && (proxy[3]==v33);
802                 passed = passed && (acopy[0]==v30) && (acopy[1]==v31) && (acopy[2]==v32) && (acopy[3]==v33);
803 
804                 targt[0] = v30_mod;
805                 passed = passed && (targt[0]==v30_mod) && (proxy[0]==v30_mod) && (acopy[0]==v30);
806                 proxy[0] = v30;
807                 passed = passed && (targt[0]==v30)     && (proxy[0]==v30)     && (acopy[0]==v30);
808 
809                 acopy = s4;
810                 proxy = acopy;
811                 passed = passed && (targt[0]==v40) && (targt[1]==v41) && (targt[2]==v42) && (targt[3]==v43);
812                 passed = passed && (proxy[0]==v40) && (proxy[1]==v41) && (proxy[2]==v42) && (proxy[3]==v43);
813                 proxy = s5;
814                 passed = passed && (targt[0]==v50) && (targt[1]==v51) && (targt[2]==v52) && (targt[3]==v53);
815                 passed = passed && (proxy[0]==v50) && (proxy[1]==v51) && (proxy[2]==v52) && (proxy[3]==v53);
816 
817                 try
818                 {
819                     acopy = s6;
820                     proxy = acopy;
821                     passed = false;
822                 }
823                 catch(alglib::ap_error e)
824                 { }
825                 catch(...)
826                 { passed = false; }
827 
828                 try
829                 {
830                     proxy = s6;
831                     passed = false;
832                 }
833                 catch(alglib::ap_error e)
834                 { }
835                 catch(...)
836                 { passed = false; }
837 
838                 try
839                 {
840                     proxy.setlength(100);
841                     passed = false;
842                 }
843                 catch(alglib::ap_error e)
844                 { }
845                 catch(...)
846                 { passed = false; }
847 
848                 try
849                 {
850                     proxy.setlength(proxy.length());
851                     passed = false;
852                 }
853                 catch(alglib::ap_error e)
854                 { }
855                 catch(...)
856                 { passed = false; }
857             }
858         }
859         catch(...)
860         { passed = false; }
861         try
862         {
863             //
864             // 1D complex
865             //
866             // Default constructor, string constructor, copy constructor, assignment constructors:
867             // * test that array sizes as reported by length match to what was specified
868             // * test item-by-item access
869             // * test to_string()
870             // * test that modification of the copied array does not change original
871             // * test that setlength() changes length
872             //
873             const char *s1     = "[2,3.5i,1-2.5E-1i]";
874             const char *s1_fmt = "[2.00,3.50i,1.00-0.25i]";
875             const char *s2     = "[5,-4+1i,3.126]";
876             const char *s2_fmt = "[5.00,-4.00+1.00i,3.13]";
877             const char *s3 = "[6,7,3,-4E2]";
878             const char *s4 = "[9,5,-12,-0.01]";
879             const char *s5 = "[1,7,2,1]";
880             const char *s6 = "[7,7,7]";
881             const int dps = 2;
882             alglib::complex v10 =  2, v11 = alglib::complex(0,3.5), v12 = alglib::complex(1,-0.25), v10_mod = 9;
883             alglib::complex v20 =  5, v21 = alglib::complex(-4,1),  v22 =  3.126;
884             alglib::complex v30 =  6, v31 =  7, v32 =  3, v33 = -400, v30_mod = -6;
885             alglib::complex v40 =  9, v41 =  5, v42 =-12, v43 = -0.01;
886             alglib::complex v50 =  1, v51 =  7, v52 =  2, v53 = 1;
887 
888             alglib::complex_1d_array arr_0, arr_1("[]"), arr_2(s1), arr_3(arr_2), arr_4, arr_5;
889             arr_4 = arr_2;
890             arr_5 = s2;
891             passed = passed && (arr_0.length()==0);
892             passed = passed && (arr_1.length()==0);
893             passed = passed && (arr_2.length()==3);
894             passed = passed && (arr_3.length()==3);
895             passed = passed && (arr_2[0]==arr_2(0)) && (arr_2[1]==arr_2(1)) && (arr_2[2]==arr_2(2));
896             passed = passed && (arr_2[0]==v10) && (arr_2[1]==v11) && (arr_2[2]==v12);
897             passed = passed && (arr_3[0]==v10) && (arr_3[1]==v11) && (arr_3[2]==v12);
898             passed = passed && (arr_4[0]==v10) && (arr_4[1]==v11) && (arr_4[2]==v12);
899             passed = passed && (arr_5[0]==v20) && (arr_5[1]==v21) && (arr_5[2]==v22);
900             passed = passed && (arr_2.tostring(dps)==s1_fmt);
901             passed = passed && (arr_3.tostring(dps)==s1_fmt);
902             passed = passed && (arr_4.tostring(dps)==s1_fmt);
903             passed = passed && (arr_5.tostring(dps)==s2_fmt);
904             arr_2[0] = v10_mod;
905             passed = passed && (arr_2[0]==v10_mod) && (arr_3[0]==v10) && (arr_4[0]==v10);
906             arr_5.setlength(99);
907             passed = passed && (arr_5.length()==99);
908 
909             // setcontent/getcontent
910             alglib::complex a0[] =   {2, 3.5, 1, 9.125, 2};
911             alglib::complex a0_mod  = 7;
912             alglib::complex a0_orig = 2;
913             alglib::complex *p6;
914             alglib::complex_1d_array arr_6;
915             arr_6.setcontent(5, a0);
916             passed = passed && (arr_6[0]==a0[0]) && (arr_6[1]==a0[1]) && (arr_6[2]==a0[2]) && (arr_6[3]==a0[3]) && (arr_6[4]==a0[4]);
917             p6 = arr_6.getcontent();
918             passed = passed && (p6!=a0);
919             passed = passed && (p6[0]==a0[0]) && (p6[1]==a0[1]) && (p6[2]==a0[2]) && (p6[3]==a0[3]) && (p6[4]==a0[4]);
920             a0[0] = a0_mod;
921             passed = passed && (arr_6[0]!=a0[0]);
922             a0[0] = a0_orig;
923 
924             // operations on constant arrays
925             {
926                 const alglib::complex_1d_array &ac = arr_6;
927                 passed = passed && (ac[0]==a0[0]) && (ac[1]==a0[1]) && (ac[2]==a0[2]) && (ac[3]==a0[3]) && (ac[4]==a0[4]);
928                 passed = passed && (ac(0)==a0[0]) && (ac(1)==a0[1]) && (ac(2)==a0[2]) && (ac(3)==a0[3]) && (ac(4)==a0[4]);
929                 const alglib::complex *p = ac.getcontent();
930                 passed = passed && (p[0]==a0[0]) && (p[1]==a0[1]) && (p[2]==a0[2]) && (p[3]==a0[3]) && (p[4]==a0[4]);
931             }
932 
933             //
934             // Operations with proxy arrays:
935             // * changes in target are propagated to proxy and vice versa
936             // * assignments where proxy is source create new independent copy
937             // * assignments to proxy are checked (their size must match to that of the target)
938             // * incorrect assignments or attempts to change length must generate exception
939             // * attempts to call setlength() must fail even when new size match original size
940             //   of the array
941             //
942             alglib::complex_1d_array targt, acopy;
943             targt = s3;
944             alglib::complex_1d_array proxy(targt.c_ptr());
945             acopy = proxy;
946             passed = passed && (targt[0]==v30) && (targt[1]==v31) && (targt[2]==v32) && (targt[3]==v33);
947             passed = passed && (proxy[0]==v30) && (proxy[1]==v31) && (proxy[2]==v32) && (proxy[3]==v33);
948             passed = passed && (acopy[0]==v30) && (acopy[1]==v31) && (acopy[2]==v32) && (acopy[3]==v33);
949 
950             targt[0] = v30_mod;
951             passed = passed && (targt[0]==v30_mod) && (proxy[0]==v30_mod) && (acopy[0]==v30);
952             proxy[0] = v30;
953             passed = passed && (targt[0]==v30)     && (proxy[0]==v30)     && (acopy[0]==v30);
954 
955             acopy = s4;
956             proxy = acopy;
957             passed = passed && (targt[0]==v40) && (targt[1]==v41) && (targt[2]==v42) && (targt[3]==v43);
958             passed = passed && (proxy[0]==v40) && (proxy[1]==v41) && (proxy[2]==v42) && (proxy[3]==v43);
959             proxy = s5;
960             passed = passed && (targt[0]==v50) && (targt[1]==v51) && (targt[2]==v52) && (targt[3]==v53);
961             passed = passed && (proxy[0]==v50) && (proxy[1]==v51) && (proxy[2]==v52) && (proxy[3]==v53);
962 
963             try
964             {
965                 acopy = s6;
966                 proxy = acopy;
967                 passed = false;
968             }
969             catch(alglib::ap_error e)
970             { }
971             catch(...)
972             { passed = false; }
973 
974             try
975             {
976                 proxy = s6;
977                 passed = false;
978             }
979             catch(alglib::ap_error e)
980             { }
981             catch(...)
982             { passed = false; }
983 
984             try
985             {
986                 proxy.setlength(100);
987                 passed = false;
988             }
989             catch(alglib::ap_error e)
990             { }
991             catch(...)
992             { passed = false; }
993 
994             try
995             {
996                 proxy.setlength(proxy.length());
997                 passed = false;
998             }
999             catch(alglib::ap_error e)
1000             { }
1001             catch(...)
1002             { passed = false; }
1003         }
1004         catch(...)
1005         { passed = false; }
1006 
1007         //
1008         // Report
1009         //
1010         printf(fmt_str, "* 1D arrays", passed ? "OK" : "FAILED");
1011         fflush(stdout);
1012         if( !passed )
1013             return 1;
1014     }
1015 
1016     {
1017         //
1018         // Testing 2D array functionality
1019         //
1020         bool passed = true;
1021         try
1022         {
1023             //
1024             // 2D real
1025             //
1026             // Default constructor, string constructor, copy constructor, assignment constructors:
1027             // * test that array sizes as reported by length match to what was specified
1028             // * test item-by-item access
1029             // * test to_string()
1030             // * test that modification of the copied array does not change original
1031             // * test that setlength() changes length
1032             //
1033             const char *s1     = "[[2,3.5,-2.5E-1],[1,2,3]]";
1034             const char *s1_fmt = "[[2.00,3.50,-0.25],[1.00,2.00,3.00]]";
1035             const char *s2     = "[[5],[4],[3.126]]";
1036             const char *s2_fmt = "[[5.00],[4.00],[3.13]]";
1037             const char *s3 = "[[6,7],[3,-4E2],[-3,-1]]";
1038             const char *s4 = "[[9,5],[-12,-0.01],[-1,-2]]";
1039             const char *s5 = "[[1,7],[2,1],[0,4]]";
1040             const char *s60 = "[[7,7],[7,7]]";
1041             const char *s61 = "[[7],[7],[7]]";
1042             const int dps = 2;
1043             const double v10 =  2, v11 =  3.5, v12 = -0.25, v13=1, v14 = 2, v15 = 3, v10_mod = 9;
1044             const double v20 =  5, v21 =  4, v22 =  3.126;
1045             const double v30 =  6, v31 =  7, v32 =  3, v33 = -400, v34=-3, v35=-1, v30_mod = -6;
1046             /*double v40 =  9, v41 =  5, v42 =-12, v43 = -0.01;
1047             double v50 =  1, v51 =  7, v52 =  2, v53 = 1;*/
1048             double r;
1049 
1050             alglib::real_2d_array arr_0, arr_1("[[]]"), arr_2(s1), arr_3(arr_2), arr_4, arr_5;
1051             arr_4 = arr_2;
1052             arr_5 = s2;
1053             passed = passed && (arr_0.rows()==0) && (arr_0.cols()==0) && (arr_0.getstride()==0);
1054             passed = passed && (arr_1.rows()==0) && (arr_1.cols()==0) && (arr_1.getstride()==0);
1055             passed = passed && (arr_2.rows()==2) && (arr_2.cols()==3) && (arr_2.getstride()>=arr_2.cols());
1056             passed = passed && (arr_3.rows()==2) && (arr_3.cols()==3) && (arr_3.getstride()>=arr_3.cols());
1057             passed = passed && (arr_4.rows()==2) && (arr_4.cols()==3) && (arr_4.getstride()>=arr_4.cols());
1058             passed = passed && (arr_5.rows()==3) && (arr_5.cols()==1) && (arr_5.getstride()>=arr_5.cols());
1059             passed = passed && (arr_2[0][0]==arr_2(0,0)) && (arr_2[0][1]==arr_2(0,1)) && (arr_2[0][2]==arr_2(0,2));
1060             passed = passed && (arr_2[1][0]==arr_2(1,0)) && (arr_2[1][1]==arr_2(1,1)) && (arr_2[1][2]==arr_2(1,2));
1061             passed = passed && (arr_2[0][0]==v10) && (arr_2[0][1]==v11) && (arr_2[0][2]==v12);
1062             passed = passed && (arr_2[1][0]==v13) && (arr_2[1][1]==v14) && (arr_2[1][2]==v15);
1063             passed = passed && (arr_3[0][0]==v10) && (arr_3[0][1]==v11) && (arr_3[0][2]==v12);
1064             passed = passed && (arr_3[1][0]==v13) && (arr_3[1][1]==v14) && (arr_3[1][2]==v15);
1065             passed = passed && (arr_4[0][0]==v10) && (arr_4[0][1]==v11) && (arr_4[0][2]==v12);
1066             passed = passed && (arr_4[1][0]==v13) && (arr_4[1][1]==v14) && (arr_4[1][2]==v15);
1067             passed = passed && (arr_5[0][0]==v20) && (arr_5[1][0]==v21) && (arr_5[2][0]==v22);
1068             passed = passed && (arr_2.tostring(dps)==s1_fmt);
1069             passed = passed && (arr_3.tostring(dps)==s1_fmt);
1070             passed = passed && (arr_4.tostring(dps)==s1_fmt);
1071             passed = passed && (arr_5.tostring(dps)==s2_fmt);
1072             arr_2[0][0] = v10_mod;
1073             passed = passed && (arr_2[0][0]==v10_mod) && (arr_3[0][0]==v10) && (arr_4[0][0]==v10);
1074             arr_5.setlength(99,97);
1075             passed = passed && (arr_5.rows()==99) && (arr_5.cols()==97);
1076 
1077             //
1078             // setcontent/elementwise access/constant arrays
1079             //
1080             ae_int_t n, m, i, j;
1081             for(n=1; n<=10; n++)
1082                 for(m=1; m<=10; m++)
1083                 {
1084                     alglib::real_2d_array arr_6;
1085                     double a0[100];
1086 
1087                     // fill array by random values, test setcontent(0
1088                     for(i=0; i<m*n; i++)
1089                         a0[i] = alglib::randomreal();
1090                     arr_6.setcontent(m, n, a0);
1091                     for(i=0; i<m; i++)
1092                         for(j=0; j<n; j++)
1093                         {
1094                             passed = passed && (arr_6[i][j]==a0[i*n+j]);
1095                             passed = passed && (arr_6(i,j)==a0[i*n+j]);
1096                         }
1097 
1098                     // test that setcontent() actually copies data instead of creating just reference
1099                     r = a0[0];
1100                     a0[0] = a0[0]+1;
1101                     passed = passed && (arr_6[0][0]!=a0[0]);
1102                     a0[0] = r;
1103 
1104                     // operations on constant arrays
1105                     {
1106                         const alglib::real_2d_array &ac = arr_6;
1107                         for(i=0; i<m; i++)
1108                             for(j=0; j<n; j++)
1109                             {
1110                                 passed = passed && (ac[i][j]==a0[i*n+j]);
1111                                 passed = passed && (ac(i,j)==a0[i*n+j]);
1112                             }
1113                     }
1114                 }
1115 
1116 
1117             //
1118             // Operations with proxy arrays:
1119             // * changes in target are propagated to proxy and vice versa
1120             // * assignments where proxy is source create new independent copy
1121             // * assignments to proxy are checked (their size must match to that of the target)
1122             // * incorrect assignments or attempts to change length must generate exception
1123             // * attempts to call setlength() must fail even when new size match original size
1124             //   of the array
1125             //
1126             { // test attach_to(ae_matrix*)
1127                 // subtest 0
1128                 alglib::real_2d_array targt, acopy, acopy2;
1129                 targt = s3;
1130                 alglib::real_2d_array proxy(targt.c_ptr());
1131                 acopy = proxy;
1132                 for(i=0; i<targt.rows(); i++)
1133                     for(j=0; j<targt.cols(); j++)
1134                     {
1135                         passed = passed && (proxy[i][j]==targt[i][j]);
1136                         passed = passed && (acopy[i][j]==targt[i][j]);
1137                     }
1138                 r = targt[0][0];
1139                 targt[0][0] = r+1;
1140                 passed = passed && (targt[0][0]!=r) && (proxy[0][0]!=r) && (acopy[0][0]==r);
1141                 proxy[0][0] = r;
1142                 passed = passed && (targt[0][0]==r) && (proxy[0][0]==r) && (acopy[0][0]==r);
1143 
1144                 // subtest 1
1145                 acopy = s4;
1146                 proxy = acopy;
1147                 for(i=0; i<acopy.rows(); i++)
1148                     for(j=0; j<acopy.cols(); j++)
1149                     {
1150                         passed = passed && (proxy[i][j]==acopy[i][j]);
1151                         passed = passed && (targt[i][j]==acopy[i][j]);
1152                     }
1153                 r = targt[0][0];
1154                 targt[0][0] = r+1;
1155                 passed = passed && (targt[0][0]!=r) && (proxy[0][0]!=r) && (acopy[0][0]==r);
1156                 proxy[0][0] = r;
1157                 passed = passed && (targt[0][0]==r) && (proxy[0][0]==r) && (acopy[0][0]==r);
1158 
1159                 // subtest 2
1160                 acopy2 = s5;
1161                 proxy = s5;
1162                 for(i=0; i<acopy.rows(); i++)
1163                     for(j=0; j<acopy.cols(); j++)
1164                     {
1165                         passed = passed && (proxy[i][j]==acopy2[i][j]);
1166                         passed = passed && (targt[i][j]==acopy2[i][j]);
1167                     }
1168 
1169                 // error handling test 0
1170                 try
1171                 {
1172                     acopy = s60;
1173                     proxy = acopy;
1174                     passed = false;
1175                 }
1176                 catch(alglib::ap_error e)
1177                 { }
1178                 catch(...)
1179                 { passed = false; }
1180 
1181                 // error handling test 1
1182                 try
1183                 {
1184                     acopy = s61;
1185                     proxy = acopy;
1186                     passed = false;
1187                 }
1188                 catch(alglib::ap_error e)
1189                 { }
1190                 catch(...)
1191                 { passed = false; }
1192 
1193                 // error handling test 2
1194                 try
1195                 {
1196                     proxy = s60;
1197                     passed = false;
1198                 }
1199                 catch(alglib::ap_error e)
1200                 { }
1201                 catch(...)
1202                 { passed = false; }
1203 
1204                 // error handling test 3
1205                 try
1206                 {
1207                     proxy = s61;
1208                     passed = false;
1209                 }
1210                 catch(alglib::ap_error e)
1211                 { }
1212                 catch(...)
1213                 { passed = false; }
1214 
1215                 // error handling test 4
1216                 try
1217                 {
1218                     proxy.setlength(100,99);
1219                     passed = false;
1220                 }
1221                 catch(alglib::ap_error e)
1222                 { }
1223                 catch(...)
1224                 { passed = false; }
1225 
1226                 // error handling test 5
1227                 try
1228                 {
1229                     proxy.setlength(proxy.rows(),proxy.cols());
1230                     passed = false;
1231                 }
1232                 catch(alglib::ap_error e)
1233                 { }
1234                 catch(...)
1235                 { passed = false; }
1236             }
1237             { // test attach_to(double*)
1238                 // subtest 0
1239                 alglib::real_2d_array proxy, acopy, acopy2;
1240                 double targt[] = {v30, v31, v32, v33, v34, v35};
1241                 const int NCOLS = 2;
1242                 proxy.attach_to_ptr(3, 2, targt);
1243                 acopy = proxy;
1244                 for(i=0; i<proxy.rows(); i++)
1245                     for(j=0; j<proxy.cols(); j++)
1246                     {
1247                         passed = passed && (proxy[i][j]==targt[i*NCOLS+j]);
1248                         passed = passed && (acopy[i][j]==targt[i*NCOLS+j]);
1249                     }
1250                 r = targt[0*NCOLS+0];
1251                 targt[0*NCOLS+0] = r+1;
1252                 passed = passed && (targt[0*NCOLS+0]!=r) && (proxy[0][0]!=r) && (acopy[0][0]==r);
1253                 proxy[0][0] = r;
1254                 passed = passed && (targt[0*NCOLS+0]==r) && (proxy[0][0]==r) && (acopy[0][0]==r);
1255 
1256                 // subtest 1
1257                 acopy = s4;
1258                 proxy = acopy;
1259                 for(i=0; i<acopy.rows(); i++)
1260                     for(j=0; j<acopy.cols(); j++)
1261                     {
1262                         passed = passed && (proxy[i][j]==acopy[i][j]);
1263                         passed = passed && (targt[i*NCOLS+j]==acopy[i][j]);
1264                     }
1265                 r = targt[0*NCOLS+0];
1266                 targt[0*NCOLS+0] = r+1;
1267                 passed = passed && (targt[0*NCOLS+0]!=r) && (proxy[0][0]!=r) && (acopy[0][0]==r);
1268                 proxy[0][0] = r;
1269                 passed = passed && (targt[0*NCOLS+0]==r) && (proxy[0][0]==r) && (acopy[0][0]==r);
1270 
1271                 // subtest 2
1272                 acopy2 = s5;
1273                 proxy = s5;
1274                 for(i=0; i<acopy.rows(); i++)
1275                     for(j=0; j<acopy.cols(); j++)
1276                     {
1277                         passed = passed && (proxy[i][j]==acopy2[i][j]);
1278                         passed = passed && (targt[i*NCOLS+j]==acopy2[i][j]);
1279                     }
1280 
1281                 // error handling test 0
1282                 try
1283                 {
1284                     acopy = s60;
1285                     proxy = acopy;
1286                     passed = false;
1287                 }
1288                 catch(alglib::ap_error e)
1289                 { }
1290                 catch(...)
1291                 { passed = false; }
1292 
1293                 // error handling test 1
1294                 try
1295                 {
1296                     acopy = s61;
1297                     proxy = acopy;
1298                     passed = false;
1299                 }
1300                 catch(alglib::ap_error e)
1301                 { }
1302                 catch(...)
1303                 { passed = false; }
1304 
1305                 // error handling test 2
1306                 try
1307                 {
1308                     proxy = s60;
1309                     passed = false;
1310                 }
1311                 catch(alglib::ap_error e)
1312                 { }
1313                 catch(...)
1314                 { passed = false; }
1315 
1316                 // error handling test 3
1317                 try
1318                 {
1319                     proxy = s61;
1320                     passed = false;
1321                 }
1322                 catch(alglib::ap_error e)
1323                 { }
1324                 catch(...)
1325                 { passed = false; }
1326 
1327                 // error handling test 4
1328                 try
1329                 {
1330                     proxy.setlength(100,99);
1331                     passed = false;
1332                 }
1333                 catch(alglib::ap_error e)
1334                 { }
1335                 catch(...)
1336                 { passed = false; }
1337 
1338                 // error handling test 5
1339                 try
1340                 {
1341                     proxy.setlength(proxy.rows(),proxy.cols());
1342                     passed = false;
1343                 }
1344                 catch(alglib::ap_error e)
1345                 { }
1346                 catch(...)
1347                 { passed = false; }
1348             }
1349         }
1350         catch(...)
1351         { passed = false; }
1352 
1353         //
1354         // Report
1355         //
1356         printf(fmt_str, "* 2D arrays", passed ? "OK" : "FAILED");
1357         fflush(stdout);
1358         if( !passed )
1359             return 1;
1360     }
1361 
1362     {
1363         //
1364         // Testing CSV functionality
1365         //
1366         const char *csv_name = "alglib-tst-35252-ndg4sf.csv";
1367         bool passed = true;
1368         try
1369         {
1370             // CSV_DEFAULT must be zero
1371             passed = passed && alglib::CSV_DEFAULT==0;
1372 
1373             // absent file - must fail
1374             try
1375             {
1376                 alglib::real_2d_array arr;
1377                 read_csv("nonexistent123foralgtestinglib", '\t', alglib::CSV_DEFAULT, arr);
1378                 passed = false;
1379             }
1380             catch(alglib::ap_error)
1381             { }
1382             catch(...)
1383             { passed = false; }
1384 
1385             // non-rectangular file - must fail
1386             try
1387             {
1388                 alglib::real_2d_array arr;
1389                 file_put_contents(csv_name, "a,b,c\r\n1,2");
1390                 read_csv(csv_name, ',', alglib::CSV_SKIP_HEADERS, arr);
1391                 remove(csv_name);
1392                 passed = false;
1393             }
1394             catch(alglib::ap_error)
1395             { }
1396             catch(...)
1397             { passed = false; }
1398             try
1399             {
1400                 alglib::real_2d_array arr;
1401                 file_put_contents(csv_name, "a,b,c\r\n1,2,3,4");
1402                 read_csv(csv_name, ',', alglib::CSV_SKIP_HEADERS, arr);
1403                 remove(csv_name);
1404                 passed = false;
1405             }
1406             catch(alglib::ap_error)
1407             { }
1408             catch(...)
1409             { passed = false; }
1410             try
1411             {
1412                 alglib::real_2d_array arr;
1413                 file_put_contents(csv_name, "1,2,3,4\n1,2,3\n1,2,3");
1414                 read_csv(csv_name, ',', alglib::CSV_DEFAULT, arr);
1415                 remove(csv_name);
1416                 passed = false;
1417             }
1418             catch(alglib::ap_error)
1419             { }
1420             catch(...)
1421             { passed = false; }
1422 
1423             // empty file
1424             try
1425             {
1426                 alglib::real_2d_array arr;
1427                 file_put_contents(csv_name, "");
1428                 read_csv(csv_name, '\t', alglib::CSV_DEFAULT, arr);
1429                 remove(csv_name);
1430                 passed = passed && arr.rows()==0 && arr.cols()==0;
1431             }
1432             catch(...)
1433             { passed = false; }
1434 
1435             // one row with header, tab separator
1436             try
1437             {
1438                 alglib::real_2d_array arr;
1439                 file_put_contents(csv_name, "a\tb\tc\n");
1440                 read_csv(csv_name, '\t', alglib::CSV_SKIP_HEADERS, arr);
1441                 remove(csv_name);
1442                 passed = passed && arr.rows()==0 && arr.cols()==0;
1443             }
1444             catch(...)
1445             { passed = false; }
1446 
1447             // no header, comma-separated, full stop as decimal point
1448             try
1449             {
1450                 alglib::real_2d_array arr;
1451                 file_put_contents(csv_name, "1.5,2,3.25\n4,5,6");
1452                 read_csv(csv_name, ',', alglib::CSV_DEFAULT, arr);
1453                 remove(csv_name);
1454                 passed = passed && arr.tostring(2)=="[[1.50,2.00,3.25],[4.00,5.00,6.00]]";
1455             }
1456             catch(...)
1457             { passed = false; }
1458 
1459             // header, tab-separated, mixed use of comma and full stop as decimal points
1460             try
1461             {
1462                 alglib::real_2d_array arr;
1463                 file_put_contents(csv_name, "a\tb\tc\n1.5\t2\t3,25\n4\t5.25\t6,1\n");
1464                 read_csv(csv_name, '\t', alglib::CSV_SKIP_HEADERS, arr);
1465                 remove(csv_name);
1466                 passed = passed && arr.tostring(2)=="[[1.50,2.00,3.25],[4.00,5.25,6.10]]";
1467             }
1468             catch(...)
1469             { passed = false; }
1470 
1471             // header, tab-separated, fixed/exponential, spaces, mixed use of comma and full stop as decimal points
1472             try
1473             {
1474                 alglib::real_2d_array arr;
1475                 file_put_contents(csv_name, " a\t b \tc\n1,1\t 2.9\t -3.5  \n  1.1E1  \t 2.0E-1 \t-3E+1 \n+1  \t -2\t 3.    \n.1\t-.2\t+.3\n");
1476                 read_csv(csv_name, '\t', alglib::CSV_SKIP_HEADERS, arr);
1477                 remove(csv_name);
1478                 passed = passed && arr.tostring(2)=="[[1.10,2.90,-3.50],[11.00,0.20,-30.00],[1.00,-2.00,3.00],[0.10,-0.20,0.30]]";
1479             }
1480             catch(...)
1481             { passed = false; }
1482         }
1483         catch(...)
1484         { passed = false; }
1485 
1486         //
1487         // Report
1488         //
1489         printf(fmt_str, "* CSV support", passed ? "OK" : "FAILED");
1490         fflush(stdout);
1491         if( !passed )
1492             return 1;
1493     }
1494 
1495 
1496     //
1497     // Serialization properties
1498     //
1499     {
1500         //
1501         // Test kd-tree serialization
1502         //
1503         bool passed = true;
1504         alglib::hqrndstate rs;
1505         alglib::kdtree tree0;
1506         alglib::real_2d_array xy, rxy0, rxy1;
1507         alglib::real_1d_array qx;
1508         const int npts = 50;
1509         const int nx = 2;
1510         const int ny = 1;
1511         int cnt0, cnt1;
1512         alglib::hqrndrandomize(rs);
1513         xy.setlength(npts, nx+ny);
1514         for(int i=0; i<npts; i++)
1515             for(int j=0; j<nx+ny; j++)
1516                 xy[i][j] = alglib::hqrndnormal(rs);
1517         alglib::kdtreebuild(xy, npts, nx, ny, 2, tree0);
1518         qx.setlength(nx);
1519 
1520         try
1521         {
1522             // test string serialization/unserialization
1523             alglib::kdtree tree1;
1524             std::string s;
1525             alglib::kdtreeserialize(tree0, s);
1526             alglib::kdtreeunserialize(s, tree1);
1527             for(int i=0; i<100; i++)
1528             {
1529                 for(int j=0; j<nx; j++)
1530                     qx[j] = alglib::hqrndnormal(rs);
1531                 cnt0 = alglib::kdtreequeryknn(tree0, qx, 1, true);
1532                 cnt1 = alglib::kdtreequeryknn(tree1, qx, 1, true);
1533                 if( (cnt0!=1) || (cnt1!=1) )
1534                 {
1535                     passed = false;
1536                     break;
1537                 }
1538                 alglib::kdtreequeryresultsxy(tree0, rxy0);
1539                 alglib::kdtreequeryresultsxy(tree1, rxy1);
1540                 for(int j=0; j<nx+ny; j++)
1541                     passed = passed && (rxy0[0][j]==rxy1[0][j]);
1542             }
1543         }
1544         catch(...)
1545         { passed = false; }
1546 
1547         try
1548         {
1549             // test stream serialization/unserialization
1550             //
1551             // NOTE: we add a few symbols at the beginning and after the end of the data
1552             //       in order to test algorithm ability to work in the middle of the stream
1553             alglib::kdtree tree1;
1554             std::stringstream s;
1555             s.put('b');
1556             s.put('e');
1557             s.put('g');
1558             alglib::kdtreeserialize(tree0, s);
1559             s.put('e');
1560             s.put('n');
1561             s.put('d');
1562             s.seekg(0);
1563             passed = passed && (s.get()=='b');
1564             passed = passed && (s.get()=='e');
1565             passed = passed && (s.get()=='g');
1566             alglib::kdtreeunserialize(s, tree1);
1567             passed = passed && (s.get()=='e');
1568             passed = passed && (s.get()=='n');
1569             passed = passed && (s.get()=='d');
1570             for(int i=0; i<100; i++)
1571             {
1572                 for(int j=0; j<nx; j++)
1573                     qx[j] = alglib::hqrndnormal(rs);
1574                 cnt0 = alglib::kdtreequeryknn(tree0, qx, 1, true);
1575                 cnt1 = alglib::kdtreequeryknn(tree1, qx, 1, true);
1576                 if( (cnt0!=1) || (cnt1!=1) )
1577                 {
1578                     passed = false;
1579                     break;
1580                 }
1581                 alglib::kdtreequeryresultsxy(tree0, rxy0);
1582                 alglib::kdtreequeryresultsxy(tree1, rxy1);
1583                 for(int j=0; j<nx+ny; j++)
1584                     passed = passed && (rxy0[0][j]==rxy1[0][j]);
1585             }
1586         }
1587         catch(...)
1588         { passed = false; }
1589 
1590         try
1591         {
1592             // test string-to-stream serialization/unserialization
1593             alglib::kdtree tree1;
1594             std::string s0;
1595             alglib::kdtreeserialize(tree0, s0);
1596             std::stringstream s1(s0);
1597             alglib::kdtreeunserialize(s1, tree1);
1598             for(int i=0; i<100; i++)
1599             {
1600                 for(int j=0; j<nx; j++)
1601                     qx[j] = alglib::hqrndnormal(rs);
1602                 cnt0 = alglib::kdtreequeryknn(tree0, qx, 1, true);
1603                 cnt1 = alglib::kdtreequeryknn(tree1, qx, 1, true);
1604                 if( (cnt0!=1) || (cnt1!=1) )
1605                 {
1606                     passed = false;
1607                     break;
1608                 }
1609                 alglib::kdtreequeryresultsxy(tree0, rxy0);
1610                 alglib::kdtreequeryresultsxy(tree1, rxy1);
1611                 for(int j=0; j<nx+ny; j++)
1612                     passed = passed && (rxy0[0][j]==rxy1[0][j]);
1613             }
1614         }
1615         catch(...)
1616         { passed = false; }
1617 
1618         try
1619         {
1620             // test stream-to-string serialization/unserialization
1621             alglib::kdtree tree1;
1622             std::stringstream s0;
1623             alglib::kdtreeserialize(tree0, s0);
1624             std::string s1 = s0.str();
1625             alglib::kdtreeunserialize(s1, tree1);
1626             for(int i=0; i<100; i++)
1627             {
1628                 for(int j=0; j<nx; j++)
1629                     qx[j] = alglib::hqrndnormal(rs);
1630                 cnt0 = alglib::kdtreequeryknn(tree0, qx, 1, true);
1631                 cnt1 = alglib::kdtreequeryknn(tree1, qx, 1, true);
1632                 if( (cnt0!=1) || (cnt1!=1) )
1633                 {
1634                     passed = false;
1635                     break;
1636                 }
1637                 alglib::kdtreequeryresultsxy(tree0, rxy0);
1638                 alglib::kdtreequeryresultsxy(tree1, rxy1);
1639                 for(int j=0; j<nx+ny; j++)
1640                     passed = passed && (rxy0[0][j]==rxy1[0][j]);
1641             }
1642         }
1643         catch(...)
1644         { passed = false; }
1645 
1646         //
1647         // Report
1648         //
1649         printf(fmt_str, "* Serialization (kd-tree)", passed ? "OK" : "FAILED");
1650         fflush(stdout);
1651         if( !passed )
1652             return 1;
1653     }
1654     {
1655         //
1656         // Test legacy RBF interface
1657         //
1658         const char *pc_str = "50000000000 00000000000 20000000000 10000000000 A0000000000 \
1659 30000000000 20000000000 00000000000 A0000000000 30000000000\r\
1660 00000000000 20000000000 A0000000000 60000000000 00000000000\n\
1661 00000000000 00000000000 00000000000 00000000000 00000000000\r\n\
1662 00000000m_3 00000000000 00000000000 00000000m_3 00000000000\n\r\
1663 00000000000 00000000004 00000000000 00000000000\t00000000004 \
1664 00000000000 00000000000 00000000804 00000000000 00000000000 \
1665 00000000804 00000000000 00000000000 00000000G04 00000000000 \
1666 00000000000 00000000G04 00000000000 00000000000 00000000O04 \
1667 00000000000 00000000000 00000000O04 00000000000 00000000000 \
1668 00000000S04 00000000000 00000000000 00000000S04 00000000000 \
1669 00000000000 00000000W04 00000000000 00000000000 00000000W04 \
1670 00000000000 00000000000 00000000Y04 00000000000 00000000000 \
1671 00000000Y04 00000000000 00000000000 00000000K04 00000000000 \
1672 00000000000 00000000K04 00000000000 00000000000 A0000000000 \
1673 00000000000 10000000000 20000000000 30000000000 40000000000 \
1674 60000000000 70000000000 80000000000 90000000000 50000000000 \
1675 30000000000 00000000000 00000000000 00000000000 30000000000 \
1676 00000000Y04 00000000000 00000000000 u1000000000 00000000000 \
1677 00000000000 00000000000 60000000000 80000000000 00000000000 \
1678 50000000000 00000000000 50000000000 50000000000 00000000000 \
1679 00000000000 00000000000 00000000000 00000000000 00000000000 \
1680 00000000000 00000000000 00000000000 00000000000 00000000000 \
1681 00000000000 00000000000 00000000000 00000000000 00000000000 \
1682 00000000000 00000000000 00000000000 00000000000 00000000000 \
1683 00000000000 00000000000 00000000000 00000000000 00000000000 \
1684 00000000000 00000000000 00000000000 00000000000 00000000000 \
1685 00000000000 00000000000 00000000000 00000000000 00000000000 \
1686 00000000000 00000000000 00000000000 00000000000 00000000000 \
1687 00000000000 00000000000 00000000000 00000000000 00000000000 \
1688 00000000000 00000000000 00000000000 00000000000 00000000000 \
1689 00000000000 00000000000 00000000000 00000000000 00000000000 \
1690 00000000000 00000000000 00000000000 00000000000 00000000000 \
1691 00000000000 00000000000 00000000000 00000000000 00000000000 \
1692 00000000000 00000000000 00000000000 00000000000 00000000000 \
1693 00000000000 00000000000 00000000000 00000000000 00000000000 \
1694 00000000000 00000000000 00000000000 00000000000 00000000000 \
1695 00000000000 00000000000 00000000000 00000000000 00000000000 \
1696 00000000000 00000000000 00000000000 00000000000 00000000000 \
1697 00000000000 00000000000 00000000000 00000000000 00000000000 \
1698 00000000000 00000000000 00000000000 00000000000 00000000000 \
1699 00000000000 00000000000 00000000000 00000000000 00000000000 \
1700 00000000000 00000000000 00000000000 00000000000 K0000000000 \
1701 00000000I04 00000000000 00000000000 00000000000 00000000000 \
1702 00000000000 00000000000 00000000000 00000000000 00000000000 \
1703 00000000000 00000000000 00000000000 00000000000 00000000000 \
1704 00000000000 00000000000 00000000000 00000000000 00000000000 \
1705 A0000000000 30000000000 00000000000 00000000000 00000000000 \
1706 00000000m_3 00000000000 00000000000 00000000004 00000000000 \
1707 00000000000 00000000804 00000000000 00000000000 00000000G04 \
1708 00000000000 00000000000 00000000K04 00000000000 00000000000 \
1709 00000000O04 00000000000 00000000000 00000000S04 00000000000 \
1710 00000000000 00000000W04 00000000000 00000000000 00000000Y04 \
1711 00000000000 00000000000 A0000000000 40000000000 00000000q04 \
1712 -pAGQnQBI14 UqUWierJ91C esm8ag6G61C 00000000q04 4wcFMyCtu04 \
1713 oPDvwHqst04 CExQXp8Ct04 00000000q04 litzPFhRb0C oKJvjcct314 \
1714 5-fT-X8w614 00000000q04 3HSOsPVH11C vZWf4dgfv04 GbZg4MTJn04 \
1715 00000000q04 iv7rMhuR71C hRtixp15r_3 EvCEDtLu-0C 00000000q04 \
1716 41CXzA_q71C umRYLK2yp0C 1zzY3Zqd91C 00000000q04 JvxJzDeI21C \
1717 TVbyd7Ygz0C JLywRdR1n0C 00000000q04 KmFarhc4g0C 1ehrn2tUt0C \
1718 AECfwTIX814 00000000q04 Big__6hwt04 nSPzmAQrh_B 2H3o-KftH14 \
1719 00000000q04 n1b9361vI14 mhJhviUE114 54a_qyBrH1C 00000000q04 \
1720 10000000000 40000000000 StLCgor39-3 00000000000 00000000000 \
1721 6qTG7Ae-1_3\n";
1722         alglib::real_1d_array ref_val("[-0.042560546916643, 0.942523544654062, 0.875197036560778, 0.0656948997826632, -0.743065973803404, -0.8903682039297, -0.26994815318748, 0.602248517290195, 0.980011992233124, 0.436594293214176]");
1723         bool passed = true;
1724 
1725         try
1726         {
1727             // test unserialization from string without trailing end-of-stream symbol (dot)
1728             // this test is necessary for backward compatibility
1729             double eps = 0.0000000001;
1730             alglib::rbfmodel model;
1731             alglib::rbfunserialize(std::string(pc_str), model);
1732             for(int i=0; i<ref_val.length(); i++)
1733                 passed = passed && (fabs(alglib::rbfcalc2(model,i,0)-ref_val[i])<eps);
1734         }
1735         catch(...)
1736         { passed = false; }
1737 
1738         try
1739         {
1740             // test unserialization from string with trailing end-of-stream symbol (dot)
1741             // this test is necessary for forward compatibility
1742             double eps = 0.0000000001;
1743             alglib::rbfmodel model;
1744             alglib::rbfunserialize(std::string(pc_str)+".", model);
1745             for(int i=0; i<ref_val.length(); i++)
1746                 passed = passed && (fabs(alglib::rbfcalc2(model,i,0)-ref_val[i])<eps);
1747         }
1748         catch(...)
1749         { passed = false; }
1750 
1751         try
1752         {
1753             // test unserialization from stream WITHOUT trailing end-of-stream symbol (dot)
1754             // this test MUST fail
1755             double eps = 0.0000000001;
1756             std::string _s(pc_str);
1757             std::istringstream stream(_s);
1758             alglib::rbfmodel model;
1759             alglib::rbfunserialize(stream, model);
1760             passed = false;
1761         }
1762         catch(...)
1763         { /* do nothing, it is expected to fail */ }
1764 
1765         try
1766         {
1767             // test unserialization from stream WITH trailing end-of-stream symbol (dot)
1768             // this test must succeed
1769             double eps = 0.0000000001;
1770             std::string _s = std::string(pc_str)+".";
1771             std::istringstream stream(_s);
1772             alglib::rbfmodel model;
1773             alglib::rbfunserialize(stream, model);
1774             for(int i=0; i<ref_val.length(); i++)
1775                 passed = passed && (fabs(alglib::rbfcalc2(model,i,0)-ref_val[i])<eps);
1776         }
1777         catch(...)
1778         { passed = false; }
1779 
1780         try
1781         {
1782             // test that we can read from the stream after unserialization
1783             double eps = 0.0000000001;
1784             std::string _s = std::string(pc_str)+".<az>";
1785             std::istringstream stream(_s);
1786             alglib::rbfmodel model;
1787             alglib::rbfunserialize(stream, model);
1788             for(int i=0; i<ref_val.length(); i++)
1789                 passed = passed && (fabs(alglib::rbfcalc2(model,i,0)-ref_val[i])<eps);
1790             passed = passed && (stream.get()=='<');
1791             passed = passed && (stream.get()=='a');
1792             passed = passed && (stream.get()=='z');
1793             passed = passed && (stream.get()=='>');
1794         }
1795         catch(...)
1796         { passed = false; }
1797 
1798         //
1799         // Report
1800         //
1801         printf(fmt_str, "* Serialization (RBF)", passed ? "OK" : "FAILED");
1802         fflush(stdout);
1803         if( !passed )
1804             return 1;
1805     }
1806     {
1807         bool passed = true;
1808 #if (AE_OS==AE_WINDOWS) || AE_OS==AE_POSIX
1809         alglib::hqrndstate rs;
1810         alglib::rbfmodel  rbf;
1811         alglib::rbfreport rep;
1812         alglib::real_2d_array xy;
1813         int n = 1000, nx = 2, ny = 1;
1814         double rbase = 1.0;
1815         async_rbf_record async_rec;
1816         alglib::hqrndseed(464, 764, rs);
1817         xy.setlength(n, nx+ny);
1818         for(int i=0; i<n; i++)
1819             for(int j=0; j<=nx+ny; j++)
1820                 xy[i][j] = alglib::hqrndnormal(rs);
1821         alglib::rbfcreate(nx, ny, rbf);
1822         alglib::rbfsetalgohierarchical(rbf, rbase, 1, 0.0);
1823         alglib::rbfsetpoints(rbf, xy);
1824         alglib::rbfsetv2its(rbf, 100000);
1825         passed = passed && (alglib::rbfpeekprogress(rbf)==0);
1826         async_rec.p_model = &rbf;
1827         async_rec.p_report= &rep;
1828         async_rec.thread_finished = false;
1829 #if AE_OS==AE_WINDOWS
1830         if( CreateThread(NULL, 0, async_build_rbf_model, &async_rec, 0, NULL)==NULL )
1831         {
1832             printf(fmt_str, "* Progress/termination (RBF)", "FAILED");
1833             printf(">>> unable to create background thread\n");
1834             fflush(stdout);
1835             return 1;
1836         }
1837 #elif AE_OS==AE_POSIX
1838         pthread_t  thread;
1839         if( pthread_create(&thread, NULL, async_build_rbf_model, &async_rec)!=0 )
1840         {
1841             printf(fmt_str, "* Progress/termination (RBF)", "FAILED");
1842             printf(">>> unable to create background thread\n");
1843             fflush(stdout);
1844             return 1;
1845         }
1846 #else
1847 #error Unable to determine OS, unexpected here
1848 #endif
1849         double last_progress = 0;
1850         for(;;)
1851         {
1852             double new_progress = alglib::rbfpeekprogress(rbf);
1853             passed = passed && (new_progress>=last_progress);
1854             passed = passed && (new_progress<=0.1); // we expect to terminate well before reaching 10%
1855             last_progress = new_progress;
1856             if( new_progress>=0.001 )
1857             {
1858                 alglib::rbfrequesttermination(rbf);
1859                 break;
1860             }
1861         }
1862         for(;;)
1863         {
1864             double new_progress = alglib::rbfpeekprogress(rbf);
1865             passed = passed && ((new_progress<=0.1) || (new_progress==1.0)); // we expect to terminate well before reaching 10%
1866             if( async_rec.thread_finished )
1867                 break;
1868         }
1869         passed = passed && (alglib::rbfpeekprogress(rbf)==1);
1870         passed = passed && (rep.terminationtype==8);
1871         passed = passed && (alglib::rbfcalc2(rbf,alglib::hqrndnormal(rs),alglib::hqrndnormal(rs))==0.0);
1872         printf(fmt_str, "* Progress/termination (RBF)", passed ? "OK" : "FAILED");
1873         fflush(stdout);
1874         if( !passed )
1875             return 1;
1876 #else
1877         printf(fmt_str, "* Progress/termination (RBF)", "??");
1878         fflush(stdout);
1879         if( !passed )
1880             return 1;
1881 #endif
1882     }
1883     {
1884         //
1885         // Test malloc() exceptions in constructors
1886         //
1887 #ifdef AE_USE_ALLOC_COUNTER
1888         bool passed = true;
1889         bool were_exceptions = false;
1890         for(int eidx=0; ; eidx++) // loop is terminated when we survive through all the tests
1891         {
1892             //
1893             // Select moment when we generate exception in the constructor
1894             //
1895             alglib_impl::_malloc_failure_after = alglib_impl::_alloc_counter_total+eidx;
1896 
1897             //
1898             // Perform many activities with ALGLIB, catch exceptions.
1899             // It is survival test, it checks that we survive exceptions.
1900             // If it fails, we are likely to end with abort().
1901             //
1902             try
1903             {
1904                 {
1905                     real_1d_array x0 = "[1,2,3]";
1906                     real_1d_array x1(x0);
1907                     real_1d_array x2;
1908                     x2 = x1;
1909                     real_1d_array *p = new real_1d_array("[1]");
1910                     delete p;
1911                 }
1912                 {
1913                     real_2d_array x0 = "[[1,2,3],[0,0,0]]";
1914                     real_2d_array x1(x0);
1915                     real_2d_array x2;
1916                     x2 = x1;
1917                     real_2d_array *p = new real_2d_array("[[1],[5]]");
1918                     delete p;
1919                 }
1920                 {
1921                     sparsematrix s;
1922                     sparsecreate(2, 2, s);
1923                     sparseset(s, 0, 0, 2.0);
1924                     sparseset(s, 1, 1, 1.0);
1925                     sparseset(s, 0, 1, 1.0);
1926                     sparseadd(s, 1, 1, 4.0);
1927                     sparsematrix s2(s), s3;
1928                     s3 = s;
1929                     double v;
1930                     v = sparseget(s, 0, 0);
1931                     v = sparseget(s, 0, 1);
1932                     v = sparseget(s, 1, 0);
1933                     v = sparseget(s, 1, 1);
1934                     sparseconverttocrs(s);
1935                     real_1d_array x = "[1,-1]";
1936                     real_1d_array y = "[]";
1937                     sparsemv(s, x, y);
1938                 }
1939                 {
1940                     real_1d_array x = "[0,0]";
1941                     double epsg = 0.0000000001;
1942                     double epsf = 0;
1943                     double epsx = 0;
1944                     double stpmax = 0.1;
1945                     ae_int_t maxits = 0;
1946                     mincgstate state;
1947                     mincgreport rep;
1948                     mincgcreate(x, state);
1949                     mincgsetcond(state, epsg, epsf, epsx, maxits);
1950                     mincgsetstpmax(state, stpmax);
1951                     mincgstate state2;
1952                     state2 = state;
1953                     mincgstate state3(state2);
1954                     mincgrestartfrom(state, x);
1955                 }
1956                 {
1957                     mlptrainer trn;
1958                     multilayerperceptron network;
1959                     mlpreport rep;
1960                     real_2d_array xy = "[[1,1,1],[1,2,2],[2,1,2],[2,2,4]]";
1961                     mlpcreatetrainer(2, 1, trn);
1962                     mlpcreate1(2, 5, 1, network);
1963                     mlpsetdataset(trn, xy, 4);
1964                     mlptrainnetwork(trn, network, 5, rep);
1965                     real_1d_array x = "[2,2]";
1966                     real_1d_array y = "[0]";
1967                     mlpprocess(network, x, y);
1968                 }
1969                 {
1970                     std::string s;
1971                     double v;
1972                     rbfmodel model0;
1973                     rbfmodel model1;
1974                     real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
1975                     rbfreport rep;
1976                     rbfcreate(2, 1, model0);
1977                     rbfsetpoints(model0, xy);
1978                     rbfsetalgohierarchical(model0, 1.0, 3, 0.0);
1979                     rbfbuildmodel(model0, rep);
1980                     alglib::rbfserialize(model0, s);
1981                     alglib::rbfunserialize(s, model1);
1982                     v = rbfcalc2(model0, 0.0, 0.0);
1983                     v = rbfcalc2(model1, 0.0, 0.0);
1984                     rbfbuildmodel(model0, rep);
1985                     v = rbfcalc2(model0, 0.0, 0.0);
1986                     rbfbuildmodel(model1, rep);
1987                     v = rbfcalc2(model1, 0.0, 0.0);
1988                 }
1989 
1990                 //
1991                 // We survived all tests, next iteration will bring no changed, terminate loop!
1992                 //
1993                 break;
1994             }
1995             catch(ap_error)
1996             { were_exceptions = true; }
1997         }
1998         alglib_impl::_malloc_failure_after = 0; // turn off artificial malloc failures
1999         printf(fmt_str, "* Exceptions in constructors", were_exceptions ? (passed ? "OK" : "FAILED") : "..");
2000         fflush(stdout);
2001         if( !passed )
2002             return 1;
2003 #else
2004         printf(fmt_str, "* Exceptions in constructors", "??");
2005         fflush(stdout);
2006 #endif
2007     }
2008     {
2009         //
2010         // Test multithreading-related settings
2011         //
2012         // For this test we measure performance of large NxNxN GEMMs
2013         // with different threading settings.
2014         //
2015         printf("SMP settings vs GEMM speedup:\n");
2016         if( alglib::_ae_cores_count()>1 )
2017         {
2018             bool passed = true;
2019             alglib_impl::ae_uint64_t default_global_threading = alglib::_ae_get_global_threading();
2020             alglib::ae_int_t default_nworkers = alglib::getnworkers();
2021             double time_default          = 0,
2022                    time_glob_ser         = 0,
2023                    time_glob_smp         = 0,
2024                    time_glob_ser_loc_ser = 0,
2025                    time_glob_ser_loc_smp = 0,
2026                    time_glob_smp_loc_ser = 0,
2027                    time_glob_smp_loc_smp = 0,
2028                    time_glob_smp_nw1     = 0;
2029             alglib::ae_int_t n = 800, mintime = 2000, cnt, t0;
2030             try
2031             {
2032                 // allocate temporary matrices
2033                 alglib::real_2d_array a, b, c;
2034                 int i, j;
2035                 a.setlength(n, n);
2036                 b.setlength(n, n);
2037                 c.setlength(n, n);
2038                 for(i=0; i<n; i++)
2039                     for(j=0; j<n; j++)
2040                     {
2041                         a[i][j] = alglib::randomreal()-0.5;
2042                         b[i][j] = alglib::randomreal()-0.5;
2043                         c[i][j] = 0.0;
2044                     }
2045 
2046                 // measure time; interleave measurements with different settings in order to
2047                 // reduce variance of results
2048                 while(time_default<mintime)
2049                 {
2050                     // default threading
2051                     t0 = alglib_impl::ae_tickcount();
2052                     alglib::rmatrixgemm(
2053                         n, n, n,
2054                         1.0,
2055                         a, 0, 0, 0,
2056                         b, 0, 0, 0,
2057                         0.0,
2058                         c, 0, 0);
2059                     time_default += alglib_impl::ae_tickcount()-t0;
2060                     alglib::_ae_set_global_threading(default_global_threading); // restore
2061 
2062                     // global serial
2063                     t0 = alglib_impl::ae_tickcount();
2064                     alglib::setglobalthreading(alglib::serial);
2065                     alglib::rmatrixgemm(
2066                         n, n, n,
2067                         1.0,
2068                         a, 0, 0, 0,
2069                         b, 0, 0, 0,
2070                         0.0,
2071                         c, 0, 0);
2072                     time_glob_ser += alglib_impl::ae_tickcount()-t0;
2073                     alglib::_ae_set_global_threading(default_global_threading); // restore
2074 
2075                     // global parallel
2076                     t0 = alglib_impl::ae_tickcount();
2077                     alglib::setglobalthreading(alglib::parallel);
2078                     alglib::rmatrixgemm(
2079                         n, n, n,
2080                         1.0,
2081                         a, 0, 0, 0,
2082                         b, 0, 0, 0,
2083                         0.0,
2084                         c, 0, 0);
2085                     time_glob_smp += alglib_impl::ae_tickcount()-t0;
2086                     alglib::_ae_set_global_threading(default_global_threading); // restore
2087 
2088                     // global serial, local serial
2089                     t0 = alglib_impl::ae_tickcount();
2090                     alglib::setglobalthreading(alglib::serial);
2091                     alglib::rmatrixgemm(
2092                         n, n, n,
2093                         1.0,
2094                         a, 0, 0, 0,
2095                         b, 0, 0, 0,
2096                         0.0,
2097                         c, 0, 0,
2098                         alglib::serial);
2099                     time_glob_ser_loc_ser += alglib_impl::ae_tickcount()-t0;
2100                     alglib::_ae_set_global_threading(default_global_threading); // restore
2101 
2102                     // global serial, local parallel
2103                     t0 = alglib_impl::ae_tickcount();
2104                     alglib::setglobalthreading(alglib::serial);
2105                     alglib::rmatrixgemm(
2106                         n, n, n,
2107                         1.0,
2108                         a, 0, 0, 0,
2109                         b, 0, 0, 0,
2110                         0.0,
2111                         c, 0, 0,
2112                         alglib::parallel);
2113                     time_glob_ser_loc_smp += alglib_impl::ae_tickcount()-t0;
2114                     alglib::_ae_set_global_threading(default_global_threading); // restore
2115 
2116                     // global parallel, local serial
2117                     t0 = alglib_impl::ae_tickcount();
2118                     alglib::setglobalthreading(alglib::parallel);
2119                     alglib::rmatrixgemm(
2120                         n, n, n,
2121                         1.0,
2122                         a, 0, 0, 0,
2123                         b, 0, 0, 0,
2124                         0.0,
2125                         c, 0, 0,
2126                         alglib::serial);
2127                     time_glob_smp_loc_ser += alglib_impl::ae_tickcount()-t0;
2128                     alglib::_ae_set_global_threading(default_global_threading); // restore
2129 
2130                     // global parallel, local parallel
2131                     t0 = alglib_impl::ae_tickcount();
2132                     alglib::setglobalthreading(alglib::parallel);
2133                     alglib::rmatrixgemm(
2134                         n, n, n,
2135                         1.0,
2136                         a, 0, 0, 0,
2137                         b, 0, 0, 0,
2138                         0.0,
2139                         c, 0, 0,
2140                         alglib::parallel);
2141                     time_glob_smp_loc_smp += alglib_impl::ae_tickcount()-t0;
2142                     alglib::_ae_set_global_threading(default_global_threading); // restore
2143 
2144                     // global parallel, nworkers=1
2145                     t0 = alglib_impl::ae_tickcount();
2146                     alglib::setglobalthreading(alglib::parallel);
2147                     alglib::setnworkers(1);
2148                     alglib::rmatrixgemm(
2149                         n, n, n,
2150                         1.0,
2151                         a, 0, 0, 0,
2152                         b, 0, 0, 0,
2153                         0.0,
2154                         c, 0, 0);
2155                     time_glob_smp_nw1 += alglib_impl::ae_tickcount()-t0;
2156                     alglib::_ae_set_global_threading(default_global_threading); // restore
2157                     alglib::setnworkers(default_nworkers);
2158                 }
2159             }
2160             catch(ap_error)
2161             { passed = false; }
2162             printf(fmt_speedup, "* default speedup",     time_glob_ser/time_glob_ser);
2163             printf(fmt_speedup, "* serial (global)",     time_glob_ser/time_default);
2164             printf(fmt_speedup, "* serial (local)",      time_glob_ser/time_glob_ser_loc_ser);
2165             printf(fmt_speedup, "* serial (nworkers=1)", time_glob_ser/time_glob_smp_nw1);
2166             printf(fmt_speedup, "* parallel (global)",   time_glob_ser/time_glob_smp);
2167             printf(fmt_speedup, "* parallel (local) v1", time_glob_ser/time_glob_ser_loc_smp);
2168             passed = passed && (time_glob_ser/time_default         >0.85) && (time_glob_ser/time_default         <1.15);
2169             passed = passed && (time_glob_ser/time_glob_ser        >0.85) && (time_glob_ser/time_glob_ser        <1.15);
2170             passed = passed && (time_glob_ser/time_glob_ser_loc_ser>0.85) && (time_glob_ser/time_glob_ser_loc_ser<1.15);
2171             passed = passed && (time_glob_ser/time_glob_smp_loc_ser>0.85) && (time_glob_ser/time_glob_smp_loc_ser<1.15);
2172             passed = passed && (time_glob_ser/time_glob_smp_nw1    >0.85) && (time_glob_ser/time_glob_smp_nw1    <1.15);
2173             passed = passed && (time_glob_ser/time_glob_smp        >1.30);
2174             passed = passed && (time_glob_ser/time_glob_ser_loc_smp>1.30);
2175             passed = passed && (time_glob_ser/time_glob_smp_loc_smp>1.30);
2176             printf(fmt_str, "* test result", passed ? "OK" : "FAILED (soft failure)");
2177             fflush(stdout);
2178             //
2179             // soft failure:
2180             // // if( !passed )
2181             // //   return 1;
2182             //
2183         }
2184         else
2185         {
2186             printf(fmt_str, "* test skipped (no SMP)", "??");
2187             fflush(stdout);
2188         }
2189     }
2190 
2191     //
2192     // Testing issues which must be fixed
2193     //
2194     printf("Issues:\n");
2195     {
2196         //
2197         // Testing issue #505 (http://bugs.alglib.net/view.php?id=505) in optimizers.
2198         // This issue was present in ALL optimizers, but we test it only on two: CG and LM.
2199         //
2200         try
2201         {
2202             //
2203             // Test CG
2204             // Stopping criteria - EpsX
2205             //
2206             mincgstate state;
2207             mincgreport rep;
2208             real_1d_array x = "[0.0]";
2209             double x0 = 20*alglib::randomreal()-10;
2210             double epsx = 1.0E-9;
2211             mincgcreate(1, x, state);
2212             mincgsetcond(state, 0.0, 0.0, epsx, 0);
2213             mincgoptimize(state, func505_grad, NULL, &x0);
2214             mincgresults(state, x, rep);
2215             issue505_passed = issue505_passed && (fabs(4*pow(x[0]-x0,3))<1.0E-3);
2216         }
2217         catch(...)
2218         { issue505_passed = false; }
2219         try
2220         {
2221             //
2222             // Test LM
2223             // Stopping criteria - after |grad|<epsG
2224             //
2225             minlmstate state;
2226             minlmreport rep;
2227             real_1d_array x = "[0.0]";
2228             double x0 = 20*alglib::randomreal()-10;
2229             double epsx = 1.0E-9;
2230             minlmcreatevj(1, 2, x, state);
2231             minlmsetcond(state, epsx, 0);
2232             minlmoptimize(state, func505_vec, func505_jac, NULL, &x0);
2233             minlmresults(state, x, rep);
2234             issue505_passed = issue505_passed && (fabs(x[0]-x0)<1.0E-3);
2235         }
2236         catch(...)
2237         { issue505_passed = false; }
2238         printf(fmt_str, "* issue 505", issue505_passed ? "OK" : "FAILED");
2239         fflush(stdout);
2240         if( !issue505_passed )
2241             return 1;
2242 
2243         //
2244         // Testing issue #478 (http://bugs.alglib.net/view.php?id=478)
2245         // in high-quality RNG. It have to correctly handle random numbers
2246         // larger than 2^31.
2247         //
2248         // This test is performed only in 64-bit mode.
2249         //
2250         if( sizeof(alglib::ae_int_t)>4 )
2251         {
2252             //
2253             // 64-bit mode, perform test:
2254             // * use large NMax>2^31
2255             // * generate 1.000.000 random numbers
2256             // * use two bins - one for numbers less then NMax/2,
2257             //   another one for the rest of them
2258             // * bin sizes are equal to n0, n1
2259             // * both bins should be approximately equal, we use
2260             //   ad hoc threshold 0.45 < n0,n1 < 0.55.
2261             //
2262             try
2263             {
2264                 alglib::hqrndstate rs;
2265                 alglib::ae_int_t nmax[3];
2266                 alglib::ae_int_t ncnt = 3, nidx;
2267                 double n0, n1;
2268                 alglib::hqrndrandomize(rs);
2269 
2270                 //
2271                 // nmax:
2272                 // * first nmax is just large value to test basic uniformity of generator
2273                 //
2274                 nmax[0]  = 1000000;
2275                 nmax[0]  = nmax[0]*nmax[0];
2276                 nmax[1]  = 2147483562;
2277                 nmax[1] *= 1.5;
2278                 nmax[2]  = 2147483562;
2279                 nmax[2] *= 3;
2280 
2281                 for(nidx=0; nidx<ncnt; nidx++)
2282                 {
2283                     n0 = 0;
2284                     n1 = 0;
2285                     for(int i=0; i<1000000; i++)
2286                     {
2287                         alglib::ae_int_t v = alglib::hqrnduniformi(rs, nmax[nidx]);
2288                         if( v<nmax[nidx]/2 )
2289                             n0++;
2290                         else
2291                             n1++;
2292                         issue478_passed = issue478_passed && (v>=0) && (v<nmax[nidx]);
2293                     }
2294                     issue478_passed = issue478_passed && (n0/(n0+n1)>0.45);
2295                     issue478_passed = issue478_passed && (n0/(n0+n1)<0.55);
2296                     issue478_passed = issue478_passed && (n1/(n0+n1)>0.45);
2297                     issue478_passed = issue478_passed && (n1/(n0+n1)<0.55);
2298                 }
2299             }
2300             catch(...)
2301             { issue478_passed = false; }
2302             printf(fmt_str, "* issue 478", issue478_passed ? "OK" : "FAILED");
2303             fflush(stdout);
2304             if( !issue478_passed )
2305                 return 1;
2306         }
2307         else
2308         {
2309             //
2310             // 32-bit mode, skip test
2311             //
2312             printf(fmt_str, "* issue 478", "OK (skipped in 32-bit mode)");
2313             fflush(stdout);
2314         }
2315 
2316         //
2317         // Testing issue #528 (http://bugs.alglib.net/view.php?id=528)
2318         // in shared pool and smart pointer which leak memory.
2319         //
2320         // In order to test it we create pool, seed it with specially
2321         // created structure, perform several operations, then clear it.
2322         // We test allocation counter before and after this operation.
2323         //
2324 #ifdef AE_USE_ALLOC_COUNTER
2325         try
2326         {
2327             int alloc_cnt;
2328             alglib_impl::ae_state _alglib_env_state;
2329             alglib_impl::ae_frame _frame_block;
2330             alglib_impl::ae_shared_pool pool;
2331             alglib_impl::ae_smart_ptr ptr0, ptr1;
2332             void *p0, *p1;
2333             seedrec seed;
2334 
2335             // case #0: just seeding the pool
2336             alloc_cnt = alglib_impl::_alloc_counter;
2337             alglib_impl::ae_state_init(&_alglib_env_state);
2338             alglib_impl::ae_frame_make(&_alglib_env_state, &_frame_block);
2339             memset(&pool, 0, sizeof(pool));
2340             memset(&seed, 0, sizeof(seed));
2341             alglib_impl::ae_shared_pool_init(&pool, &_alglib_env_state, true);
2342             _seedrec_init(&seed, &_alglib_env_state, ae_true);
2343             alglib_impl::ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _seedrec_init, _seedrec_init_copy, _seedrec_destroy, &_alglib_env_state);
2344             alglib_impl::ae_state_clear(&_alglib_env_state);
2345             issue528_passed = issue528_passed && (alloc_cnt==alglib_impl::_alloc_counter);
2346 
2347             // case #1: seeding and retrieving, not recycling
2348             alloc_cnt = alglib_impl::_alloc_counter;
2349             alglib_impl::ae_state_init(&_alglib_env_state);
2350             alglib_impl::ae_frame_make(&_alglib_env_state, &_frame_block);
2351             memset(&seed, 0, sizeof(seed));
2352             memset(&pool, 0, sizeof(pool));
2353             memset(&ptr0, 0, sizeof(ptr0));
2354             alglib_impl::ae_smart_ptr_init(&ptr0, (void**)&p0, &_alglib_env_state, true);
2355             alglib_impl::ae_shared_pool_init(&pool, &_alglib_env_state, true);
2356             _seedrec_init(&seed, &_alglib_env_state, true);
2357             alglib_impl::ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _seedrec_init, _seedrec_init_copy, _seedrec_destroy, &_alglib_env_state);
2358             alglib_impl::ae_shared_pool_retrieve(&pool, &ptr0, &_alglib_env_state);
2359             alglib_impl::ae_state_clear(&_alglib_env_state);
2360             issue528_passed = issue528_passed && (alloc_cnt==alglib_impl::_alloc_counter);
2361 
2362             // case #2: seeding and retrieving twice to different pointers, recycling both
2363             alloc_cnt = alglib_impl::_alloc_counter;
2364             alglib_impl::ae_state_init(&_alglib_env_state);
2365             alglib_impl::ae_frame_make(&_alglib_env_state, &_frame_block);
2366             memset(&ptr0, 0, sizeof(ptr0));
2367             memset(&ptr1, 0, sizeof(ptr1));
2368             memset(&pool, 0, sizeof(pool));
2369             memset(&seed, 0, sizeof(seed));
2370             alglib_impl::ae_smart_ptr_init(&ptr0, (void**)&p0, &_alglib_env_state, true);
2371             alglib_impl::ae_smart_ptr_init(&ptr1, (void**)&p1, &_alglib_env_state, true);
2372             alglib_impl::ae_shared_pool_init(&pool, &_alglib_env_state, true);
2373             _seedrec_init(&seed, &_alglib_env_state, true);
2374             alglib_impl::ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _seedrec_init, _seedrec_init_copy, _seedrec_destroy, &_alglib_env_state);
2375             alglib_impl::ae_shared_pool_retrieve(&pool, &ptr0, &_alglib_env_state);
2376             alglib_impl::ae_shared_pool_retrieve(&pool, &ptr1, &_alglib_env_state);
2377             alglib_impl::ae_shared_pool_recycle(&pool,  &ptr0, &_alglib_env_state);
2378             alglib_impl::ae_shared_pool_recycle(&pool,  &ptr1, &_alglib_env_state);
2379             alglib_impl::ae_state_clear(&_alglib_env_state);
2380             issue528_passed = issue528_passed && (alloc_cnt==alglib_impl::_alloc_counter);
2381         }
2382         catch(...)
2383         { issue528_passed = false; }
2384         printf(fmt_str, "* issue 528", issue528_passed ? "OK" : "FAILED");
2385         fflush(stdout);
2386         if( !issue528_passed )
2387             return 1;
2388 #else
2389         printf(fmt_str, "* issue 528", "??");
2390         fflush(stdout);
2391 #endif
2392 
2393         //
2394         // Testing issue #591 (http://bugs.alglib.net/view.php?id=591)
2395         // in copying of object containing shared pool as one of its
2396         // fields.
2397         //
2398         // Unfixed ALGLIB crashes because of unneeded assertion in the
2399         // ae_shared_pool_init_copy() function.
2400         //
2401         try
2402         {
2403             alglib::multilayerperceptron net0, net1;
2404             alglib::real_1d_array x("[1,2]"), y0("[0,0]"), y1("[0,0]"), y2("[0,0]");
2405             alglib::mlpcreate0(2, 2, net0);
2406             alglib::mlpprocess(net0, x, y0);
2407 
2408             //
2409             // Test assignment constructor
2410             //
2411             net1 = net0;
2412             alglib::mlpprocess(net1, x, y1);
2413             issue591_passed = issue591_passed && (fabs(y0[0]-y1[0])<1.0E-9) && (fabs(y0[1]-y1[1])<1.0E-9);
2414 
2415             //
2416             // Test copy constructor
2417             //
2418             alglib::multilayerperceptron net2(net0);
2419             alglib::mlpprocess(net2, x, y2);
2420             issue591_passed = issue591_passed && (fabs(y0[0]-y2[0])<1.0E-9) && (fabs(y0[1]-y2[1])<1.0E-9);
2421         }
2422         catch(...)
2423         { issue591_passed = false; }
2424         printf(fmt_str, "* issue 591", issue591_passed ? "OK" : "FAILED");
2425         fflush(stdout);
2426         if( !issue591_passed )
2427             return 1;
2428 
2429         //
2430         // Task #594 (http://bugs.alglib.net/view.php?id=594) - additional
2431         // test for correctness of copying of objects. When we copy ALGLIB
2432         // object, indenendent new copy is created.
2433         //
2434         // This test checks both copying with copy constructor and assignment
2435         // constructor
2436         //
2437         try
2438         {
2439             alglib::multilayerperceptron net0, net1;
2440             alglib::real_1d_array x("[1,2]"), y0("[0,0]"), y1("[0,0]"), y2("[0,0]");
2441             alglib::mlpcreate0(2, 2, net0);
2442             alglib::mlpprocess(net0, x, y0);
2443 
2444             //
2445             // Test assignment and copy constructors:
2446             // * copy object with one of the constructors
2447             // * process vector with original network
2448             // * randomize original network
2449             // * process vector with copied networks and compare
2450             //
2451             net1 = net0;
2452             alglib::multilayerperceptron net2(net0);
2453             alglib::mlprandomize(net0);
2454             alglib::mlpprocess(net1, x, y1);
2455             alglib::mlpprocess(net2, x, y2);
2456             issue594_passed = issue594_passed && (fabs(y0[0]-y1[0])<1.0E-9) && (fabs(y0[1]-y1[1])<1.0E-9);
2457             issue594_passed = issue594_passed && (fabs(y0[0]-y2[0])<1.0E-9) && (fabs(y0[1]-y2[1])<1.0E-9);
2458         }
2459         catch(...)
2460         { issue594_passed = false; }
2461         printf(fmt_str, "* issue 594", issue594_passed ? "OK" : "FAILED");
2462         fflush(stdout);
2463         if( !issue594_passed )
2464             return 1;
2465 
2466         //
2467         // Issue 764#, potential memory leak in the smart pointer
2468         //
2469 #ifdef AE_USE_ALLOC_COUNTER
2470         try
2471         {
2472             int alloc_cnt;
2473             alglib_impl::ae_state _alglib_env_state;
2474             alglib_impl::ae_frame _frame_block;
2475             alglib_impl::ae_shared_pool pool;
2476             alglib_impl::ae_smart_ptr ptr0;
2477             void *p0, *p1;
2478             seedrec seed;
2479 
2480             // seeding shared pool and retrieving twice to same pointer, no recycling
2481             alloc_cnt = alglib_impl::_alloc_counter;
2482             alglib_impl::ae_state_init(&_alglib_env_state);
2483             alglib_impl::ae_frame_make(&_alglib_env_state, &_frame_block);
2484             memset(&ptr0, 0, sizeof(ptr0));
2485             memset(&pool, 0, sizeof(pool));
2486             memset(&seed, 0, sizeof(seed));
2487             alglib_impl::ae_smart_ptr_init(&ptr0, (void**)&p0, &_alglib_env_state, true);
2488             alglib_impl::ae_shared_pool_init(&pool, &_alglib_env_state, true);
2489             _seedrec_init(&seed, &_alglib_env_state, true);
2490             alglib_impl::ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _seedrec_init, _seedrec_init_copy, _seedrec_destroy, &_alglib_env_state);
2491             alglib_impl::ae_shared_pool_retrieve(&pool, &ptr0, &_alglib_env_state);
2492             alglib_impl::ae_shared_pool_retrieve(&pool, &ptr0, &_alglib_env_state);
2493             alglib_impl::ae_state_clear(&_alglib_env_state);
2494             issue764_passed = issue764_passed && (alloc_cnt==alglib_impl::_alloc_counter);
2495         }
2496         catch(...)
2497         { issue764_passed = false; }
2498         printf(fmt_str, "* issue 764", issue764_passed ? "OK" : "FAILED");
2499         fflush(stdout);
2500         if( !issue764_passed )
2501             return 1;
2502 #else
2503         printf(fmt_str, "* issue 764", "??");
2504         fflush(stdout);
2505 #endif
2506 
2507         //
2508         // Issue 813: MSVC is unable to handle longjmp() from catch() block; the code
2509         //            cycles forever.
2510         //
2511         {
2512             alglib::minlmstate state;
2513             alglib::real_1d_array x;
2514             x.setlength(1);
2515             x[0] = 0;
2516             alglib::minlmcreatev(1, x, 1e-5, state);
2517             issue813_passed = false;
2518             try
2519             {
2520                 alglib::minlmoptimize(state, &issue813_callback);
2521             }
2522             catch(...)
2523             {
2524                 issue813_passed = true;
2525             }
2526             printf(fmt_str, "* issue 813", issue813_passed ? "OK" : "FAILED");
2527             fflush(stdout);
2528             if( !issue813_passed )
2529                 return 1;
2530         }
2531 
2532         //
2533         // Issue 824: pre-3.16 versions of ALGLIB hide exceptions generated in user callbacks
2534         //
2535         {
2536             alglib::mincgstate state;
2537             alglib::real_1d_array x;
2538             x.setlength(1);
2539             x[0] = 0;
2540             alglib::mincgcreatef(1, x, 1e-5, state);
2541             issue824_passed = true;
2542 
2543             // throw int*
2544             try
2545             {
2546                 alglib::mincgoptimize(state, &issue824_callback_i);
2547             }
2548             catch(int*)
2549             {
2550             }
2551             catch(double *)
2552             {
2553                 issue824_passed = false;
2554             }
2555             catch(...)
2556             {
2557                 issue824_passed = false;
2558             }
2559 
2560             // throw double*
2561             try
2562             {
2563                 alglib::mincgoptimize(state, &issue824_callback_d);
2564             }
2565             catch(int*)
2566             {
2567                 issue824_passed = false;
2568             }
2569             catch(double *)
2570             {
2571             }
2572             catch(...)
2573             {
2574                 issue824_passed = false;
2575             }
2576 
2577             // done
2578             printf(fmt_str, "* issue 824", issue824_passed ? "OK" : "FAILED");
2579             fflush(stdout);
2580             if( !issue824_passed )
2581                 return 1;
2582         }
2583     }
2584 
2585     //
2586     // Performance testing
2587     //
2588     printf("Performance:\n");
2589     {
2590         {
2591             int _n[]       = { 16, 32, 64, 1024, 0};
2592             int i, j, k, t, nidx;
2593             for(nidx=0; _n[nidx]!=0; nidx++)
2594             {
2595                 //
2596                 // Settings:
2597                 // * n - matrix size
2598                 // * nrepeat - number of repeated multiplications, always divisible by 4
2599                 //
2600                 int n = _n[nidx];
2601                 double desiredflops = n>64 ? 1.0E10 : 1.0E9;
2602                 int nrepeat = (int)(desiredflops/(2*pow((double)n,3.0)));
2603                 nrepeat = 4*(nrepeat/4+1);
2604 
2605                 //
2606                 // Actual processing
2607                 //
2608                 alglib::real_2d_array a, b, c;
2609                 double perf0, perf1, perf2;
2610                 a.setlength(n, n);
2611                 b.setlength(n, n);
2612                 c.setlength(n, n);
2613                 for(i=0; i<n; i++)
2614                     for(j=0; j<n; j++)
2615                     {
2616                         a[i][j] = alglib::randomreal()-0.5;
2617                         b[i][j] = alglib::randomreal()-0.5;
2618                         c[i][j] = 0.0;
2619                     }
2620 
2621                 t = alglib_impl::ae_tickcount();
2622                 for(k=0; k<nrepeat; k++)
2623                     alglib::rmatrixgemm(
2624                         n, n, n,
2625                         1.0,
2626                         a, 0, 0, k%2,
2627                         b, 0, 0, (k/2)%2,
2628                         0.0,
2629                         c, 0, 0);
2630                 t = alglib_impl::ae_tickcount()-t;
2631                 perf0 = 1.0E-6*pow((double)n,3)*2.0*nrepeat/(0.001*t);
2632                 printf("* RGEMM-SEQ-%-4ld (MFLOPS)  %5.0lf\n", (long)n, (double)perf0);
2633 
2634                 alglib::setnworkers(0);
2635                 t = alglib_impl::ae_tickcount();
2636                 for(k=0; k<nrepeat; k++)
2637                     alglib::rmatrixgemm(
2638                         n, n, n,
2639                         1.0,
2640                         a, 0, 0, k%2,
2641                         b, 0, 0, (k/2)%2,
2642                         0.0,
2643                         c, 0, 0, alglib::parallel);
2644                 t = alglib_impl::ae_tickcount()-t;
2645                 perf2 = 1.0E-6*pow((double)n,3)*2.0*nrepeat/(0.001*t);
2646                 printf("* RGEMM-MTN-%-4ld           %4.1lfx\n", (long)n, (double)(perf2/perf0));
2647                 alglib::setnworkers(1);
2648 
2649             }
2650         }
2651     }
2652 
2653     //
2654     // Check allocation counter on exit
2655     //
2656 #ifdef AE_USE_ALLOC_COUNTER
2657     printf("Allocation counter checked... ");
2658 #ifdef _ALGLIB_HAS_WORKSTEALING
2659     alglib_impl::ae_free_disposed_items();
2660     alglib_impl::ae_complete_finalization_before_exit();
2661 #endif
2662     if( alglib_impl::_alloc_counter!=0 )
2663     {
2664         printf("FAILURE: alloc_counter is non-zero on end!\n");
2665         return 1;
2666     }
2667     else
2668         printf("OK\n");
2669 #endif
2670 
2671     //
2672     // Return
2673     //
2674     return 0;
2675 }
2676