]> rtime.felk.cvut.cz Git - opencv.git/blob - opencv/tests/cxcore/src/aarithm.cpp
fixed GCC4.1 warnings
[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 };
72
73
74 CxCore_ArithmTestImpl::CxCore_ArithmTestImpl( const char* test_name, const char* test_funcs,
75                                               int _generate_scalars, bool _allow_mask, bool _calc_abs )
76     : CvArrTest( test_name, test_funcs, "" ),
77     gen_scalars(_generate_scalars), calc_abs(_calc_abs)
78 {
79     test_array[INPUT].push(NULL);
80     test_array[INPUT].push(NULL);
81     optional_mask = _allow_mask;
82
83     if( optional_mask )
84     {
85         test_array[INPUT_OUTPUT].push(NULL);
86         test_array[REF_INPUT_OUTPUT].push(NULL);
87         test_array[TEMP].push(NULL);
88         test_array[MASK].push(NULL);
89     }
90     else
91     {
92         test_array[OUTPUT].push(NULL);
93         test_array[REF_OUTPUT].push(NULL);
94     }
95     alpha = beta = gamma = cvScalarAll(0);
96
97     size_list = arithm_sizes;
98     whole_size_list = arithm_whole_sizes;
99     depth_list = arithm_depths;
100     cn_list = arithm_channels;
101 }
102
103
104 void CxCore_ArithmTestImpl::generate_scalars( int depth )
105 {
106     bool is_timing = ts->get_testing_mode() == CvTS::TIMING_MODE;
107     double ab_min_val = -1.;
108     double ab_max_val = 1.;
109     double gamma_min_val = depth == CV_8U ? -100 : depth < CV_32F ? -10000 : -1e6;
110     double gamma_max_val = depth == CV_8U ? 100 : depth < CV_32F ? 10000 : 1e6;
111     
112     if( gen_scalars )
113     {
114         CvRNG* rng = ts->get_rng();
115         int i;
116         double m = 10.;
117         for( i = 0; i < 4; i++ )
118         {
119             if( gen_scalars & 1 )
120             {
121                 alpha.val[i] = exp((cvTsRandReal(rng)-0.5)*m*2*CV_LOG2);
122                 alpha.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
123                 if( is_timing )
124                 {
125                     alpha.val[i] = MAX( alpha.val[i], ab_min_val );
126                     alpha.val[i] = MIN( alpha.val[i], ab_max_val );
127                 }
128             }
129             if( gen_scalars & 2 )
130             {
131                 beta.val[i] = exp((cvTsRandReal(rng)-0.5)*m*2*CV_LOG2);
132                 beta.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
133                 if( is_timing )
134                 {
135                     beta.val[i] = MAX( beta.val[i], ab_min_val );
136                     beta.val[i] = MIN( beta.val[i], ab_max_val );
137                 }
138             }
139             if( gen_scalars & 4 )
140             {
141                 gamma.val[i] = exp((cvTsRandReal(rng)-0.5)*m*2*CV_LOG2);
142                 gamma.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
143                 if( is_timing )
144                 {
145                     gamma.val[i] = MAX( gamma.val[i], gamma_min_val );
146                     gamma.val[i] = MIN( gamma.val[i], gamma_max_val );
147                 }
148             }
149         }
150     }
151
152     if( depth == CV_32F )
153     {
154         CvMat fl = cvMat( 1, 4, CV_32F, buf );
155         CvMat db = cvMat( 1, 4, CV_64F, 0 );
156
157         db.data.db = alpha.val;
158         cvTsConvert( &db, &fl );
159         cvTsConvert( &fl, &db );
160
161         db.data.db = beta.val;
162         cvTsConvert( &db, &fl );
163         cvTsConvert( &fl, &db );
164
165         db.data.db = gamma.val;
166         cvTsConvert( &db, &fl );
167         cvTsConvert( &fl, &db );
168     }
169 }
170
171 void CxCore_ArithmTestImpl::get_test_array_types_and_sizes( int test_case_idx,
172                                                             CvSize** sizes, int** types )
173 {
174     CvRNG* rng = ts->get_rng();
175     int depth = cvTsRandInt(rng)%CV_64F;
176     int cn = cvTsRandInt(rng) % 4 + 1;
177     int i, j;
178     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
179     depth += depth == CV_8S;
180
181     for( i = 0; i < max_arr; i++ )
182     {
183         int count = test_array[i].size();
184         int type = i != MASK ? CV_MAKETYPE(depth, cn) : CV_8UC1;
185         for( j = 0; j < count; j++ )
186         {
187             types[i][j] = type;
188         }
189     }
190 }
191
192
193 void CxCore_ArithmTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
194                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
195 {
196     CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
197                                                       whole_sizes, are_images );
198     generate_scalars( types[INPUT][0] );
199 }
200
201
202 void CxCore_ArithmTestImpl::prepare_to_validation( int /*test_case_idx*/ )
203 {
204     const CvMat* mask = test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0;
205     CvMat* output = test_array[REF_INPUT_OUTPUT].size() > 0 ?
206         &test_mat[REF_INPUT_OUTPUT][0] : &test_mat[REF_OUTPUT][0];
207     CvMat* temp_dst = mask ? &test_mat[TEMP][0] : output;
208     cvTsAdd( &test_mat[INPUT][0], alpha,
209              test_array[INPUT].size() > 1 ? &test_mat[INPUT][1] : 0, beta,
210              gamma, temp_dst, calc_abs );
211     if( mask )
212         cvTsCopy( temp_dst, output, mask );
213 }
214
215
216 CxCore_ArithmTestImpl arithm( "arithm", "", 0, false );
217
218
219 class CxCore_ArithmTest : public CxCore_ArithmTestImpl
220 {
221 public:
222     CxCore_ArithmTest( const char* test_name, const char* test_funcs,
223                        int _generate_scalars=0, bool _allow_mask=true, bool _calc_abs=false );
224 };
225
226
227 CxCore_ArithmTest::CxCore_ArithmTest( const char* test_name, const char* test_funcs,
228                                       int _generate_scalars, bool _allow_mask, bool _calc_abs ) :
229     CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask, _calc_abs )
230 {
231     default_timing_param_names = optional_mask ? arithm_mask_param_names : arithm_param_names;
232         
233     // inherit the default parameters from arithmetical test
234     size_list = 0;
235     whole_size_list = 0;
236     depth_list = 0;
237     cn_list = 0;
238 }
239
240
241 ////////////////////////////// add /////////////////////////////
242
243 class CxCore_AddTest : public CxCore_ArithmTest
244 {
245 public:
246     CxCore_AddTest();
247 protected:
248     void run_func();
249 };
250
251 CxCore_AddTest::CxCore_AddTest()
252     : CxCore_ArithmTest( "arithm-add", "cvAdd", 0, true )
253 {
254     alpha = beta = cvScalarAll(1.);
255 }
256
257 void CxCore_AddTest::run_func()
258 {
259     cvAdd( test_array[INPUT][0], test_array[INPUT][1],
260         test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
261 }
262
263 CxCore_AddTest add_test;
264
265 ////////////////////////////// sub /////////////////////////////
266
267 class CxCore_SubTest : public CxCore_ArithmTest
268 {
269 public:
270     CxCore_SubTest();
271 protected:
272     void run_func();
273 };
274
275 CxCore_SubTest::CxCore_SubTest()
276     : CxCore_ArithmTest( "arithm-sub", "cvSub", 0, true )
277 {
278     alpha = cvScalarAll(1.);
279     beta = cvScalarAll(-1.);
280 }
281
282 void CxCore_SubTest::run_func()
283 {
284     cvSub( test_array[INPUT][0], test_array[INPUT][1],
285            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
286 }
287
288 CxCore_SubTest sub_test;
289
290
291 ////////////////////////////// adds /////////////////////////////
292
293 class CxCore_AddSTest : public CxCore_ArithmTest
294 {
295 public:
296     CxCore_AddSTest();
297 protected:
298     void run_func();
299 };
300
301 CxCore_AddSTest::CxCore_AddSTest()
302     : CxCore_ArithmTest( "arithm-adds", "cvAddS", 4, true )
303 {
304     test_array[INPUT].pop();
305     alpha = cvScalarAll(1.);
306 }
307
308 void CxCore_AddSTest::run_func()
309 {
310     cvAddS( test_array[INPUT][0], gamma,
311             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
312 }
313
314 CxCore_AddSTest adds_test;
315
316 ////////////////////////////// subrs /////////////////////////////
317
318 class CxCore_SubRSTest : public CxCore_ArithmTest
319 {
320 public:
321     CxCore_SubRSTest();
322 protected:
323     void run_func();
324 };
325
326 CxCore_SubRSTest::CxCore_SubRSTest()
327     : CxCore_ArithmTest( "arithm-subrs", "cvSubRS", 4, true )
328 {
329     test_array[INPUT].pop();
330     alpha = cvScalarAll(-1.);
331 }
332
333 void CxCore_SubRSTest::run_func()
334 {
335     cvSubRS( test_array[INPUT][0], gamma,
336              test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
337 }
338
339 CxCore_SubRSTest subrs_test;
340
341 ////////////////////////////// addweighted /////////////////////////////
342
343 class CxCore_AddWeightedTest : public CxCore_ArithmTest
344 {
345 public:
346     CxCore_AddWeightedTest();
347 protected:
348     void get_test_array_types_and_sizes( int test_case_idx,
349                                           CvSize** sizes, int** types );
350     double get_success_error_level( int test_case_idx, int i, int j );
351     void run_func();
352 };
353
354 CxCore_AddWeightedTest::CxCore_AddWeightedTest()
355     : CxCore_ArithmTest( "arithm-addweighted", "cvAddWeighted", 7, false )
356 {
357 }
358
359 void CxCore_AddWeightedTest::get_test_array_types_and_sizes( int test_case_idx,
360                                                     CvSize** sizes, int** types )
361 {
362     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
363     alpha = cvScalarAll(alpha.val[0]);
364     beta = cvScalarAll(beta.val[0]);
365     gamma = cvScalarAll(gamma.val[0]);
366 }
367
368
369 double CxCore_AddWeightedTest::get_success_error_level( int test_case_idx, int i, int j )
370 {
371     if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
372     {
373         return alpha.val[0] != cvRound(alpha.val[0]) ||
374                beta.val[0] != cvRound(beta.val[0]) ||
375                gamma.val[0] != cvRound(gamma.val[0]);
376     }
377     else
378         return CvArrTest::get_success_error_level( test_case_idx, i, j );
379 }
380
381
382 void CxCore_AddWeightedTest::run_func()
383 {
384     cvAddWeighted( test_array[INPUT][0], alpha.val[0],
385                    test_array[INPUT][1], beta.val[0],
386                    gamma.val[0], test_array[OUTPUT][0] );
387 }
388
389 CxCore_AddWeightedTest addweighted_test;
390
391
392 ////////////////////////////// absdiff /////////////////////////////
393
394 class CxCore_AbsDiffTest : public CxCore_ArithmTest
395 {
396 public:
397     CxCore_AbsDiffTest();
398 protected:
399     void run_func();
400 };
401
402 CxCore_AbsDiffTest::CxCore_AbsDiffTest()
403     : CxCore_ArithmTest( "arithm-absdiff", "cvAbsDiff", 0, false, true )
404 {
405     alpha = cvScalarAll(1.);
406     beta = cvScalarAll(-1.);
407 }
408
409 void CxCore_AbsDiffTest::run_func()
410 {
411     cvAbsDiff( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
412 }
413
414 CxCore_AbsDiffTest absdiff_test;
415
416 ////////////////////////////// absdiffs /////////////////////////////
417
418 class CxCore_AbsDiffSTest : public CxCore_ArithmTest
419 {
420 public:
421     CxCore_AbsDiffSTest();
422 protected:
423     void run_func();
424 };
425
426 CxCore_AbsDiffSTest::CxCore_AbsDiffSTest()
427     : CxCore_ArithmTest( "arithm-absdiffs", "cvAbsDiffS", 4, false, true )
428 {
429     alpha = cvScalarAll(-1.);
430     test_array[INPUT].pop();
431 }
432
433 void CxCore_AbsDiffSTest::run_func()
434 {
435     cvAbsDiffS( test_array[INPUT][0], test_array[OUTPUT][0], gamma );
436 }
437
438 CxCore_AbsDiffSTest absdiffs_test;
439
440
441 ////////////////////////////// mul /////////////////////////////
442
443 static const char* mul_param_names[] = { "size", "scale", "channels", "depth", 0 };
444 static const char* mul_scale_flags[] = { "scale==1", "scale!=1", 0 };
445
446 class CxCore_MulTest : public CxCore_ArithmTest
447 {
448 public:
449     CxCore_MulTest();
450 protected:
451     void run_func();
452     void get_timing_test_array_types_and_sizes( int test_case_idx,
453                                                 CvSize** sizes, int** types,
454                                                 CvSize** whole_sizes, bool* are_images );
455     double get_success_error_level( int test_case_idx, int i, int j );
456     void print_timing_params( int test_case_idx, char* ptr, int params_left );
457     void prepare_to_validation( int test_case_idx );
458     int write_default_params( CvFileStorage* fs );
459 };
460
461
462 CxCore_MulTest::CxCore_MulTest()
463     : CxCore_ArithmTest( "arithm-mul", "cvMul", 4, false, false )
464 {
465     default_timing_param_names = mul_param_names;
466 }
467
468
469 int CxCore_MulTest::write_default_params( CvFileStorage* fs )
470 {
471     int code = CxCore_ArithmTest::write_default_params(fs);
472     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
473         return code;
474     write_string_list( fs, "scale", mul_scale_flags );
475     return code;
476 }
477
478
479 void CxCore_MulTest::get_timing_test_array_types_and_sizes( int test_case_idx,
480                                                     CvSize** sizes, int** types,
481                                                     CvSize** whole_sizes, bool* are_images )
482 {
483     CxCore_ArithmTest::get_timing_test_array_types_and_sizes( test_case_idx,
484                                     sizes, types, whole_sizes, are_images );
485     const char* scale_flag_str = cvReadString( find_timing_param( "scale" ), "scale==1" );
486     if( strstr( scale_flag_str, "==1" ) )
487         alpha.val[0] = 1.;
488     else
489     {
490         double val = alpha.val[0];
491         int depth = CV_MAT_DEPTH(types[INPUT][0]);
492         if( val == 1. )
493             val = 1./CV_PI;
494         if( depth == CV_16U || depth == CV_16S || depth == CV_32S )
495         {
496             double minmax = 1./cvTsMaxVal(depth);
497             if( val < -minmax )
498                 val = -minmax;
499             else if( val > minmax )
500                 val = minmax;
501             if( depth == CV_16U && val < 0 )
502                 val = -val;
503         }
504         alpha.val[0] = val;
505         ts->printf( CvTS::LOG, "alpha = %g\n", alpha.val[0] );
506     }
507 }
508
509
510 void CxCore_MulTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
511 {
512     sprintf( ptr, "%s,", alpha.val[0] == 1. ? "scale==1" : "scale!=1" );
513     ptr += strlen(ptr);
514     params_left--;
515     CxCore_ArithmTest::print_timing_params( test_case_idx, ptr, params_left );
516 }
517
518
519 double CxCore_MulTest::get_success_error_level( int test_case_idx, int i, int j )
520 {
521     if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
522     {
523         return gamma.val[0] != cvRound(gamma.val[0]);
524     }
525     else
526         return CvArrTest::get_success_error_level( test_case_idx, i, j );
527 }
528
529
530 void CxCore_MulTest::run_func()
531 {
532     cvMul( test_array[INPUT][0], test_array[INPUT][1],
533            test_array[OUTPUT][0], alpha.val[0] );
534 }
535
536 void CxCore_MulTest::prepare_to_validation( int /*test_case_idx*/ )
537 {
538     cvTsMul( &test_mat[INPUT][0], &test_mat[INPUT][1],
539              cvScalarAll(alpha.val[0]),
540              &test_mat[REF_OUTPUT][0] );
541 }
542
543 CxCore_MulTest mul_test;
544
545 ////////////////////////////// div /////////////////////////////
546
547 class CxCore_DivTest : public CxCore_ArithmTest
548 {
549 public:
550     CxCore_DivTest();
551 protected:
552     void run_func();
553     void print_timing_params( int test_case_idx, char* ptr, int params_left );
554     void prepare_to_validation( int /*test_case_idx*/ );
555 };
556
557 CxCore_DivTest::CxCore_DivTest()
558     : CxCore_ArithmTest( "arithm-div", "cvDiv", 4, false, false )
559 {
560 }
561
562 void CxCore_DivTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
563 {
564     sprintf( ptr, "s*A(i)/B(i)," );
565     ptr += strlen(ptr);
566     params_left--;
567     CxCore_ArithmTest::print_timing_params( test_case_idx, ptr, params_left );
568 }
569
570 void CxCore_DivTest::run_func()
571 {
572     cvDiv( test_array[INPUT][0], test_array[INPUT][1],
573            test_array[OUTPUT][0], alpha.val[0] );
574 }
575
576 void CxCore_DivTest::prepare_to_validation( int /*test_case_idx*/ )
577 {
578     cvTsDiv( &test_mat[INPUT][0], &test_mat[INPUT][1],
579              cvScalarAll(alpha.val[0]),
580              &test_mat[REF_OUTPUT][0] );
581 }
582
583 CxCore_DivTest div_test;
584
585 ////////////////////////////// recip /////////////////////////////
586
587 class CxCore_RecipTest : public CxCore_ArithmTest
588 {
589 public:
590     CxCore_RecipTest();
591 protected:
592     void run_func();
593     void print_timing_params( int test_case_idx, char* ptr, int params_left );
594     void prepare_to_validation( int /*test_case_idx*/ );
595 };
596
597 CxCore_RecipTest::CxCore_RecipTest()
598     : CxCore_ArithmTest( "arithm-recip", "cvDiv", 4, false, false )
599 {
600     test_array[INPUT].pop();
601 }
602
603 void CxCore_RecipTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
604 {
605     sprintf( ptr, "s/B(i)," );
606     ptr += strlen(ptr);
607     params_left--;
608     CxCore_ArithmTest::print_timing_params( test_case_idx, ptr, params_left );
609 }
610
611 void CxCore_RecipTest::run_func()
612 {
613     cvDiv( 0, test_array[INPUT][0],
614            test_array[OUTPUT][0], gamma.val[0] );
615 }
616
617 void CxCore_RecipTest::prepare_to_validation( int /*test_case_idx*/ )
618 {
619     cvTsDiv( 0, &test_mat[INPUT][0],
620              cvScalarAll(gamma.val[0]),
621              &test_mat[REF_OUTPUT][0] );
622 }
623
624 CxCore_RecipTest recip_test;
625
626
627 ///////////////// matrix copy/initializing/permutations /////////////////////
628                                                    
629 class CxCore_MemTestImpl : public CxCore_ArithmTestImpl
630 {
631 public:
632     CxCore_MemTestImpl( const char* test_name, const char* test_funcs,
633                         int _generate_scalars=0, bool _allow_mask=true );
634 protected:
635     double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
636 };
637
638 CxCore_MemTestImpl::CxCore_MemTestImpl( const char* test_name, const char* test_funcs,
639                                         int _generate_scalars, bool _allow_mask ) :
640     CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask, false )
641 {
642 }
643
644 double CxCore_MemTestImpl::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
645 {
646     return 0;
647 }
648
649 CxCore_MemTestImpl mem_test( "mem", "", 0, false );
650
651
652 class CxCore_MemTest : public CxCore_MemTestImpl
653 {
654 public:
655     CxCore_MemTest( const char* test_name, const char* test_funcs,
656                     int _generate_scalars=0, bool _allow_mask=true );
657 };
658
659 CxCore_MemTest::CxCore_MemTest( const char* test_name, const char* test_funcs,
660                                 int _generate_scalars, bool _allow_mask ) :
661     CxCore_MemTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask )
662 {
663     default_timing_param_names = optional_mask ? arithm_mask_param_names : arithm_param_names;
664         
665     // inherit the default parameters from arithmerical test
666     size_list = 0;
667     whole_size_list = 0;
668     depth_list = 0;
669     cn_list = 0;
670 }
671
672
673 ///////////////// setidentity /////////////////////
674
675 class CxCore_SetIdentityTest : public CxCore_MemTest
676 {
677 public:
678     CxCore_SetIdentityTest();
679 protected:
680     void run_func();
681     void prepare_to_validation( int test_case_idx );
682 };
683
684
685 CxCore_SetIdentityTest::CxCore_SetIdentityTest() :
686     CxCore_MemTest( "mem-setidentity", "cvSetIdentity", 4, false )
687 {
688     test_array[INPUT].clear();
689 }
690
691
692 void CxCore_SetIdentityTest::run_func()
693 {
694     cvSetIdentity(test_array[OUTPUT][0], gamma);
695 }
696
697
698 void CxCore_SetIdentityTest::prepare_to_validation( int )
699 {
700     cvTsSetIdentity( &test_mat[REF_OUTPUT][0], gamma );
701 }
702
703 CxCore_SetIdentityTest setidentity_test;
704
705
706 ///////////////// SetZero /////////////////////
707
708 class CxCore_SetZeroTest : public CxCore_MemTest
709 {
710 public:
711     CxCore_SetZeroTest();
712 protected:
713     void run_func();
714     void prepare_to_validation( int test_case_idx );
715 };
716
717
718 CxCore_SetZeroTest::CxCore_SetZeroTest() :
719     CxCore_MemTest( "mem-setzero", "cvSetZero", 0, false )
720 {
721     test_array[INPUT].clear();
722 }
723
724
725 void CxCore_SetZeroTest::run_func()
726 {
727     cvSetZero(test_array[OUTPUT][0]);
728 }
729
730
731 void CxCore_SetZeroTest::prepare_to_validation( int )
732 {
733     cvTsZero( &test_mat[REF_OUTPUT][0] );
734 }
735
736 CxCore_SetZeroTest setzero_test;
737
738
739 ///////////////// Set /////////////////////
740
741 class CxCore_FillTest : public CxCore_MemTest
742 {
743 public:
744     CxCore_FillTest();
745 protected:
746     void run_func();
747     void prepare_to_validation( int test_case_idx );
748 };
749
750
751 CxCore_FillTest::CxCore_FillTest() :
752     CxCore_MemTest( "mem-fill", "cvSet", 4, true )
753 {
754     test_array[INPUT].clear();
755 }
756
757
758 void CxCore_FillTest::run_func()
759 {
760     cvSet(test_array[INPUT_OUTPUT][0], gamma, test_array[MASK][0]);
761 }
762
763
764 void CxCore_FillTest::prepare_to_validation( int )
765 {
766     if( test_array[MASK][0] )
767     {
768         cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), gamma, &test_mat[TEMP][0], 0 );
769         cvTsCopy( &test_mat[TEMP][0], &test_mat[REF_INPUT_OUTPUT][0], &test_mat[MASK][0] );
770     }
771     else
772     {
773         cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), gamma, &test_mat[REF_INPUT_OUTPUT][0], 0 );
774     }
775 }
776
777 CxCore_FillTest fill_test;
778
779
780 ///////////////// Copy /////////////////////
781
782 class CxCore_CopyTest : public CxCore_MemTest
783 {
784 public:
785     CxCore_CopyTest();
786 protected:
787     double get_success_error_level( int test_case_idx, int i, int j );
788     void run_func();
789     void prepare_to_validation( int test_case_idx );
790 };
791
792
793 CxCore_CopyTest::CxCore_CopyTest() :
794     CxCore_MemTest( "mem-copy", "cvCopy", 0, true )
795 {
796     test_array[INPUT].pop();
797 }
798
799
800 double CxCore_CopyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
801 {
802     return 0;
803 }
804
805
806 void CxCore_CopyTest::run_func()
807 {
808     cvCopy(test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[MASK][0]);
809 }
810
811
812 void CxCore_CopyTest::prepare_to_validation( int )
813 {
814     cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_INPUT_OUTPUT][0],
815               test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0 );
816 }
817
818 CxCore_CopyTest copy_test;
819
820 ///////////////// Transpose /////////////////////
821
822 class CxCore_TransposeTest : public CxCore_MemTest
823 {
824 public:
825     CxCore_TransposeTest();
826 protected:
827     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
828     void get_timing_test_array_types_and_sizes( int test_case_idx,
829                                                 CvSize** sizes, int** types,
830                                                 CvSize** whole_sizes, bool* are_images );
831     int prepare_test_case( int test_case_idx );
832     void run_func();
833     void prepare_to_validation( int test_case_idx );
834     bool inplace;
835 };
836
837
838 CxCore_TransposeTest::CxCore_TransposeTest() :
839     CxCore_MemTest( "mem-transpose", "cvTranspose", 0, false ), inplace(false)
840 {
841     test_array[INPUT].pop();
842 }
843
844
845 void CxCore_TransposeTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
846 {
847     int bits = cvTsRandInt(ts->get_rng());
848     CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
849
850     inplace = false;
851     if( bits & 1 )
852     {
853         sizes[INPUT][0].height = sizes[INPUT][0].width;
854         inplace = (bits & 2) != 0;
855     }
856
857     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][0].height, sizes[INPUT][0].width );
858 }
859
860
861 void CxCore_TransposeTest::get_timing_test_array_types_and_sizes( int test_case_idx,
862                 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
863 {
864     CxCore_MemTest::get_timing_test_array_types_and_sizes( test_case_idx,
865                                     sizes, types, whole_sizes, are_images );
866     CvSize size = sizes[INPUT][0];
867     if( size.width != size.height )
868     {
869         sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] =
870         whole_sizes[OUTPUT][0] = whole_sizes[REF_OUTPUT][0] = cvSize(size.height,size.width);
871     }
872 }
873
874
875 int CxCore_TransposeTest::prepare_test_case( int test_case_idx )
876 {
877     int code = CxCore_MemTest::prepare_test_case( test_case_idx );
878     if( inplace && code > 0 )
879         cvTsCopy( &test_mat[INPUT][0], &test_mat[OUTPUT][0] );
880     return code;
881 }
882
883 void CxCore_TransposeTest::run_func()
884 {
885     cvTranspose( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], test_array[OUTPUT][0]);
886 }
887
888
889 void CxCore_TransposeTest::prepare_to_validation( int )
890 {
891     cvTsTranspose( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0] );
892 }
893
894 CxCore_TransposeTest transpose_test;
895
896
897 ///////////////// Flip /////////////////////
898
899 static const int flip_codes[] = { 0, 1, -1, INT_MIN };
900 static const char* flip_strings[] = { "center", "vert", "horiz", 0 };
901 static const char* flip_param_names[] = { "size", "flip_op", "channels", "depth", 0 };
902
903 class CxCore_FlipTest : public CxCore_MemTest
904 {
905 public:
906     CxCore_FlipTest();
907 protected:
908     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
909     void get_timing_test_array_types_and_sizes( int test_case_idx,
910                                                 CvSize** sizes, int** types,
911                                                 CvSize** whole_sizes, bool* are_images );
912     int prepare_test_case( int test_case_idx );
913     void print_timing_params( int test_case_idx, char* ptr, int params_left );
914     void run_func();
915     void prepare_to_validation( int test_case_idx );
916     int write_default_params( CvFileStorage* fs );
917     int flip_type;
918     bool inplace;
919 };
920
921
922 CxCore_FlipTest::CxCore_FlipTest() :
923     CxCore_MemTest( "mem-flip", "cvFlip", 0, false ), flip_type(0), inplace(false)
924 {
925     test_array[INPUT].pop();
926     default_timing_param_names = flip_param_names;
927 }
928
929
930 int CxCore_FlipTest::write_default_params( CvFileStorage* fs )
931 {
932     int i, code = CxCore_MemTest::write_default_params(fs);
933     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
934         return code;
935     start_write_param( fs );
936     cvStartWriteStruct( fs, "flip_op", CV_NODE_SEQ + CV_NODE_FLOW );
937     for( i = 0; flip_codes[i] != INT_MIN; i++ )
938         cvWriteString( fs, 0, flip_strings[flip_codes[i]+1] );
939     cvEndWriteStruct(fs);
940     return code;
941 }
942
943
944 void CxCore_FlipTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
945 {
946     int bits = cvTsRandInt(ts->get_rng());
947     CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
948
949     flip_type = (bits & 3) - 2;
950     flip_type += flip_type == -2;
951     inplace = (bits & 4) != 0;
952 }
953
954
955 void CxCore_FlipTest::get_timing_test_array_types_and_sizes( int test_case_idx,
956                                                     CvSize** sizes, int** types,
957                                                     CvSize** whole_sizes, bool* are_images )
958 {
959     CxCore_MemTest::get_timing_test_array_types_and_sizes( test_case_idx,
960                                     sizes, types, whole_sizes, are_images );
961     const char* flip_op_str = cvReadString( find_timing_param( "flip_op" ), "center" );
962     if( strcmp( flip_op_str, "vert" ) == 0 )
963         flip_type = 0;
964     else if( strcmp( flip_op_str, "horiz" ) == 0 )
965         flip_type = 1;
966     else
967         flip_type = -1;
968 }
969
970
971 void CxCore_FlipTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
972 {
973     sprintf( ptr, "%s,", flip_type > 0 ? "horiz" : flip_type < 0 ? "center" : "vert" );
974     ptr += strlen(ptr);
975     params_left--;
976     CxCore_MemTest::print_timing_params( test_case_idx, ptr, params_left );
977 }
978
979
980 int CxCore_FlipTest::prepare_test_case( int test_case_idx )
981 {
982     int code = CxCore_MemTest::prepare_test_case( test_case_idx );
983     if( inplace && code > 0 )
984         cvTsCopy( &test_mat[INPUT][0], &test_mat[OUTPUT][0] );
985     return code;
986 }
987
988
989 void CxCore_FlipTest::run_func()
990 {
991     cvFlip(inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], test_array[OUTPUT][0], flip_type);
992 }
993
994
995 void CxCore_FlipTest::prepare_to_validation( int )
996 {
997     cvTsFlip( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], flip_type );
998 }
999
1000 CxCore_FlipTest flip_test;
1001
1002
1003 ///////////////// Split/Merge /////////////////////
1004
1005 static const char* split_merge_types[] = { "all", "single", 0 };
1006 static int split_merge_channels[] = { 2, 3, 4, -1 };
1007 static const char* split_merge_param_names[] = { "size", "planes", "channels", "depth", 0 };
1008
1009 class CxCore_SplitMergeBaseTest : public CxCore_MemTest
1010 {
1011 public:
1012     CxCore_SplitMergeBaseTest( const char* test_name, const char* test_funcs, int _is_split );
1013 protected:
1014     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1015     void get_timing_test_array_types_and_sizes( int test_case_idx,
1016                                                 CvSize** sizes, int** types,
1017                                                 CvSize** whole_sizes, bool* are_images );
1018     int prepare_test_case( int test_case_idx );
1019     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1020     void prepare_to_validation( int test_case_idx );
1021     int write_default_params( CvFileStorage* fs );
1022     bool are_images;
1023     int is_split, coi; 
1024     void* hdrs[4];
1025 };
1026
1027
1028 CxCore_SplitMergeBaseTest::CxCore_SplitMergeBaseTest( const char* test_name,
1029     const char* test_funcs, int _is_split )
1030     : CxCore_MemTest( test_name, test_funcs, 0, false ), are_images(false), is_split(_is_split), coi(0)
1031 {
1032     test_array[INPUT].pop();
1033     if( is_split )
1034         ;
1035     else
1036     {
1037         test_array[OUTPUT].clear();
1038         test_array[REF_OUTPUT].clear();
1039         test_array[INPUT_OUTPUT].push(NULL);
1040         test_array[REF_INPUT_OUTPUT].push(NULL);
1041     }
1042     memset( hdrs, 0, sizeof(hdrs) );
1043
1044     default_timing_param_names = split_merge_param_names;
1045     cn_list = split_merge_channels;
1046 }
1047
1048
1049 int CxCore_SplitMergeBaseTest::write_default_params( CvFileStorage* fs )
1050 {
1051     int code = CxCore_MemTest::write_default_params(fs);
1052     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1053         return code;
1054     write_string_list( fs, "planes", split_merge_types );
1055     return code;
1056 }
1057
1058
1059 void CxCore_SplitMergeBaseTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1060 {
1061     int cn, depth;
1062     CvRNG* rng = ts->get_rng();
1063     CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1064     cn = cvTsRandInt(rng)%3 + 2;
1065     depth = CV_MAT_DEPTH(types[INPUT][0]);
1066     
1067     if( is_split )
1068     {
1069         types[INPUT][0] = CV_MAKETYPE(depth, cn);
1070         types[OUTPUT][0] = types[REF_OUTPUT][0] = depth;
1071     }
1072     else
1073     {
1074         types[INPUT][0] = depth;
1075         types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1076     }
1077
1078     if( (cvTsRandInt(rng) & 3) != 0 )
1079     {
1080         coi = cvTsRandInt(rng) % cn;
1081     }
1082     else
1083     {
1084         CvSize size = sizes[INPUT][0];
1085         size.height *= cn;
1086
1087         if( is_split )
1088             sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = size;
1089         else
1090             sizes[INPUT][0] = size;
1091         coi = -1;
1092     }
1093
1094     are_images = cvTsRandInt(rng)%2 != 0;
1095 }
1096
1097
1098 void CxCore_SplitMergeBaseTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1099                     CvSize** sizes, int** types, CvSize** whole_sizes, bool* _are_images )
1100 {
1101     CxCore_MemTest::get_timing_test_array_types_and_sizes( test_case_idx,
1102                                     sizes, types, whole_sizes, _are_images );
1103     const char* split_merge_type = cvReadString( find_timing_param( "planes" ), "all" );
1104     int type0 = types[INPUT][0];
1105     int depth = CV_MAT_DEPTH(type0);
1106     int cn = CV_MAT_CN(type0);
1107     CvSize size = sizes[INPUT][0];
1108
1109     if( strcmp( split_merge_type, "single" ) == 0 )
1110         coi = cvTsRandInt(ts->get_rng()) % cn;
1111     else
1112     {
1113         coi = -1;
1114         size.height *= cn;
1115     }
1116
1117     if( is_split )
1118     {
1119         types[OUTPUT][0] = types[REF_OUTPUT][0] = depth;
1120         sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = size;
1121         
1122         // planes are put into separate arrays, not ROI's
1123         whole_sizes[OUTPUT][0] = whole_sizes[REF_OUTPUT][0] = size;
1124     }
1125     else
1126     {
1127         types[INPUT][0] = depth;
1128         sizes[INPUT][0] = size;
1129         
1130         // planes are put into separate arrays, not ROI's
1131         whole_sizes[INPUT][0] = size;
1132     }
1133
1134     are_images = false;
1135 }
1136
1137
1138 void CxCore_SplitMergeBaseTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1139 {
1140     int i;
1141     
1142     sprintf( ptr, "%s,", coi >= 0 ? "single" : "all" );
1143     ptr += strlen(ptr);
1144     params_left--;
1145
1146     // at once, delete the headers, though is not very good from structural point of view ...
1147     for( i = 0; i < 4; i++ )
1148         cvRelease( &hdrs[i] );
1149
1150     CxCore_MemTest::print_timing_params( test_case_idx, ptr, params_left );
1151 }
1152
1153
1154 int CxCore_SplitMergeBaseTest::prepare_test_case( int test_case_idx )
1155 {
1156     int code = CxCore_MemTest::prepare_test_case( test_case_idx );
1157     if( code > 0 )
1158     {
1159         CvMat* input = &test_mat[INPUT][0];
1160         CvMat* output = &test_mat[is_split ? OUTPUT : INPUT_OUTPUT][0];
1161         CvMat* merged = is_split ? input : output;
1162         CvMat* planes = is_split ? output : input;
1163         int depth = CV_MAT_DEPTH(merged->type);
1164         int i, cn = CV_MAT_CN(merged->type), y = 0;
1165         CvSize sz = cvGetMatSize(merged);
1166
1167         for( i = 0; i < cn; i++ )
1168         {
1169             if( coi < 0 || coi == i )
1170             {
1171                 if( are_images )
1172                     hdrs[i] = cvCreateImageHeader( sz, cvCvToIplDepth(depth), 1 );
1173                 else
1174                     hdrs[i] = cvCreateMatHeader( sz.height, sz.width, depth );
1175                 cvSetData( hdrs[i], planes->data.ptr + planes->step*y, planes->step );
1176                 y += sz.height;
1177             }
1178         }
1179     }
1180
1181     return code;
1182 }
1183
1184
1185 void CxCore_SplitMergeBaseTest::prepare_to_validation( int )
1186 {
1187     CvMat* input = &test_mat[INPUT][0];
1188     CvMat* output = &test_mat[is_split ? REF_OUTPUT : REF_INPUT_OUTPUT][0];
1189     CvMat* merged = is_split ? input : output;
1190     CvMat* planes = is_split ? output : input;
1191     int i, cn = CV_MAT_CN(merged->type), y = 0;
1192     CvSize sz = cvGetSize(merged);
1193
1194     for( i = 0; i < cn; i++ )
1195     {
1196         if( coi < 0 || coi == i )
1197         {
1198             CvMat stub, *h;
1199             cvSetData( hdrs[i], planes->data.ptr + planes->step*y, planes->step );
1200             h = cvGetMat( hdrs[i], &stub );
1201             if( is_split )
1202                 cvTsExtract( input, h, i );
1203             else
1204                 cvTsInsert( h, output, i );
1205             cvSetData( hdrs[i], 0, 0 );
1206             cvRelease( &hdrs[i] );
1207             y += sz.height;
1208         }
1209     }
1210 }
1211
1212
1213 class CxCore_SplitTest : public CxCore_SplitMergeBaseTest
1214 {
1215 public:
1216     CxCore_SplitTest();
1217 protected:
1218     void run_func();
1219 };
1220
1221
1222 CxCore_SplitTest::CxCore_SplitTest() :
1223     CxCore_SplitMergeBaseTest( "mem-split", "cvSplit", 1 )
1224 {
1225 }
1226
1227
1228 void CxCore_SplitTest::run_func()
1229 {
1230     cvSplit( test_array[INPUT][0], hdrs[0], hdrs[1], hdrs[2], hdrs[3] );
1231 }
1232
1233 CxCore_SplitTest split_test;
1234
1235 class CxCore_MergeTest : public CxCore_SplitMergeBaseTest
1236 {
1237 public:
1238     CxCore_MergeTest();
1239 protected:
1240     void run_func();
1241 };
1242
1243
1244 CxCore_MergeTest::CxCore_MergeTest() :
1245     CxCore_SplitMergeBaseTest( "mem-merge", "cvMerge", 0 )
1246 {
1247 }
1248
1249
1250 void CxCore_MergeTest::run_func()
1251 {
1252     cvMerge( hdrs[0], hdrs[1], hdrs[2], hdrs[3], test_array[INPUT_OUTPUT][0] );
1253 }
1254
1255 CxCore_MergeTest merge_test;
1256
1257 ////////////////////////////// min/max  /////////////////////////////
1258
1259 class CxCore_MinMaxBaseTest : public CxCore_ArithmTest
1260 {
1261 public:
1262     CxCore_MinMaxBaseTest( const char* test_name, const char* test_funcs,
1263                            int _op_type, int _generate_scalars=0 );
1264 protected:
1265     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1266     double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
1267     void prepare_to_validation( int /*test_case_idx*/ );
1268     int op_type;
1269 };
1270
1271 CxCore_MinMaxBaseTest::CxCore_MinMaxBaseTest( const char* test_name, const char* test_funcs,
1272                                               int _op_type, int _generate_scalars )
1273     : CxCore_ArithmTest( test_name, test_funcs, _generate_scalars, false, false ), op_type(_op_type)
1274 {
1275     if( _generate_scalars )
1276         test_array[INPUT].pop();
1277     default_timing_param_names = minmax_param_names;
1278 }
1279
1280 double CxCore_MinMaxBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1281 {
1282     return 0;
1283 }
1284
1285 void CxCore_MinMaxBaseTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1286 {
1287     int i, j;
1288     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1289     for( i = 0; i < max_arr; i++ )
1290     {
1291         int count = test_array[i].size();
1292         for( j = 0; j < count; j++ )
1293         {
1294             types[i][j] &= ~CV_MAT_CN_MASK;            
1295         }
1296     }
1297 }
1298
1299 void CxCore_MinMaxBaseTest::prepare_to_validation( int /*test_case_idx*/ )
1300 {
1301     if( !gen_scalars )
1302         cvTsMinMax( &test_mat[INPUT][0], &test_mat[INPUT][1],
1303                     &test_mat[REF_OUTPUT][0], op_type );
1304     else
1305         cvTsMinMaxS( &test_mat[INPUT][0], gamma.val[0],
1306                      &test_mat[REF_OUTPUT][0], op_type );
1307 }
1308
1309
1310 class CxCore_MinTest : public CxCore_MinMaxBaseTest
1311 {
1312 public:
1313     CxCore_MinTest();
1314 protected:
1315     void run_func();
1316 };
1317
1318
1319 CxCore_MinTest::CxCore_MinTest()
1320     : CxCore_MinMaxBaseTest( "arithm-min", "cvMin", CV_TS_MIN, 0 )
1321 {
1322 }
1323
1324 void CxCore_MinTest::run_func()
1325 {
1326     cvMin( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1327 }
1328
1329 CxCore_MinTest min_test;
1330
1331
1332 ////////////////////////////// max /////////////////////////////
1333
1334 class CxCore_MaxTest : public CxCore_MinMaxBaseTest
1335 {
1336 public:
1337     CxCore_MaxTest();
1338 protected:
1339     void run_func();
1340 };
1341
1342 CxCore_MaxTest::CxCore_MaxTest()
1343     : CxCore_MinMaxBaseTest( "arithm-max", "cvMax", CV_TS_MAX, 0 )
1344 {
1345 }
1346
1347 void CxCore_MaxTest::run_func()
1348 {
1349     cvMax( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1350 }
1351
1352 CxCore_MaxTest max_test;
1353
1354
1355 ////////////////////////////// mins /////////////////////////////
1356
1357 class CxCore_MinSTest : public CxCore_MinMaxBaseTest
1358 {
1359 public:
1360     CxCore_MinSTest();
1361 protected:
1362     void run_func();
1363 };
1364
1365 CxCore_MinSTest::CxCore_MinSTest()
1366     : CxCore_MinMaxBaseTest( "arithm-mins", "cvMinS", CV_TS_MIN, 4 )
1367 {
1368 }
1369
1370 void CxCore_MinSTest::run_func()
1371 {
1372     cvMinS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
1373 }
1374
1375 CxCore_MinSTest mins_test;
1376
1377 ////////////////////////////// maxs /////////////////////////////
1378
1379 class CxCore_MaxSTest : public CxCore_MinMaxBaseTest
1380 {
1381 public:
1382     CxCore_MaxSTest();
1383 protected:
1384     void run_func();
1385 };
1386
1387 CxCore_MaxSTest::CxCore_MaxSTest()
1388     : CxCore_MinMaxBaseTest( "arithm-maxs", "cvMaxS", CV_TS_MAX, 4 )
1389 {
1390 }
1391
1392 void CxCore_MaxSTest::run_func()
1393 {
1394     cvMaxS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
1395 }
1396
1397 CxCore_MaxSTest maxs_test;
1398
1399
1400 //////////////////////////////// logic ///////////////////////////////////////
1401
1402 class CxCore_LogicTestImpl : public CxCore_ArithmTestImpl
1403 {
1404 public:
1405     CxCore_LogicTestImpl( const char* test_name, const char* test_funcs, int _logic_op,
1406                       int _generate_scalars=0, bool _allow_mask=true );
1407 protected:
1408     void prepare_to_validation( int test_case_idx );
1409     int logic_op;
1410 };
1411
1412 CxCore_LogicTestImpl::CxCore_LogicTestImpl( const char* test_name, const char* test_funcs,
1413                             int _logic_op, int _generate_scalars, bool _allow_mask )
1414     : CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, _allow_mask, false ),
1415     logic_op(_logic_op)
1416 {
1417     if( _generate_scalars )
1418         test_array[INPUT].pop();
1419 }
1420
1421 void CxCore_LogicTestImpl::prepare_to_validation( int /*test_case_idx*/ )
1422 {
1423     int ref_output_idx = optional_mask ? REF_INPUT_OUTPUT : REF_OUTPUT;
1424     int output_idx = optional_mask ? INPUT_OUTPUT : OUTPUT;
1425     const CvMat* mask = test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0;
1426     CvMat* dst = mask ? &test_mat[TEMP][0] : &test_mat[ref_output_idx][0];
1427     int i;
1428     if( test_array[INPUT].size() > 1 )
1429     {
1430         cvTsLogic( &test_mat[INPUT][0], &test_mat[INPUT][1], dst, logic_op );
1431     }
1432     else
1433     {
1434         cvTsLogicS( &test_mat[INPUT][0], gamma, dst, logic_op );
1435     }
1436     if( mask )
1437         cvTsCopy( dst, &test_mat[ref_output_idx][0], mask );
1438     
1439     for( i = 0; i < 2; i++ )
1440     {
1441         dst = i == 0 ? &test_mat[ref_output_idx][0] : &test_mat[output_idx][0];
1442
1443         if( CV_IS_MAT(dst) )
1444         {
1445             CvMat* mat = (CvMat*)dst;
1446             mat->cols *= CV_ELEM_SIZE(mat->type);
1447             mat->type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_8UC1;
1448         }
1449         else
1450         {
1451             IplImage* img = (IplImage*)dst;
1452             int elem_size;
1453         
1454             assert( CV_IS_IMAGE(dst) );
1455             elem_size = ((img->depth & 255)>>3)*img->nChannels;
1456             img->width *= elem_size;
1457         
1458             if( img->roi )
1459             {
1460                 img->roi->xOffset *= elem_size;
1461                 img->roi->width *= elem_size;
1462             }
1463             img->depth = IPL_DEPTH_8U;
1464             img->nChannels = 1;
1465         }
1466     }
1467 }
1468
1469 CxCore_LogicTestImpl logic_test("logic", "", -1, 0, false );
1470
1471 class CxCore_LogicTest : public CxCore_LogicTestImpl
1472 {
1473 public:
1474     CxCore_LogicTest( const char* test_name, const char* test_funcs, int _logic_op,
1475                       int _generate_scalars=0, bool _allow_mask=true );
1476 };
1477
1478 CxCore_LogicTest::CxCore_LogicTest( const char* test_name, const char* test_funcs,
1479                             int _logic_op, int _generate_scalars, bool _allow_mask )
1480     : CxCore_LogicTestImpl( test_name, test_funcs, _logic_op, _generate_scalars, _allow_mask )
1481 {
1482     default_timing_param_names = optional_mask ? arithm_mask_param_names : arithm_param_names;
1483
1484     // inherit the default parameters from arithmerical test
1485     size_list = 0;
1486     whole_size_list = 0;
1487     depth_list = 0;
1488     cn_list = 0;
1489 }
1490
1491
1492 ///////////////////////// and //////////////////////////
1493
1494 class CxCore_AndTest : public CxCore_LogicTest
1495 {
1496 public:
1497     CxCore_AndTest();
1498 protected:
1499     void run_func();
1500 };
1501
1502 CxCore_AndTest::CxCore_AndTest()
1503     : CxCore_LogicTest( "logic-and", "cvAnd", CV_TS_LOGIC_AND )
1504 {
1505 }
1506
1507 void CxCore_AndTest::run_func()
1508 {
1509     cvAnd( test_array[INPUT][0], test_array[INPUT][1],
1510            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1511 }
1512
1513 CxCore_AndTest and_test;
1514
1515
1516 class CxCore_AndSTest : public CxCore_LogicTest
1517 {
1518 public:
1519     CxCore_AndSTest();
1520 protected:
1521     void run_func();
1522 };
1523
1524 CxCore_AndSTest::CxCore_AndSTest()
1525     : CxCore_LogicTest( "logic-ands", "cvAndS", CV_TS_LOGIC_AND, 4 )
1526 {
1527 }
1528
1529 void CxCore_AndSTest::run_func()
1530 {
1531     cvAndS( test_array[INPUT][0], gamma,
1532             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1533 }
1534
1535 CxCore_AndSTest ands_test;
1536
1537
1538 ///////////////////////// or /////////////////////////
1539
1540 class CxCore_OrTest : public CxCore_LogicTest
1541 {
1542 public:
1543     CxCore_OrTest();
1544 protected:
1545     void run_func();
1546 };
1547
1548 CxCore_OrTest::CxCore_OrTest()
1549     : CxCore_LogicTest( "logic-or", "cvOr", CV_TS_LOGIC_OR )
1550 {
1551 }
1552
1553 void CxCore_OrTest::run_func()
1554 {
1555     cvOr( test_array[INPUT][0], test_array[INPUT][1],
1556           test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1557 }
1558
1559 CxCore_OrTest or_test;
1560
1561
1562 class CxCore_OrSTest : public CxCore_LogicTest
1563 {
1564 public:
1565     CxCore_OrSTest();
1566 protected:
1567     void run_func();
1568 };
1569
1570 CxCore_OrSTest::CxCore_OrSTest()
1571     : CxCore_LogicTest( "logic-ors", "cvOrS", CV_TS_LOGIC_OR, 4 )
1572 {
1573 }
1574
1575 void CxCore_OrSTest::run_func()
1576 {
1577     cvOrS( test_array[INPUT][0], gamma,
1578            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1579 }
1580
1581 CxCore_OrSTest ors_test;
1582
1583
1584 ////////////////////////// xor ////////////////////////////
1585
1586 class CxCore_XorTest : public CxCore_LogicTest
1587 {
1588 public:
1589     CxCore_XorTest();
1590 protected:
1591     void run_func();
1592 };
1593
1594 CxCore_XorTest::CxCore_XorTest()
1595     : CxCore_LogicTest( "logic-xor", "cvXor", CV_TS_LOGIC_XOR )
1596 {
1597 }
1598
1599 void CxCore_XorTest::run_func()
1600 {
1601     cvXor( test_array[INPUT][0], test_array[INPUT][1],
1602            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1603 }
1604
1605 CxCore_XorTest xor_test;
1606
1607
1608 class CxCore_XorSTest : public CxCore_LogicTest
1609 {
1610 public:
1611     CxCore_XorSTest();
1612 protected:
1613     void run_func();
1614 };
1615
1616 CxCore_XorSTest::CxCore_XorSTest()
1617     : CxCore_LogicTest( "logic-xors", "cvXorS", CV_TS_LOGIC_XOR, 4 )
1618 {
1619 }
1620
1621 void CxCore_XorSTest::run_func()
1622 {
1623     cvXorS( test_array[INPUT][0], gamma,
1624             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1625 }
1626
1627 CxCore_XorSTest xors_test;
1628
1629
1630 ////////////////////////// not ////////////////////////////
1631
1632 class CxCore_NotTest : public CxCore_LogicTest
1633 {
1634 public:
1635     CxCore_NotTest();
1636 protected:
1637     void run_func();
1638 };
1639
1640 CxCore_NotTest::CxCore_NotTest()
1641     : CxCore_LogicTest( "logic-not", "cvNot", CV_TS_LOGIC_NOT, 4, false )
1642 {
1643 }
1644
1645 void CxCore_NotTest::run_func()
1646 {
1647     cvNot( test_array[INPUT][0],
1648            test_array[OUTPUT][0] );
1649 }
1650
1651 CxCore_NotTest nots_test;
1652
1653 ///////////////////////// cmp //////////////////////////////
1654
1655 static int cmp_op_values[] = { CV_CMP_GE, CV_CMP_EQ, CV_CMP_NE, -1 };
1656
1657 class CxCore_CmpBaseTestImpl : public CxCore_ArithmTestImpl
1658 {
1659 public:
1660     CxCore_CmpBaseTestImpl( const char* test_name, const char* test_funcs,
1661                             int in_range, int _generate_scalars=0 );
1662 protected:
1663     double get_success_error_level( int test_case_idx, int i, int j );
1664     void get_test_array_types_and_sizes( int test_case_idx,
1665                                          CvSize** sizes, int** types );
1666     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes,
1667                             int** types, CvSize** whole_sizes, bool* are_images );
1668     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1669     void prepare_to_validation( int test_case_idx );
1670     int write_default_params( CvFileStorage* fs );
1671     int in_range;
1672     int cmp_op;
1673     enum { CMP_OP_COUNT=6 };
1674     const char* cmp_op_strings[CMP_OP_COUNT];
1675 };
1676
1677 CxCore_CmpBaseTestImpl::CxCore_CmpBaseTestImpl( const char* test_name, const char* test_funcs,
1678                                         int _in_range, int _generate_scalars )
1679     : CxCore_ArithmTestImpl( test_name, test_funcs, _generate_scalars, 0, 0 ), in_range(_in_range)
1680 {
1681     static const char* cmp_param_names[] = { "size", "cmp_op", "depth", 0 };
1682     static const char* inrange_param_names[] = { "size", "channels", "depth", 0 };
1683
1684     if( in_range )
1685     {
1686         test_array[INPUT].push(NULL);
1687         test_array[TEMP].push(NULL);
1688         test_array[TEMP].push(NULL);
1689         if( !gen_scalars )
1690             test_array[TEMP].push(NULL);
1691     }
1692     if( gen_scalars )
1693         test_array[INPUT].pop();
1694
1695     default_timing_param_names = in_range == 1 ? inrange_param_names : cmp_param_names;
1696
1697     cmp_op_strings[CV_CMP_EQ] = "eq";
1698     cmp_op_strings[CV_CMP_LT] = "lt";
1699     cmp_op_strings[CV_CMP_LE] = "le";
1700     cmp_op_strings[CV_CMP_GE] = "ge";
1701     cmp_op_strings[CV_CMP_GT] = "gt";
1702     cmp_op_strings[CV_CMP_NE] = "ne";
1703
1704     cmp_op = -1;
1705 }
1706
1707 double CxCore_CmpBaseTestImpl::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1708 {
1709     return 0;
1710 }
1711
1712
1713 void CxCore_CmpBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
1714                                                     CvSize** sizes, int** types )
1715 {
1716     int j, count;
1717     CxCore_ArithmTestImpl::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1718     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8UC1;
1719     if( in_range == 0 )
1720     {
1721         // for cmp tests make all the input arrays single-channel
1722         count = test_array[INPUT].size();
1723         for( j = 0; j < count; j++ )
1724             types[INPUT][j] &= ~CV_MAT_CN_MASK;
1725
1726         cmp_op = cvTsRandInt(ts->get_rng()) % 6; // == > >= < <= !=
1727     }
1728     else if( in_range == 1 )
1729     {
1730         types[TEMP][0] = CV_8UC1;
1731         types[TEMP][1] &= ~CV_MAT_CN_MASK;
1732         if( !gen_scalars )
1733             types[TEMP][2] &= ~CV_MAT_CN_MASK;
1734     }
1735 }
1736
1737
1738 int CxCore_CmpBaseTestImpl::write_default_params( CvFileStorage* fs )
1739 {
1740     int code = CxCore_ArithmTestImpl::write_default_params(fs);
1741     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1742         return code;
1743     if( in_range == 0 )
1744     {
1745         start_write_param( fs );
1746         int i;
1747         cvStartWriteStruct( fs, "cmp_op", CV_NODE_SEQ + CV_NODE_FLOW );
1748         for( i = 0; cmp_op_values[i] >= 0; i++ )
1749             cvWriteString( fs, 0, cmp_op_strings[cmp_op_values[i]] );
1750         cvEndWriteStruct(fs);
1751     }
1752     return code;
1753 }
1754
1755
1756 void CxCore_CmpBaseTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
1757                                                     CvSize** sizes, int** types,
1758                                                     CvSize** whole_sizes, bool* are_images )
1759 {
1760     CxCore_ArithmTestImpl::get_timing_test_array_types_and_sizes( test_case_idx,
1761                                             sizes, types, whole_sizes, are_images );
1762     types[OUTPUT][0] = CV_8UC1;
1763     if( in_range == 0 )
1764     {
1765         const char* cmp_op_str = cvReadString( find_timing_param( "cmp_op" ), "ge" );
1766         int i;
1767         cmp_op = CV_CMP_GE;
1768         for( i = 0; i < CMP_OP_COUNT; i++ )
1769             if( strcmp( cmp_op_str, cmp_op_strings[i] ) == 0 )
1770             {
1771                 cmp_op = i;
1772                 break;
1773             }
1774     }
1775 }
1776
1777
1778 void CxCore_CmpBaseTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
1779 {
1780     if( in_range == 0 )
1781     {
1782         sprintf( ptr, "%s,", cmp_op_strings[cmp_op] );
1783         ptr += strlen(ptr);
1784         params_left--;
1785     }
1786     CxCore_ArithmTestImpl::print_timing_params( test_case_idx, ptr, params_left );
1787 }
1788
1789
1790 void CxCore_CmpBaseTestImpl::prepare_to_validation( int /*test_case_idx*/ )
1791 {
1792     CvMat* dst = &test_mat[REF_OUTPUT][0];
1793     if( !in_range )
1794     {
1795         if( test_array[INPUT].size() > 1 )
1796         {
1797             cvTsCmp( &test_mat[INPUT][0], &test_mat[INPUT][1], dst, cmp_op );
1798         }
1799         else
1800         {
1801             cvTsCmpS( &test_mat[INPUT][0], gamma.val[0], dst, cmp_op );
1802         }
1803     }
1804     else
1805     {
1806         int el_type = CV_MAT_TYPE( test_mat[INPUT][0].type );
1807         int i, cn = CV_MAT_CN(el_type);
1808         CvMat* tdst = dst;
1809
1810         for( i = 0; i < cn*2; i++ )
1811         {
1812             int coi = i / 2, is_lower = (i % 2) == 0;
1813             int cmp_op = is_lower ? CV_CMP_GE : CV_CMP_LT;
1814             const CvMat* src = &test_mat[INPUT][0];
1815             const CvMat* lu = gen_scalars ? 0 : &test_mat[INPUT][is_lower?1:2];
1816             double luS = is_lower ? alpha.val[coi] : gamma.val[coi];
1817             
1818             if( cn > 1 )
1819             {
1820                 cvTsExtract( src, &test_mat[TEMP][1], coi );
1821                 src = &test_mat[TEMP][1];
1822
1823                 if( !gen_scalars )
1824                 {
1825                     cvTsExtract( lu, &test_mat[TEMP][2], coi );
1826                     lu = &test_mat[TEMP][2];
1827                 }
1828             }
1829
1830             if( !gen_scalars )
1831                 cvTsCmp( src, lu, tdst, cmp_op );
1832             else
1833                 cvTsCmpS( src, luS, tdst, cmp_op );
1834             if( i > 0 )
1835                 cvTsLogic( tdst, dst, dst, CV_TS_LOGIC_AND );
1836             tdst = &test_mat[TEMP][0];
1837         }
1838     }
1839 }
1840
1841
1842 CxCore_CmpBaseTestImpl cmpbase_test( "cmp", "", -1 );
1843
1844
1845 class CxCore_CmpBaseTest : public CxCore_CmpBaseTestImpl
1846 {
1847 public:
1848     CxCore_CmpBaseTest( const char* test_name, const char* test_funcs,
1849                         int in_range, int _generate_scalars=0 );
1850 };
1851
1852 CxCore_CmpBaseTest::CxCore_CmpBaseTest( const char* test_name, const char* test_funcs,
1853                                         int _in_range, int _generate_scalars )
1854     : CxCore_CmpBaseTestImpl( test_name, test_funcs, _in_range, _generate_scalars )
1855 {
1856     // inherit the default parameters from arithmerical test
1857     size_list = 0;
1858     depth_list = 0;
1859     cn_list = 0;
1860 }
1861
1862
1863 class CxCore_CmpTest : public CxCore_CmpBaseTest
1864 {
1865 public:
1866     CxCore_CmpTest();
1867 protected:
1868     void run_func();
1869 };
1870
1871 CxCore_CmpTest::CxCore_CmpTest()
1872     : CxCore_CmpBaseTest( "cmp-cmp", "cvCmp", 0, 0 )
1873 {
1874 }
1875
1876 void CxCore_CmpTest::run_func()
1877 {
1878     cvCmp( test_array[INPUT][0], test_array[INPUT][1],
1879            test_array[OUTPUT][0], cmp_op );
1880 }
1881
1882 CxCore_CmpTest cmp_test;
1883
1884
1885 class CxCore_CmpSTest : public CxCore_CmpBaseTest
1886 {
1887 public:
1888     CxCore_CmpSTest();
1889 protected:
1890     void run_func();
1891 };
1892
1893 CxCore_CmpSTest::CxCore_CmpSTest()
1894     : CxCore_CmpBaseTest( "cmp-cmps", "cvCmpS", 0, 4 )
1895 {
1896 }
1897
1898 void CxCore_CmpSTest::run_func()
1899 {
1900     cvCmpS( test_array[INPUT][0], gamma.val[0],
1901             test_array[OUTPUT][0], cmp_op );
1902 }
1903
1904 CxCore_CmpSTest cmps_test;
1905
1906
1907 class CxCore_InRangeTest : public CxCore_CmpBaseTest
1908 {
1909 public:
1910     CxCore_InRangeTest();
1911 protected:
1912     void run_func();
1913 };
1914
1915 CxCore_InRangeTest::CxCore_InRangeTest()
1916     : CxCore_CmpBaseTest( "cmp-inrange", "cvInRange", 1, 0 )
1917 {
1918 }
1919
1920 void CxCore_InRangeTest::run_func()
1921 {
1922     cvInRange( test_array[INPUT][0], test_array[INPUT][1],
1923                test_array[INPUT][2], test_array[OUTPUT][0] );
1924 }
1925
1926 CxCore_InRangeTest inrange_test;
1927
1928
1929 class CxCore_InRangeSTest : public CxCore_CmpBaseTest
1930 {
1931 public:
1932     CxCore_InRangeSTest();
1933 protected:
1934     void run_func();
1935 };
1936
1937 CxCore_InRangeSTest::CxCore_InRangeSTest()
1938     : CxCore_CmpBaseTest( "cmp-inranges", "cvInRangeS", 1, 5 )
1939 {
1940 }
1941
1942 void CxCore_InRangeSTest::run_func()
1943 {
1944     cvInRangeS( test_array[INPUT][0], alpha, gamma, test_array[OUTPUT][0] );
1945 }
1946
1947 CxCore_InRangeSTest inranges_test;
1948
1949
1950 /////////////////////////// convertscale[abs] ////////////////////////////////////////
1951
1952 static const char* cvt_param_names[] = { "size", "scale", "dst_depth", "depth", 0 };
1953 static const char* cvt_abs_param_names[] = { "size", "depth", 0 };
1954 static const int cvt_scale_flags[] = { 0, 1 };
1955
1956 class CxCore_CvtBaseTestImpl : public CxCore_ArithmTestImpl
1957 {
1958 public:
1959     CxCore_CvtBaseTestImpl( const char* test_name, const char* test_funcs, bool calc_abs );
1960 protected:
1961     void get_test_array_types_and_sizes( int test_case_idx,
1962                                          CvSize** sizes, int** types );
1963     void get_timing_test_array_types_and_sizes( int test_case_idx,
1964                                         CvSize** sizes, int** types,
1965                                         CvSize** whole_sizes, bool *are_images );
1966     double get_success_error_level( int test_case_idx, int i, int j );
1967
1968     int prepare_test_case( int test_case_idx );
1969     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1970     int write_default_params( CvFileStorage* fs );
1971
1972     void prepare_to_validation( int test_case_idx );
1973 };
1974
1975
1976 CxCore_CvtBaseTestImpl::CxCore_CvtBaseTestImpl( const char* test_name,
1977                                                 const char* test_funcs,
1978                                                 bool _calc_abs )
1979     : CxCore_ArithmTestImpl( test_name, test_funcs, 5, false, _calc_abs )
1980 {
1981     test_array[INPUT].pop();
1982     default_timing_param_names = 0;
1983     cn_list = 0;
1984 }
1985
1986
1987 // unlike many other arithmetic functions, conversion operations support 8s type,
1988 // also, for cvCvtScale output array depth may be arbitrary and
1989 // for cvCvtScaleAbs output depth = CV_8U
1990 void CxCore_CvtBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
1991                                                 CvSize** sizes, int** types )
1992 {
1993     CxCore_ArithmTestImpl::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1994     CvRNG* rng = ts->get_rng();
1995     int depth = CV_8U, rbits;
1996     types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|
1997                     cvTsRandInt(rng)%(CV_64F+1);
1998     if( !calc_abs )
1999         depth = cvTsRandInt(rng) % (CV_64F+1);
2000     types[OUTPUT][0] = types[REF_OUTPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|depth;
2001
2002     rbits = cvTsRandInt(rng);
2003     // check special cases: shift=0 and/or scale=1.
2004     if( (rbits & 3) == 0 )
2005         gamma.val[0] = 0;
2006     if( (rbits & 12) == 0 )
2007         alpha.val[0] = 1;
2008 }
2009
2010
2011 double CxCore_CvtBaseTestImpl::get_success_error_level( int test_case_idx, int i, int j )
2012 {
2013     if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
2014     {
2015         return alpha.val[0] != cvRound(alpha.val[0]) ||
2016                beta.val[0] != cvRound(beta.val[0]) ||
2017                gamma.val[0] != cvRound(gamma.val[0]);
2018     }
2019     else
2020         return CvArrTest::get_success_error_level( test_case_idx, i, j );
2021 }
2022
2023
2024 void CxCore_CvtBaseTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
2025                     CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
2026 {
2027     CxCore_ArithmTestImpl::get_timing_test_array_types_and_sizes( test_case_idx,
2028                                     sizes, types, whole_sizes, are_images );
2029     bool scale = true;
2030     int dst_depth = CV_8U;
2031     int cn = CV_MAT_CN(types[INPUT][0]);
2032     if( !calc_abs )
2033     {
2034         scale = cvReadInt( find_timing_param( "scale" ), 1 ) != 0;
2035         dst_depth = cvTsTypeByName( cvReadString(find_timing_param( "dst_depth" ), "8u") );
2036     }
2037
2038     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(dst_depth, cn);
2039
2040     if( scale )
2041     {
2042         alpha.val[0] = 2.1;
2043         gamma.val[0] = -100.;
2044     }
2045     else
2046     {
2047         alpha.val[0] = 1.;
2048         gamma.val[0] = 0.;
2049     }
2050 }
2051
2052
2053 int CxCore_CvtBaseTestImpl::prepare_test_case( int test_case_idx )
2054 {
2055     int code = CxCore_ArithmTestImpl::prepare_test_case( test_case_idx );
2056
2057     if( code > 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
2058     {
2059         if( CV_ARE_TYPES_EQ( &test_mat[INPUT][0], &test_mat[OUTPUT][0] ) &&
2060             !calc_abs && alpha.val[0] == 1 && gamma.val[0] == 0 )
2061             code = 0; // skip the case when no any transformation is done
2062     }
2063
2064     return code;
2065 }
2066
2067
2068 void CxCore_CvtBaseTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
2069 {
2070     sprintf( ptr, "%s,", alpha.val[0] == 1. && gamma.val[0] == 0. ? "no_scale" : "scale" );
2071     ptr += strlen(ptr);
2072     params_left--;
2073     CxCore_ArithmTestImpl::print_timing_params( test_case_idx, ptr, params_left );
2074 }
2075
2076
2077 int CxCore_CvtBaseTestImpl::write_default_params( CvFileStorage* fs )
2078 {
2079     int i, code = CxCore_ArithmTestImpl::write_default_params(fs);
2080     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2081         return code;
2082     if( !calc_abs )
2083     {
2084         start_write_param( fs );
2085         cvStartWriteStruct( fs, "dst_depth", CV_NODE_SEQ + CV_NODE_FLOW );
2086         for( i = 0; arithm_depths[i] >= 0; i++ )
2087             cvWriteString( fs, 0, cvTsGetTypeName(arithm_depths[i]) );
2088         cvEndWriteStruct(fs);
2089         write_int_list( fs, "scale", cvt_scale_flags, CV_DIM(cvt_scale_flags) );
2090     }
2091     return code;
2092 }
2093
2094
2095 void CxCore_CvtBaseTestImpl::prepare_to_validation( int /*test_case_idx*/ )
2096 {
2097     cvTsAdd( &test_mat[INPUT][0], cvScalarAll(alpha.val[0]), 0, beta,
2098              cvScalarAll(gamma.val[0]), &test_mat[REF_OUTPUT][0], calc_abs );
2099 }
2100
2101 CxCore_CvtBaseTestImpl cvt_test( "cvt", "", true );
2102
2103
2104 class CxCore_CvtBaseTest : public CxCore_CvtBaseTestImpl
2105 {
2106 public:
2107     CxCore_CvtBaseTest( const char* test_name, const char* test_funcs, bool calc_abs );
2108 };
2109
2110
2111 CxCore_CvtBaseTest::CxCore_CvtBaseTest( const char* test_name, const char* test_funcs, bool _calc_abs )
2112     : CxCore_CvtBaseTestImpl( test_name, test_funcs, _calc_abs )
2113 {
2114     // inherit the default parameters from arithmerical test
2115     size_list = 0;
2116     whole_size_list = 0;
2117     depth_list = 0;
2118     cn_list = 0;
2119 }
2120
2121
2122 class CxCore_CvtScaleTest : public CxCore_CvtBaseTest
2123 {
2124 public:
2125     CxCore_CvtScaleTest();
2126 protected:
2127     void run_func();
2128 };
2129
2130 CxCore_CvtScaleTest::CxCore_CvtScaleTest()
2131     : CxCore_CvtBaseTest( "cvt-scale", "cvCvtScale", false )
2132 {
2133     default_timing_param_names = cvt_param_names;
2134 }
2135
2136 void CxCore_CvtScaleTest::run_func()
2137 {
2138     cvConvertScale( test_array[INPUT][0], test_array[OUTPUT][0],
2139                     alpha.val[0], gamma.val[0] );
2140 }
2141
2142 CxCore_CvtScaleTest cvtscale_test;
2143
2144
2145 class CxCore_CvtScaleAbsTest : public CxCore_CvtBaseTest
2146 {
2147 public:
2148     CxCore_CvtScaleAbsTest();
2149 protected:
2150     void run_func();
2151 };
2152
2153 CxCore_CvtScaleAbsTest::CxCore_CvtScaleAbsTest()
2154     : CxCore_CvtBaseTest( "cvt-scaleabs", "cvCvtScaleAbs", true )
2155 {
2156     default_timing_param_names = cvt_abs_param_names;
2157 }
2158
2159 void CxCore_CvtScaleAbsTest::run_func()
2160 {
2161     cvConvertScaleAbs( test_array[INPUT][0], test_array[OUTPUT][0],
2162                        alpha.val[0], gamma.val[0] );
2163 }
2164
2165 CxCore_CvtScaleAbsTest cvtscaleabs_test;
2166
2167
2168 /////////////////////////////// statistics //////////////////////////////////
2169
2170 static const char* stat_param_names[] = { "size", "coi", "channels", "depth", 0 };
2171 static const char* stat_mask_param_names[] = { "size", "coi", "channels", "depth", "use_mask", 0 };
2172 static const char* stat_single_param_names[] = { "size", "channels", "depth", 0 };
2173 static const char* stat_single_mask_param_names[] = { "size", "channels", "depth", "use_mask", 0 };
2174 static const char* stat_coi_modes[] = { "all", "single", 0 };
2175
2176 class CxCore_StatTestImpl : public CvArrTest
2177 {
2178 public:
2179     CxCore_StatTestImpl( const char* test_name, const char* test_funcs,
2180                      int _output_count, bool _single_channel,
2181                      bool _allow_mask=true, bool _is_binary=false );
2182 protected:
2183     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2184     void get_timing_test_array_types_and_sizes( int test_case_idx,
2185                                                 CvSize** sizes, int** types,
2186                                                 CvSize** whole_sizes, bool* are_images );
2187     void print_timing_params( int test_case_idx, char* ptr, int params_left );
2188     int write_default_params( CvFileStorage* fs );    
2189     int prepare_test_case( int test_case_idx );
2190     double get_success_error_level( int test_case_idx, int i, int j );
2191
2192     int coi;
2193     int output_count;
2194     bool single_channel;
2195     bool is_binary;
2196 };
2197
2198
2199 CxCore_StatTestImpl::CxCore_StatTestImpl( const char* test_name,
2200                         const char* test_funcs, int _output_count,
2201                         bool _single_channel, bool _allow_mask, bool _is_binary )
2202     : CvArrTest( test_name, test_funcs, "" ), output_count(_output_count),
2203     single_channel(_single_channel), is_binary(_is_binary)
2204 {
2205     test_array[INPUT].push(NULL);
2206     if( is_binary )
2207         test_array[INPUT].push(NULL);
2208     optional_mask = _allow_mask;
2209     if( optional_mask )
2210         test_array[MASK].push(NULL);
2211     test_array[OUTPUT].push(NULL);
2212     test_array[REF_OUTPUT].push(NULL);
2213     coi = 0;
2214
2215     size_list = arithm_sizes;
2216     whole_size_list = arithm_whole_sizes;
2217     depth_list = arithm_depths;
2218     cn_list = arithm_channels;
2219 }
2220
2221
2222 void CxCore_StatTestImpl::get_test_array_types_and_sizes( int test_case_idx,
2223                                             CvSize** sizes, int** types )
2224 {
2225     CvRNG* rng = ts->get_rng();
2226     int depth = cvTsRandInt(rng)%(CV_64F+1);
2227     int cn = cvTsRandInt(rng) % 4 + 1;
2228     int j, count = test_array[INPUT].size();
2229     
2230     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2231     depth += depth == CV_8S;
2232
2233     for( j = 0; j < count; j++ )
2234         types[INPUT][j] = CV_MAKETYPE(depth, cn);
2235
2236     // regardless of the test case, the output is always a fixed-size tuple of numbers
2237     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( output_count, 1 );
2238     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
2239
2240     coi = 0;
2241     cvmat_allowed = true;
2242     if( cn > 1 && (single_channel || (cvTsRandInt(rng) & 3) == 0) )
2243     {
2244         coi = cvTsRandInt(rng) % cn + 1;
2245         cvmat_allowed = false;
2246     }
2247 }
2248
2249
2250 void CxCore_StatTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
2251                 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
2252 {
2253     CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
2254                                                       whole_sizes, are_images );
2255     const char* coi_mode_str = cvReadString(find_timing_param("coi"), single_channel ? "single" : "all");
2256
2257     // regardless of the test case, the output is always a fixed-size tuple of numbers
2258     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( output_count, 1 );
2259     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
2260
2261     int cn = CV_MAT_CN(types[INPUT][0]);
2262     coi = 0;
2263     cvmat_allowed = true;
2264     if( strcmp( coi_mode_str, "single" ) == 0 )
2265     {
2266         CvRNG* rng = ts->get_rng();
2267         coi = cvTsRandInt(rng) % cn + 1;
2268         cvmat_allowed = false;
2269         *are_images = true;
2270     }
2271 }
2272
2273
2274 int CxCore_StatTestImpl::write_default_params( CvFileStorage* fs )
2275 {
2276     int code = CvArrTest::write_default_params(fs);
2277     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2278         return code;
2279     if( !single_channel )
2280         write_string_list( fs, "coi", stat_coi_modes );
2281     return code;
2282 }
2283
2284
2285 int CxCore_StatTestImpl::prepare_test_case( int test_case_idx )
2286 {
2287     int code = CvArrTest::prepare_test_case( test_case_idx );
2288     
2289     if( coi && code > 0 )
2290     {
2291         int j, count = test_array[INPUT].size();
2292
2293         if( ts->get_testing_mode() == CvTS::TIMING_MODE && CV_MAT_CN(test_mat[INPUT][0].type) == 1 )
2294             return 0;
2295
2296         for( j = 0; j < count; j++ )
2297         {
2298             IplImage* img = (IplImage*)test_array[INPUT][j];
2299             if( img )
2300                 cvSetImageCOI( img, coi );
2301         }
2302     }
2303
2304     return code;
2305 }
2306
2307
2308 void CxCore_StatTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
2309 {
2310     sprintf( ptr, "%s,", coi > 0 || CV_MAT_CN(test_mat[INPUT][0].type) == 1 ? "single" : "all" );
2311     ptr += strlen(ptr);
2312     params_left--;
2313     CvArrTest::print_timing_params( test_case_idx, ptr, params_left );
2314 }
2315
2316
2317 double CxCore_StatTestImpl::get_success_error_level( int test_case_idx, int i, int j )
2318 {
2319     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
2320     if( depth == CV_32F )
2321         return FLT_EPSILON*1000;
2322     if( depth == CV_64F )
2323         return DBL_EPSILON*1000;
2324     else
2325         return CvArrTest::get_success_error_level( test_case_idx, i, j );
2326 }
2327
2328 CxCore_StatTestImpl stat_test( "stat", "", 0, true, false );
2329
2330
2331 class CxCore_StatTest : public CxCore_StatTestImpl
2332 {
2333 public:
2334     CxCore_StatTest( const char* test_name, const char* test_funcs,
2335                      int _output_count, bool _single_channel,
2336                      bool _allow_mask=1, bool _is_binary=0 );
2337 };
2338
2339 CxCore_StatTest::CxCore_StatTest( const char* test_name, const char* test_funcs,
2340                      int _output_count, bool _single_channel,
2341                      bool _allow_mask, bool _is_binary )
2342     : CxCore_StatTestImpl( test_name, test_funcs, _output_count, _single_channel, _allow_mask, _is_binary )
2343 {
2344     if( !single_channel )
2345         default_timing_param_names = optional_mask ? stat_single_mask_param_names : stat_single_param_names;
2346     else
2347         default_timing_param_names = optional_mask ? stat_mask_param_names : stat_param_names;
2348     
2349     // inherit the default parameters from arithmerical test
2350     size_list = 0;
2351     whole_size_list = 0;
2352     depth_list = 0;
2353     cn_list = 0;
2354 }
2355
2356 ////////////////// sum /////////////////
2357 class CxCore_SumTest : public CxCore_StatTest
2358 {
2359 public:
2360     CxCore_SumTest();
2361 protected:
2362     void run_func();
2363     void prepare_to_validation( int test_case_idx );
2364     double get_success_error_level( int test_case_idx, int i, int j );
2365 };
2366
2367
2368 CxCore_SumTest::CxCore_SumTest()
2369     : CxCore_StatTest( "stat-sum", "cvSum", 4 /* CvScalar */, false, false, false )
2370 {
2371 }
2372
2373 double CxCore_SumTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2374 {
2375     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
2376     if( depth == CV_32F )
2377         return FLT_EPSILON*1000;
2378     return DBL_EPSILON*10000;
2379 }
2380
2381
2382 void CxCore_SumTest::run_func()
2383 {
2384     *(CvScalar*)(test_mat[OUTPUT][0].data.db) = cvSum(test_array[INPUT][0]);
2385 }
2386
2387 void CxCore_SumTest::prepare_to_validation( int /*test_case_idx*/ )
2388 {
2389     CvScalar mean;
2390     int nonzero = cvTsMeanStdDevNonZero( &test_mat[INPUT][0], 0, &mean, 0, coi );
2391
2392     *(CvScalar*)(test_mat[REF_OUTPUT][0].data.db) = mean;
2393     mean = *(CvScalar*)(test_mat[OUTPUT][0].data.db);
2394
2395     mean.val[0] /= nonzero;
2396     mean.val[1] /= nonzero;
2397     mean.val[2] /= nonzero;
2398     mean.val[3] /= nonzero;
2399     *(CvScalar*)(test_mat[OUTPUT][0].data.db) = mean;
2400 }
2401
2402 CxCore_SumTest sum_test;
2403
2404
2405 ////////////////// nonzero /////////////////
2406 class CxCore_NonZeroTest : public CxCore_StatTest
2407 {
2408 public:
2409     CxCore_NonZeroTest();
2410 protected:
2411     void run_func();
2412     void prepare_to_validation( int test_case_idx );
2413     void get_test_array_types_and_sizes( int test_case_idx,
2414                                          CvSize** sizes, int** types );
2415 };
2416
2417
2418 CxCore_NonZeroTest::CxCore_NonZeroTest()
2419     : CxCore_StatTest( "stat-nonzero", "cvCountNonZero", 1 /* int */, true, false, false )
2420 {
2421     test_array[TEMP].push(NULL);
2422     test_array[TEMP].push(NULL);
2423 }
2424
2425 void CxCore_NonZeroTest::run_func()
2426 {
2427     test_mat[OUTPUT][0].data.db[0] = cvCountNonZero(test_array[INPUT][0]);
2428 }
2429
2430 void CxCore_NonZeroTest::get_test_array_types_and_sizes( int test_case_idx,
2431                                               CvSize** sizes, int** types )
2432 {
2433     CxCore_StatTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2434     types[TEMP][0] = CV_8UC1;
2435     if( CV_MAT_CN(types[INPUT][0]) > 1 )
2436         types[TEMP][1] = types[INPUT][0] & ~CV_MAT_CN_MASK;
2437     else
2438         sizes[TEMP][1] = cvSize(0,0);
2439 }
2440
2441
2442 void CxCore_NonZeroTest::prepare_to_validation( int /*test_case_idx*/ )
2443 {
2444     CvMat* plane = &test_mat[INPUT][0];
2445     if( CV_MAT_CN(plane->type) > 1 )
2446     {
2447         plane = &test_mat[TEMP][1];
2448         assert( coi > 0 );
2449         cvTsExtract( &test_mat[INPUT][0], plane, coi-1 );
2450     }
2451     cvTsCmpS( plane, 0, &test_mat[TEMP][0], CV_CMP_NE );
2452     int nonzero = cvTsMeanStdDevNonZero( &test_mat[INPUT][0], &test_mat[TEMP][0], 0, 0, coi );
2453     test_mat[REF_OUTPUT][0].data.db[0] = nonzero;
2454 }
2455
2456
2457 CxCore_NonZeroTest nonzero_test;
2458
2459
2460 /////////////////// mean //////////////////////
2461 class CxCore_MeanTest : public CxCore_StatTest
2462 {
2463 public:
2464     CxCore_MeanTest();
2465 protected:
2466     void run_func();
2467     void prepare_to_validation( int test_case_idx );
2468 };
2469
2470
2471 CxCore_MeanTest::CxCore_MeanTest()
2472     : CxCore_StatTest( "stat-mean", "cvAvg", 4 /* CvScalar */, false, true, false )
2473 {
2474 }
2475
2476 void CxCore_MeanTest::run_func()
2477 {
2478     *(CvScalar*)(test_mat[OUTPUT][0].data.db) =
2479         cvAvg(test_array[INPUT][0], test_array[MASK][0]);
2480 }
2481
2482 void CxCore_MeanTest::prepare_to_validation( int /*test_case_idx*/ )
2483 {
2484     CvScalar mean;
2485     cvTsMeanStdDevNonZero( &test_mat[INPUT][0],
2486         test_array[MASK][0] ? &test_mat[MASK][0] : 0,
2487         &mean, 0, coi );
2488     *(CvScalar*)(test_mat[REF_OUTPUT][0].data.db) = mean;
2489 }
2490
2491 CxCore_MeanTest mean_test;
2492
2493
2494 /////////////////// mean_stddev //////////////////////
2495 class CxCore_MeanStdDevTest : public CxCore_StatTest
2496 {
2497 public:
2498     CxCore_MeanStdDevTest();
2499 protected:
2500     void run_func();
2501     void prepare_to_validation( int test_case_idx );
2502 };
2503
2504
2505 CxCore_MeanStdDevTest::CxCore_MeanStdDevTest()
2506     : CxCore_StatTest( "stat-mean_stddev", "cvAvgSdv", 8 /* CvScalar x 2 */, false, true, false )
2507 {
2508 }
2509
2510 void CxCore_MeanStdDevTest::run_func()
2511 {
2512     cvAvgSdv( test_array[INPUT][0],
2513               &((CvScalar*)(test_mat[OUTPUT][0].data.db))[0],
2514               &((CvScalar*)(test_mat[OUTPUT][0].data.db))[1],
2515               test_array[MASK][0] );
2516 }
2517
2518 void CxCore_MeanStdDevTest::prepare_to_validation( int /*test_case_idx*/ )
2519 {
2520     CvScalar mean, stddev;
2521     cvTsMeanStdDevNonZero( &test_mat[INPUT][0],
2522         test_array[MASK][0] ? &test_mat[MASK][0] : 0,
2523         &mean, &stddev, coi );
2524     ((CvScalar*)(test_mat[REF_OUTPUT][0].data.db))[0] = mean;
2525     ((CvScalar*)(test_mat[REF_OUTPUT][0].data.db))[1] = stddev;
2526 }
2527
2528 CxCore_MeanStdDevTest mean_stddev_test;
2529
2530
2531 /////////////////// minmaxloc //////////////////////
2532 class CxCore_MinMaxLocTest : public CxCore_StatTest
2533 {
2534 public:
2535     CxCore_MinMaxLocTest();
2536 protected:
2537     void run_func();
2538     void prepare_to_validation( int test_case_idx );
2539 };
2540
2541
2542 CxCore_MinMaxLocTest::CxCore_MinMaxLocTest()
2543     : CxCore_StatTest( "stat-minmaxloc", "cvMinMaxLoc", 6 /* double x 2 + CvPoint x 2 */, true, true, false )
2544 {
2545 }
2546
2547 void CxCore_MinMaxLocTest::run_func()
2548 {
2549     CvPoint minloc = {0,0}, maxloc = {0,0};
2550     double* output = test_mat[OUTPUT][0].data.db;
2551
2552     cvMinMaxLoc( test_array[INPUT][0],
2553         output, output+1, &minloc, &maxloc,
2554         test_array[MASK][0] );
2555     output[2] = minloc.x;
2556     output[3] = minloc.y;
2557     output[4] = maxloc.x;
2558     output[5] = maxloc.y;
2559 }
2560
2561 void CxCore_MinMaxLocTest::prepare_to_validation( int /*test_case_idx*/ )
2562 {
2563     double minval = 0, maxval = 0;
2564     CvPoint minloc = {0,0}, maxloc = {0,0};
2565     double* ref_output = test_mat[REF_OUTPUT][0].data.db;
2566     cvTsMinMaxLoc( &test_mat[INPUT][0], test_array[MASK][0] ?
2567         &test_mat[MASK][0] : 0, &minval, &maxval, &minloc, &maxloc, coi );
2568     ref_output[0] = minval;
2569     ref_output[1] = maxval;
2570     ref_output[2] = minloc.x;
2571     ref_output[3] = minloc.y;
2572     ref_output[4] = maxloc.x;
2573     ref_output[5] = maxloc.y;
2574 }
2575
2576 CxCore_MinMaxLocTest minmaxloc_test;
2577
2578
2579 /////////////////// norm //////////////////////
2580
2581 static const char* stat_norm_param_names[] = { "size", "coi", "norm_type", "channels", "depth", "use_mask", 0 };
2582 static const char* stat_norm_type_names[] = { "Inf", "L1", "L2", "diff_Inf", "diff_L1", "diff_L2", 0 };
2583
2584 class CxCore_NormTest : public CxCore_StatTest
2585 {
2586 public:
2587     CxCore_NormTest();
2588 protected:
2589     void run_func();
2590     void prepare_to_validation( int test_case_idx );
2591     void get_test_array_types_and_sizes( int test_case_idx,
2592                                          CvSize** sizes, int** types );
2593     void get_timing_test_array_types_and_sizes( int /*test_case_idx*/,
2594         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images );
2595     int prepare_test_case( int test_case_idx );
2596     void print_timing_params( int test_case_idx, char* ptr, int params_left );
2597     int write_default_params( CvFileStorage* fs );
2598     double get_success_error_level( int test_case_idx, int i, int j );
2599     int norm_type;
2600 };
2601
2602
2603 CxCore_NormTest::CxCore_NormTest()
2604     : CxCore_StatTest( "stat-norm", "cvNorm", 1 /* double */, false, true, true )
2605 {
2606     test_array[TEMP].push(NULL);
2607     default_timing_param_names = stat_norm_param_names;
2608 }
2609
2610
2611 double CxCore_NormTest::get_success_error_level( int test_case_idx, int i, int j )
2612 {
2613     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
2614     if( (depth == CV_16U || depth == CV_16S) /*&& (norm_type&3) != CV_C*/ )
2615         return 1e-4;
2616     else
2617         return CxCore_StatTest::get_success_error_level( test_case_idx, i, j );
2618 }
2619
2620
2621 void CxCore_NormTest::get_test_array_types_and_sizes( int test_case_idx,
2622                                                CvSize** sizes, int** types )
2623 {
2624     int intype;
2625     int norm_kind;
2626     CxCore_StatTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2627     norm_type = cvTsRandInt(ts->get_rng()) % 3; // CV_C, CV_L1 or CV_L2
2628     norm_kind = cvTsRandInt(ts->get_rng()) % 3; // simple, difference or relative difference
2629     if( norm_kind == 0 )
2630         sizes[INPUT][1] = cvSize(0,0);
2631     norm_type = (1 << norm_type) | (norm_kind*8);
2632     intype = types[INPUT][0];
2633     if( CV_MAT_CN(intype) > 1 && coi == 0 )
2634         sizes[MASK][0] = cvSize(0,0);
2635     sizes[TEMP][0] = cvSize(0,0);
2636     if( (norm_type & (CV_DIFF|CV_RELATIVE)) && CV_MAT_DEPTH(intype) <= CV_32F )
2637     {
2638         sizes[TEMP][0] = sizes[INPUT][0];
2639         types[TEMP][0] = (intype & ~CV_MAT_DEPTH_MASK)|
2640             (CV_MAT_DEPTH(intype) < CV_32F ? CV_32S : CV_64F);
2641     }
2642 }
2643
2644
2645 void CxCore_NormTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2646                                                     CvSize** sizes, int** types,
2647                                                     CvSize** whole_sizes, bool* are_images )
2648 {
2649     CxCore_StatTest::get_timing_test_array_types_and_sizes( test_case_idx,
2650                                     sizes, types, whole_sizes, are_images );
2651     const char* norm_type_str = cvReadString( find_timing_param( "norm_type" ), "L2" );
2652     bool diff = false;
2653     if( strncmp( norm_type_str, "diff_", 5 ) == 0 )
2654     {
2655         diff = true;
2656         norm_type_str += 5;
2657     }
2658     
2659     if( strcmp( norm_type_str, "L1" ) == 0 )
2660         norm_type = CV_L1;
2661     else if( strcmp( norm_type_str, "L2" ) == 0 )
2662         norm_type = CV_L2;
2663     else
2664         norm_type = CV_C;
2665
2666     if( diff )
2667         norm_type += CV_DIFF;
2668     else
2669         sizes[INPUT][1] = cvSize(0,0);
2670 }
2671
2672
2673 int CxCore_NormTest::prepare_test_case( int test_case_idx )
2674 {
2675     int code = CxCore_StatTest::prepare_test_case( test_case_idx );
2676     if( code > 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
2677     {
2678         // currently it is not supported
2679         if( test_array[MASK][0] && CV_MAT_CN(test_mat[INPUT][0].type) > 1 && coi == 0 )
2680             return 0;
2681     }
2682     return code;
2683 }
2684
2685
2686 int CxCore_NormTest::write_default_params( CvFileStorage* fs )
2687 {
2688     int code = CxCore_StatTest::write_default_params(fs);
2689     if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2690         return code;
2691     write_string_list( fs, "norm_type", stat_norm_type_names );
2692     return code;
2693 }
2694
2695
2696 void CxCore_NormTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2697 {
2698     int nt = norm_type & CV_NORM_MASK;
2699     sprintf( ptr, "%s%s,", norm_type & CV_DIFF ? "diff_" : "",
2700              nt == CV_C ? "Inf" : nt == CV_L1 ? "L1" : "L2" );
2701     ptr += strlen(ptr);
2702     params_left--;
2703     CxCore_StatTest::print_timing_params( test_case_idx, ptr, params_left );
2704 }
2705
2706
2707 void CxCore_NormTest::run_func()
2708 {
2709     test_mat[OUTPUT][0].data.db[0] = cvNorm( test_array[INPUT][0],
2710             test_array[INPUT][1], norm_type, test_array[MASK][0] );
2711 }
2712
2713 void CxCore_NormTest::prepare_to_validation( int /*test_case_idx*/ )
2714 {
2715     double a_norm = 0, b_norm = 0;
2716     CvMat* a = &test_mat[INPUT][0];
2717     CvMat* b = &test_mat[INPUT][1];
2718     CvMat* mask = test_array[MASK][0] ? &test_mat[MASK][0] : 0;
2719     CvMat* diff = a;
2720
2721     if( norm_type & (CV_DIFF|CV_RELATIVE) )
2722     {
2723         diff = test_array[TEMP][0] ? &test_mat[TEMP][0] : a;
2724         cvTsAdd( a, cvScalarAll(1.), b, cvScalarAll(-1.),
2725                  cvScalarAll(0.), diff, 0 );
2726     }
2727     a_norm = cvTsNorm( diff, mask, norm_type & CV_NORM_MASK, coi );
2728     if( norm_type & CV_RELATIVE )
2729     {
2730         b_norm = cvTsNorm( b, mask, norm_type & CV_NORM_MASK, coi );
2731         a_norm /= (b_norm + DBL_EPSILON );
2732     }
2733     test_mat[REF_OUTPUT][0].data.db[0] = a_norm;
2734 }
2735
2736 CxCore_NormTest norm_test;
2737
2738 // TODO: repeat(?), reshape(?), lut
2739
2740 /* End of file. */