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