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