]> rtime.felk.cvut.cz Git - opencv.git/blob - opencv/tests/cxcore/src/aarithm.cpp
round scalars in the case of integer arrays in adds, subrs and absdiffs tests (will...
[opencv.git] / opencv / tests / cxcore / src / aarithm.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 //////////////////////////////////////////////////////////////////////////////////////////
43 ////////////////// tests for arithmetic, logic and statistical functions /////////////////
44 //////////////////////////////////////////////////////////////////////////////////////////
45
46 #include "cxcoretest.h"
47 #include <float.h>
48
49 static const CvSize arithm_sizes[] = {{10,10}, {100,100}, {720,480}, {-1,-1}};
50 static const CvSize arithm_whole_sizes[] = {{10,10}, {720,480}, {720,480}, {-1,-1}};
51 static const int arithm_depths[] = { CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, -1 };
52 static const int arithm_channels[] = { 1, 2, 3, 4, -1 };
53 static const char* arithm_mask_param_names[] = { "size", "channels", "depth", "use_mask", 0 };
54 static const char* arithm_param_names[] = { "size", "channels", "depth", 0 };
55 static const char* minmax_param_names[] = { "size", "depth", 0 };
56
57 class CxCore_ArithmTestImpl : public CvArrTest
58 {
59 public:
60     CxCore_ArithmTestImpl( const char* test_name, const char* test_funcs,
61                            int _generate_scalars=0, bool _allow_mask=true, bool _calc_abs=false );
62 protected:
63     void prepare_to_validation( int test_case_idx );
64     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
65     void get_timing_test_array_types_and_sizes( int /*test_case_idx*/,
66                         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images );
67     void generate_scalars( int depth );
68     void finalize_scalar( CvScalar& s );
69     CvScalar alpha, beta, gamma;
70     int gen_scalars;
71     bool calc_abs;
72     bool test_nd;
73 };
74
75
76 CxCore_ArithmTestImpl::CxCore_ArithmTestImpl( const char* test_name, const char* test_funcs,
77                                               int _generate_scalars, bool _allow_mask, bool _calc_abs )
78     : CvArrTest( test_name, test_funcs, "" ),
79     gen_scalars(_generate_scalars), calc_abs(_calc_abs)
80 {
81     test_array[INPUT].push(NULL);
82     test_array[INPUT].push(NULL);
83     optional_mask = _allow_mask;
84
85     if( optional_mask )
86     {
87         test_array[INPUT_OUTPUT].push(NULL);
88         test_array[REF_INPUT_OUTPUT].push(NULL);
89         test_array[TEMP].push(NULL);
90         test_array[MASK].push(NULL);
91     }
92     else
93     {
94         test_array[OUTPUT].push(NULL);
95         test_array[REF_OUTPUT].push(NULL);
96     }
97     alpha = beta = gamma = cvScalarAll(0);
98
99     size_list = arithm_sizes;
100     whole_size_list = arithm_whole_sizes;
101     depth_list = arithm_depths;
102     cn_list = arithm_channels;
103     test_nd = false;
104 }
105
106
107 void CxCore_ArithmTestImpl::generate_scalars( int depth )
108 {
109     bool is_timing = ts->get_testing_mode() == CvTS::TIMING_MODE;
110     double ab_min_val = -1.;
111     double ab_max_val = 1.;
112     double gamma_min_val = depth == CV_8U ? -100 : depth < CV_32F ? -10000 : -1e6;
113     double gamma_max_val = depth == CV_8U ? 100 : depth < CV_32F ? 10000 : 1e6;
114     
115     if( gen_scalars )
116     {
117         CvRNG* rng = ts->get_rng();
118         int i;
119         double m = 3.;
120         for( i = 0; i < 4; i++ )
121         {
122             if( gen_scalars & 1 )
123             {
124                 alpha.val[i] = exp((cvTsRandReal(rng)-0.5)*m*2*CV_LOG2);
125                 alpha.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
126                 if( is_timing )
127                 {
128                     alpha.val[i] = MAX( alpha.val[i], ab_min_val );
129                     alpha.val[i] = MIN( alpha.val[i], ab_max_val );
130                 }
131             }
132             if( gen_scalars & 2 )
133             {
134                 beta.val[i] = exp((cvTsRandReal(rng)-0.5)*m*2*CV_LOG2);
135                 beta.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
136                 if( is_timing )
137                 {
138                     beta.val[i] = MAX( beta.val[i], ab_min_val );
139                     beta.val[i] = MIN( beta.val[i], ab_max_val );
140                 }
141             }
142             if( gen_scalars & 4 )
143             {
144                 gamma.val[i] = exp((cvTsRandReal(rng)-0.5)*m*2*CV_LOG2);
145                 gamma.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
146                 if( is_timing )
147                 {
148                     gamma.val[i] = MAX( gamma.val[i], gamma_min_val );
149                     gamma.val[i] = MIN( gamma.val[i], gamma_max_val );
150                 }
151             }
152         }
153     }
154
155     if( depth == CV_32F )
156     {
157         CvMat fl = cvMat( 1, 4, CV_32F, buf );
158         CvMat db = cvMat( 1, 4, CV_64F, 0 );
159
160         db.data.db = alpha.val;
161         cvTsConvert( &db, &fl );
162         cvTsConvert( &fl, &db );
163
164         db.data.db = beta.val;
165         cvTsConvert( &db, &fl );
166         cvTsConvert( &fl, &db );
167
168         db.data.db = gamma.val;
169         cvTsConvert( &db, &fl );
170         cvTsConvert( &fl, &db );
171     }
172 }
173
174 void CxCore_ArithmTestImpl::finalize_scalar( CvScalar& s )
175 {
176     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
177     if( depth < CV_32F )
178         s = cvScalar(cvRound(s.val[0]), cvRound(s.val[1]), cvRound(s.val[2]), cvRound(s.val[3]));
179 }
180
181 void CxCore_ArithmTestImpl::get_test_array_types_and_sizes( int test_case_idx,
182                                                             CvSize** sizes, int** types )
183 {
184     CvRNG* rng = ts->get_rng();
185     int depth = cvTsRandInt(rng)%(CV_64F+1);
186     int cn = cvTsRandInt(rng) % 4 + 1;
187     int i, j;
188     depth += depth == CV_8S;
189     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
190     generate_scalars( depth );
191
192     for( i = 0; i < max_arr; i++ )
193     {
194         int count = test_array[i].size();
195         int type = i != MASK ? CV_MAKETYPE(depth, cn) : CV_8UC1;
196         for( j = 0; j < count; j++ )
197         {
198             types[i][j] = type;
199         }
200     }
201     test_nd = cvTsRandInt(rng)%3 == 0;
202 }
203
204
205 void CxCore_ArithmTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
206                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
207 {
208     CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
209                                                       whole_sizes, are_images );
210     generate_scalars( types[INPUT][0] );
211     test_nd = false;
212 }
213
214
215 void CxCore_ArithmTestImpl::prepare_to_validation( int /*test_case_idx*/ )
216 {
217     const CvMat* mask = test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0;
218     CvMat* output = test_array[REF_INPUT_OUTPUT].size() > 0 ?
219         &test_mat[REF_INPUT_OUTPUT][0] : &test_mat[REF_OUTPUT][0];
220     CvMat* temp_dst = mask ? &test_mat[TEMP][0] : output;
221     cvTsAdd( &test_mat[INPUT][0], alpha,
222              test_array[INPUT].size() > 1 ? &test_mat[INPUT][1] : 0, beta,
223              gamma, temp_dst, calc_abs );
224     if( mask )
225         cvTsCopy( temp_dst, output, mask );
226 }
227
228
229 CxCore_ArithmTestImpl arithm( "arithm", "", 0, false );
230
231
232 class CxCore_ArithmTest : public CxCore_ArithmTestImpl
233 {
234 public:
235     CxCore_ArithmTest( const char* test_name, const char* test_funcs,
236                        int _generate_scalars=0, bool _allow_mask=true, bool _calc_abs=false );
237 };
238
239
240 CxCore_ArithmTest::CxCore_ArithmTest( const char* test_name, const char* test_funcs,
241                                       int _generate_scalars, bool _allow_mask, bool _calc_abs ) :
242     CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask, _calc_abs )
243 {
244     default_timing_param_names = optional_mask ? arithm_mask_param_names : arithm_param_names;
245         
246     // inherit the default parameters from arithmetical test
247     size_list = 0;
248     whole_size_list = 0;
249     depth_list = 0;
250     cn_list = 0;
251 }
252
253
254 ////////////////////////////// add /////////////////////////////
255
256 class CxCore_AddTest : public CxCore_ArithmTest
257 {
258 public:
259     CxCore_AddTest();
260 protected:
261     void run_func();
262 };
263
264 CxCore_AddTest::CxCore_AddTest()
265     : CxCore_ArithmTest( "arithm-add", "cvAdd", 0, true )
266 {
267     alpha = beta = cvScalarAll(1.);
268 }
269
270 void CxCore_AddTest::run_func()
271 {
272     if(!test_nd)
273     {
274         cvAdd( test_array[INPUT][0], test_array[INPUT][1],
275             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
276     }
277     else
278     {
279         cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
280         cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
281         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
282         if( !test_array[MASK][0] )
283             cv::add(a, b, c);
284         else
285             cv::add(a, b, c, cv::cvarrToMatND(test_array[MASK][0]));
286     }
287 }
288
289 CxCore_AddTest add_test;
290
291 ////////////////////////////// sub /////////////////////////////
292
293 class CxCore_SubTest : public CxCore_ArithmTest
294 {
295 public:
296     CxCore_SubTest();
297 protected:
298     void run_func();
299 };
300
301 CxCore_SubTest::CxCore_SubTest()
302     : CxCore_ArithmTest( "arithm-sub", "cvSub", 0, true )
303 {
304     alpha = cvScalarAll(1.);
305     beta = cvScalarAll(-1.);
306 }
307
308 void CxCore_SubTest::run_func()
309 {
310     if(!test_nd)
311     {
312         cvSub( test_array[INPUT][0], test_array[INPUT][1],
313             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
314     }
315     else
316     {
317         cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
318         cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
319         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
320         if( !test_array[MASK][0] )
321             cv::subtract(a, b, c);
322         else
323             cv::subtract(a, b, c, cv::cvarrToMatND(test_array[MASK][0]));
324     }
325 }
326
327 CxCore_SubTest sub_test;
328
329
330 ////////////////////////////// adds /////////////////////////////
331
332 class CxCore_AddSTest : public CxCore_ArithmTest
333 {
334 public:
335     CxCore_AddSTest();
336 protected:
337     void run_func();
338 };
339
340 CxCore_AddSTest::CxCore_AddSTest()
341     : CxCore_ArithmTest( "arithm-adds", "cvAddS", 4, true )
342 {
343     test_array[INPUT].pop();
344     alpha = cvScalarAll(1.);
345 }
346
347 void CxCore_AddSTest::run_func()
348 {
349     finalize_scalar(gamma);
350     if(!test_nd)
351     {
352         if( test_mat[INPUT][0].cols % 2 == 0 )
353             cvAddS( test_array[INPUT][0], gamma,
354                 test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
355         else
356         {
357             cv::Mat a = cv::cvarrToMat(test_array[INPUT][0]),
358                 c = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]);
359                 cv::subtract(a, -cv::Scalar(gamma), c, test_array[MASK][0] ?
360                     cv::cvarrToMat(test_array[MASK][0]) : cv::Mat());
361         }
362     }
363     else
364     {
365         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
366         cv::add( cv::cvarrToMatND(test_array[INPUT][0]),
367                  gamma, c, test_array[MASK][0] ?
368                  cv::cvarrToMatND(test_array[MASK][0]) : cv::MatND());
369     }
370 }
371
372 CxCore_AddSTest adds_test;
373
374 ////////////////////////////// subrs /////////////////////////////
375
376 class CxCore_SubRSTest : public CxCore_ArithmTest
377 {
378 public:
379     CxCore_SubRSTest();
380 protected:
381     void run_func();
382 };
383
384 CxCore_SubRSTest::CxCore_SubRSTest()
385     : CxCore_ArithmTest( "arithm-subrs", "cvSubRS", 4, true )
386 {
387     test_array[INPUT].pop();
388     alpha = cvScalarAll(-1.);
389 }
390
391 void CxCore_SubRSTest::run_func()
392 {
393     finalize_scalar(gamma);
394     if(!test_nd)
395     {
396         cvSubRS( test_array[INPUT][0], gamma,
397                 test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
398     }
399     else
400     {
401         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
402         cv::subtract( gamma,
403                 cv::cvarrToMatND(test_array[INPUT][0]),
404                 c, test_array[MASK][0] ?
405                     cv::cvarrToMatND(test_array[MASK][0]) : cv::MatND());
406     }
407 }
408
409 CxCore_SubRSTest subrs_test;
410
411 ////////////////////////////// addweighted /////////////////////////////
412
413 class CxCore_AddWeightedTest : public CxCore_ArithmTest
414 {
415 public:
416     CxCore_AddWeightedTest();
417 protected:
418     void get_test_array_types_and_sizes( int test_case_idx,
419                                           CvSize** sizes, int** types );
420     double get_success_error_level( int test_case_idx, int i, int j );
421     void run_func();
422 };
423
424 CxCore_AddWeightedTest::CxCore_AddWeightedTest()
425     : CxCore_ArithmTest( "arithm-addweighted", "cvAddWeighted", 7, false )
426 {
427 }
428
429 void CxCore_AddWeightedTest::get_test_array_types_and_sizes( int test_case_idx,
430                                                     CvSize** sizes, int** types )
431 {
432     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
433     alpha = cvScalarAll(alpha.val[0]);
434     beta = cvScalarAll(beta.val[0]);
435     gamma = cvScalarAll(gamma.val[0]);
436 }
437
438
439 double CxCore_AddWeightedTest::get_success_error_level( int test_case_idx, int i, int j )
440 {
441     int type = cvGetElemType(test_array[i][j]), depth = CV_MAT_DEPTH(type);
442     if( depth <= CV_32S )
443         return 2;
444     if( depth == CV_32F )
445     {
446         CvScalar low=cvScalarAll(0), high=low;
447         get_minmax_bounds(i,j,type, &low, &high);
448         double a = (fabs(alpha.val[0])+fabs(beta.val[0]))*(fabs(low.val[0])+fabs(high.val[0]));
449         double b = fabs(gamma.val[0]);
450         return (a+b)*500*FLT_EPSILON;
451     }
452     return CvArrTest::get_success_error_level( test_case_idx, i, j );
453 }
454
455
456 void CxCore_AddWeightedTest::run_func()
457 {
458     if(!test_nd)
459     {
460         cvAddWeighted( test_array[INPUT][0], alpha.val[0],
461                     test_array[INPUT][1], beta.val[0],
462                     gamma.val[0], test_array[OUTPUT][0] );
463     }
464     else
465     {
466         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
467         cv::addWeighted(cv::cvarrToMatND(test_array[INPUT][0]),
468                 alpha.val[0],
469                 cv::cvarrToMatND(test_array[INPUT][1]),
470                 beta.val[0], gamma.val[0], c);
471     }
472 }
473
474 CxCore_AddWeightedTest addweighted_test;
475
476
477 ////////////////////////////// absdiff /////////////////////////////
478
479 class CxCore_AbsDiffTest : public CxCore_ArithmTest
480 {
481 public:
482     CxCore_AbsDiffTest();
483 protected:
484     void run_func();
485 };
486
487 CxCore_AbsDiffTest::CxCore_AbsDiffTest()
488     : CxCore_ArithmTest( "arithm-absdiff", "cvAbsDiff", 0, false, true )
489 {
490     alpha = cvScalarAll(1.);
491     beta = cvScalarAll(-1.);
492 }
493
494 void CxCore_AbsDiffTest::run_func()
495 {
496     if(!test_nd)
497     {
498         cvAbsDiff( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
499     }
500     else
501     {
502         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
503         cv::absdiff(cv::cvarrToMatND(test_array[INPUT][0]),
504                 cv::cvarrToMatND(test_array[INPUT][1]),
505                  c );
506     }
507 }
508
509 CxCore_AbsDiffTest absdiff_test;
510
511 ////////////////////////////// absdiffs /////////////////////////////
512
513 class CxCore_AbsDiffSTest : public CxCore_ArithmTest
514 {
515 public:
516     CxCore_AbsDiffSTest();
517 protected:
518     void run_func();
519 };
520
521 CxCore_AbsDiffSTest::CxCore_AbsDiffSTest()
522     : CxCore_ArithmTest( "arithm-absdiffs", "cvAbsDiffS", 4, false, true )
523 {
524     alpha = cvScalarAll(-1.);
525     test_array[INPUT].pop();
526 }
527
528 void CxCore_AbsDiffSTest::run_func()
529 {
530     finalize_scalar(gamma);
531     if(!test_nd)
532     {
533         cvAbsDiffS( test_array[INPUT][0], test_array[OUTPUT][0], gamma );
534     }
535     else
536     {
537         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
538         cv::absdiff(cv::cvarrToMatND(test_array[INPUT][0]),
539                 gamma, c);
540     }
541 }
542
543 CxCore_AbsDiffSTest absdiffs_test;
544
545
546 ////////////////////////////// mul /////////////////////////////
547
548 static const char* mul_param_names[] = { "size", "scale", "channels", "depth", 0 };
549 static const char* mul_scale_flags[] = { "scale==1", "scale!=1", 0 };
550
551 class CxCore_MulTest : public CxCore_ArithmTest
552 {
553 public:
554     CxCore_MulTest();
555 protected:
556     void run_func();
557     void get_timing_test_array_types_and_sizes( int test_case_idx,
558                                                 CvSize** sizes, int** types,
559                                                 CvSize** whole_sizes, bool* are_images );
560     double get_success_error_level( int test_case_idx, int i, int j );
561     void print_timing_params( int test_case_idx, char* ptr, int params_left );
562     void prepare_to_validation( int test_case_idx );
563     int write_default_params( CvFileStorage* fs );
564 };
565
566
567 CxCore_MulTest::CxCore_MulTest()
568     : CxCore_ArithmTest( "arithm-mul", "cvMul", 4, false, false )
569 {
570     default_timing_param_names = mul_param_names;
571 }
572
573
574 int CxCore_MulTest::write_default_params( CvFileStorage* fs )
575 {
576     int code = CxCore_ArithmTest::write_default_params(fs);
577     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
578         return code;
579     write_string_list( fs, "scale", mul_scale_flags );
580     return code;
581 }
582
583
584 void CxCore_MulTest::get_timing_test_array_types_and_sizes( int test_case_idx,
585                                                     CvSize** sizes, int** types,
586                                                     CvSize** whole_sizes, bool* are_images )
587 {
588     CxCore_ArithmTest::get_timing_test_array_types_and_sizes( test_case_idx,
589                                     sizes, types, whole_sizes, are_images );
590     const char* scale_flag_str = cvReadString( find_timing_param( "scale" ), "scale==1" );
591     if( strstr( scale_flag_str, "==1" ) )
592         alpha.val[0] = 1.;
593     else
594     {
595         double val = alpha.val[0];
596         int depth = CV_MAT_DEPTH(types[INPUT][0]);
597         if( val == 1. )
598             val = 1./CV_PI;
599         if( depth == CV_16U || depth == CV_16S || depth == CV_32S )
600         {
601             double minmax = 1./cvTsMaxVal(depth);
602             if( val < -minmax )
603                 val = -minmax;
604             else if( val > minmax )
605                 val = minmax;
606             if( depth == CV_16U && val < 0 )
607                 val = -val;
608         }
609         alpha.val[0] = val;
610         ts->printf( CvTS::LOG, "alpha = %g\n", alpha.val[0] );
611     }
612 }
613
614
615 void CxCore_MulTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
616 {
617     sprintf( ptr, "%s,", alpha.val[0] == 1. ? "scale==1" : "scale!=1" );
618     ptr += strlen(ptr);
619     params_left--;
620     CxCore_ArithmTest::print_timing_params( test_case_idx, ptr, params_left );
621 }
622
623
624 double CxCore_MulTest::get_success_error_level( int test_case_idx, int i, int j )
625 {
626     if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
627     {
628         return gamma.val[0] != cvRound(gamma.val[0]);
629     }
630     else
631         return CvArrTest::get_success_error_level( test_case_idx, i, j );
632 }
633
634
635 void CxCore_MulTest::run_func()
636 {
637     if(!test_nd)
638     {
639         cvMul( test_array[INPUT][0], test_array[INPUT][1],
640               test_array[OUTPUT][0], alpha.val[0] );
641     }
642     else
643     {
644         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
645         cv::multiply(cv::cvarrToMatND(test_array[INPUT][0]),
646                      cv::cvarrToMatND(test_array[INPUT][1]),
647                      c, alpha.val[0]);
648     }
649 }
650
651 void CxCore_MulTest::prepare_to_validation( int /*test_case_idx*/ )
652 {
653     cvTsMul( &test_mat[INPUT][0], &test_mat[INPUT][1],
654              cvScalarAll(alpha.val[0]),
655              &test_mat[REF_OUTPUT][0] );
656 }
657
658 CxCore_MulTest mul_test;
659
660 ////////////////////////////// div /////////////////////////////
661
662 class CxCore_DivTest : public CxCore_ArithmTest
663 {
664 public:
665     CxCore_DivTest();
666 protected:
667     void run_func();
668     void print_timing_params( int test_case_idx, char* ptr, int params_left );
669     void prepare_to_validation( int /*test_case_idx*/ );
670 };
671
672 CxCore_DivTest::CxCore_DivTest()
673     : CxCore_ArithmTest( "arithm-div", "cvDiv", 4, false, false )
674 {
675 }
676
677 void CxCore_DivTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
678 {
679     sprintf( ptr, "s*A(i)/B(i)," );
680     ptr += strlen(ptr);
681     params_left--;
682     CxCore_ArithmTest::print_timing_params( test_case_idx, ptr, params_left );
683 }
684
685 void CxCore_DivTest::run_func()
686 {
687     if(!test_nd)
688     {
689         cvDiv( test_array[INPUT][0], test_array[INPUT][1],
690               test_array[OUTPUT][0], alpha.val[0] );
691     }
692     else
693     {
694         cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
695         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
696         cv::divide(cv::cvarrToMatND(test_array[INPUT][0]),
697                    b, c, alpha.val[0]);
698     }
699 }
700
701 void CxCore_DivTest::prepare_to_validation( int /*test_case_idx*/ )
702 {
703     cvTsDiv( &test_mat[INPUT][0], &test_mat[INPUT][1],
704              cvScalarAll(alpha.val[0]),
705              &test_mat[REF_OUTPUT][0] );
706 }
707
708 CxCore_DivTest div_test;
709
710 ////////////////////////////// recip /////////////////////////////
711
712 class CxCore_RecipTest : public CxCore_ArithmTest
713 {
714 public:
715     CxCore_RecipTest();
716 protected:
717     void run_func();
718     void print_timing_params( int test_case_idx, char* ptr, int params_left );
719     void prepare_to_validation( int /*test_case_idx*/ );
720 };
721
722 CxCore_RecipTest::CxCore_RecipTest()
723     : CxCore_ArithmTest( "arithm-recip", "cvDiv", 4, false, false )
724 {
725     test_array[INPUT].pop();
726 }
727
728 void CxCore_RecipTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
729 {
730     sprintf( ptr, "s/B(i)," );
731     ptr += strlen(ptr);
732     params_left--;
733     CxCore_ArithmTest::print_timing_params( test_case_idx, ptr, params_left );
734 }
735
736 void CxCore_RecipTest::run_func()
737 {
738     if(!test_nd)
739     {
740         cvDiv( 0, test_array[INPUT][0],
741               test_array[OUTPUT][0], gamma.val[0] );
742     }
743     else
744     {
745         cv::MatND b = cv::cvarrToMatND(test_array[INPUT][0]);
746         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
747         cv::divide(gamma.val[0], b, c);
748     }
749 }
750
751 void CxCore_RecipTest::prepare_to_validation( int /*test_case_idx*/ )
752 {
753     cvTsDiv( 0, &test_mat[INPUT][0],
754              cvScalarAll(gamma.val[0]),
755              &test_mat[REF_OUTPUT][0] );
756 }
757
758 CxCore_RecipTest recip_test;
759
760
761 ///////////////// matrix copy/initializing/permutations /////////////////////
762                                                    
763 class CxCore_MemTestImpl : public CxCore_ArithmTestImpl
764 {
765 public:
766     CxCore_MemTestImpl( const char* test_name, const char* test_funcs,
767                         int _generate_scalars=0, bool _allow_mask=true );
768 protected:
769     double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
770 };
771
772 CxCore_MemTestImpl::CxCore_MemTestImpl( const char* test_name, const char* test_funcs,
773                                         int _generate_scalars, bool _allow_mask ) :
774     CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask, false )
775 {
776 }
777
778 double CxCore_MemTestImpl::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
779 {
780     return 0;
781 }
782
783 CxCore_MemTestImpl mem_test( "mem", "", 0, false );
784
785
786 class CxCore_MemTest : public CxCore_MemTestImpl
787 {
788 public:
789     CxCore_MemTest( const char* test_name, const char* test_funcs,
790                     int _generate_scalars=0, bool _allow_mask=true );
791 };
792
793 CxCore_MemTest::CxCore_MemTest( const char* test_name, const char* test_funcs,
794                                 int _generate_scalars, bool _allow_mask ) :
795     CxCore_MemTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask )
796 {
797     default_timing_param_names = optional_mask ? arithm_mask_param_names : arithm_param_names;
798         
799     // inherit the default parameters from arithmerical test
800     size_list = 0;
801     whole_size_list = 0;
802     depth_list = 0;
803     cn_list = 0;
804 }
805
806
807 ///////////////// setidentity /////////////////////
808
809 class CxCore_SetIdentityTest : public CxCore_MemTest
810 {
811 public:
812     CxCore_SetIdentityTest();
813 protected:
814     void run_func();
815     void prepare_to_validation( int test_case_idx );
816 };
817
818
819 CxCore_SetIdentityTest::CxCore_SetIdentityTest() :
820     CxCore_MemTest( "mem-setidentity", "cvSetIdentity", 4, false )
821 {
822     test_array[INPUT].clear();
823 }
824
825
826 void CxCore_SetIdentityTest::run_func()
827 {
828     if(!test_nd)
829         cvSetIdentity(test_array[OUTPUT][0], gamma);
830     else
831     {
832         cv::Mat a = cv::cvarrToMat(test_array[OUTPUT][0]);
833         cv::setIdentity(a, gamma);
834     }
835 }
836
837
838 void CxCore_SetIdentityTest::prepare_to_validation( int )
839 {
840     cvTsSetIdentity( &test_mat[REF_OUTPUT][0], gamma );
841 }
842
843 CxCore_SetIdentityTest setidentity_test;
844
845
846 ///////////////// SetZero /////////////////////
847
848 class CxCore_SetZeroTest : public CxCore_MemTest
849 {
850 public:
851     CxCore_SetZeroTest();
852 protected:
853     void run_func();
854     void prepare_to_validation( int test_case_idx );
855 };
856
857
858 CxCore_SetZeroTest::CxCore_SetZeroTest() :
859     CxCore_MemTest( "mem-setzero", "cvSetZero", 0, false )
860 {
861     test_array[INPUT].clear();
862 }
863
864
865 void CxCore_SetZeroTest::run_func()
866 {
867     if(!test_nd)
868         cvSetZero(test_array[OUTPUT][0]);
869     else
870     {
871         cv::MatND a = cv::cvarrToMatND(test_array[OUTPUT][0]);
872         a.setTo(cv::Scalar());
873     }
874 }
875
876
877 void CxCore_SetZeroTest::prepare_to_validation( int )
878 {
879     cvTsZero( &test_mat[REF_OUTPUT][0] );
880 }
881
882 CxCore_SetZeroTest setzero_test;
883
884
885 ///////////////// Set /////////////////////
886
887 class CxCore_FillTest : public CxCore_MemTest
888 {
889 public:
890     CxCore_FillTest();
891 protected:
892     void run_func();
893     void prepare_to_validation( int test_case_idx );
894 };
895
896
897 CxCore_FillTest::CxCore_FillTest() :
898     CxCore_MemTest( "mem-fill", "cvSet", 4, true )
899 {
900     test_array[INPUT].clear();
901 }
902
903
904 void CxCore_FillTest::run_func()
905 {
906     const CvArr* mask = test_array[MASK][0];
907     if(!test_nd)
908         cvSet(test_array[INPUT_OUTPUT][0], gamma, mask);
909     else
910     {
911         cv::MatND a = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
912         a.setTo(gamma, mask ? cv::cvarrToMatND(mask) : cv::MatND());
913     }
914 }
915
916
917 void CxCore_FillTest::prepare_to_validation( int )
918 {
919     if( test_array[MASK][0] )
920     {
921         cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), gamma, &test_mat[TEMP][0], 0 );
922         cvTsCopy( &test_mat[TEMP][0], &test_mat[REF_INPUT_OUTPUT][0], &test_mat[MASK][0] );
923     }
924     else
925     {
926         cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), gamma, &test_mat[REF_INPUT_OUTPUT][0], 0 );
927     }
928 }
929
930 CxCore_FillTest fill_test;
931
932
933 ///////////////// Copy /////////////////////
934
935 class CxCore_CopyTest : public CxCore_MemTest
936 {
937 public:
938     CxCore_CopyTest();
939 protected:
940     double get_success_error_level( int test_case_idx, int i, int j );
941     void run_func();
942     void prepare_to_validation( int test_case_idx );
943 };
944
945
946 CxCore_CopyTest::CxCore_CopyTest() :
947     CxCore_MemTest( "mem-copy", "cvCopy", 0, true )
948 {
949     test_array[INPUT].pop();
950 }
951
952
953 double CxCore_CopyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
954 {
955     return 0;
956 }
957
958
959 void CxCore_CopyTest::run_func()
960 {
961     const CvArr* mask = test_array[MASK][0];
962     if(!test_nd)
963         cvCopy(test_array[INPUT][0], test_array[INPUT_OUTPUT][0], mask);
964     else
965     {
966         cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
967         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
968         if(!mask)
969             a.copyTo(c);
970         else
971             a.copyTo(c, cv::cvarrToMatND(mask));
972     }
973 }
974
975
976 void CxCore_CopyTest::prepare_to_validation( int )
977 {
978     cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_INPUT_OUTPUT][0],
979               test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0 );
980 }
981
982 CxCore_CopyTest copy_test;
983
984 ///////////////// Transpose /////////////////////
985
986 class CxCore_TransposeTest : public CxCore_MemTest
987 {
988 public:
989     CxCore_TransposeTest();
990 protected:
991     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
992     void get_timing_test_array_types_and_sizes( int test_case_idx,
993                                                 CvSize** sizes, int** types,
994                                                 CvSize** whole_sizes, bool* are_images );
995     int prepare_test_case( int test_case_idx );
996     void run_func();
997     void prepare_to_validation( int test_case_idx );
998     bool inplace;
999 };
1000
1001
1002 CxCore_TransposeTest::CxCore_TransposeTest() :
1003     CxCore_MemTest( "mem-transpose", "cvTranspose", 0, false ), inplace(false)
1004 {
1005     test_array[INPUT].pop();
1006 }
1007
1008
1009 void CxCore_TransposeTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1010 {
1011     int bits = cvTsRandInt(ts->get_rng());
1012     CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1013
1014     inplace = false;
1015     if( bits & 1 )
1016     {
1017         sizes[INPUT][0].height = sizes[INPUT][0].width;
1018         inplace = (bits & 2) != 0;
1019     }
1020
1021     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][0].height, sizes[INPUT][0].width );
1022 }
1023
1024
1025 void CxCore_TransposeTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1026                 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1027 {
1028     CxCore_MemTest::get_timing_test_array_types_and_sizes( test_case_idx,
1029                                     sizes, types, whole_sizes, are_images );
1030     CvSize size = sizes[INPUT][0];
1031     if( size.width != size.height )
1032     {
1033         sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] =
1034         whole_sizes[OUTPUT][0] = whole_sizes[REF_OUTPUT][0] = cvSize(size.height,size.width);
1035     }
1036 }
1037
1038
1039 int CxCore_TransposeTest::prepare_test_case( int test_case_idx )
1040 {
1041     int code = CxCore_MemTest::prepare_test_case( test_case_idx );
1042     if( inplace && code > 0 )
1043         cvTsCopy( &test_mat[INPUT][0], &test_mat[OUTPUT][0] );
1044     return code;
1045 }
1046
1047 void CxCore_TransposeTest::run_func()
1048 {
1049     cvTranspose( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], test_array[OUTPUT][0]);
1050 }
1051
1052
1053 void CxCore_TransposeTest::prepare_to_validation( int )
1054 {
1055     cvTsTranspose( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0] );
1056 }
1057
1058 CxCore_TransposeTest transpose_test;
1059
1060
1061 ///////////////// Flip /////////////////////
1062
1063 static const int flip_codes[] = { 0, 1, -1, INT_MIN };
1064 static const char* flip_strings[] = { "center", "vert", "horiz", 0 };
1065 static const char* flip_param_names[] = { "size", "flip_op", "channels", "depth", 0 };
1066
1067 class CxCore_FlipTest : public CxCore_MemTest
1068 {
1069 public:
1070     CxCore_FlipTest();
1071 protected:
1072     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1073     void get_timing_test_array_types_and_sizes( int test_case_idx,
1074                                                 CvSize** sizes, int** types,
1075                                                 CvSize** whole_sizes, bool* are_images );
1076     int prepare_test_case( int test_case_idx );
1077     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1078     void run_func();
1079     void prepare_to_validation( int test_case_idx );
1080     int write_default_params( CvFileStorage* fs );
1081     int flip_type;
1082     bool inplace;
1083 };
1084
1085
1086 CxCore_FlipTest::CxCore_FlipTest() :
1087     CxCore_MemTest( "mem-flip", "cvFlip", 0, false ), flip_type(0), inplace(false)
1088 {
1089     test_array[INPUT].pop();
1090     default_timing_param_names = flip_param_names;
1091 }
1092
1093
1094 int CxCore_FlipTest::write_default_params( CvFileStorage* fs )
1095 {
1096     int i, code = CxCore_MemTest::write_default_params(fs);
1097     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1098         return code;
1099     start_write_param( fs );
1100     cvStartWriteStruct( fs, "flip_op", CV_NODE_SEQ + CV_NODE_FLOW );
1101     for( i = 0; flip_codes[i] != INT_MIN; i++ )
1102         cvWriteString( fs, 0, flip_strings[flip_codes[i]+1] );
1103     cvEndWriteStruct(fs);
1104     return code;
1105 }
1106
1107
1108 void CxCore_FlipTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1109 {
1110     int bits = cvTsRandInt(ts->get_rng());
1111     CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1112
1113     flip_type = (bits & 3) - 2;
1114     flip_type += flip_type == -2;
1115     inplace = (bits & 4) != 0;
1116 }
1117
1118
1119 void CxCore_FlipTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1120                                                     CvSize** sizes, int** types,
1121                                                     CvSize** whole_sizes, bool* are_images )
1122 {
1123     CxCore_MemTest::get_timing_test_array_types_and_sizes( test_case_idx,
1124                                     sizes, types, whole_sizes, are_images );
1125     const char* flip_op_str = cvReadString( find_timing_param( "flip_op" ), "center" );
1126     if( strcmp( flip_op_str, "vert" ) == 0 )
1127         flip_type = 0;
1128     else if( strcmp( flip_op_str, "horiz" ) == 0 )
1129         flip_type = 1;
1130     else
1131         flip_type = -1;
1132 }
1133
1134
1135 void CxCore_FlipTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1136 {
1137     sprintf( ptr, "%s,", flip_type > 0 ? "horiz" : flip_type < 0 ? "center" : "vert" );
1138     ptr += strlen(ptr);
1139     params_left--;
1140     CxCore_MemTest::print_timing_params( test_case_idx, ptr, params_left );
1141 }
1142
1143
1144 int CxCore_FlipTest::prepare_test_case( int test_case_idx )
1145 {
1146     int code = CxCore_MemTest::prepare_test_case( test_case_idx );
1147     if( inplace && code > 0 )
1148         cvTsCopy( &test_mat[INPUT][0], &test_mat[OUTPUT][0] );
1149     return code;
1150 }
1151
1152
1153 void CxCore_FlipTest::run_func()
1154 {
1155     cvFlip(inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], test_array[OUTPUT][0], flip_type);
1156 }
1157
1158
1159 void CxCore_FlipTest::prepare_to_validation( int )
1160 {
1161     cvTsFlip( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], flip_type );
1162 }
1163
1164 CxCore_FlipTest flip_test;
1165
1166
1167 ///////////////// Split/Merge /////////////////////
1168
1169 static const char* split_merge_types[] = { "all", "single", 0 };
1170 static int split_merge_channels[] = { 2, 3, 4, -1 };
1171 static const char* split_merge_param_names[] = { "size", "planes", "channels", "depth", 0 };
1172
1173 class CxCore_SplitMergeBaseTest : public CxCore_MemTest
1174 {
1175 public:
1176     CxCore_SplitMergeBaseTest( const char* test_name, const char* test_funcs, int _is_split );
1177 protected:
1178     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1179     void get_timing_test_array_types_and_sizes( int test_case_idx,
1180                                                 CvSize** sizes, int** types,
1181                                                 CvSize** whole_sizes, bool* are_images );
1182     int prepare_test_case( int test_case_idx );
1183     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1184     void prepare_to_validation( int test_case_idx );
1185     int write_default_params( CvFileStorage* fs );
1186     bool are_images;
1187     int is_split, coi; 
1188     void* hdrs[4];
1189 };
1190
1191
1192 CxCore_SplitMergeBaseTest::CxCore_SplitMergeBaseTest( const char* test_name,
1193     const char* test_funcs, int _is_split )
1194     : CxCore_MemTest( test_name, test_funcs, 0, false ), are_images(false), is_split(_is_split), coi(0)
1195 {
1196     test_array[INPUT].pop();
1197     if( is_split )
1198         ;
1199     else
1200     {
1201         test_array[OUTPUT].clear();
1202         test_array[REF_OUTPUT].clear();
1203         test_array[INPUT_OUTPUT].push(NULL);
1204         test_array[REF_INPUT_OUTPUT].push(NULL);
1205     }
1206     memset( hdrs, 0, sizeof(hdrs) );
1207
1208     default_timing_param_names = split_merge_param_names;
1209     cn_list = split_merge_channels;
1210 }
1211
1212
1213 int CxCore_SplitMergeBaseTest::write_default_params( CvFileStorage* fs )
1214 {
1215     int code = CxCore_MemTest::write_default_params(fs);
1216     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1217         return code;
1218     write_string_list( fs, "planes", split_merge_types );
1219     return code;
1220 }
1221
1222
1223 void CxCore_SplitMergeBaseTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1224 {
1225     int cn, depth;
1226     CvRNG* rng = ts->get_rng();
1227     CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1228     cn = cvTsRandInt(rng)%3 + 2;
1229     depth = CV_MAT_DEPTH(types[INPUT][0]);
1230     
1231     if( is_split )
1232     {
1233         types[INPUT][0] = CV_MAKETYPE(depth, cn);
1234         types[OUTPUT][0] = types[REF_OUTPUT][0] = depth;
1235     }
1236     else
1237     {
1238         types[INPUT][0] = depth;
1239         types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1240     }
1241
1242     if( (cvTsRandInt(rng) & 3) != 0 )
1243     {
1244         coi = cvTsRandInt(rng) % cn;
1245     }
1246     else
1247     {
1248         CvSize size = sizes[INPUT][0];
1249         size.height *= cn;
1250
1251         if( is_split )
1252             sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = size;
1253         else
1254             sizes[INPUT][0] = size;
1255         coi = -1;
1256     }
1257
1258     are_images = cvTsRandInt(rng)%2 != 0;
1259 }
1260
1261
1262 void CxCore_SplitMergeBaseTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1263                     CvSize** sizes, int** types, CvSize** whole_sizes, bool* _are_images )
1264 {
1265     CxCore_MemTest::get_timing_test_array_types_and_sizes( test_case_idx,
1266                                     sizes, types, whole_sizes, _are_images );
1267     const char* split_merge_type = cvReadString( find_timing_param( "planes" ), "all" );
1268     int type0 = types[INPUT][0];
1269     int depth = CV_MAT_DEPTH(type0);
1270     int cn = CV_MAT_CN(type0);
1271     CvSize size = sizes[INPUT][0];
1272
1273     if( strcmp( split_merge_type, "single" ) == 0 )
1274         coi = cvTsRandInt(ts->get_rng()) % cn;
1275     else
1276     {
1277         coi = -1;
1278         size.height *= cn;
1279     }
1280
1281     if( is_split )
1282     {
1283         types[OUTPUT][0] = types[REF_OUTPUT][0] = depth;
1284         sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = size;
1285         
1286         // planes are put into separate arrays, not ROI's
1287         whole_sizes[OUTPUT][0] = whole_sizes[REF_OUTPUT][0] = size;
1288     }
1289     else
1290     {
1291         types[INPUT][0] = depth;
1292         sizes[INPUT][0] = size;
1293         
1294         // planes are put into separate arrays, not ROI's
1295         whole_sizes[INPUT][0] = size;
1296     }
1297
1298     are_images = false;
1299 }
1300
1301
1302 void CxCore_SplitMergeBaseTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1303 {
1304     int i;
1305     
1306     sprintf( ptr, "%s,", coi >= 0 ? "single" : "all" );
1307     ptr += strlen(ptr);
1308     params_left--;
1309
1310     // at once, delete the headers, though is not very good from structural point of view ...
1311     for( i = 0; i < 4; i++ )
1312         cvRelease( &hdrs[i] );
1313
1314     CxCore_MemTest::print_timing_params( test_case_idx, ptr, params_left );
1315 }
1316
1317
1318 int CxCore_SplitMergeBaseTest::prepare_test_case( int test_case_idx )
1319 {
1320     int code = CxCore_MemTest::prepare_test_case( test_case_idx );
1321     if( code > 0 )
1322     {
1323         CvMat* input = &test_mat[INPUT][0];
1324         CvMat* output = &test_mat[is_split ? OUTPUT : INPUT_OUTPUT][0];
1325         CvMat* merged = is_split ? input : output;
1326         CvMat* planes = is_split ? output : input;
1327         int depth = CV_MAT_DEPTH(merged->type);
1328         int i, cn = CV_MAT_CN(merged->type), y = 0;
1329         CvSize sz = cvGetMatSize(merged);
1330
1331         for( i = 0; i < cn; i++ )
1332         {
1333             if( coi < 0 || coi == i )
1334             {
1335                 if( are_images )
1336                     hdrs[i] = cvCreateImageHeader( sz, cvIplDepth(depth), 1 );
1337                 else
1338                     hdrs[i] = cvCreateMatHeader( sz.height, sz.width, depth );
1339                 cvSetData( hdrs[i], planes->data.ptr + planes->step*y, planes->step );
1340                 y += sz.height;
1341             }
1342         }
1343     }
1344
1345     return code;
1346 }
1347
1348
1349 void CxCore_SplitMergeBaseTest::prepare_to_validation( int )
1350 {
1351     CvMat* input = &test_mat[INPUT][0];
1352     CvMat* output = &test_mat[is_split ? REF_OUTPUT : REF_INPUT_OUTPUT][0];
1353     CvMat* merged = is_split ? input : output;
1354     CvMat* planes = is_split ? output : input;
1355     int i, cn = CV_MAT_CN(merged->type), y = 0;
1356     CvSize sz = cvGetSize(merged);
1357
1358     for( i = 0; i < cn; i++ )
1359     {
1360         if( coi < 0 || coi == i )
1361         {
1362             CvMat stub, *h;
1363             cvSetData( hdrs[i], planes->data.ptr + planes->step*y, planes->step );
1364             h = cvGetMat( hdrs[i], &stub );
1365             if( is_split )
1366                 cvTsExtract( input, h, i );
1367             else
1368                 cvTsInsert( h, output, i );
1369             cvSetData( hdrs[i], 0, 0 );
1370             cvRelease( &hdrs[i] );
1371             y += sz.height;
1372         }
1373     }
1374 }
1375
1376
1377 class CxCore_SplitTest : public CxCore_SplitMergeBaseTest
1378 {
1379 public:
1380     CxCore_SplitTest();
1381 protected:
1382     void run_func();
1383 };
1384
1385
1386 CxCore_SplitTest::CxCore_SplitTest() :
1387     CxCore_SplitMergeBaseTest( "mem-split", "cvSplit", 1 )
1388 {
1389 }
1390
1391
1392 void CxCore_SplitTest::run_func()
1393 {
1394     int i, nz = (hdrs[0] != 0) + (hdrs[1] != 0) + (hdrs[2] != 0) + (hdrs[3] != 0);
1395     
1396     if(!test_nd || nz != CV_MAT_CN(test_mat[INPUT][0].type))
1397         cvSplit( test_array[INPUT][0], hdrs[0], hdrs[1], hdrs[2], hdrs[3] );
1398     else
1399     {
1400         cv::MatND _hdrs[4];
1401         for( i = 0; i < nz; i++ )
1402             _hdrs[i] = cv::cvarrToMatND(hdrs[i]);
1403         cv::split(cv::cvarrToMatND(test_array[INPUT][0]), _hdrs);
1404     }
1405 }
1406
1407 CxCore_SplitTest split_test;
1408
1409 class CxCore_MergeTest : public CxCore_SplitMergeBaseTest
1410 {
1411 public:
1412     CxCore_MergeTest();
1413 protected:
1414     void run_func();
1415 };
1416
1417
1418 CxCore_MergeTest::CxCore_MergeTest() :
1419     CxCore_SplitMergeBaseTest( "mem-merge", "cvMerge", 0 )
1420 {
1421 }
1422
1423
1424 void CxCore_MergeTest::run_func()
1425 {
1426     int i, nz = (hdrs[0] != 0) + (hdrs[1] != 0) + (hdrs[2] != 0) + (hdrs[3] != 0);
1427     
1428     if(!test_nd || nz != CV_MAT_CN(test_mat[INPUT_OUTPUT][0].type))
1429         cvMerge( hdrs[0], hdrs[1], hdrs[2], hdrs[3], test_array[INPUT_OUTPUT][0] );
1430     else
1431     {
1432         cv::MatND _hdrs[4], dst = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
1433         for( i = 0; i < nz; i++ )
1434             _hdrs[i] = cv::cvarrToMatND(hdrs[i]);
1435         cv::merge(_hdrs, nz, dst);
1436     }
1437 }
1438
1439 CxCore_MergeTest merge_test;
1440
1441 ///////////////// CompleteSymm /////////////////////
1442
1443 class CxCore_CompleteSymm : public CvArrTest
1444 {
1445 public:
1446     CxCore_CompleteSymm();
1447 protected:
1448     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1449     int prepare_test_case( int test_case_idx );
1450     void run_func();
1451     void prepare_to_validation( int test_case_idx );
1452         int LtoR; //flags 
1453 };
1454
1455 CxCore_CompleteSymm::CxCore_CompleteSymm() :
1456     CvArrTest("matrix-symm", "cvCompleteSymm", "Test of cvCompleteSymm function")
1457 {
1458         /*Generates 1 input and 1 outputs (by default we have 2 inputs and 1 output)*/
1459         test_array[INPUT].clear();
1460         test_array[INPUT].push(NULL);
1461         test_array[OUTPUT].clear();
1462         test_array[OUTPUT].push(NULL);
1463         test_array[REF_OUTPUT].clear();
1464         test_array[REF_OUTPUT].push(NULL);
1465 }
1466
1467
1468 void CxCore_CompleteSymm::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1469 {
1470     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1471     sizes[INPUT][0] =sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][0].height, sizes[INPUT][0].height );
1472
1473         /*Making input and output matrixes one-channel*/
1474         int type;
1475         switch (test_case_idx % 3)
1476         {
1477                 case 0:
1478                         type = CV_32FC1;
1479                         break;
1480                 case 1:
1481                         type = CV_32SC1;
1482                         break;
1483                 default:
1484                         type = CV_64FC1;
1485         }
1486         types[OUTPUT][0] = types[INPUT][0] = types[REF_OUTPUT][0] = type;
1487 }
1488
1489 int CxCore_CompleteSymm::prepare_test_case( int test_case_idx )
1490 {
1491     int code = CvArrTest::prepare_test_case( test_case_idx );
1492         if (code)
1493         {
1494                 CvRNG* rng = ts->get_rng();
1495                 unsigned val = cvRandInt(rng);
1496                 LtoR = val % 2;
1497                 cvConvert(&test_mat[INPUT][0], &test_mat[OUTPUT][0]);
1498         }
1499         return code;
1500 }
1501
1502 void CxCore_CompleteSymm::run_func()
1503 {
1504         cvCompleteSymm(&test_mat[OUTPUT][0],LtoR);
1505 }
1506
1507 void CxCore_CompleteSymm::prepare_to_validation( int )
1508 {
1509         CvMat* ref_output = cvCreateMat(test_mat[OUTPUT][0].rows, test_mat[OUTPUT][0].cols, CV_64F); 
1510         CvMat* input = cvCreateMat(test_mat[INPUT][0].rows, test_mat[INPUT][0].cols, CV_64F);
1511         cvConvert(&test_mat[INPUT][0], input);
1512         
1513         for (int i=0;i<input->rows;i++)
1514         {
1515                 ref_output->data.db[i*input->cols+i]=input->data.db[i*input->cols+i];
1516                 if (LtoR)
1517                 {
1518                         for (int j=0;j<i;j++)
1519                         {
1520                                 ref_output->data.db[j*input->cols+i] = ref_output->data.db[i*input->cols+j]=input->data.db[i*input->cols+j];
1521                         }
1522                                 
1523                 }
1524                 else 
1525                 {
1526                         for (int j=0;j<i;j++)
1527                         {
1528                                 ref_output->data.db[j*input->cols+i] = ref_output->data.db[i*input->cols+j]=input->data.db[j*input->cols+i];
1529                         }
1530                 }
1531         }
1532
1533         cvConvert(ref_output, &test_mat[REF_OUTPUT][0]);
1534         cvReleaseMat(&input);
1535         cvReleaseMat(&ref_output);
1536 }
1537
1538 CxCore_CompleteSymm complete_symm;
1539
1540
1541 ////////////////////////////// Sort /////////////////////////////////
1542
1543 class CxCore_SortTest : public CxCore_MemTest
1544 {
1545 public:
1546     CxCore_SortTest();
1547 protected:
1548     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1549     int prepare_test_case( int test_case_idx );
1550     void run_func();
1551     void prepare_to_validation( int test_case_idx );
1552         int flags; //flags for sorting
1553 private:
1554         static int compareIndexes (const void * a, const void * b); // comparing two elements of the matrix with pointers sorting
1555         static int compare(const void * a, const void * b); // comparing two elements of the matrix with pointers sorting
1556         bool useIndexMatrix;
1557         bool useInPlaceSort;
1558         CvMat* input;
1559
1560 };
1561
1562 CxCore_SortTest::CxCore_SortTest() :
1563     CxCore_MemTest( "matrix-sort", "cvSort", 0, false )
1564 {
1565         /*Generates 1 input and 2 outputs (by default we have 2 inputs and 1 output)*/
1566         test_array[INPUT].clear();
1567         test_array[INPUT].push(NULL);
1568         test_array[OUTPUT].push(NULL);
1569         test_array[REF_OUTPUT].push(NULL);
1570 }
1571
1572
1573 void CxCore_SortTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1574 {
1575     CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1576     sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(sizes[INPUT][0].height, sizes[INPUT][0].width );
1577         types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_32SC1;
1578
1579         /*Making input and output matrixes one-channel*/
1580         types[OUTPUT][0] = types[INPUT][0] = CV_MAKETYPE(CV_MAT_DEPTH(types[INPUT][0]), 1);
1581         types[REF_OUTPUT][0] = CV_MAKETYPE(CV_MAT_DEPTH(types[REF_OUTPUT][0]), 1);
1582 }
1583
1584 int CxCore_SortTest::prepare_test_case( int test_case_idx )
1585 {
1586         if (test_case_idx==0)
1587         {
1588                 useIndexMatrix=true;
1589                 useInPlaceSort=false;
1590         }
1591    int code = CxCore_MemTest::prepare_test_case( test_case_idx );
1592
1593    if( code > 0 )
1594         {
1595                 //Copying input data
1596                 input = cvCreateMat(test_mat[INPUT][0].rows, test_mat[INPUT][0].cols, CV_64F);
1597                 cvConvert(&test_mat[INPUT][0], input);
1598                 CvRNG* rng = ts->get_rng();
1599                 unsigned val = cvRandInt(rng);
1600         // Setting up flags
1601                 switch (val%4)
1602                 {
1603                         case 0:
1604                                 flags = CV_SORT_EVERY_ROW + CV_SORT_DESCENDING;
1605                                 break;
1606                         case 1:
1607                                 flags = CV_SORT_EVERY_ROW + CV_SORT_ASCENDING;
1608                                 break;
1609                         case 2:
1610                                 flags = CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING;
1611                                 break;
1612                         case 3:
1613                                 flags = CV_SORT_EVERY_COLUMN + CV_SORT_ASCENDING;
1614                                 break;
1615                 }
1616                 if (val%3) 
1617                         useIndexMatrix = !useIndexMatrix;
1618
1619                 if (val%5) 
1620                         useInPlaceSort = !useInPlaceSort;
1621
1622         }
1623     return code;
1624 }
1625
1626 void CxCore_SortTest::run_func()
1627 {
1628         //test_mat[OUTPUT][0] is sorted matrix
1629         //test_mat[OUTPUT][1] is index matrix
1630         if (useInPlaceSort)
1631         {
1632                 cvConvert(&test_mat[INPUT][0], &test_mat[OUTPUT][0]);
1633                 if (useIndexMatrix)
1634                         cvSort(&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][1]),flags);
1635                 else
1636                 {
1637                         cvSort(&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][0]),0,flags);
1638                 }
1639
1640         }
1641         else
1642         {
1643                 if (useIndexMatrix)
1644                         cvSort(&(test_mat[INPUT][0]),&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][1]),flags);
1645                 else
1646                 {
1647                         cvSort(&(test_mat[INPUT][0]),&(test_mat[OUTPUT][0]),0,flags);
1648                 }
1649         }
1650 }
1651
1652 int CxCore_SortTest::compareIndexes (const void * a, const void * b)
1653 {
1654         double zero = 1e-30;
1655         double res=(**((double**)a)-**((double**)b));
1656         return res<-zero?-1:(res>zero?1:0);
1657 }
1658 int CxCore_SortTest::compare (const void * a, const void * b)
1659 {
1660         return *((int*)a)-*((int*)b);
1661 }
1662
1663 void CxCore_SortTest::prepare_to_validation(int)
1664 {
1665         /*Creating matrixes copies to work with*/
1666         CvMat* ref_indexes = cvCreateMat(test_mat[REF_OUTPUT][1].rows, test_mat[REF_OUTPUT][1].cols, CV_32SC1); 
1667         CvMat* indexes = cvCreateMat(test_mat[OUTPUT][1].rows, test_mat[OUTPUT][1].cols, CV_32SC1); 
1668         CvMat* ref_output = cvCreateMat(test_mat[OUTPUT][0].rows, test_mat[OUTPUT][0].cols,CV_64F); 
1669         
1670         /*Copying data*/
1671         cvConvert(&test_mat[REF_OUTPUT][1], ref_indexes);
1672         cvConvert(&test_mat[OUTPUT][1], indexes);
1673
1674         /*Following block generates REF_OUTPUT indexes matrix*/
1675         if ((flags == (CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)) ||(flags == (CV_SORT_EVERY_ROW+CV_SORT_DESCENDING)))
1676         for (int i=0;i<test_mat[REF_OUTPUT][1].rows;i++)
1677                 for (int j=0;j<test_mat[REF_OUTPUT][1].cols;j++)
1678                         ref_indexes->data.i[ref_indexes->cols*i + j]=j;
1679         else 
1680         for (int i=0;i<test_mat[REF_OUTPUT][1].rows;i++)
1681                 for (int j=0;j<test_mat[REF_OUTPUT][1].cols;j++)
1682                         ref_indexes->data.i[ref_indexes->cols*i + j]=i;
1683         cvConvert(ref_indexes, &test_mat[REF_OUTPUT][1]);
1684         /*End of block*/
1685
1686         /* Matrix User's Sorting Algorithm */
1687         int order = -1; // order of sorting (ASCENDING or DESCENDING)
1688         //// Following to variables are for sorting rows or cols in one block without any conditions (if statements)
1689         short rowsSort=0;
1690         short colsSort=0;
1691         if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_COLUMN+CV_SORT_ASCENDING)) order=1;
1692         if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_ROW+CV_SORT_DESCENDING)) rowsSort=1;
1693         else colsSort=1;
1694         int i,j;
1695         
1696         // For accessing [i,j] element using index matrix we can use following formula
1697         // input->data.db[(input->cols*i+ref_indexes->cols*i+j)*rowsSort+(cols*(ref_indexes->cols*i+j)+j)*colsSort];
1698
1699     if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_ROW+CV_SORT_DESCENDING))
1700         {
1701                 double** row = new double*[input->cols];
1702                 for (i=0;i<input->rows; i++)
1703                 {
1704                         for (int j=0;j<input->cols;j++)
1705                                 row[j]=&(input->data.db[(input->cols*i+j)]);
1706                         qsort(row,input->cols,sizeof(row[0]),&CxCore_SortTest::compareIndexes);
1707                         for (int j=0;j<ref_indexes->cols;j++)
1708                         {
1709                                 if (order==1)
1710                                         ref_indexes->data.i[ref_indexes->cols*i+j]=(int)(row[j]-&(input->data.db[input->cols*i]));
1711                                 else
1712                                         ref_indexes->data.i[ref_indexes->cols*(i+1)-1-j]=(int)(row[j]-&(input->data.db[input->cols*i]));
1713                         }
1714                 }
1715                 delete[] row;
1716         }
1717         else
1718         {
1719                 double** col = new double*[input->rows];
1720                 for (j=0;j<input->cols; j++)
1721                 {
1722                         for (int i=0;i<input->rows;i++)
1723                                 col[i]=&(input->data.db[(input->cols*i+j)]);
1724                         qsort(col,input->rows,sizeof(col[0]),&CxCore_SortTest::compareIndexes);
1725                         for (int i=0;i<ref_indexes->rows;i++)
1726                         {
1727                                 if (order==1)
1728                                         ref_indexes->data.i[ref_indexes->cols*i+j]=(int)((col[i]-&(input->data.db[j]))/(ref_output->cols));
1729                                 else
1730                                         ref_indexes->data.i[ref_indexes->cols*(ref_indexes->rows-1-i)+j]=(int)(col[i]-&(input->data.db[j]))/(ref_output->cols);
1731                         }
1732                 }
1733                 delete[] col;
1734         }
1735
1736         /*End of Sort*/
1737
1738         int n;
1739         for (i=0;i<input->rows;i++)
1740                 for (j=0;j<input->cols;j++)
1741                 {
1742                         n=(input->cols*i+ref_indexes->data.i[ref_indexes->cols*i+j])*rowsSort+
1743                         (input->cols*(ref_indexes->data.i[ref_indexes->cols*i+j])+j)*colsSort;
1744                         ref_output->data.db[ref_output->cols*i+j] = input->data.db[n];
1745                 }
1746
1747         if (useIndexMatrix)
1748         {
1749                 /* Comparing indexes matrixes */
1750                 if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_ROW+CV_SORT_DESCENDING))
1751                 {
1752                         int begin=0,end=0;
1753                         double temp;
1754                         for (i=0;i<indexes->rows;i++)
1755                         {
1756                                 for (j=0;j<indexes->cols-1;j++)
1757                                         if (ref_output->data.db[ref_output->cols*i+j]==ref_output->data.db[ref_output->cols*i+j+1])
1758                                         {
1759                                                 temp=ref_output->data.db[ref_output->cols*i+j];
1760                                                 begin=j++;
1761                                                 while ((j<ref_output->cols)&&(temp==ref_output->data.db[ref_output->cols*i+j])) j++;
1762                                                 end=--j;
1763                                                 int* row = new int[end-begin+1];
1764                                                 int* row1 = new int[end-begin+1];
1765
1766                                                 for (int k=0;k<=end-begin;k++)
1767                                                 {
1768                                                         row[k]=ref_indexes->data.i[ref_indexes->cols*i+k+begin];
1769                                                         row1[k]=indexes->data.i[indexes->cols*i+k+begin];
1770                                                 }
1771                                                 qsort(row,end-begin+1,sizeof(row[0]),&CxCore_SortTest::compare);
1772                                                 qsort(row1,end-begin+1,sizeof(row1[0]),&CxCore_SortTest::compare);
1773                                                 for (int k=0;k<=end-begin;k++)
1774                                                 {
1775                                                         ref_indexes->data.i[ref_indexes->cols*i+k+begin]=row[k];
1776                                                         indexes->data.i[indexes->cols*i+k+begin]=row1[k];
1777                                                 }       
1778                                                 delete[] row;
1779                                                 delete[] row1;
1780                                         }
1781                         }
1782                 }
1783                 else
1784                 {
1785                         int begin=0,end=0;
1786                         double temp;
1787                         for (j=0;j<indexes->cols;j++)
1788                         {
1789                                 for (i=0;i<indexes->rows-1;i++)
1790                                         if (ref_output->data.db[ref_output->cols*i+j]==ref_output->data.db[ref_output->cols*(i+1)+j])
1791                                         {
1792                                                 temp=ref_output->data.db[ref_output->cols*i+j];
1793                                                 begin=i++;
1794                                                 while ((i<ref_output->rows)&&(temp==ref_output->data.db[ref_output->cols*i+j])) i++;
1795                                                 end=--i;
1796
1797                                                 int* col = new int[end-begin+1];
1798                                                 int* col1 = new int[end-begin+1];
1799
1800                                                 for (int k=0;k<=end-begin;k++)
1801                                                 {
1802                                                         col[k]=ref_indexes->data.i[ref_indexes->cols*(k+begin)+j];
1803                                                         col1[k]=indexes->data.i[indexes->cols*(k+begin)+j];
1804                                                 }
1805                                                 qsort(col,end-begin+1,sizeof(col[0]),&CxCore_SortTest::compare);
1806                                                 qsort(col1,end-begin+1,sizeof(col1[0]),&CxCore_SortTest::compare);
1807                                                 for (int k=0;k<=end-begin;k++)
1808                                                 {
1809                                                         ref_indexes->data.i[ref_indexes->cols*(k+begin)+j]=col[k];
1810                                                         indexes->data.i[indexes->cols*(k+begin)+j]=col1[k];
1811                                                 }       
1812                                                 delete[] col;
1813                                                 delete[] col1;
1814                                         }
1815                         }
1816                 }
1817         /* End of compare*/
1818         cvConvert(ref_indexes, &test_mat[REF_OUTPUT][1]);
1819         cvConvert(indexes, &test_mat[OUTPUT][1]);
1820         }
1821         else
1822         {
1823                 cvConvert(ref_indexes, &test_mat[REF_OUTPUT][1]);
1824                 cvConvert(ref_indexes, &test_mat[OUTPUT][1]);
1825         }
1826
1827         cvConvert(ref_output, &test_mat[REF_OUTPUT][0]);
1828
1829         /*releasing matrixes*/
1830         cvReleaseMat(&ref_output); 
1831         cvReleaseMat(&input); 
1832         cvReleaseMat(&indexes); 
1833         cvReleaseMat(&ref_indexes);   
1834 }
1835
1836 CxCore_SortTest sort_test;
1837
1838 ////////////////////////////// min/max  /////////////////////////////
1839
1840 class CxCore_MinMaxBaseTest : public CxCore_ArithmTest
1841 {
1842 public:
1843     CxCore_MinMaxBaseTest( const char* test_name, const char* test_funcs,
1844                            int _op_type, int _generate_scalars=0 );
1845 protected:
1846     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1847     double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
1848     void prepare_to_validation( int /*test_case_idx*/ );
1849     int op_type;
1850 };
1851
1852 CxCore_MinMaxBaseTest::CxCore_MinMaxBaseTest( const char* test_name, const char* test_funcs,
1853                                               int _op_type, int _generate_scalars )
1854     : CxCore_ArithmTest( test_name, test_funcs, _generate_scalars, false, false ), op_type(_op_type)
1855 {
1856     if( _generate_scalars )
1857         test_array[INPUT].pop();
1858     default_timing_param_names = minmax_param_names;
1859 }
1860
1861 double CxCore_MinMaxBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1862 {
1863     return 0;
1864 }
1865
1866 void CxCore_MinMaxBaseTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1867 {
1868     int i, j;
1869     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1870     for( i = 0; i < max_arr; i++ )
1871     {
1872         int count = test_array[i].size();
1873         for( j = 0; j < count; j++ )
1874         {
1875             types[i][j] &= ~CV_MAT_CN_MASK;            
1876         }
1877     }
1878 }
1879
1880 void CxCore_MinMaxBaseTest::prepare_to_validation( int /*test_case_idx*/ )
1881 {
1882     if( !gen_scalars )
1883         cvTsMinMax( &test_mat[INPUT][0], &test_mat[INPUT][1],
1884                     &test_mat[REF_OUTPUT][0], op_type );
1885     else
1886         cvTsMinMaxS( &test_mat[INPUT][0], gamma.val[0],
1887                      &test_mat[REF_OUTPUT][0], op_type );
1888 }
1889
1890
1891 class CxCore_MinTest : public CxCore_MinMaxBaseTest
1892 {
1893 public:
1894     CxCore_MinTest();
1895 protected:
1896     void run_func();
1897 };
1898
1899
1900 CxCore_MinTest::CxCore_MinTest()
1901     : CxCore_MinMaxBaseTest( "arithm-min", "cvMin", CV_TS_MIN, 0 )
1902 {
1903 }
1904
1905 void CxCore_MinTest::run_func()
1906 {
1907     if(!test_nd)
1908     {
1909         cvMin( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1910     }
1911     else
1912     {
1913         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
1914         cv::min(cv::cvarrToMatND(test_array[INPUT][0]),
1915                 cv::cvarrToMatND(test_array[INPUT][1]), c);
1916     }
1917 }
1918
1919 CxCore_MinTest min_test;
1920
1921
1922 ////////////////////////////// max /////////////////////////////
1923
1924 class CxCore_MaxTest : public CxCore_MinMaxBaseTest
1925 {
1926 public:
1927     CxCore_MaxTest();
1928 protected:
1929     void run_func();
1930 };
1931
1932 CxCore_MaxTest::CxCore_MaxTest()
1933     : CxCore_MinMaxBaseTest( "arithm-max", "cvMax", CV_TS_MAX, 0 )
1934 {
1935 }
1936
1937 void CxCore_MaxTest::run_func()
1938 {
1939     if(!test_nd)
1940     {
1941         cvMax( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1942     }
1943     else
1944     {
1945         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
1946         cv::max(cv::cvarrToMatND(test_array[INPUT][0]),
1947                 cv::cvarrToMatND(test_array[INPUT][1]), c);
1948     }
1949 }
1950
1951 CxCore_MaxTest max_test;
1952
1953
1954 ////////////////////////////// mins /////////////////////////////
1955
1956 class CxCore_MinSTest : public CxCore_MinMaxBaseTest
1957 {
1958 public:
1959     CxCore_MinSTest();
1960 protected:
1961     void run_func();
1962 };
1963
1964 CxCore_MinSTest::CxCore_MinSTest()
1965     : CxCore_MinMaxBaseTest( "arithm-mins", "cvMinS", CV_TS_MIN, 4 )
1966 {
1967 }
1968
1969 void CxCore_MinSTest::run_func()
1970 {
1971     if(!test_nd)
1972     {
1973         cvMinS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
1974     }
1975     else
1976     {
1977         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
1978         cv::min(cv::cvarrToMatND(test_array[INPUT][0]),
1979                 gamma.val[0], c);
1980     }
1981 }
1982
1983 CxCore_MinSTest mins_test;
1984
1985 ////////////////////////////// maxs /////////////////////////////
1986
1987 class CxCore_MaxSTest : public CxCore_MinMaxBaseTest
1988 {
1989 public:
1990     CxCore_MaxSTest();
1991 protected:
1992     void run_func();
1993 };
1994
1995 CxCore_MaxSTest::CxCore_MaxSTest()
1996     : CxCore_MinMaxBaseTest( "arithm-maxs", "cvMaxS", CV_TS_MAX, 4 )
1997 {
1998 }
1999
2000 void CxCore_MaxSTest::run_func()
2001 {
2002     if(!test_nd)
2003     {
2004         cvMaxS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
2005     }
2006     else
2007     {
2008         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
2009         cv::max(cv::cvarrToMatND(test_array[INPUT][0]),
2010                 gamma.val[0], c);
2011     }
2012 }
2013
2014 CxCore_MaxSTest maxs_test;
2015
2016
2017 //////////////////////////////// logic ///////////////////////////////////////
2018
2019 class CxCore_LogicTestImpl : public CxCore_ArithmTestImpl
2020 {
2021 public:
2022     CxCore_LogicTestImpl( const char* test_name, const char* test_funcs, int _logic_op,
2023                       int _generate_scalars=0, bool _allow_mask=true );
2024 protected:
2025     void prepare_to_validation( int test_case_idx );
2026     int logic_op;
2027 };
2028
2029 CxCore_LogicTestImpl::CxCore_LogicTestImpl( const char* test_name, const char* test_funcs,
2030                             int _logic_op, int _generate_scalars, bool _allow_mask )
2031     : CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask, false ),
2032     logic_op(_logic_op)
2033 {
2034     if( _generate_scalars )
2035         test_array[INPUT].pop();
2036 }
2037
2038 void CxCore_LogicTestImpl::prepare_to_validation( int /*test_case_idx*/ )
2039 {
2040     int ref_output_idx = optional_mask ? REF_INPUT_OUTPUT : REF_OUTPUT;
2041     int output_idx = optional_mask ? INPUT_OUTPUT : OUTPUT;
2042     const CvMat* mask = test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0;
2043     CvMat* dst = mask ? &test_mat[TEMP][0] : &test_mat[ref_output_idx][0];
2044     int i;
2045     if( test_array[INPUT].size() > 1 )
2046     {
2047         cvTsLogic( &test_mat[INPUT][0], &test_mat[INPUT][1], dst, logic_op );
2048     }
2049     else
2050     {
2051         cvTsLogicS( &test_mat[INPUT][0], gamma, dst, logic_op );
2052     }
2053     if( mask )
2054         cvTsCopy( dst, &test_mat[ref_output_idx][0], mask );
2055     
2056     for( i = 0; i < 2; i++ )
2057     {
2058         dst = i == 0 ? &test_mat[ref_output_idx][0] : &test_mat[output_idx][0];
2059
2060         if( CV_IS_MAT(dst) )
2061         {
2062             CvMat* mat = (CvMat*)dst;
2063             mat->cols *= CV_ELEM_SIZE(mat->type);
2064             mat->type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_8UC1;
2065         }
2066         else
2067         {
2068             IplImage* img = (IplImage*)dst;
2069             int elem_size;
2070         
2071             assert( CV_IS_IMAGE(dst) );
2072             elem_size = ((img->depth & 255)>>3)*img->nChannels;
2073             img->width *= elem_size;
2074         
2075             if( img->roi )
2076             {
2077                 img->roi->xOffset *= elem_size;
2078                 img->roi->width *= elem_size;
2079             }
2080             img->depth = IPL_DEPTH_8U;
2081             img->nChannels = 1;
2082         }
2083     }
2084 }
2085
2086 CxCore_LogicTestImpl logic_test("logic", "", -1, 0, false );
2087
2088 class CxCore_LogicTest : public CxCore_LogicTestImpl
2089 {
2090 public:
2091     CxCore_LogicTest( const char* test_name, const char* test_funcs, int _logic_op,
2092                       int _generate_scalars=0, bool _allow_mask=true );
2093 };
2094
2095 CxCore_LogicTest::CxCore_LogicTest( const char* test_name, const char* test_funcs,
2096                             int _logic_op, int _generate_scalars, bool _allow_mask )
2097     : CxCore_LogicTestImpl( test_name, test_funcs, _logic_op, _generate_scalars, _allow_mask )
2098 {
2099     default_timing_param_names = optional_mask ? arithm_mask_param_names : arithm_param_names;
2100
2101     // inherit the default parameters from arithmerical test
2102     size_list = 0;
2103     whole_size_list = 0;
2104     depth_list = 0;
2105     cn_list = 0;
2106 }
2107
2108
2109 ///////////////////////// and //////////////////////////
2110
2111 class CxCore_AndTest : public CxCore_LogicTest
2112 {
2113 public:
2114     CxCore_AndTest();
2115 protected:
2116     void run_func();
2117 };
2118
2119 CxCore_AndTest::CxCore_AndTest()
2120     : CxCore_LogicTest( "logic-and", "cvAnd", CV_TS_LOGIC_AND )
2121 {
2122 }
2123
2124 void CxCore_AndTest::run_func()
2125 {
2126     if(!test_nd)
2127     {
2128         cvAnd( test_array[INPUT][0], test_array[INPUT][1],
2129               test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
2130     }
2131     else
2132     {
2133         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
2134         cv::bitwise_and(cv::cvarrToMatND(test_array[INPUT][0]),
2135                         cv::cvarrToMatND(test_array[INPUT][1]),
2136                         c, cv::cvarrToMatND(test_array[MASK][0]));
2137     }
2138 }
2139
2140 CxCore_AndTest and_test;
2141
2142
2143 class CxCore_AndSTest : public CxCore_LogicTest
2144 {
2145 public:
2146     CxCore_AndSTest();
2147 protected:
2148     void run_func();
2149 };
2150
2151 CxCore_AndSTest::CxCore_AndSTest()
2152     : CxCore_LogicTest( "logic-ands", "cvAndS", CV_TS_LOGIC_AND, 4 )
2153 {
2154 }
2155
2156 void CxCore_AndSTest::run_func()
2157 {
2158     if(!test_nd)
2159     {
2160         cvAndS( test_array[INPUT][0], gamma,
2161               test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
2162     }
2163     else
2164     {
2165         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
2166         cv::bitwise_and(cv::cvarrToMatND(test_array[INPUT][0]),
2167                         gamma, c,
2168                         cv::cvarrToMatND(test_array[MASK][0]));
2169     }
2170 }
2171
2172 CxCore_AndSTest ands_test;
2173
2174
2175 ///////////////////////// or /////////////////////////
2176
2177 class CxCore_OrTest : public CxCore_LogicTest
2178 {
2179 public:
2180     CxCore_OrTest();
2181 protected:
2182     void run_func();
2183 };
2184
2185 CxCore_OrTest::CxCore_OrTest()
2186     : CxCore_LogicTest( "logic-or", "cvOr", CV_TS_LOGIC_OR )
2187 {
2188 }
2189
2190 void CxCore_OrTest::run_func()
2191 {
2192     if(!test_nd)
2193     {
2194         cvOr( test_array[INPUT][0], test_array[INPUT][1],
2195               test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
2196     }
2197     else
2198     {
2199         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
2200         cv::bitwise_or(cv::cvarrToMatND(test_array[INPUT][0]),
2201                         cv::cvarrToMatND(test_array[INPUT][1]),
2202                         c, cv::cvarrToMatND(test_array[MASK][0]));
2203     }
2204     
2205 }
2206
2207 CxCore_OrTest or_test;
2208
2209
2210 class CxCore_OrSTest : public CxCore_LogicTest
2211 {
2212 public:
2213     CxCore_OrSTest();
2214 protected:
2215     void run_func();
2216 };
2217
2218 CxCore_OrSTest::CxCore_OrSTest()
2219     : CxCore_LogicTest( "logic-ors", "cvOrS", CV_TS_LOGIC_OR, 4 )
2220 {
2221 }
2222
2223 void CxCore_OrSTest::run_func()
2224 {
2225     if(!test_nd)
2226     {
2227         cvOrS( test_array[INPUT][0], gamma,
2228                test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
2229     }
2230     else
2231     {
2232         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
2233         cv::bitwise_or(cv::cvarrToMatND(test_array[INPUT][0]),
2234                         gamma, c,
2235                         cv::cvarrToMatND(test_array[MASK][0]));
2236     }
2237 }
2238
2239 CxCore_OrSTest ors_test;
2240
2241
2242 ////////////////////////// xor ////////////////////////////
2243
2244 class CxCore_XorTest : public CxCore_LogicTest
2245 {
2246 public:
2247     CxCore_XorTest();
2248 protected:
2249     void run_func();
2250 };
2251
2252 CxCore_XorTest::CxCore_XorTest()
2253     : CxCore_LogicTest( "logic-xor", "cvXor", CV_TS_LOGIC_XOR )
2254 {
2255 }
2256
2257 void CxCore_XorTest::run_func()
2258 {
2259     if(!test_nd)
2260     {
2261         cvXor( test_array[INPUT][0], test_array[INPUT][1],
2262                test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
2263     }
2264     else
2265     {
2266         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
2267         cv::bitwise_xor(cv::cvarrToMatND(test_array[INPUT][0]),
2268                         cv::cvarrToMatND(test_array[INPUT][1]),
2269                         c, cv::cvarrToMatND(test_array[MASK][0]));
2270     }
2271     
2272 }
2273
2274 CxCore_XorTest xor_test;
2275
2276
2277 class CxCore_XorSTest : public CxCore_LogicTest
2278 {
2279 public:
2280     CxCore_XorSTest();
2281 protected:
2282     void run_func();
2283 };
2284
2285 CxCore_XorSTest::CxCore_XorSTest()
2286     : CxCore_LogicTest( "logic-xors", "cvXorS", CV_TS_LOGIC_XOR, 4 )
2287 {
2288 }
2289
2290 void CxCore_XorSTest::run_func()
2291 {
2292     if(!test_nd)
2293     {
2294         cvXorS( test_array[INPUT][0], gamma,
2295                test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
2296     }
2297     else
2298     {
2299         cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
2300         cv::bitwise_xor(cv::cvarrToMatND(test_array[INPUT][0]),
2301                         gamma, c,
2302                         cv::cvarrToMatND(test_array[MASK][0]));
2303     }
2304 }
2305
2306 CxCore_XorSTest xors_test;
2307
2308
2309 ////////////////////////// not ////////////////////////////
2310
2311 class CxCore_NotTest : public CxCore_LogicTest
2312 {
2313 public:
2314     CxCore_NotTest();
2315 protected:
2316     void run_func();
2317 };
2318
2319 CxCore_NotTest::CxCore_NotTest()
2320     : CxCore_LogicTest( "logic-not", "cvNot", CV_TS_LOGIC_NOT, 4, false )
2321 {
2322 }
2323
2324 void CxCore_NotTest::run_func()
2325 {
2326     if(!test_nd)
2327     {
2328         cvNot( test_array[INPUT][0], test_array[OUTPUT][0] );
2329     }
2330     else
2331     {
2332         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
2333         cv::bitwise_not(cv::cvarrToMatND(test_array[INPUT][0]), c);
2334     }
2335 }
2336
2337 CxCore_NotTest nots_test;
2338
2339 ///////////////////////// cmp //////////////////////////////
2340
2341 static int cmp_op_values[] = { CV_CMP_GE, CV_CMP_EQ, CV_CMP_NE, -1 };
2342
2343 class CxCore_CmpBaseTestImpl : public CxCore_ArithmTestImpl
2344 {
2345 public:
2346     CxCore_CmpBaseTestImpl( const char* test_name, const char* test_funcs,
2347                             int in_range, int _generate_scalars=0 );
2348 protected:
2349     double get_success_error_level( int test_case_idx, int i, int j );
2350     void get_test_array_types_and_sizes( int test_case_idx,
2351                                          CvSize** sizes, int** types );
2352     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes,
2353                             int** types, CvSize** whole_sizes, bool* are_images );
2354     void print_timing_params( int test_case_idx, char* ptr, int params_left );
2355     void prepare_to_validation( int test_case_idx );
2356     int write_default_params( CvFileStorage* fs );
2357     int in_range;
2358     int cmp_op;
2359     enum { CMP_OP_COUNT=6 };
2360     const char* cmp_op_strings[CMP_OP_COUNT];
2361 };
2362
2363 CxCore_CmpBaseTestImpl::CxCore_CmpBaseTestImpl( const char* test_name, const char* test_funcs,
2364                                         int _in_range, int _generate_scalars )
2365     : CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, 0, 0 ), in_range(_in_range)
2366 {
2367     static const char* cmp_param_names[] = { "size", "cmp_op", "depth", 0 };
2368     static const char* inrange_param_names[] = { "size", "channels", "depth", 0 };
2369
2370     if( in_range )
2371     {
2372         test_array[INPUT].push(NULL);
2373         test_array[TEMP].push(NULL);
2374         test_array[TEMP].push(NULL);
2375         if( !gen_scalars )
2376             test_array[TEMP].push(NULL);
2377     }
2378     if( gen_scalars )
2379         test_array[INPUT].pop();
2380
2381     default_timing_param_names = in_range == 1 ? inrange_param_names : cmp_param_names;
2382
2383     cmp_op_strings[CV_CMP_EQ] = "eq";
2384     cmp_op_strings[CV_CMP_LT] = "lt";
2385     cmp_op_strings[CV_CMP_LE] = "le";
2386     cmp_op_strings[CV_CMP_GE] = "ge";
2387     cmp_op_strings[CV_CMP_GT] = "gt";
2388     cmp_op_strings[CV_CMP_NE] = "ne";
2389
2390     cmp_op = -1;
2391 }
2392
2393 double CxCore_CmpBaseTestImpl::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2394 {
2395     return 0;
2396 }
2397
2398
2399 void CxCore_CmpBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
2400                                                     CvSize** sizes, int** types )
2401 {
2402     int j, count;
2403     CxCore_ArithmTestImpl::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2404     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8UC1;
2405     if( in_range == 0 )
2406     {
2407         // for cmp tests make all the input arrays single-channel
2408         count = test_array[INPUT].size();
2409         for( j = 0; j < count; j++ )
2410             types[INPUT][j] &= ~CV_MAT_CN_MASK;
2411
2412         cmp_op = cvTsRandInt(ts->get_rng()) % 6; // == > >= < <= !=
2413     }
2414     else if( in_range == 1 )
2415     {
2416         types[TEMP][0] = CV_8UC1;
2417         types[TEMP][1] &= ~CV_MAT_CN_MASK;
2418         if( !gen_scalars )
2419             types[TEMP][2] &= ~CV_MAT_CN_MASK;
2420     }
2421 }
2422
2423
2424 int CxCore_CmpBaseTestImpl::write_default_params( CvFileStorage* fs )
2425 {
2426     int code = CxCore_ArithmTestImpl::write_default_params(fs);
2427     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2428         return code;
2429     if( in_range == 0 )
2430     {
2431         start_write_param( fs );
2432         int i;
2433         cvStartWriteStruct( fs, "cmp_op", CV_NODE_SEQ + CV_NODE_FLOW );
2434         for( i = 0; cmp_op_values[i] >= 0; i++ )
2435             cvWriteString( fs, 0, cmp_op_strings[cmp_op_values[i]] );
2436         cvEndWriteStruct(fs);
2437     }
2438     return code;
2439 }
2440
2441
2442 void CxCore_CmpBaseTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
2443                                                     CvSize** sizes, int** types,
2444                                                     CvSize** whole_sizes, bool* are_images )
2445 {
2446     CxCore_ArithmTestImpl::get_timing_test_array_types_and_sizes( test_case_idx,
2447                                             sizes, types, whole_sizes, are_images );
2448     types[OUTPUT][0] = CV_8UC1;
2449     if( in_range == 0 )
2450     {
2451         const char* cmp_op_str = cvReadString( find_timing_param( "cmp_op" ), "ge" );
2452         int i;
2453         cmp_op = CV_CMP_GE;
2454         for( i = 0; i < CMP_OP_COUNT; i++ )
2455             if( strcmp( cmp_op_str, cmp_op_strings[i] ) == 0 )
2456             {
2457                 cmp_op = i;
2458                 break;
2459             }
2460     }
2461 }
2462
2463
2464 void CxCore_CmpBaseTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
2465 {
2466     if( in_range == 0 )
2467     {
2468         sprintf( ptr, "%s,", cmp_op_strings[cmp_op] );
2469         ptr += strlen(ptr);
2470         params_left--;
2471     }
2472     CxCore_ArithmTestImpl::print_timing_params( test_case_idx, ptr, params_left );
2473 }
2474
2475
2476 void CxCore_CmpBaseTestImpl::prepare_to_validation( int /*test_case_idx*/ )
2477 {
2478     CvMat* dst = &test_mat[REF_OUTPUT][0];
2479     if( !in_range )
2480     {
2481         if( test_array[INPUT].size() > 1 )
2482         {
2483             cvTsCmp( &test_mat[INPUT][0], &test_mat[INPUT][1], dst, cmp_op );
2484         }
2485         else
2486         {
2487             cvTsCmpS( &test_mat[INPUT][0], gamma.val[0], dst, cmp_op );
2488         }
2489     }
2490     else
2491     {
2492         int el_type = CV_MAT_TYPE( test_mat[INPUT][0].type );
2493         int i, cn = CV_MAT_CN(el_type);
2494         CvMat* tdst = dst;
2495
2496         for( i = 0; i < cn*2; i++ )
2497         {
2498             int coi = i / 2, is_lower = (i % 2) == 0;
2499             int cmp_op = is_lower ? CV_CMP_GE : CV_CMP_LT;
2500             const CvMat* src = &test_mat[INPUT][0];
2501             const CvMat* lu = gen_scalars ? 0 : &test_mat[INPUT][is_lower?1:2];
2502             double luS = is_lower ? alpha.val[coi] : gamma.val[coi];
2503             
2504             if( cn > 1 )
2505             {
2506                 cvTsExtract( src, &test_mat[TEMP][1], coi );
2507                 src = &test_mat[TEMP][1];
2508
2509                 if( !gen_scalars )
2510                 {
2511                     cvTsExtract( lu, &test_mat[TEMP][2], coi );
2512                     lu = &test_mat[TEMP][2];
2513                 }
2514             }
2515
2516             if( !gen_scalars )
2517                 cvTsCmp( src, lu, tdst, cmp_op );
2518             else
2519                 cvTsCmpS( src, luS, tdst, cmp_op );
2520             if( i > 0 )
2521                 cvTsLogic( tdst, dst, dst, CV_TS_LOGIC_AND );
2522             tdst = &test_mat[TEMP][0];
2523         }
2524     }
2525 }
2526
2527
2528 CxCore_CmpBaseTestImpl cmpbase_test( "cmp", "", -1 );
2529
2530
2531 class CxCore_CmpBaseTest : public CxCore_CmpBaseTestImpl
2532 {
2533 public:
2534     CxCore_CmpBaseTest( const char* test_name, const char* test_funcs,
2535                         int in_range, int _generate_scalars=0 );
2536 };
2537
2538 CxCore_CmpBaseTest::CxCore_CmpBaseTest( const char* test_name, const char* test_funcs,
2539                                         int _in_range, int _generate_scalars )
2540     : CxCore_CmpBaseTestImpl( test_name, test_funcs, _in_range, _generate_scalars )
2541 {
2542     // inherit the default parameters from arithmerical test
2543     size_list = 0;
2544     depth_list = 0;
2545     cn_list = 0;
2546 }
2547
2548
2549 class CxCore_CmpTest : public CxCore_CmpBaseTest
2550 {
2551 public:
2552     CxCore_CmpTest();
2553 protected:
2554     void run_func();
2555 };
2556
2557 CxCore_CmpTest::CxCore_CmpTest()
2558     : CxCore_CmpBaseTest( "cmp-cmp", "cvCmp", 0, 0 )
2559 {
2560 }
2561
2562 void CxCore_CmpTest::run_func()
2563 {
2564     if(!test_nd)
2565     {
2566         cvCmp( test_array[INPUT][0], test_array[INPUT][1],
2567               test_array[OUTPUT][0], cmp_op );
2568     }
2569     else
2570     {
2571         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
2572         cv::compare(cv::cvarrToMatND(test_array[INPUT][0]),
2573                     cv::cvarrToMatND(test_array[INPUT][1]),
2574                     c, cmp_op);
2575     }
2576 }
2577
2578 CxCore_CmpTest cmp_test;
2579
2580
2581 class CxCore_CmpSTest : public CxCore_CmpBaseTest
2582 {
2583 public:
2584     CxCore_CmpSTest();
2585 protected:
2586     void run_func();
2587 };
2588
2589 CxCore_CmpSTest::CxCore_CmpSTest()
2590     : CxCore_CmpBaseTest( "cmp-cmps", "cvCmpS", 0, 4 )
2591 {
2592 }
2593
2594 void CxCore_CmpSTest::run_func()
2595 {
2596     if(!test_nd)
2597     {
2598         cvCmpS( test_array[INPUT][0], gamma.val[0],
2599             test_array[OUTPUT][0], cmp_op );
2600     }
2601     else
2602     {
2603         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
2604         cv::compare(cv::cvarrToMatND(test_array[INPUT][0]),
2605                     gamma.val[0], c, cmp_op);
2606     }
2607 }
2608
2609 CxCore_CmpSTest cmps_test;
2610
2611
2612 class CxCore_InRangeTest : public CxCore_CmpBaseTest
2613 {
2614 public:
2615     CxCore_InRangeTest();
2616 protected:
2617     void run_func();
2618 };
2619
2620 CxCore_InRangeTest::CxCore_InRangeTest()
2621     : CxCore_CmpBaseTest( "cmp-inrange", "cvInRange", 1, 0 )
2622 {
2623 }
2624
2625 void CxCore_InRangeTest::run_func()
2626 {
2627     if(!test_nd)
2628     {
2629         cvInRange( test_array[INPUT][0], test_array[INPUT][1],
2630                   test_array[INPUT][2], test_array[OUTPUT][0] );
2631     }
2632     else
2633     {
2634         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
2635         cv::inRange(cv::cvarrToMatND(test_array[INPUT][0]),
2636                     cv::cvarrToMatND(test_array[INPUT][1]),
2637                     cv::cvarrToMatND(test_array[INPUT][2]),
2638                     c);
2639     }
2640 }
2641
2642 CxCore_InRangeTest inrange_test;
2643
2644
2645 class CxCore_InRangeSTest : public CxCore_CmpBaseTest
2646 {
2647 public:
2648     CxCore_InRangeSTest();
2649 protected:
2650     void run_func();
2651 };
2652
2653 CxCore_InRangeSTest::CxCore_InRangeSTest()
2654     : CxCore_CmpBaseTest( "cmp-inranges", "cvInRangeS", 1, 5 )
2655 {
2656 }
2657
2658 void CxCore_InRangeSTest::run_func()
2659 {
2660     if(!test_nd)
2661     {
2662         cvInRangeS( test_array[INPUT][0], alpha, gamma, test_array[OUTPUT][0] );
2663     }
2664     else
2665     {
2666         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
2667         cv::inRange(cv::cvarrToMatND(test_array[INPUT][0]), alpha, gamma, c);
2668     }
2669 }
2670
2671 CxCore_InRangeSTest inranges_test;
2672
2673
2674 /////////////////////////// convertscale[abs] ////////////////////////////////////////
2675
2676 static const char* cvt_param_names[] = { "size", "scale", "dst_depth", "depth", 0 };
2677 static const char* cvt_abs_param_names[] = { "size", "depth", 0 };
2678 static const int cvt_scale_flags[] = { 0, 1 };
2679
2680 class CxCore_CvtBaseTestImpl : public CxCore_ArithmTestImpl
2681 {
2682 public:
2683     CxCore_CvtBaseTestImpl( const char* test_name, const char* test_funcs, bool calc_abs );
2684 protected:
2685     void get_test_array_types_and_sizes( int test_case_idx,
2686                                          CvSize** sizes, int** types );
2687     void get_timing_test_array_types_and_sizes( int test_case_idx,
2688                                         CvSize** sizes, int** types,
2689                                         CvSize** whole_sizes, bool *are_images );
2690     double get_success_error_level( int test_case_idx, int i, int j );
2691
2692     int prepare_test_case( int test_case_idx );
2693     void print_timing_params( int test_case_idx, char* ptr, int params_left );
2694     int write_default_params( CvFileStorage* fs );
2695
2696     void prepare_to_validation( int test_case_idx );
2697 };
2698
2699
2700 CxCore_CvtBaseTestImpl::CxCore_CvtBaseTestImpl( const char* test_name,
2701                                                 const char* test_funcs,
2702                                                 bool _calc_abs )
2703     : CxCore_ArithmTestImpl( test_name, test_funcs, 5, false, _calc_abs )
2704 {
2705     test_array[INPUT].pop();
2706     default_timing_param_names = 0;
2707     cn_list = 0;
2708 }
2709
2710
2711 // unlike many other arithmetic functions, conversion operations support 8s type,
2712 // also, for cvCvtScale output array depth may be arbitrary and
2713 // for cvCvtScaleAbs output depth = CV_8U
2714 void CxCore_CvtBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
2715                                                 CvSize** sizes, int** types )
2716 {
2717     CxCore_ArithmTestImpl::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2718     CvRNG* rng = ts->get_rng();
2719     int depth = CV_8U, rbits;
2720     types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|
2721                     cvTsRandInt(rng)%(CV_64F+1);
2722     if( !calc_abs )
2723         depth = cvTsRandInt(rng) % (CV_64F+1);
2724     types[OUTPUT][0] = types[REF_OUTPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|depth;
2725
2726     rbits = cvTsRandInt(rng);
2727     // check special cases: shift=0 and/or scale=1.
2728     if( (rbits & 3) == 0 )
2729         gamma.val[0] = 0;
2730     if( (rbits & 12) == 0 )
2731         alpha.val[0] = 1;
2732 }
2733
2734
2735 double CxCore_CvtBaseTestImpl::get_success_error_level( int, int, int )
2736 {
2737     if( CV_MAT_DEPTH(test_mat[OUTPUT][0].type) <= CV_32S )
2738         return alpha.val[0] != cvRound(alpha.val[0]) ||
2739                beta.val[0] != cvRound(beta.val[0]) ||
2740                gamma.val[0] != cvRound(gamma.val[0]);
2741
2742     CvScalar l1, h1, l2, h2;
2743     int stype = CV_MAT_TYPE(test_mat[INPUT][0].type);
2744     int dtype = CV_MAT_TYPE(test_mat[OUTPUT][0].type);
2745     get_minmax_bounds( INPUT, 0, stype, &l1, &h1 );
2746     get_minmax_bounds( OUTPUT, 0, dtype, &l2, &h2 );
2747     double maxval = 0;
2748     for( int i = 0; i < 4; i++ )
2749     {
2750         maxval = MAX(maxval, fabs(l1.val[i]));
2751         maxval = MAX(maxval, fabs(h1.val[i]));
2752         maxval = MAX(maxval, fabs(l2.val[i]));
2753         maxval = MAX(maxval, fabs(h2.val[i]));
2754     }
2755     double max_err = (CV_MAT_DEPTH(stype) == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F ?
2756         DBL_EPSILON : FLT_EPSILON)*maxval*MAX(fabs(alpha.val[0]), 1.)*100;
2757     return max_err;
2758 }
2759
2760
2761 void CxCore_CvtBaseTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
2762                     CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
2763 {
2764     CxCore_ArithmTestImpl::get_timing_test_array_types_and_sizes( test_case_idx,
2765                                     sizes, types, whole_sizes, are_images );
2766     bool scale = true;
2767     int dst_depth = CV_8U;
2768     int cn = CV_MAT_CN(types[INPUT][0]);
2769     if( !calc_abs )
2770     {
2771         scale = cvReadInt( find_timing_param( "scale" ), 1 ) != 0;
2772         dst_depth = cvTsTypeByName( cvReadString(find_timing_param( "dst_depth" ), "8u") );
2773     }
2774
2775     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(dst_depth, cn);
2776
2777     if( scale )
2778     {
2779         alpha.val[0] = 2.1;
2780         gamma.val[0] = -100.;
2781     }
2782     else
2783     {
2784         alpha.val[0] = 1.;
2785         gamma.val[0] = 0.;
2786     }
2787 }
2788
2789
2790 int CxCore_CvtBaseTestImpl::prepare_test_case( int test_case_idx )
2791 {
2792     int code = CxCore_ArithmTestImpl::prepare_test_case( test_case_idx );
2793
2794     if( code > 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
2795     {
2796         if( CV_ARE_TYPES_EQ( &test_mat[INPUT][0], &test_mat[OUTPUT][0] ) &&
2797             !calc_abs && alpha.val[0] == 1 && gamma.val[0] == 0 )
2798             code = 0; // skip the case when no any transformation is done
2799     }
2800
2801     return code;
2802 }
2803
2804
2805 void CxCore_CvtBaseTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
2806 {
2807     sprintf( ptr, "%s,", alpha.val[0] == 1. && gamma.val[0] == 0. ? "no_scale" : "scale" );
2808     ptr += strlen(ptr);
2809     params_left--;
2810     CxCore_ArithmTestImpl::print_timing_params( test_case_idx, ptr, params_left );
2811 }
2812
2813
2814 int CxCore_CvtBaseTestImpl::write_default_params( CvFileStorage* fs )
2815 {
2816     int i, code = CxCore_ArithmTestImpl::write_default_params(fs);
2817     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2818         return code;
2819     if( !calc_abs )
2820     {
2821         start_write_param( fs );
2822         cvStartWriteStruct( fs, "dst_depth", CV_NODE_SEQ + CV_NODE_FLOW );
2823         for( i = 0; arithm_depths[i] >= 0; i++ )
2824             cvWriteString( fs, 0, cvTsGetTypeName(arithm_depths[i]) );
2825         cvEndWriteStruct(fs);
2826         write_int_list( fs, "scale", cvt_scale_flags, CV_DIM(cvt_scale_flags) );
2827     }
2828     return code;
2829 }
2830
2831
2832 void CxCore_CvtBaseTestImpl::prepare_to_validation( int /*test_case_idx*/ )
2833 {
2834     cvTsAdd( &test_mat[INPUT][0], cvScalarAll(alpha.val[0]), 0, beta,
2835              cvScalarAll(gamma.val[0]), &test_mat[REF_OUTPUT][0], calc_abs );
2836 }
2837
2838 CxCore_CvtBaseTestImpl cvt_test( "cvt", "", true );
2839
2840
2841 class CxCore_CvtBaseTest : public CxCore_CvtBaseTestImpl
2842 {
2843 public:
2844     CxCore_CvtBaseTest( const char* test_name, const char* test_funcs, bool calc_abs );
2845 };
2846
2847
2848 CxCore_CvtBaseTest::CxCore_CvtBaseTest( const char* test_name, const char* test_funcs, bool _calc_abs )
2849     : CxCore_CvtBaseTestImpl( test_name, test_funcs, _calc_abs )
2850 {
2851     // inherit the default parameters from arithmerical test
2852     size_list = 0;
2853     whole_size_list = 0;
2854     depth_list = 0;
2855     cn_list = 0;
2856 }
2857
2858
2859 class CxCore_CvtScaleTest : public CxCore_CvtBaseTest
2860 {
2861 public:
2862     CxCore_CvtScaleTest();
2863 protected:
2864     void run_func();
2865 };
2866
2867 CxCore_CvtScaleTest::CxCore_CvtScaleTest()
2868     : CxCore_CvtBaseTest( "cvt-scale", "cvCvtScale", false )
2869 {
2870     default_timing_param_names = cvt_param_names;
2871 }
2872
2873 void CxCore_CvtScaleTest::run_func()
2874 {
2875     if(!test_nd)
2876     {
2877         cvConvertScale( test_array[INPUT][0], test_array[OUTPUT][0],
2878                        alpha.val[0], gamma.val[0] );
2879     }
2880     else
2881     {
2882         cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
2883         cv::cvarrToMatND(test_array[INPUT][0]).convertTo(c,c.type(),alpha.val[0], gamma.val[0]);
2884     }
2885 }
2886
2887 CxCore_CvtScaleTest cvtscale_test;
2888
2889
2890 class CxCore_CvtScaleAbsTest : public CxCore_CvtBaseTest
2891 {
2892 public:
2893     CxCore_CvtScaleAbsTest();
2894 protected:
2895     void run_func();
2896 };
2897
2898 CxCore_CvtScaleAbsTest::CxCore_CvtScaleAbsTest()
2899     : CxCore_CvtBaseTest( "cvt-scaleabs", "cvCvtScaleAbs", true )
2900 {
2901     default_timing_param_names = cvt_abs_param_names;
2902 }
2903
2904 void CxCore_CvtScaleAbsTest::run_func()
2905 {
2906     if(!test_nd)
2907     {
2908         cvConvertScaleAbs( test_array[INPUT][0], test_array[OUTPUT][0],
2909                        alpha.val[0], gamma.val[0] );
2910     }
2911     else
2912     {
2913         cv::Mat c = cv::cvarrToMat(test_array[OUTPUT][0]);
2914         cv::convertScaleAbs(cv::cvarrToMat(test_array[INPUT][0]),c,alpha.val[0], gamma.val[0]);
2915     }
2916 }
2917
2918 CxCore_CvtScaleAbsTest cvtscaleabs_test;
2919
2920
2921 /////////////////////////////// statistics //////////////////////////////////
2922
2923 static const char* stat_param_names[] = { "size", "coi", "channels", "depth", 0 };
2924 static const char* stat_mask_param_names[] = { "size", "coi", "channels", "depth", "use_mask", 0 };
2925 static const char* stat_single_param_names[] = { "size", "channels", "depth", 0 };
2926 static const char* stat_single_mask_param_names[] = { "size", "channels", "depth", "use_mask", 0 };
2927 static const char* stat_coi_modes[] = { "all", "single", 0 };
2928
2929 class CxCore_StatTestImpl : public CvArrTest
2930 {
2931 public:
2932     CxCore_StatTestImpl( const char* test_name, const char* test_funcs,
2933                      int _output_count, bool _single_channel,
2934                      bool _allow_mask=true, bool _is_binary=false );
2935 protected:
2936     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2937     void get_timing_test_array_types_and_sizes( int test_case_idx,
2938                                                 CvSize** sizes, int** types,
2939                                                 CvSize** whole_sizes, bool* are_images );
2940     void print_timing_params( int test_case_idx, char* ptr, int params_left );
2941     int write_default_params( CvFileStorage* fs );    
2942     int prepare_test_case( int test_case_idx );
2943     double get_success_error_level( int test_case_idx, int i, int j );
2944
2945     int coi;
2946     int output_count;
2947     bool single_channel;
2948     bool is_binary;
2949     bool test_nd;
2950 };
2951
2952
2953 CxCore_StatTestImpl::CxCore_StatTestImpl( const char* test_name,
2954                         const char* test_funcs, int _output_count,
2955                         bool _single_channel, bool _allow_mask, bool _is_binary )
2956     : CvArrTest( test_name, test_funcs, "" ), output_count(_output_count),
2957     single_channel(_single_channel), is_binary(_is_binary)
2958 {
2959     test_array[INPUT].push(NULL);
2960     if( is_binary )
2961         test_array[INPUT].push(NULL);
2962     optional_mask = _allow_mask;
2963     if( optional_mask )
2964         test_array[MASK].push(NULL);
2965     test_array[OUTPUT].push(NULL);
2966     test_array[REF_OUTPUT].push(NULL);
2967     coi = 0;
2968
2969     size_list = arithm_sizes;
2970     whole_size_list = arithm_whole_sizes;
2971     depth_list = arithm_depths;
2972     cn_list = arithm_channels;
2973     test_nd = false;
2974 }
2975
2976
2977 void CxCore_StatTestImpl::get_test_array_types_and_sizes( int test_case_idx,
2978                                             CvSize** sizes, int** types )
2979 {
2980     CvRNG* rng = ts->get_rng();
2981     int depth = cvTsRandInt(rng)%(CV_64F+1);
2982     int cn = cvTsRandInt(rng) % 4 + 1;
2983     int j, count = test_array[INPUT].size();
2984     
2985     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2986     depth += depth == CV_8S;
2987
2988     for( j = 0; j < count; j++ )
2989         types[INPUT][j] = CV_MAKETYPE(depth, cn);
2990
2991     // regardless of the test case, the output is always a fixed-size tuple of numbers
2992     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( output_count, 1 );
2993     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
2994
2995     coi = 0;
2996     cvmat_allowed = true;
2997     if( cn > 1 && (single_channel || (cvTsRandInt(rng) & 3) == 0) )
2998     {
2999         coi = cvTsRandInt(rng) % cn + 1;
3000         cvmat_allowed = false;
3001     }
3002     test_nd = cvTsRandInt(rng) % 3 == 0;
3003 }
3004
3005
3006 void CxCore_StatTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
3007                 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
3008 {
3009     CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
3010                                                       whole_sizes, are_images );
3011     const char* coi_mode_str = cvReadString(find_timing_param("coi"), single_channel ? "single" : "all");
3012
3013     // regardless of the test case, the output is always a fixed-size tuple of numbers
3014     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( output_count, 1 );
3015     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
3016
3017     int cn = CV_MAT_CN(types[INPUT][0]);
3018     coi = 0;
3019     cvmat_allowed = true;
3020     if( strcmp( coi_mode_str, "single" ) == 0 )
3021     {
3022         CvRNG* rng = ts->get_rng();
3023         coi = cvTsRandInt(rng) % cn + 1;
3024         cvmat_allowed = false;
3025         *are_images = true;
3026     }
3027 }
3028
3029
3030 int CxCore_StatTestImpl::write_default_params( CvFileStorage* fs )
3031 {
3032     int code = CvArrTest::write_default_params(fs);
3033     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
3034         return code;
3035     if( !single_channel )
3036         write_string_list( fs, "coi", stat_coi_modes );
3037     return code;
3038 }
3039
3040
3041 int CxCore_StatTestImpl::prepare_test_case( int test_case_idx )
3042 {
3043     int code = CvArrTest::prepare_test_case( test_case_idx );
3044     
3045     if( coi && code > 0 )
3046     {
3047         int j, count = test_array[INPUT].size();
3048
3049         if( ts->get_testing_mode() == CvTS::TIMING_MODE && CV_MAT_CN(test_mat[INPUT][0].type) == 1 )
3050             return 0;
3051
3052         for( j = 0; j < count; j++ )
3053         {
3054             IplImage* img = (IplImage*)test_array[INPUT][j];
3055             if( img )
3056                 cvSetImageCOI( img, coi );
3057         }
3058     }
3059
3060     return code;
3061 }
3062
3063
3064 void CxCore_StatTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
3065 {
3066     sprintf( ptr, "%s,", coi > 0 || CV_MAT_CN(test_mat[INPUT][0].type) == 1 ? "single" : "all" );
3067     ptr += strlen(ptr);
3068     params_left--;
3069     CvArrTest::print_timing_params( test_case_idx, ptr, params_left );
3070 }
3071
3072
3073 double CxCore_StatTestImpl::get_success_error_level( int test_case_idx, int i, int j )
3074 {
3075     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
3076     if( depth == CV_32F )
3077         return FLT_EPSILON*1000;
3078     if( depth == CV_64F )
3079         return DBL_EPSILON*100000;
3080     else
3081         return CvArrTest::get_success_error_level( test_case_idx, i, j );
3082 }
3083
3084 CxCore_StatTestImpl stat_test( "stat", "", 0, true, false );
3085
3086
3087 class CxCore_StatTest : public CxCore_StatTestImpl
3088 {
3089 public:
3090     CxCore_StatTest( const char* test_name, const char* test_funcs,
3091                      int _output_count, bool _single_channel,
3092                      bool _allow_mask=1, bool _is_binary=0 );
3093 };
3094
3095 CxCore_StatTest::CxCore_StatTest( const char* test_name, const char* test_funcs,
3096                      int _output_count, bool _single_channel,
3097                      bool _allow_mask, bool _is_binary )
3098     : CxCore_StatTestImpl( test_name, test_funcs, _output_count, _single_channel, _allow_mask, _is_binary )
3099 {
3100     if( !single_channel )
3101         default_timing_param_names = optional_mask ? stat_single_mask_param_names : stat_single_param_names;
3102     else
3103         default_timing_param_names = optional_mask ? stat_mask_param_names : stat_param_names;
3104     
3105     // inherit the default parameters from arithmerical test
3106     size_list = 0;
3107     whole_size_list = 0;
3108     depth_list = 0;
3109     cn_list = 0;
3110 }
3111
3112 ////////////////// sum /////////////////
3113 class CxCore_SumTest : public CxCore_StatTest
3114 {
3115 public:
3116     CxCore_SumTest();
3117 protected:
3118     void run_func();
3119     void prepare_to_validation( int test_case_idx );
3120     double get_success_error_level( int test_case_idx, int i, int j );
3121 };
3122
3123
3124 CxCore_SumTest::CxCore_SumTest()
3125     : CxCore_StatTest( "stat-sum", "cvSum", 4 /* CvScalar */, false, false, false )
3126 {
3127 }
3128
3129 double CxCore_SumTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
3130 {
3131     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
3132     if( depth == CV_32F )
3133         return FLT_EPSILON*1000;
3134     return DBL_EPSILON*100000;
3135 }
3136
3137
3138 void CxCore_SumTest::run_func()
3139 {
3140     if(!test_nd || coi)
3141     {
3142         *(CvScalar*)(test_mat[OUTPUT][0].data.db) = cvSum(test_array[INPUT][0]);
3143     }
3144     else
3145     {
3146         *(cv::Scalar*)(test_mat[OUTPUT][0].data.db) = cv::sum(cv::cvarrToMatND(test_array[INPUT][0]));
3147     }
3148 }
3149
3150 void CxCore_SumTest::prepare_to_validation( int /*test_case_idx*/ )
3151 {
3152     CvScalar mean;
3153     int nonzero = cvTsMeanStdDevNonZero( &test_mat[INPUT][0], 0, &mean, 0, coi );
3154
3155     *(CvScalar*)(test_mat[REF_OUTPUT][0].data.db) = mean;
3156     mean = *(CvScalar*)(test_mat[OUTPUT][0].data.db);
3157
3158     mean.val[0] /= nonzero;
3159     mean.val[1] /= nonzero;
3160     mean.val[2] /= nonzero;
3161     mean.val[3] /= nonzero;
3162     *(CvScalar*)(test_mat[OUTPUT][0].data.db) = mean;
3163 }
3164
3165 CxCore_SumTest sum_test;
3166
3167
3168 ////////////////// nonzero /////////////////
3169 class CxCore_NonZeroTest : public CxCore_StatTest
3170 {
3171 public:
3172     CxCore_NonZeroTest();
3173 protected:
3174     void run_func();
3175     void prepare_to_validation( int test_case_idx );
3176     void get_test_array_types_and_sizes( int test_case_idx,
3177                                          CvSize** sizes, int** types );
3178 };
3179
3180
3181 CxCore_NonZeroTest::CxCore_NonZeroTest()
3182     : CxCore_StatTest( "stat-nonzero", "cvCountNonZero", 1 /* int */, true, false, false )
3183 {
3184     test_array[TEMP].push(NULL);
3185     test_array[TEMP].push(NULL);
3186 }
3187
3188 void CxCore_NonZeroTest::run_func()
3189 {
3190     if(!test_nd || coi)
3191     {
3192         test_mat[OUTPUT][0].data.db[0] = cvCountNonZero(test_array[INPUT][0]);
3193     }
3194     else
3195     {
3196         test_mat[OUTPUT][0].data.db[0] = cv::countNonZero(cv::cvarrToMatND(test_array[INPUT][0]));
3197     }
3198 }
3199
3200 void CxCore_NonZeroTest::get_test_array_types_and_sizes( int test_case_idx,
3201                                               CvSize** sizes, int** types )
3202 {
3203     CxCore_StatTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
3204     types[TEMP][0] = CV_8UC1;
3205     if( CV_MAT_CN(types[INPUT][0]) > 1 )
3206         types[TEMP][1] = types[INPUT][0] & ~CV_MAT_CN_MASK;
3207     else
3208         sizes[TEMP][1] = cvSize(0,0);
3209 }
3210
3211
3212 void CxCore_NonZeroTest::prepare_to_validation( int /*test_case_idx*/ )
3213 {
3214     CvMat* plane = &test_mat[INPUT][0];
3215     if( CV_MAT_CN(plane->type) > 1 )
3216     {
3217         plane = &test_mat[TEMP][1];
3218         assert( coi > 0 );
3219         cvTsExtract( &test_mat[INPUT][0], plane, coi-1 );
3220     }
3221     cvTsCmpS( plane, 0, &test_mat[TEMP][0], CV_CMP_NE );
3222     int nonzero = cvTsMeanStdDevNonZero( &test_mat[INPUT][0], &test_mat[TEMP][0], 0, 0, coi );
3223     test_mat[REF_OUTPUT][0].data.db[0] = nonzero;
3224 }
3225
3226
3227 CxCore_NonZeroTest nonzero_test;
3228
3229
3230 /////////////////// mean //////////////////////
3231 class CxCore_MeanTest : public CxCore_StatTest
3232 {
3233 public:
3234     CxCore_MeanTest();
3235 protected:
3236     void run_func();
3237     void prepare_to_validation( int test_case_idx );
3238 };
3239
3240
3241 CxCore_MeanTest::CxCore_MeanTest()
3242     : CxCore_StatTest( "stat-mean", "cvAvg", 4 /* CvScalar */, false, true, false )
3243 {
3244 }
3245
3246 void CxCore_MeanTest::run_func()
3247 {
3248     if(!test_nd || coi)
3249     {
3250         *(CvScalar*)(test_mat[OUTPUT][0].data.db) =
3251             cvAvg(test_array[INPUT][0], test_array[MASK][0]);
3252     }
3253     else
3254     {
3255         *(cv::Scalar*)(test_mat[OUTPUT][0].data.db) = cv::mean(
3256                     cv::cvarrToMatND(test_array[INPUT][0]),
3257                     cv::cvarrToMatND(test_array[MASK][0]));
3258     }
3259 }
3260
3261 void CxCore_MeanTest::prepare_to_validation( int /*test_case_idx*/ )
3262 {
3263     CvScalar mean;
3264     cvTsMeanStdDevNonZero( &test_mat[INPUT][0],
3265         test_array[MASK][0] ? &test_mat[MASK][0] : 0,
3266         &mean, 0, coi );
3267     *(CvScalar*)(test_mat[REF_OUTPUT][0].data.db) = mean;
3268 }
3269
3270 CxCore_MeanTest mean_test;
3271
3272
3273 /////////////////// mean_stddev //////////////////////
3274 class CxCore_MeanStdDevTest : public CxCore_StatTest
3275 {
3276 public:
3277     CxCore_MeanStdDevTest();
3278 protected:
3279     void run_func();
3280     void prepare_to_validation( int test_case_idx );
3281     double get_success_error_level( int test_case_idx, int i, int j );
3282 };
3283
3284
3285 CxCore_MeanStdDevTest::CxCore_MeanStdDevTest()
3286     : CxCore_StatTest( "stat-mean_stddev", "cvAvgSdv", 8 /* CvScalar x 2 */, false, true, false )
3287 {
3288 }
3289
3290 void CxCore_MeanStdDevTest::run_func()
3291 {
3292     if(!test_nd || coi)
3293     {
3294         cvAvgSdv( test_array[INPUT][0],
3295                   &((CvScalar*)(test_mat[OUTPUT][0].data.db))[0],
3296                   &((CvScalar*)(test_mat[OUTPUT][0].data.db))[1],
3297                   test_array[MASK][0] );
3298     }
3299     else
3300     {
3301         cv::meanStdDev(cv::cvarrToMatND(test_array[INPUT][0]),
3302                        ((cv::Scalar*)(test_mat[OUTPUT][0].data.db))[0],
3303                        ((cv::Scalar*)(test_mat[OUTPUT][0].data.db))[1],
3304                        cv::cvarrToMatND(test_array[MASK][0]) );
3305     }
3306 }
3307
3308 double CxCore_MeanStdDevTest::get_success_error_level( int test_case_idx, int i, int j )
3309 {
3310     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
3311     if( depth < CV_64F && depth != CV_32S )
3312         return CxCore_StatTest::get_success_error_level( test_case_idx, i, j );
3313     return DBL_EPSILON*1e6;
3314 }
3315
3316 void CxCore_MeanStdDevTest::prepare_to_validation( int /*test_case_idx*/ )
3317 {
3318     CvScalar mean, stddev;
3319     int i;
3320     CvMat* output = &test_mat[OUTPUT][0];
3321     CvMat* ref_output = &test_mat[REF_OUTPUT][0];
3322     cvTsMeanStdDevNonZero( &test_mat[INPUT][0],
3323         test_array[MASK][0] ? &test_mat[MASK][0] : 0,
3324         &mean, &stddev, coi );
3325     ((CvScalar*)(ref_output->data.db))[0] = mean;
3326     ((CvScalar*)(ref_output->data.db))[1] = stddev;
3327     for( i = 0; i < 4; i++ )
3328     {
3329         output->data.db[i] *= output->data.db[i];
3330         output->data.db[i+4] = output->data.db[i+4]*output->data.db[i+4] + 1000;
3331         ref_output->data.db[i] *= ref_output->data.db[i];
3332         ref_output->data.db[i+4] = ref_output->data.db[i+4]*ref_output->data.db[i+4] + 1000;
3333     }
3334 }
3335
3336 CxCore_MeanStdDevTest mean_stddev_test;
3337
3338
3339 /////////////////// minmaxloc //////////////////////
3340 class CxCore_MinMaxLocTest : public CxCore_StatTest
3341 {
3342 public:
3343     CxCore_MinMaxLocTest();
3344 protected:
3345     void run_func();
3346     void prepare_to_validation( int test_case_idx );
3347 };
3348
3349
3350 CxCore_MinMaxLocTest::CxCore_MinMaxLocTest()
3351     : CxCore_StatTest( "stat-minmaxloc", "cvMinMaxLoc", 6 /* double x 2 + CvPoint x 2 */, true, true, false )
3352 {
3353 }
3354
3355 void CxCore_MinMaxLocTest::run_func()
3356 {
3357     CvPoint minloc = {0,0}, maxloc = {0,0};
3358     double* output = test_mat[OUTPUT][0].data.db;
3359
3360     cvMinMaxLoc( test_array[INPUT][0],
3361         output, output+1, &minloc, &maxloc,
3362         test_array[MASK][0] );
3363     output[2] = minloc.x;
3364     output[3] = minloc.y;
3365     output[4] = maxloc.x;
3366     output[5] = maxloc.y;
3367 }
3368
3369 void CxCore_MinMaxLocTest::prepare_to_validation( int /*test_case_idx*/ )
3370 {
3371     double minval = 0, maxval = 0;
3372     CvPoint minloc = {0,0}, maxloc = {0,0};
3373     double* ref_output = test_mat[REF_OUTPUT][0].data.db;
3374     cvTsMinMaxLoc( &test_mat[INPUT][0], test_array[MASK][0] ?
3375         &test_mat[MASK][0] : 0, &minval, &maxval, &minloc, &maxloc, coi );
3376     ref_output[0] = minval;
3377     ref_output[1] = maxval;
3378     ref_output[2] = minloc.x;
3379     ref_output[3] = minloc.y;
3380     ref_output[4] = maxloc.x;
3381     ref_output[5] = maxloc.y;
3382 }
3383
3384 CxCore_MinMaxLocTest minmaxloc_test;
3385
3386
3387 /////////////////// norm //////////////////////
3388
3389 static const char* stat_norm_param_names[] = { "size", "coi", "norm_type", "channels", "depth", "use_mask", 0 };
3390 static const char* stat_norm_type_names[] = { "Inf", "L1", "L2", "diff_Inf", "diff_L1", "diff_L2", 0 };
3391
3392 class CxCore_NormTest : public CxCore_StatTest
3393 {
3394 public:
3395     CxCore_NormTest();
3396 protected:
3397     void run_func();
3398     void prepare_to_validation( int test_case_idx );
3399     void get_test_array_types_and_sizes( int test_case_idx,
3400                                          CvSize** sizes, int** types );
3401     void get_timing_test_array_types_and_sizes( int /*test_case_idx*/,
3402         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images );
3403     int prepare_test_case( int test_case_idx );
3404     void print_timing_params( int test_case_idx, char* ptr, int params_left );
3405     int write_default_params( CvFileStorage* fs );
3406     double get_success_error_level( int test_case_idx, int i, int j );
3407     int norm_type;
3408 };
3409
3410
3411 CxCore_NormTest::CxCore_NormTest()
3412     : CxCore_StatTest( "stat-norm", "cvNorm", 1 /* double */, false, true, true )
3413 {
3414     test_array[TEMP].push(NULL);
3415     default_timing_param_names = stat_norm_param_names;
3416 }
3417
3418
3419 double CxCore_NormTest::get_success_error_level( int test_case_idx, int i, int j )
3420 {
3421     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
3422     if( (depth == CV_16U || depth == CV_16S) /*&& (norm_type&3) != CV_C*/ )
3423         return 1e-4;
3424     else
3425         return CxCore_StatTest::get_success_error_level( test_case_idx, i, j );
3426 }
3427
3428
3429 void CxCore_NormTest::get_test_array_types_and_sizes( int test_case_idx,
3430                                                CvSize** sizes, int** types )
3431 {
3432     int intype;
3433     int norm_kind;
3434     CxCore_StatTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
3435     norm_type = cvTsRandInt(ts->get_rng()) % 3; // CV_C, CV_L1 or CV_L2
3436     norm_kind = cvTsRandInt(ts->get_rng()) % 3; // simple, difference or relative difference
3437     if( norm_kind == 0 )
3438         sizes[INPUT][1] = cvSize(0,0);
3439     norm_type = (1 << norm_type) | (norm_kind*8);
3440     intype = types[INPUT][0];
3441     if( CV_MAT_CN(intype) > 1 && coi == 0 )
3442         sizes[MASK][0] = cvSize(0,0);
3443     sizes[TEMP][0] = cvSize(0,0);
3444     if( (norm_type & (CV_DIFF|CV_RELATIVE)) && CV_MAT_DEPTH(intype) <= CV_32F )
3445     {
3446         sizes[TEMP][0] = sizes[INPUT][0];
3447         types[TEMP][0] = (intype & ~CV_MAT_DEPTH_MASK)|
3448             (CV_MAT_DEPTH(intype) < CV_32F ? CV_32S : CV_64F);
3449     }
3450 }
3451
3452
3453 void CxCore_NormTest::get_timing_test_array_types_and_sizes( int test_case_idx,
3454                                                     CvSize** sizes, int** types,
3455                                                     CvSize** whole_sizes, bool* are_images )
3456 {
3457     CxCore_StatTest::get_timing_test_array_types_and_sizes( test_case_idx,
3458                                     sizes, types, whole_sizes, are_images );
3459     const char* norm_type_str = cvReadString( find_timing_param( "norm_type" ), "L2" );
3460     bool diff = false;
3461     if( strncmp( norm_type_str, "diff_", 5 ) == 0 )
3462     {
3463         diff = true;
3464         norm_type_str += 5;
3465     }
3466     
3467     if( strcmp( norm_type_str, "L1" ) == 0 )
3468         norm_type = CV_L1;
3469     else if( strcmp( norm_type_str, "L2" ) == 0 )
3470         norm_type = CV_L2;
3471     else
3472         norm_type = CV_C;
3473
3474     if( diff )
3475         norm_type += CV_DIFF;
3476     else
3477         sizes[INPUT][1] = cvSize(0,0);
3478 }
3479
3480
3481 int CxCore_NormTest::prepare_test_case( int test_case_idx )
3482 {
3483     int code = CxCore_StatTest::prepare_test_case( test_case_idx );
3484     if( code > 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
3485     {
3486         // currently it is not supported
3487         if( test_array[MASK][0] && CV_MAT_CN(test_mat[INPUT][0].type) > 1 && coi == 0 )
3488             return 0;
3489     }
3490     return code;
3491 }
3492
3493
3494 int CxCore_NormTest::write_default_params( CvFileStorage* fs )
3495 {
3496     int code = CxCore_StatTest::write_default_params(fs);
3497     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
3498         return code;
3499     write_string_list( fs, "norm_type", stat_norm_type_names );
3500     return code;
3501 }
3502
3503
3504 void CxCore_NormTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
3505 {
3506     int nt = norm_type & CV_NORM_MASK;
3507     sprintf( ptr, "%s%s,", norm_type & CV_DIFF ? "diff_" : "",
3508              nt == CV_C ? "Inf" : nt == CV_L1 ? "L1" : "L2" );
3509     ptr += strlen(ptr);
3510     params_left--;
3511     CxCore_StatTest::print_timing_params( test_case_idx, ptr, params_left );
3512 }
3513
3514
3515 void CxCore_NormTest::run_func()
3516 {
3517     if(!test_nd || coi)
3518     {
3519         test_mat[OUTPUT][0].data.db[0] = cvNorm( test_array[INPUT][0],
3520                  test_array[INPUT][1], norm_type, test_array[MASK][0] );
3521     }
3522     else
3523     {
3524         cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
3525         cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
3526         cv::MatND mask = cv::cvarrToMatND(test_array[MASK][0]);
3527         test_mat[OUTPUT][0].data.db[0] = b.data ?
3528             cv::norm( a, b, norm_type, mask ) :
3529             cv::norm( a, norm_type, mask );
3530     }
3531 }
3532
3533 void CxCore_NormTest::prepare_to_validation( int /*test_case_idx*/ )
3534 {
3535     double a_norm = 0, b_norm = 0;
3536     CvMat* a = &test_mat[INPUT][0];
3537     CvMat* b = &test_mat[INPUT][1];
3538     CvMat* mask = test_array[MASK][0] ? &test_mat[MASK][0] : 0;
3539     CvMat* diff = a;
3540
3541     if( norm_type & (CV_DIFF|CV_RELATIVE) )
3542     {
3543         diff = test_array[TEMP][0] ? &test_mat[TEMP][0] : a;
3544         cvTsAdd( a, cvScalarAll(1.), b, cvScalarAll(-1.),
3545                  cvScalarAll(0.), diff, 0 );
3546     }
3547     a_norm = cvTsNorm( diff, mask, norm_type & CV_NORM_MASK, coi );
3548     if( norm_type & CV_RELATIVE )
3549     {
3550         b_norm = cvTsNorm( b, mask, norm_type & CV_NORM_MASK, coi );
3551         a_norm /= (b_norm + DBL_EPSILON );
3552     }
3553     test_mat[REF_OUTPUT][0].data.db[0] = a_norm;
3554 }
3555
3556 CxCore_NormTest norm_test;
3557
3558 // TODO: repeat(?), reshape(?), lut
3559
3560 /* End of file. */