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