]> rtime.felk.cvut.cz Git - opencv.git/blob - opencv/tests/cxcore/src/aarithm.cpp
now tests can be grouped
[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 class CxCore_ArithmTest : public CvArrTest
50 {
51 public:
52     CxCore_ArithmTest( const char* test_name, const char* test_funcs,
53                        int _generate_scalars=0, bool _allow_mask=true, bool _calc_abs=false );
54 protected:
55     void prepare_to_validation( int test_case_idx );
56     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
57     CvScalar alpha, beta, gamma;
58     int generate_scalars;
59     bool allow_mask, calc_abs;
60 };
61
62
63 CxCore_ArithmTest::CxCore_ArithmTest( const char* test_name, const char* test_funcs,
64                                       int _generate_scalars, bool _allow_mask, bool _calc_abs )
65     : CvArrTest( test_name, test_funcs, "" ),
66     generate_scalars(_generate_scalars), allow_mask(_allow_mask), calc_abs(_calc_abs)
67 {
68     test_array[INPUT].push(NULL);
69     test_array[INPUT].push(NULL);
70     if( allow_mask )
71     {
72         test_array[INPUT_OUTPUT].push(NULL);
73         test_array[REF_INPUT_OUTPUT].push(NULL);
74         test_array[TEMP].push(NULL);
75         test_array[MASK].push(NULL);
76     }
77     else
78     {
79         test_array[OUTPUT].push(NULL);
80         test_array[REF_OUTPUT].push(NULL);
81     }
82     alpha = beta = gamma = cvScalarAll(0);
83 }
84
85 void CxCore_ArithmTest::get_test_array_types_and_sizes( int test_case_idx,
86                                                CvSize** sizes, int** types )
87 {
88     CvRNG* rng = ts->get_rng();
89     int depth = test_case_idx*CV_64F/test_case_count;
90     int cn = cvTsRandInt(rng) % 4 + 1;
91     int i, j;
92     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
93     depth += depth == CV_8S;
94
95     for( i = 0; i < max_arr; i++ )
96     {
97         int count = test_array[i].size();
98         int type = i != MASK ? CV_MAKETYPE(depth, cn) : CV_8UC1;
99         for( j = 0; j < count; j++ )
100         {
101             types[i][j] = type;
102         }
103     }
104
105     if( generate_scalars )
106     {
107         double max_val = 10.;
108         for( i = 0; i < 4; i++ )
109         {
110             if( generate_scalars & 1 )
111             {
112                 alpha.val[i] = exp((cvTsRandReal(rng)-0.5)*max_val*2*CV_LOG2);
113                 alpha.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
114             }
115             if( generate_scalars & 2 )
116             {
117                 beta.val[i] = exp((cvTsRandReal(rng)-0.5)*max_val*2*CV_LOG2);
118                 beta.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
119             }
120             if( generate_scalars & 4 )
121             {
122                 gamma.val[i] = exp((cvTsRandReal(rng)-0.5)*max_val*2*CV_LOG2);
123                 gamma.val[i] *= (cvTsRandInt(rng) & 1) ? 1 : -1;
124             }
125         }
126     }
127
128     if( depth == CV_32F )
129     {
130         CvMat fl = cvMat( 1, 4, CV_32F, buf );
131         CvMat db = cvMat( 1, 4, CV_64F, 0 );
132
133         db.data.db = alpha.val;
134         cvTsConvert( &db, &fl );
135         cvTsConvert( &fl, &db );
136
137         db.data.db = beta.val;
138         cvTsConvert( &db, &fl );
139         cvTsConvert( &fl, &db );
140
141         db.data.db = gamma.val;
142         cvTsConvert( &db, &fl );
143         cvTsConvert( &fl, &db );
144     }
145 }
146
147 void CxCore_ArithmTest::prepare_to_validation( int /*test_case_idx*/ )
148 {
149     const CvMat* mask = test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0;
150     CvMat* output = test_array[REF_INPUT_OUTPUT].size() > 0 ?
151         &test_mat[REF_INPUT_OUTPUT][0] : &test_mat[REF_OUTPUT][0];
152     CvMat* temp_dst = mask ? &test_mat[TEMP][0] : output;
153     cvTsAdd( &test_mat[INPUT][0], alpha,
154              test_array[INPUT].size() > 1 ? &test_mat[INPUT][1] : 0, beta,
155              gamma, temp_dst, calc_abs );
156     if( mask )
157         cvTsCopy( temp_dst, output, mask );
158 }
159
160
161 CxCore_ArithmTest arithm( "arithm", "" );
162
163 ////////////////////////////// add /////////////////////////////
164
165 class CxCore_AddTest : public CxCore_ArithmTest
166 {
167 public:
168     CxCore_AddTest();
169 protected:
170     void run_func();
171 };
172
173 CxCore_AddTest::CxCore_AddTest()
174     : CxCore_ArithmTest( "arithm-add", "cvAdd", 0, true )
175 {
176     alpha = beta = cvScalarAll(1.);
177 }
178
179 void CxCore_AddTest::run_func()
180 {
181     cvAdd( test_array[INPUT][0], test_array[INPUT][1],
182         test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
183 }
184
185 CxCore_AddTest add_test;
186
187 ////////////////////////////// sub /////////////////////////////
188
189 class CxCore_SubTest : public CxCore_ArithmTest
190 {
191 public:
192     CxCore_SubTest();
193 protected:
194     void run_func();
195 };
196
197 CxCore_SubTest::CxCore_SubTest()
198     : CxCore_ArithmTest( "arithm-sub", "cvSub", 0, true )
199 {
200     alpha = cvScalarAll(1.);
201     beta = cvScalarAll(-1.);
202 }
203
204 void CxCore_SubTest::run_func()
205 {
206     cvSub( test_array[INPUT][0], test_array[INPUT][1],
207            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
208 }
209
210 CxCore_SubTest sub_test;
211
212
213 ////////////////////////////// adds /////////////////////////////
214
215 class CxCore_AddSTest : public CxCore_ArithmTest
216 {
217 public:
218     CxCore_AddSTest();
219 protected:
220     void run_func();
221 };
222
223 CxCore_AddSTest::CxCore_AddSTest()
224     : CxCore_ArithmTest( "arithm-adds", "cvAddS", 4, true )
225 {
226     test_array[INPUT].pop();
227     alpha = cvScalarAll(1.);
228 }
229
230 void CxCore_AddSTest::run_func()
231 {
232     cvAddS( test_array[INPUT][0], gamma,
233             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
234 }
235
236 CxCore_AddSTest adds_test;
237
238 ////////////////////////////// subrs /////////////////////////////
239
240 class CxCore_SubRSTest : public CxCore_ArithmTest
241 {
242 public:
243     CxCore_SubRSTest();
244 protected:
245     void run_func();
246 };
247
248 CxCore_SubRSTest::CxCore_SubRSTest()
249     : CxCore_ArithmTest( "arithm-subrs", "cvSubRS", 4, true )
250 {
251     test_array[INPUT].pop();
252     alpha = cvScalarAll(-1.);
253 }
254
255 void CxCore_SubRSTest::run_func()
256 {
257     cvSubRS( test_array[INPUT][0], gamma,
258              test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
259 }
260
261 CxCore_SubRSTest subrs_test;
262
263 ////////////////////////////// addweighted /////////////////////////////
264
265 class CxCore_AddWeightedTest : public CxCore_ArithmTest
266 {
267 public:
268     CxCore_AddWeightedTest();
269 protected:
270     void get_test_array_types_and_sizes( int test_case_idx,
271                                           CvSize** sizes, int** types );
272     double get_success_error_level( int test_case_idx, int i, int j );
273     void run_func();
274 };
275
276 CxCore_AddWeightedTest::CxCore_AddWeightedTest()
277     : CxCore_ArithmTest( "arithm-addweighted", "cvAddWeighted", 7, false )
278 {
279 }
280
281 void CxCore_AddWeightedTest::get_test_array_types_and_sizes( int test_case_idx,
282                                                     CvSize** sizes, int** types )
283 {
284     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
285     alpha = cvScalarAll(alpha.val[0]);
286     beta = cvScalarAll(beta.val[0]);
287     gamma = cvScalarAll(gamma.val[0]);
288 }
289
290
291 double CxCore_AddWeightedTest::get_success_error_level( int test_case_idx, int i, int j )
292 {
293     if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
294     {
295         return alpha.val[0] != cvRound(alpha.val[0]) ||
296                beta.val[0] != cvRound(beta.val[0]) ||
297                gamma.val[0] != cvRound(gamma.val[0]);
298     }
299     else
300         return CvArrTest::get_success_error_level( test_case_idx, i, j );
301 }
302
303
304 void CxCore_AddWeightedTest::run_func()
305 {
306     cvAddWeighted( test_array[INPUT][0], alpha.val[0],
307                    test_array[INPUT][1], beta.val[0],
308                    gamma.val[0], test_array[OUTPUT][0] );
309 }
310
311 CxCore_AddWeightedTest addweighted_test;
312
313
314 ////////////////////////////// absdiff /////////////////////////////
315
316 class CxCore_AbsDiffTest : public CxCore_ArithmTest
317 {
318 public:
319     CxCore_AbsDiffTest();
320 protected:
321     void run_func();
322 };
323
324 CxCore_AbsDiffTest::CxCore_AbsDiffTest()
325     : CxCore_ArithmTest( "arithm-absdiff", "cvAbsDiff", 0, false, true )
326 {
327     alpha = cvScalarAll(1.);
328     beta = cvScalarAll(-1.);
329 }
330
331 void CxCore_AbsDiffTest::run_func()
332 {
333     cvAbsDiff( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
334 }
335
336 CxCore_AbsDiffTest absdiff_test;
337
338 ////////////////////////////// absdiffs /////////////////////////////
339
340 class CxCore_AbsDiffSTest : public CxCore_ArithmTest
341 {
342 public:
343     CxCore_AbsDiffSTest();
344 protected:
345     void run_func();
346 };
347
348 CxCore_AbsDiffSTest::CxCore_AbsDiffSTest()
349     : CxCore_ArithmTest( "arithm-absdiffs", "cvAbsDiffS", 4, false, true )
350 {
351     alpha = cvScalarAll(-1.);
352     test_array[INPUT].pop();
353 }
354
355 void CxCore_AbsDiffSTest::run_func()
356 {
357     cvAbsDiffS( test_array[INPUT][0], test_array[OUTPUT][0], gamma );
358 }
359
360 CxCore_AbsDiffSTest absdiffs_test;
361
362
363 ////////////////////////////// mul /////////////////////////////
364
365 class CxCore_MulTest : public CxCore_ArithmTest
366 {
367 public:
368     CxCore_MulTest();
369 protected:
370     void run_func();
371     void prepare_to_validation( int /*test_case_idx*/ );
372     double get_success_error_level( int test_case_idx, int i, int j );
373 };
374
375 CxCore_MulTest::CxCore_MulTest()
376     : CxCore_ArithmTest( "arithm-mul", "cvMul", 4, false, false )
377 {
378 }
379
380
381 double CxCore_MulTest::get_success_error_level( int test_case_idx, int i, int j )
382 {
383     if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
384     {
385         return gamma.val[0] != cvRound(gamma.val[0]);
386     }
387     else
388         return CvArrTest::get_success_error_level( test_case_idx, i, j );
389 }
390
391
392 void CxCore_MulTest::run_func()
393 {
394     cvMul( test_array[INPUT][0], test_array[INPUT][1],
395            test_array[OUTPUT][0], gamma.val[0] );
396 }
397
398 void CxCore_MulTest::prepare_to_validation( int /*test_case_idx*/ )
399 {
400     cvTsMul( &test_mat[INPUT][0], &test_mat[INPUT][1],
401              cvScalarAll(gamma.val[0]),
402              &test_mat[REF_OUTPUT][0] );
403 }
404
405 CxCore_MulTest mul_test;
406
407 ////////////////////////////// div /////////////////////////////
408
409 class CxCore_DivTest : public CxCore_ArithmTest
410 {
411 public:
412     CxCore_DivTest();
413 protected:
414     void run_func();
415     void prepare_to_validation( int /*test_case_idx*/ );
416 };
417
418 CxCore_DivTest::CxCore_DivTest()
419     : CxCore_ArithmTest( "arithm-div", "cvDiv", 4, false, false )
420 {
421 }
422
423 void CxCore_DivTest::run_func()
424 {
425     cvDiv( test_array[INPUT][0], test_array[INPUT][1],
426            test_array[OUTPUT][0], gamma.val[0] );
427 }
428
429 void CxCore_DivTest::prepare_to_validation( int /*test_case_idx*/ )
430 {
431     cvTsDiv( &test_mat[INPUT][0], &test_mat[INPUT][1],
432              cvScalarAll(gamma.val[0]),
433              &test_mat[REF_OUTPUT][0] );
434 }
435
436 CxCore_DivTest div_test;
437
438 ////////////////////////////// recip /////////////////////////////
439
440 class CxCore_RecipTest : public CxCore_ArithmTest
441 {
442 public:
443     CxCore_RecipTest();
444 protected:
445     void run_func();
446     void prepare_to_validation( int /*test_case_idx*/ );
447 };
448
449 CxCore_RecipTest::CxCore_RecipTest()
450     : CxCore_ArithmTest( "arithm-recip", "cvDiv", 4, false, false )
451 {
452     test_array[INPUT].pop();
453 }
454
455 void CxCore_RecipTest::run_func()
456 {
457     cvDiv( 0, test_array[INPUT][0],
458            test_array[OUTPUT][0], gamma.val[0] );
459 }
460
461 void CxCore_RecipTest::prepare_to_validation( int /*test_case_idx*/ )
462 {
463     cvTsDiv( 0, &test_mat[INPUT][0],
464              cvScalarAll(gamma.val[0]),
465              &test_mat[REF_OUTPUT][0] );
466 }
467
468 CxCore_RecipTest recip_test;
469
470
471 ///////////////// matrix copy/initializing/permutations /////////////////////
472                                                    
473 class CxCore_MemTest : public CxCore_ArithmTest
474 {
475 public:
476     CxCore_MemTest( const char* test_name, const char* test_funcs,
477                     int _generate_scalars=0, bool _allow_mask=true );
478 protected:
479     double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
480 };
481
482 CxCore_MemTest::CxCore_MemTest( const char* test_name, const char* test_funcs,
483                                 int _generate_scalars, bool _allow_mask ) :
484     CxCore_ArithmTest( test_name, test_funcs, _generate_scalars, _allow_mask, false )
485 {
486 }
487
488 double CxCore_MemTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
489 {
490     return 0;
491 }
492
493 CxCore_MemTest mem_test( "mem", "" );
494
495 ///////////////// setidentity /////////////////////
496
497 class CxCore_SetIdentityTest : public CxCore_MemTest
498 {
499 public:
500     CxCore_SetIdentityTest();
501 protected:
502     void run_func();
503     void prepare_to_validation( int test_case_idx );
504 };
505
506
507 CxCore_SetIdentityTest::CxCore_SetIdentityTest() :
508     CxCore_MemTest( "mem-setidentity", "cvSetIdentity", 4, false )
509 {
510     test_array[INPUT].clear();
511 }
512
513
514 void CxCore_SetIdentityTest::run_func()
515 {
516     cvSetIdentity(test_array[OUTPUT][0], gamma);
517 }
518
519
520 void CxCore_SetIdentityTest::prepare_to_validation( int )
521 {
522     cvTsSetIdentity( &test_mat[REF_OUTPUT][0], gamma );
523 }
524
525 CxCore_SetIdentityTest setidentity_test;
526
527
528 ///////////////// SetZero /////////////////////
529
530 class CxCore_SetZeroTest : public CxCore_MemTest
531 {
532 public:
533     CxCore_SetZeroTest();
534 protected:
535     void run_func();
536     void prepare_to_validation( int test_case_idx );
537 };
538
539
540 CxCore_SetZeroTest::CxCore_SetZeroTest() :
541     CxCore_MemTest( "mem-setzero", "cvSetZero", 0, false )
542 {
543     test_array[INPUT].clear();
544 }
545
546
547 void CxCore_SetZeroTest::run_func()
548 {
549     cvSetZero(test_array[OUTPUT][0]);
550 }
551
552
553 void CxCore_SetZeroTest::prepare_to_validation( int )
554 {
555     cvTsZero( &test_mat[REF_OUTPUT][0] );
556 }
557
558 CxCore_SetZeroTest setzero_test;
559
560
561 ///////////////// Set /////////////////////
562
563 class CxCore_FillTest : public CxCore_MemTest
564 {
565 public:
566     CxCore_FillTest();
567 protected:
568     void run_func();
569     void prepare_to_validation( int test_case_idx );
570 };
571
572
573 CxCore_FillTest::CxCore_FillTest() :
574     CxCore_MemTest( "mem-fill", "cvSet", 4, true )
575 {
576     test_array[INPUT].clear();
577 }
578
579
580 void CxCore_FillTest::run_func()
581 {
582     cvSet(test_array[INPUT_OUTPUT][0], gamma, test_array[MASK][0]);
583 }
584
585
586 void CxCore_FillTest::prepare_to_validation( int )
587 {
588     if( test_array[MASK][0] )
589     {
590         cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), gamma, &test_mat[TEMP][0], 0 );
591         cvTsCopy( &test_mat[TEMP][0], &test_mat[REF_INPUT_OUTPUT][0], &test_mat[MASK][0] );
592     }
593     else
594     {
595         cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), gamma, &test_mat[REF_INPUT_OUTPUT][0], 0 );
596     }
597 }
598
599 CxCore_FillTest fill_test;
600
601
602 ///////////////// Copy /////////////////////
603
604 class CxCore_CopyTest : public CxCore_MemTest
605 {
606 public:
607     CxCore_CopyTest();
608 protected:
609     double get_success_error_level( int test_case_idx, int i, int j );
610     void run_func();
611     void prepare_to_validation( int test_case_idx );
612 };
613
614
615 CxCore_CopyTest::CxCore_CopyTest() :
616     CxCore_MemTest( "mem-copy", "cvCopy", 0, true )
617 {
618     test_array[INPUT].pop();
619 }
620
621
622 double CxCore_CopyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
623 {
624     return 0;
625 }
626
627
628 void CxCore_CopyTest::run_func()
629 {
630     cvCopy(test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[MASK][0]);
631 }
632
633
634 void CxCore_CopyTest::prepare_to_validation( int )
635 {
636     cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_INPUT_OUTPUT][0],
637               test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0 );
638 }
639
640 CxCore_CopyTest copy_test;
641
642 ///////////////// Transpose /////////////////////
643
644 class CxCore_TransposeTest : public CxCore_MemTest
645 {
646 public:
647     CxCore_TransposeTest();
648 protected:
649     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
650     int prepare_test_case( int test_case_idx );
651     double get_success_error_level( int test_case_idx, int i, int j );
652     void run_func();
653     void prepare_to_validation( int test_case_idx );
654     bool inplace;
655 };
656
657
658 CxCore_TransposeTest::CxCore_TransposeTest() :
659     CxCore_MemTest( "mem-transpose", "cvTranspose", 0, false ), inplace(false)
660 {
661     test_array[INPUT].pop();
662 }
663
664
665 double CxCore_TransposeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
666 {
667     return 0;
668 }
669
670 void CxCore_TransposeTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
671 {
672     int bits = cvTsRandInt(ts->get_rng());
673     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
674
675     inplace = false;
676     if( bits & 1 )
677     {
678         sizes[INPUT][0].height = sizes[INPUT][0].width;
679         inplace = (bits & 2) != 0;
680     }
681
682     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][0].height, sizes[INPUT][0].width );
683 }
684
685
686 int CxCore_TransposeTest::prepare_test_case( int test_case_idx )
687 {
688     int ok = CxCore_ArithmTest::prepare_test_case( test_case_idx );
689     if( inplace )
690         cvTsCopy( &test_mat[INPUT][0], &test_mat[OUTPUT][0] );
691     return ok;
692 }
693
694 void CxCore_TransposeTest::run_func()
695 {
696     cvTranspose( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], test_array[OUTPUT][0]);
697 }
698
699
700 void CxCore_TransposeTest::prepare_to_validation( int )
701 {
702     cvTsTranspose( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0] );
703 }
704
705 CxCore_TransposeTest transpose_test;
706
707
708 ///////////////// Flip /////////////////////
709
710 class CxCore_FlipTest : public CxCore_MemTest
711 {
712 public:
713     CxCore_FlipTest();
714 protected:
715     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
716     int prepare_test_case( int test_case_idx );
717     double get_success_error_level( int test_case_idx, int i, int j );
718     void run_func();
719     void prepare_to_validation( int test_case_idx );
720     int flip_type;
721     bool inplace;
722 };
723
724
725 CxCore_FlipTest::CxCore_FlipTest() :
726     CxCore_MemTest( "mem-flip", "cvFlip", 0, false ), flip_type(0), inplace(false)
727 {
728     test_array[INPUT].pop();
729 }
730
731
732 double CxCore_FlipTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
733 {
734     return 0;
735 }
736
737 void CxCore_FlipTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
738 {
739     int bits = cvTsRandInt(ts->get_rng());
740     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
741
742     flip_type = (bits & 3) - 2;
743     flip_type += flip_type == -2;
744     inplace = (bits & 4) != 0;
745 }
746
747
748 int CxCore_FlipTest::prepare_test_case( int test_case_idx )
749 {
750     int ok = CxCore_ArithmTest::prepare_test_case( test_case_idx );
751     if( inplace )
752         cvTsCopy( &test_mat[INPUT][0], &test_mat[OUTPUT][0] );
753     return ok;
754 }
755
756 void CxCore_FlipTest::run_func()
757 {
758     cvFlip(inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], test_array[OUTPUT][0], flip_type);
759 }
760
761
762 void CxCore_FlipTest::prepare_to_validation( int )
763 {
764     cvTsFlip( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], flip_type );
765 }
766
767 CxCore_FlipTest flip_test;
768
769
770 ///////////////// Split /////////////////////
771
772 class CxCore_SplitTest : public CxCore_MemTest
773 {
774 public:
775     CxCore_SplitTest();
776 protected:
777     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
778     int prepare_test_case( int test_case_idx );
779     double get_success_error_level( int test_case_idx, int i, int j );
780     void run_func();
781     void prepare_to_validation( int test_case_idx );
782     bool are_images;
783     int coi;
784     void* hdrs[4];
785 };
786
787
788 CxCore_SplitTest::CxCore_SplitTest() :
789     CxCore_MemTest( "mem-split", "cvSplit", 0, false ), are_images(false), coi(0)
790 {
791     test_array[INPUT].pop();
792     memset( hdrs, 0, sizeof(hdrs) );
793 }
794
795
796 double CxCore_SplitTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
797 {
798     return 0;
799 }
800
801 void CxCore_SplitTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
802 {
803     int cn, depth;
804     CvRNG* rng = ts->get_rng();
805     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
806     cn = cvTsRandInt(rng)%3 + 2;
807     depth = CV_MAT_DEPTH(types[INPUT][0]);
808     types[INPUT][0] = CV_MAKETYPE(depth, cn);
809     types[OUTPUT][0] = types[REF_OUTPUT][0] = depth;
810
811     if( (cvTsRandInt(rng) & 3) != 0 )
812     {
813         coi = cvTsRandInt(rng) % cn;
814     }
815     else
816     {
817         sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] =
818             cvSize(sizes[INPUT][0].width,sizes[INPUT][0].height*cn);
819         coi = -1;
820     }
821
822     are_images = cvTsRandInt(rng)%2 != 0;
823 }
824
825 int CxCore_SplitTest::prepare_test_case( int test_case_idx )
826 {
827     int ok = CxCore_ArithmTest::prepare_test_case( test_case_idx );
828     CvMat* input = &test_mat[INPUT][0];
829     CvMat* output = &test_mat[OUTPUT][0];
830     int depth = CV_MAT_DEPTH(input->type);
831     int i, cn = CV_MAT_CN(input->type), y = 0;
832     CvSize sz = cvGetSize(input);
833     for( i = 0; i < cn; i++ )
834     {
835         if( coi < 0 || coi == i )
836         {
837             if( are_images )
838                 hdrs[i] = cvCreateImageHeader( sz, cvCvToIplDepth(depth), 1 );
839             else
840                 hdrs[i] = cvCreateMatHeader( sz.height, sz.width, depth );
841             cvSetData( hdrs[i], output->data.ptr + output->step*y, output->step );
842             y += sz.height;
843         }
844     }
845
846     return ok;
847 }
848
849
850 void CxCore_SplitTest::run_func()
851 {
852     cvSplit( test_array[INPUT][0], hdrs[0], hdrs[1], hdrs[2], hdrs[3] );
853 }
854
855
856 void CxCore_SplitTest::prepare_to_validation( int )
857 {
858     CvMat* input = &test_mat[INPUT][0];
859     CvMat* output = &test_mat[REF_OUTPUT][0];
860     int i, cn = CV_MAT_CN(input->type), y = 0;
861     CvSize sz = cvGetSize(input);
862
863     for( i = 0; i < cn; i++ )
864     {
865         if( coi < 0 || coi == i )
866         {
867             CvMat stub, *h;
868             cvSetData( hdrs[i], output->data.ptr + output->step*y, output->step );
869             h = cvGetMat( hdrs[i], &stub );
870             cvTsExtract( input, h, i );
871             if( are_images )
872                 cvReleaseImageHeader( (IplImage**)&hdrs[i] );
873             else
874                 cvReleaseMat( (CvMat**)&hdrs[i] );
875             y += sz.height;
876
877         }
878     }
879 }
880
881 CxCore_SplitTest split_test;
882
883
884 ///////////////// Merge /////////////////////
885
886 class CxCore_MergeTest : public CxCore_MemTest
887 {
888 public:
889     CxCore_MergeTest();
890 protected:
891     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
892     int prepare_test_case( int test_case_idx );
893     double get_success_error_level( int test_case_idx, int i, int j );
894     void run_func();
895     void prepare_to_validation( int test_case_idx );
896     bool are_images;
897     int coi;
898     void* hdrs[4];
899 };
900
901
902 CxCore_MergeTest::CxCore_MergeTest() :
903     CxCore_MemTest( "mem-merge", "cvMerge", 0, false ), are_images(false), coi(0)
904 {
905     test_array[INPUT].pop();
906     test_array[OUTPUT].clear();
907     test_array[REF_OUTPUT].clear();
908     test_array[INPUT_OUTPUT].push(NULL);
909     test_array[REF_INPUT_OUTPUT].push(NULL);
910     memset( hdrs, 0, sizeof(hdrs) );
911 }
912
913
914 double CxCore_MergeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
915 {
916     return 0;
917 }
918
919
920 void CxCore_MergeTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
921 {
922     int cn, depth;
923     CvRNG* rng = ts->get_rng();
924     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
925     cn = cvTsRandInt(rng)%3 + 2;
926     depth = CV_MAT_DEPTH(types[INPUT][0]);
927     types[INPUT][0] = depth;
928     types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
929
930     if( (cvTsRandInt(rng) & 3) != 0 )
931         coi = cvTsRandInt(rng) % cn;
932     else
933     {
934         sizes[INPUT][0] = cvSize(sizes[INPUT_OUTPUT][0].width,sizes[INPUT_OUTPUT][0].height*cn);
935         coi = -1;
936     }
937
938     are_images = cvTsRandInt(rng)%2 != 0;
939 }
940
941
942 int CxCore_MergeTest::prepare_test_case( int test_case_idx )
943 {
944     int ok = CxCore_ArithmTest::prepare_test_case( test_case_idx );
945     CvMat* input = &test_mat[INPUT][0];
946     CvMat* output = &test_mat[INPUT_OUTPUT][0];
947     int depth = CV_MAT_DEPTH(input->type);
948     int i, cn = CV_MAT_CN(output->type), y = 0;
949     CvSize sz = cvGetSize(output);
950     for( i = 0; i < cn; i++ )
951     {
952         assert( hdrs[i] == 0 );
953         
954         if( coi < 0 || coi == i )
955         {
956             if( are_images )
957                 hdrs[i] = cvCreateImageHeader( sz, cvCvToIplDepth(depth), 1 );
958             else
959                 hdrs[i] = cvCreateMatHeader( sz.height, sz.width, depth );
960             cvSetData( hdrs[i], input->data.ptr + input->step*y, input->step );
961             y += sz.height;
962         }
963     }
964
965     return ok;
966 }
967
968
969 void CxCore_MergeTest::run_func()
970 {
971     cvMerge( hdrs[0], hdrs[1], hdrs[2], hdrs[3], test_array[INPUT_OUTPUT][0] );
972 }
973
974
975 void CxCore_MergeTest::prepare_to_validation( int )
976 {
977     CvMat* input = &test_mat[INPUT][0];
978     CvMat* output = &test_mat[REF_INPUT_OUTPUT][0];
979     int i, cn = CV_MAT_CN(output->type), y = 0;
980     CvSize sz = cvGetSize(output);
981
982     for( i = 0; i < cn; i++ )
983     {
984         if( coi < 0 || coi == i )
985         {
986             CvMat stub, *h;
987             cvSetData( hdrs[i], input->data.ptr + input->step*y, input->step );
988             h = cvGetMat( hdrs[i], &stub, 0 );
989             cvTsInsert( h, output, i );
990             if( are_images )
991                 cvReleaseImageHeader( (IplImage**)&hdrs[i] );
992             else
993                 cvReleaseMat( (CvMat**)&hdrs[i] );
994             y += sz.height;
995         }
996     }
997 }
998
999 CxCore_MergeTest merge_test;
1000
1001
1002 ////////////////////////////// min/max  /////////////////////////////
1003
1004 class CxCore_MinMaxBaseTest : public CxCore_ArithmTest
1005 {
1006 public:
1007     CxCore_MinMaxBaseTest( const char* test_name, const char* test_funcs,
1008                            int _op_type, int _generate_scalars=0 );
1009 protected:
1010     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1011     double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
1012     void prepare_to_validation( int /*test_case_idx*/ );
1013     int op_type;
1014 };
1015
1016 CxCore_MinMaxBaseTest::CxCore_MinMaxBaseTest( const char* test_name, const char* test_funcs,
1017                                               int _op_type, int _generate_scalars )
1018     : CxCore_ArithmTest( test_name, test_funcs, _generate_scalars, false, false ), op_type(_op_type)
1019 {
1020     if( _generate_scalars )
1021         test_array[INPUT].pop();
1022 }
1023
1024 double CxCore_MinMaxBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1025 {
1026     return 0;
1027 }
1028
1029 void CxCore_MinMaxBaseTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1030 {
1031     int i, j;
1032     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1033     for( i = 0; i < max_arr; i++ )
1034     {
1035         int count = test_array[i].size();
1036         for( j = 0; j < count; j++ )
1037         {
1038             types[i][j] &= ~CV_MAT_CN_MASK;            
1039         }
1040     }
1041 }
1042
1043 void CxCore_MinMaxBaseTest::prepare_to_validation( int /*test_case_idx*/ )
1044 {
1045     if( !generate_scalars )
1046         cvTsMinMax( &test_mat[INPUT][0], &test_mat[INPUT][1],
1047                     &test_mat[REF_OUTPUT][0], op_type );
1048     else
1049         cvTsMinMaxS( &test_mat[INPUT][0], gamma.val[0],
1050                      &test_mat[REF_OUTPUT][0], op_type );
1051 }
1052
1053
1054 class CxCore_MinTest : public CxCore_MinMaxBaseTest
1055 {
1056 public:
1057     CxCore_MinTest();
1058 protected:
1059     void run_func();
1060 };
1061
1062
1063 CxCore_MinTest::CxCore_MinTest()
1064     : CxCore_MinMaxBaseTest( "arithm-min", "cvMin", CV_TS_MIN, 0 )
1065 {
1066 }
1067
1068 void CxCore_MinTest::run_func()
1069 {
1070     cvMin( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1071 }
1072
1073 CxCore_MinTest min_test;
1074
1075
1076 ////////////////////////////// max /////////////////////////////
1077
1078 class CxCore_MaxTest : public CxCore_MinMaxBaseTest
1079 {
1080 public:
1081     CxCore_MaxTest();
1082 protected:
1083     void run_func();
1084 };
1085
1086 CxCore_MaxTest::CxCore_MaxTest()
1087     : CxCore_MinMaxBaseTest( "arithm-max", "cvMax", CV_TS_MAX, 0 )
1088 {
1089 }
1090
1091 void CxCore_MaxTest::run_func()
1092 {
1093     cvMax( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1094 }
1095
1096 CxCore_MaxTest max_test;
1097
1098
1099 ////////////////////////////// mins /////////////////////////////
1100
1101 class CxCore_MinSTest : public CxCore_MinMaxBaseTest
1102 {
1103 public:
1104     CxCore_MinSTest();
1105 protected:
1106     void run_func();
1107 };
1108
1109 CxCore_MinSTest::CxCore_MinSTest()
1110     : CxCore_MinMaxBaseTest( "arithm-mins", "cvMinS", CV_TS_MIN, 4 )
1111 {
1112 }
1113
1114 void CxCore_MinSTest::run_func()
1115 {
1116     cvMinS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
1117 }
1118
1119 CxCore_MinSTest mins_test;
1120
1121 ////////////////////////////// maxs /////////////////////////////
1122
1123 class CxCore_MaxSTest : public CxCore_MinMaxBaseTest
1124 {
1125 public:
1126     CxCore_MaxSTest();
1127 protected:
1128     void run_func();
1129 };
1130
1131 CxCore_MaxSTest::CxCore_MaxSTest()
1132     : CxCore_MinMaxBaseTest( "arithm-maxs", "cvMaxS", CV_TS_MAX, 4 )
1133 {
1134 }
1135
1136 void CxCore_MaxSTest::run_func()
1137 {
1138     cvMaxS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
1139 }
1140
1141 CxCore_MaxSTest maxs_test;
1142
1143
1144 //////////////////////////////// logic ///////////////////////////////////////
1145
1146 class CxCore_LogicTest : public CxCore_ArithmTest
1147 {
1148 public:
1149     CxCore_LogicTest( const char* test_name, const char* test_funcs, int _logic_op,
1150                       int _generate_scalars=0, bool _allow_mask=true );
1151 protected:
1152     void prepare_to_validation( int test_case_idx );
1153     int logic_op;
1154 };
1155
1156 CxCore_LogicTest::CxCore_LogicTest( const char* test_name, const char* test_funcs,
1157                             int _logic_op, int _generate_scalars, bool _allow_mask )
1158     : CxCore_ArithmTest( test_name, test_funcs, _generate_scalars, _allow_mask, false ),
1159     logic_op(_logic_op)
1160 {
1161     if( _generate_scalars )
1162         test_array[INPUT].pop();
1163 }
1164
1165 void CxCore_LogicTest::prepare_to_validation( int /*test_case_idx*/ )
1166 {
1167     int ref_output_idx = allow_mask ? REF_INPUT_OUTPUT : REF_OUTPUT;
1168     int output_idx = allow_mask ? INPUT_OUTPUT : OUTPUT;
1169     const CvMat* mask = test_array[MASK].size() > 0 && test_array[MASK][0] ? &test_mat[MASK][0] : 0;
1170     CvMat* dst = mask ? &test_mat[TEMP][0] : &test_mat[ref_output_idx][0];
1171     int i;
1172     if( test_array[INPUT].size() > 1 )
1173     {
1174         cvTsLogic( &test_mat[INPUT][0], &test_mat[INPUT][1], dst, logic_op );
1175     }
1176     else
1177     {
1178         cvTsLogicS( &test_mat[INPUT][0], gamma, dst, logic_op );
1179     }
1180     if( mask )
1181         cvTsCopy( dst, &test_mat[ref_output_idx][0], mask );
1182     
1183     for( i = 0; i < 2; i++ )
1184     {
1185         dst = i == 0 ? &test_mat[ref_output_idx][0] : &test_mat[output_idx][0];
1186
1187         if( CV_IS_MAT(dst) )
1188         {
1189             CvMat* mat = (CvMat*)dst;
1190             mat->cols *= CV_ELEM_SIZE(mat->type);
1191             mat->type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_8UC1;
1192         }
1193         else
1194         {
1195             IplImage* img = (IplImage*)dst;
1196             int elem_size;
1197         
1198             assert( CV_IS_IMAGE(dst) );
1199             elem_size = ((img->depth & 255)>>3)*img->nChannels;
1200             img->width *= elem_size;
1201         
1202             if( img->roi )
1203             {
1204                 img->roi->xOffset *= elem_size;
1205                 img->roi->width *= elem_size;
1206             }
1207             img->depth = IPL_DEPTH_8U;
1208             img->nChannels = 1;
1209         }
1210     }
1211 }
1212
1213 CxCore_LogicTest logic_test("logic", "", -1);
1214
1215 ///////////////////////// and //////////////////////////
1216
1217 class CxCore_AndTest : public CxCore_LogicTest
1218 {
1219 public:
1220     CxCore_AndTest();
1221 protected:
1222     void run_func();
1223 };
1224
1225 CxCore_AndTest::CxCore_AndTest()
1226     : CxCore_LogicTest( "logic-and", "cvAnd", CV_TS_LOGIC_AND )
1227 {
1228 }
1229
1230 void CxCore_AndTest::run_func()
1231 {
1232     cvAnd( test_array[INPUT][0], test_array[INPUT][1],
1233            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1234 }
1235
1236 CxCore_AndTest and_test;
1237
1238
1239 class CxCore_AndSTest : public CxCore_LogicTest
1240 {
1241 public:
1242     CxCore_AndSTest();
1243 protected:
1244     void run_func();
1245 };
1246
1247 CxCore_AndSTest::CxCore_AndSTest()
1248     : CxCore_LogicTest( "logic-ands", "cvAndS", CV_TS_LOGIC_AND, 4 )
1249 {
1250 }
1251
1252 void CxCore_AndSTest::run_func()
1253 {
1254     cvAndS( test_array[INPUT][0], gamma,
1255             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1256 }
1257
1258 CxCore_AndSTest ands_test;
1259
1260
1261 ///////////////////////// or /////////////////////////
1262
1263 class CxCore_OrTest : public CxCore_LogicTest
1264 {
1265 public:
1266     CxCore_OrTest();
1267 protected:
1268     void run_func();
1269 };
1270
1271 CxCore_OrTest::CxCore_OrTest()
1272     : CxCore_LogicTest( "logic-or", "cvOr", CV_TS_LOGIC_OR )
1273 {
1274 }
1275
1276 void CxCore_OrTest::run_func()
1277 {
1278     cvOr( test_array[INPUT][0], test_array[INPUT][1],
1279           test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1280 }
1281
1282 CxCore_OrTest or_test;
1283
1284
1285 class CxCore_OrSTest : public CxCore_LogicTest
1286 {
1287 public:
1288     CxCore_OrSTest();
1289 protected:
1290     void run_func();
1291 };
1292
1293 CxCore_OrSTest::CxCore_OrSTest()
1294     : CxCore_LogicTest( "logic-ors", "cvOrS", CV_TS_LOGIC_OR, 4 )
1295 {
1296 }
1297
1298 void CxCore_OrSTest::run_func()
1299 {
1300     cvOrS( test_array[INPUT][0], gamma,
1301            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1302 }
1303
1304 CxCore_OrSTest ors_test;
1305
1306
1307 ////////////////////////// xor ////////////////////////////
1308
1309 class CxCore_XorTest : public CxCore_LogicTest
1310 {
1311 public:
1312     CxCore_XorTest();
1313 protected:
1314     void run_func();
1315 };
1316
1317 CxCore_XorTest::CxCore_XorTest()
1318     : CxCore_LogicTest( "logic-xor", "cvXor", CV_TS_LOGIC_XOR )
1319 {
1320 }
1321
1322 void CxCore_XorTest::run_func()
1323 {
1324     cvXor( test_array[INPUT][0], test_array[INPUT][1],
1325            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1326 }
1327
1328 CxCore_XorTest xor_test;
1329
1330
1331 class CxCore_XorSTest : public CxCore_LogicTest
1332 {
1333 public:
1334     CxCore_XorSTest();
1335 protected:
1336     void run_func();
1337 };
1338
1339 CxCore_XorSTest::CxCore_XorSTest()
1340     : CxCore_LogicTest( "logic-xors", "cvXorS", CV_TS_LOGIC_XOR, 4 )
1341 {
1342 }
1343
1344 void CxCore_XorSTest::run_func()
1345 {
1346     cvXorS( test_array[INPUT][0], gamma,
1347             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
1348 }
1349
1350 CxCore_XorSTest xors_test;
1351
1352
1353 ////////////////////////// not ////////////////////////////
1354
1355 class CxCore_NotTest : public CxCore_LogicTest
1356 {
1357 public:
1358     CxCore_NotTest();
1359 protected:
1360     void run_func();
1361 };
1362
1363 CxCore_NotTest::CxCore_NotTest()
1364     : CxCore_LogicTest( "logic-not", "cvNot", CV_TS_LOGIC_NOT, 4, false )
1365 {
1366 }
1367
1368 void CxCore_NotTest::run_func()
1369 {
1370     cvNot( test_array[INPUT][0],
1371            test_array[OUTPUT][0] );
1372 }
1373
1374 CxCore_NotTest nots_test;
1375
1376 ///////////////////////// cmp //////////////////////////////
1377
1378 class CxCore_CmpBaseTest : public CxCore_ArithmTest
1379 {
1380 public:
1381     CxCore_CmpBaseTest( const char* test_name, const char* test_funcs,
1382                         int in_range, int _generate_scalars=0 );
1383 protected:
1384     double get_success_error_level( int test_case_idx, int i, int j );
1385     void get_test_array_types_and_sizes( int test_case_idx,
1386                                          CvSize** sizes, int** types );
1387     void prepare_to_validation( int test_case_idx );
1388     int in_range;
1389     int cmp_op;
1390 };
1391
1392 CxCore_CmpBaseTest::CxCore_CmpBaseTest( const char* test_name, const char* test_funcs,
1393                                         int _in_range, int _generate_scalars )
1394     : CxCore_ArithmTest( test_name, test_funcs, _generate_scalars, 0, 0 ), in_range(_in_range)
1395 {
1396     if( in_range )
1397     {
1398         test_array[INPUT].push(NULL);
1399         test_array[TEMP].push(NULL);
1400         test_array[TEMP].push(NULL);
1401         if( !generate_scalars )
1402             test_array[TEMP].push(NULL);
1403     }
1404     if( generate_scalars )
1405         test_array[INPUT].pop();
1406     cmp_op = -1;
1407 }
1408
1409 double CxCore_CmpBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1410 {
1411     return 0;
1412 }
1413
1414
1415 void CxCore_CmpBaseTest::get_test_array_types_and_sizes( int test_case_idx,
1416                                                CvSize** sizes, int** types )
1417 {
1418     int j, count;
1419     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1420     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8UC1;
1421     if( !in_range )
1422     {
1423         // for cmp tests make all the input arrays single-channel
1424         count = test_array[INPUT].size();
1425         for( j = 0; j < count; j++ )
1426             types[INPUT][j] &= ~CV_MAT_CN_MASK;
1427
1428         cmp_op = cvTsRandInt(ts->get_rng()) % 6; // == > >= < <= !=
1429     }
1430     else
1431     {
1432         types[TEMP][0] = CV_8UC1;
1433         types[TEMP][1] &= ~CV_MAT_CN_MASK;
1434         if( !generate_scalars )
1435             types[TEMP][2] &= ~CV_MAT_CN_MASK;
1436     }
1437 }
1438
1439
1440 void CxCore_CmpBaseTest::prepare_to_validation( int /*test_case_idx*/ )
1441 {
1442     CvMat* dst = &test_mat[REF_OUTPUT][0];
1443     if( !in_range )
1444     {
1445         if( test_array[INPUT].size() > 1 )
1446         {
1447             cvTsCmp( &test_mat[INPUT][0], &test_mat[INPUT][1], dst, cmp_op );
1448         }
1449         else
1450         {
1451             cvTsCmpS( &test_mat[INPUT][0], gamma.val[0], dst, cmp_op );
1452         }
1453     }
1454     else
1455     {
1456         int el_type = CV_MAT_TYPE( test_mat[INPUT][0].type );
1457         int i, cn = CV_MAT_CN(el_type);
1458         CvMat* tdst = dst;
1459
1460         for( i = 0; i < cn*2; i++ )
1461         {
1462             int coi = i / 2, is_lower = (i % 2) == 0;
1463             int cmp_op = is_lower ? CV_CMP_GE : CV_CMP_LT;
1464             const CvMat* src = &test_mat[INPUT][0];
1465             const CvMat* lu = generate_scalars ? 0 : &test_mat[INPUT][is_lower?1:2];
1466             double luS = is_lower ? alpha.val[coi] : gamma.val[coi];
1467             
1468             if( cn > 1 )
1469             {
1470                 cvTsExtract( src, &test_mat[TEMP][1], coi );
1471                 src = &test_mat[TEMP][1];
1472
1473                 if( !generate_scalars )
1474                 {
1475                     cvTsExtract( lu, &test_mat[TEMP][2], coi );
1476                     lu = &test_mat[TEMP][2];
1477                 }
1478             }
1479
1480             if( !generate_scalars )
1481                 cvTsCmp( src, lu, tdst, cmp_op );
1482             else
1483                 cvTsCmpS( src, luS, tdst, cmp_op );
1484             if( i > 0 )
1485                 cvTsLogic( tdst, dst, dst, CV_TS_LOGIC_AND );
1486             tdst = &test_mat[TEMP][0];
1487         }
1488     }
1489 }
1490
1491 CxCore_CmpBaseTest cmpbase_test( "cmp", "", 0 );
1492
1493 class CxCore_CmpTest : public CxCore_CmpBaseTest
1494 {
1495 public:
1496     CxCore_CmpTest();
1497 protected:
1498     void run_func();
1499 };
1500
1501 CxCore_CmpTest::CxCore_CmpTest()
1502     : CxCore_CmpBaseTest( "cmp-cmp", "cvCmp", 0, 0 )
1503 {
1504 }
1505
1506 void CxCore_CmpTest::run_func()
1507 {
1508     cvCmp( test_array[INPUT][0], test_array[INPUT][1],
1509            test_array[OUTPUT][0], cmp_op );
1510 }
1511
1512 CxCore_CmpTest cmp_test;
1513
1514
1515 class CxCore_CmpSTest : public CxCore_CmpBaseTest
1516 {
1517 public:
1518     CxCore_CmpSTest();
1519 protected:
1520     void run_func();
1521 };
1522
1523 CxCore_CmpSTest::CxCore_CmpSTest()
1524     : CxCore_CmpBaseTest( "cmp-cmps", "cvCmpS", 0, 4 )
1525 {
1526 }
1527
1528 void CxCore_CmpSTest::run_func()
1529 {
1530     cvCmpS( test_array[INPUT][0], gamma.val[0],
1531             test_array[OUTPUT][0], cmp_op );
1532 }
1533
1534 CxCore_CmpSTest cmps_test;
1535
1536
1537 class CxCore_InRangeTest : public CxCore_CmpBaseTest
1538 {
1539 public:
1540     CxCore_InRangeTest();
1541 protected:
1542     void run_func();
1543 };
1544
1545 CxCore_InRangeTest::CxCore_InRangeTest()
1546     : CxCore_CmpBaseTest( "cmp-inrange", "cvInRange", 1, 0 )
1547 {
1548 }
1549
1550 void CxCore_InRangeTest::run_func()
1551 {
1552     cvInRange( test_array[INPUT][0], test_array[INPUT][1],
1553                test_array[INPUT][2], test_array[OUTPUT][0] );
1554 }
1555
1556 CxCore_InRangeTest inrange_test;
1557
1558
1559 class CxCore_InRangeSTest : public CxCore_CmpBaseTest
1560 {
1561 public:
1562     CxCore_InRangeSTest();
1563 protected:
1564     void run_func();
1565 };
1566
1567 CxCore_InRangeSTest::CxCore_InRangeSTest()
1568     : CxCore_CmpBaseTest( "cmp-inranges", "cvInRangeS", 1, 5 )
1569 {
1570 }
1571
1572 void CxCore_InRangeSTest::run_func()
1573 {
1574     cvInRangeS( test_array[INPUT][0], alpha, gamma, test_array[OUTPUT][0] );
1575 }
1576
1577 CxCore_InRangeSTest inranges_test;
1578
1579
1580 /////////////////////////// convertscale[abs] ////////////////////////////////////////
1581
1582 class CxCore_CvtBaseTest : public CxCore_ArithmTest
1583 {
1584 public:
1585     CxCore_CvtBaseTest( const char* test_name, const char* test_funcs,
1586                         bool calc_abs );
1587 protected:
1588     void get_test_array_types_and_sizes( int test_case_idx,
1589                                          CvSize** sizes, int** types );
1590     double get_success_error_level( int test_case_idx, int i, int j );
1591     void prepare_to_validation( int /*test_case_idx*/ );
1592 };
1593
1594
1595 CxCore_CvtBaseTest::CxCore_CvtBaseTest( const char* test_name,
1596                                         const char* test_funcs,
1597                                         bool _calc_abs )
1598     : CxCore_ArithmTest( test_name, test_funcs, 5, false, _calc_abs )
1599 {
1600     test_array[INPUT].pop();
1601 }
1602
1603 // unlike many other arithmetic functions, conversion operations support 8s type,
1604 // also, for cvCvtScale output array depth may be arbitrary and
1605 // for cvCvtScaleAbs output depth = CV_8U
1606 void CxCore_CvtBaseTest::get_test_array_types_and_sizes( int test_case_idx,
1607                                                 CvSize** sizes, int** types )
1608 {
1609     CxCore_ArithmTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1610     CvRNG* rng = ts->get_rng();
1611     int depth = CV_8U, rbits;
1612     types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|
1613                     (test_case_idx*6/test_case_count);
1614     if( !calc_abs )
1615         depth = cvTsRandInt(rng) % 6;
1616     types[OUTPUT][0] = types[REF_OUTPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|depth;
1617
1618     rbits = cvTsRandInt(rng);
1619     // check special cases: shift=0 and/or scale=1.
1620     if( (rbits & 3) == 0 )
1621         gamma.val[0] = 0;
1622     if( (rbits & 12) == 0 )
1623         alpha.val[0] = 0;
1624 }
1625
1626
1627 double CxCore_CvtBaseTest::get_success_error_level( int test_case_idx, int i, int j )
1628 {
1629     if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
1630     {
1631         return alpha.val[0] != cvRound(alpha.val[0]) ||
1632                beta.val[0] != cvRound(beta.val[0]) ||
1633                gamma.val[0] != cvRound(gamma.val[0]);
1634     }
1635     else
1636         return CvArrTest::get_success_error_level( test_case_idx, i, j );
1637 }
1638
1639
1640 void CxCore_CvtBaseTest::prepare_to_validation( int /*test_case_idx*/ )
1641 {
1642     cvTsAdd( &test_mat[INPUT][0], cvScalarAll(alpha.val[0]), 0, beta,
1643              cvScalarAll(gamma.val[0]), &test_mat[REF_OUTPUT][0], calc_abs );
1644 }
1645
1646 CxCore_CvtBaseTest cvt_test( "cvt", "", false );
1647
1648
1649 class CxCore_CvtScaleTest : public CxCore_CvtBaseTest
1650 {
1651 public:
1652     CxCore_CvtScaleTest();
1653 protected:
1654     void run_func();
1655 };
1656
1657 CxCore_CvtScaleTest::CxCore_CvtScaleTest()
1658     : CxCore_CvtBaseTest( "cvt-scale", "cvCvtScale", false )
1659 {
1660 }
1661
1662 void CxCore_CvtScaleTest::run_func()
1663 {
1664     cvConvertScale( test_array[INPUT][0], test_array[OUTPUT][0],
1665                     alpha.val[0], gamma.val[0] );
1666 }
1667
1668 CxCore_CvtScaleTest cvtscale_test;
1669
1670
1671 class CxCore_CvtScaleAbsTest : public CxCore_CvtBaseTest
1672 {
1673 public:
1674     CxCore_CvtScaleAbsTest();
1675 protected:
1676     void run_func();
1677 };
1678
1679 CxCore_CvtScaleAbsTest::CxCore_CvtScaleAbsTest()
1680     : CxCore_CvtBaseTest( "cvt-scaleabs", "cvCvtScaleAbs", true )
1681 {
1682 }
1683
1684 void CxCore_CvtScaleAbsTest::run_func()
1685 {
1686     cvConvertScaleAbs( test_array[INPUT][0], test_array[OUTPUT][0],
1687                        alpha.val[0], gamma.val[0] );
1688 }
1689
1690 CxCore_CvtScaleAbsTest cvtscaleabs_test;
1691
1692
1693 /////////////////////////////// statistics //////////////////////////////////
1694
1695 class CxCore_StatTest : public CvArrTest
1696 {
1697 public:
1698     CxCore_StatTest( const char* test_name, const char* test_funcs,
1699                      int _output_count, bool _single_channel,
1700                      bool _allow_mask=1, bool _is_binary=0 );
1701 protected:
1702     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1703     int  prepare_test_case( int test_case_idx );
1704     double get_success_error_level( int test_case_idx, int i, int j );
1705
1706     int coi;
1707     int output_count;
1708     bool single_channel;
1709     bool allow_mask;
1710     bool is_binary;
1711 };
1712
1713 CxCore_StatTest::CxCore_StatTest( const char* test_name,
1714                         const char* test_funcs, int _output_count,
1715                         bool _single_channel, bool _allow_mask, bool _is_binary )
1716     : CvArrTest( test_name, test_funcs, "" ), output_count(_output_count),
1717     single_channel(_single_channel), allow_mask(_allow_mask), is_binary(_is_binary)
1718 {
1719     test_array[INPUT].push(NULL);
1720     if( is_binary )
1721         test_array[INPUT].push(NULL);
1722     if( allow_mask )
1723         test_array[MASK].push(NULL);
1724     test_array[OUTPUT].push(NULL);
1725     test_array[REF_OUTPUT].push(NULL);
1726     coi = 0;
1727 }
1728
1729 void CxCore_StatTest::get_test_array_types_and_sizes( int test_case_idx,
1730                                             CvSize** sizes, int** types )
1731 {
1732     CvRNG* rng = ts->get_rng();
1733     int depth = test_case_idx*CV_64F/test_case_count;
1734     int cn = cvTsRandInt(rng) % 4 + 1;
1735     int j, count = test_array[INPUT].size();
1736     
1737     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1738     depth += depth == CV_8S;
1739
1740     for( j = 0; j < count; j++ )
1741         types[INPUT][j] = CV_MAKETYPE(depth, cn);
1742
1743     // regardless of the test case, the output is always a fixed-size tuple of numbers
1744     sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( output_count, 1 );
1745     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
1746
1747     coi = 0;
1748     cvmat_allowed = true;
1749     if( cn > 1 && (single_channel || (cvTsRandInt(rng) & 3) == 0) )
1750     {
1751         coi = cvTsRandInt(rng) % cn + 1;
1752         cvmat_allowed = false;
1753     }
1754 }
1755
1756 int CxCore_StatTest::prepare_test_case( int test_case_idx )
1757 {
1758     int code = CvArrTest::prepare_test_case( test_case_idx );
1759     
1760     if( coi )
1761     {
1762         int j, count = test_array[INPUT].size();
1763         for( j = 0; j < count; j++ )
1764         {
1765             IplImage* img = (IplImage*)test_array[INPUT][j];
1766             if( img )
1767                 cvSetImageCOI( img, coi );
1768         }
1769     }
1770
1771     return code;
1772 }
1773
1774 double CxCore_StatTest::get_success_error_level( int test_case_idx, int i, int j )
1775 {
1776     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
1777     if( depth == CV_32F )
1778         return FLT_EPSILON*1000;
1779     if( depth == CV_64F )
1780         return DBL_EPSILON*1000;
1781     else
1782         return CvArrTest::get_success_error_level( test_case_idx, i, j );
1783 }
1784
1785 CxCore_StatTest stat_test( "stat", "", 0, 1 );
1786
1787 ////////////////// sum /////////////////
1788 class CxCore_SumTest : public CxCore_StatTest
1789 {
1790 public:
1791     CxCore_SumTest();
1792 protected:
1793     void run_func();
1794     void prepare_to_validation( int test_case_idx );
1795 };
1796
1797
1798 CxCore_SumTest::CxCore_SumTest()
1799     : CxCore_StatTest( "stat-sum", "cvSum", 4 /* CvScalar */, false, false, false )
1800 {
1801 }
1802
1803 void CxCore_SumTest::run_func()
1804 {
1805     *(CvScalar*)(test_mat[OUTPUT][0].data.db) = cvSum(test_array[INPUT][0]);
1806 }
1807
1808 void CxCore_SumTest::prepare_to_validation( int /*test_case_idx*/ )
1809 {
1810     CvScalar mean;
1811     int nonzero = cvTsMeanStdDevNonZero( &test_mat[INPUT][0], 0, &mean, 0, coi );
1812     mean.val[0] *= nonzero;
1813     mean.val[1] *= nonzero;
1814     mean.val[2] *= nonzero;
1815     mean.val[3] *= nonzero;
1816
1817     *(CvScalar*)(test_mat[REF_OUTPUT][0].data.db) = mean;
1818 }
1819
1820 CxCore_SumTest sum_test;
1821
1822
1823 ////////////////// nonzero /////////////////
1824 class CxCore_NonZeroTest : public CxCore_StatTest
1825 {
1826 public:
1827     CxCore_NonZeroTest();
1828 protected:
1829     void run_func();
1830     void prepare_to_validation( int test_case_idx );
1831     void get_test_array_types_and_sizes( int test_case_idx,
1832                                          CvSize** sizes, int** types );
1833 };
1834
1835
1836 CxCore_NonZeroTest::CxCore_NonZeroTest()
1837     : CxCore_StatTest( "stat-nonzero", "cvCountNonZero", 1 /* int */, true, false, false )
1838 {
1839     test_array[TEMP].push(NULL);
1840     test_array[TEMP].push(NULL);
1841 }
1842
1843 void CxCore_NonZeroTest::run_func()
1844 {
1845     test_mat[OUTPUT][0].data.db[0] = cvCountNonZero(test_array[INPUT][0]);
1846 }
1847
1848 void CxCore_NonZeroTest::get_test_array_types_and_sizes( int test_case_idx,
1849                                               CvSize** sizes, int** types )
1850 {
1851     CxCore_StatTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1852     types[TEMP][0] = CV_8UC1;
1853     if( CV_MAT_CN(types[INPUT][0]) > 1 )
1854         types[TEMP][1] = types[INPUT][0] & ~CV_MAT_CN_MASK;
1855     else
1856         sizes[TEMP][1] = cvSize(0,0);
1857 }
1858
1859
1860 void CxCore_NonZeroTest::prepare_to_validation( int /*test_case_idx*/ )
1861 {
1862     CvMat* plane = &test_mat[INPUT][0];
1863     if( CV_MAT_CN(plane->type) > 1 )
1864     {
1865         plane = &test_mat[TEMP][1];
1866         assert( coi > 0 );
1867         cvTsExtract( &test_mat[INPUT][0], plane, coi-1 );
1868     }
1869     cvTsCmpS( plane, 0, &test_mat[TEMP][0], CV_CMP_NE );
1870     int nonzero = cvTsMeanStdDevNonZero( &test_mat[INPUT][0], &test_mat[TEMP][0], 0, 0, coi );
1871     test_mat[REF_OUTPUT][0].data.db[0] = nonzero;
1872 }
1873
1874
1875 CxCore_NonZeroTest nonzero_test;
1876
1877
1878 /////////////////// mean //////////////////////
1879 class CxCore_MeanTest : public CxCore_StatTest
1880 {
1881 public:
1882     CxCore_MeanTest();
1883 protected:
1884     void run_func();
1885     void prepare_to_validation( int test_case_idx );
1886 };
1887
1888
1889 CxCore_MeanTest::CxCore_MeanTest()
1890     : CxCore_StatTest( "stat-mean", "cvAvg", 4 /* CvScalar */, false, true, false )
1891 {
1892 }
1893
1894 void CxCore_MeanTest::run_func()
1895 {
1896     *(CvScalar*)(test_mat[OUTPUT][0].data.db) =
1897         cvAvg(test_array[INPUT][0], test_array[MASK][0]);
1898 }
1899
1900 void CxCore_MeanTest::prepare_to_validation( int /*test_case_idx*/ )
1901 {
1902     CvScalar mean;
1903     cvTsMeanStdDevNonZero( &test_mat[INPUT][0],
1904         test_array[MASK][0] ? &test_mat[MASK][0] : 0,
1905         &mean, 0, coi );
1906     *(CvScalar*)(test_mat[REF_OUTPUT][0].data.db) = mean;
1907 }
1908
1909 CxCore_MeanTest mean_test;
1910
1911
1912 /////////////////// mean_stddev //////////////////////
1913 class CxCore_MeanStdDevTest : public CxCore_StatTest
1914 {
1915 public:
1916     CxCore_MeanStdDevTest();
1917 protected:
1918     void run_func();
1919     void prepare_to_validation( int test_case_idx );
1920 };
1921
1922
1923 CxCore_MeanStdDevTest::CxCore_MeanStdDevTest()
1924     : CxCore_StatTest( "stat-mean_stddev", "cvAvgSdv", 8 /* CvScalar x 2 */, false, true, false )
1925 {
1926 }
1927
1928 void CxCore_MeanStdDevTest::run_func()
1929 {
1930     cvAvgSdv( test_array[INPUT][0],
1931               &((CvScalar*)(test_mat[OUTPUT][0].data.db))[0],
1932               &((CvScalar*)(test_mat[OUTPUT][0].data.db))[1],
1933               test_array[MASK][0] );
1934 }
1935
1936 void CxCore_MeanStdDevTest::prepare_to_validation( int /*test_case_idx*/ )
1937 {
1938     CvScalar mean, stddev;
1939     cvTsMeanStdDevNonZero( &test_mat[INPUT][0],
1940         test_array[MASK][0] ? &test_mat[MASK][0] : 0,
1941         &mean, &stddev, coi );
1942     ((CvScalar*)(test_mat[REF_OUTPUT][0].data.db))[0] = mean;
1943     ((CvScalar*)(test_mat[REF_OUTPUT][0].data.db))[1] = stddev;
1944 }
1945
1946 CxCore_MeanStdDevTest mean_stddev_test;
1947
1948
1949 /////////////////// minmaxloc //////////////////////
1950 class CxCore_MinMaxLocTest : public CxCore_StatTest
1951 {
1952 public:
1953     CxCore_MinMaxLocTest();
1954 protected:
1955     void run_func();
1956     void prepare_to_validation( int test_case_idx );
1957 };
1958
1959
1960 CxCore_MinMaxLocTest::CxCore_MinMaxLocTest()
1961     : CxCore_StatTest( "stat-minmaxloc", "cvMinMaxLoc", 6 /* double x 2 + CvPoint x 2 */, true, true, false )
1962 {
1963 }
1964
1965 void CxCore_MinMaxLocTest::run_func()
1966 {
1967     CvPoint minloc = {0,0}, maxloc = {0,0};
1968     double* output = test_mat[OUTPUT][0].data.db;
1969
1970     cvMinMaxLoc( test_array[INPUT][0],
1971         output, output+1, &minloc, &maxloc,
1972         test_array[MASK][0] );
1973     output[2] = minloc.x;
1974     output[3] = minloc.y;
1975     output[4] = maxloc.x;
1976     output[5] = maxloc.y;
1977 }
1978
1979 void CxCore_MinMaxLocTest::prepare_to_validation( int /*test_case_idx*/ )
1980 {
1981     double minval = 0, maxval = 0;
1982     CvPoint minloc = {0,0}, maxloc = {0,0};
1983     double* ref_output = test_mat[REF_OUTPUT][0].data.db;
1984     cvTsMinMaxLoc( &test_mat[INPUT][0], test_array[MASK][0] ?
1985         &test_mat[MASK][0] : 0, &minval, &maxval, &minloc, &maxloc, coi );
1986     ref_output[0] = minval;
1987     ref_output[1] = maxval;
1988     ref_output[2] = minloc.x;
1989     ref_output[3] = minloc.y;
1990     ref_output[4] = maxloc.x;
1991     ref_output[5] = maxloc.y;
1992 }
1993
1994 CxCore_MinMaxLocTest minmaxloc_test;
1995
1996
1997 /////////////////// norm //////////////////////
1998 class CxCore_NormTest : public CxCore_StatTest
1999 {
2000 public:
2001     CxCore_NormTest();
2002 protected:
2003     void run_func();
2004     void prepare_to_validation( int test_case_idx );
2005     void get_test_array_types_and_sizes( int test_case_idx,
2006                                          CvSize** sizes, int** types );
2007     double get_success_error_level( int test_case_idx, int i, int j );
2008     int norm_type;
2009 };
2010
2011
2012 CxCore_NormTest::CxCore_NormTest()
2013     : CxCore_StatTest( "stat-norm", "cvNorm", 1 /* double */, false, true, true )
2014 {
2015     test_array[TEMP].push(NULL);
2016 }
2017
2018
2019 double CxCore_NormTest::get_success_error_level( int test_case_idx, int i, int j )
2020 {
2021     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
2022     if( (depth == CV_16U || depth == CV_16S) && (norm_type&3) != CV_C  )
2023         return FLT_EPSILON*100;
2024     else
2025         return CxCore_StatTest::get_success_error_level( test_case_idx, i, j );
2026 }
2027
2028 void CxCore_NormTest::get_test_array_types_and_sizes( int test_case_idx,
2029                                                CvSize** sizes, int** types )
2030 {
2031     int intype;
2032     int norm_kind;
2033     CxCore_StatTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2034     norm_type = cvTsRandInt(ts->get_rng()) % 3; // CV_C, CV_L1 or CV_L2
2035     norm_kind = cvTsRandInt(ts->get_rng()) % 3; // simple, difference or relative difference
2036     if( norm_kind == 0 )
2037         sizes[INPUT][1] = cvSize(0,0);
2038     norm_type = (1 << norm_type) | (norm_kind*8);
2039     intype = types[INPUT][0];
2040     if( CV_MAT_CN(intype) > 1 && coi == 0 )
2041         sizes[MASK][0] = cvSize(0,0);
2042     sizes[TEMP][0] = cvSize(0,0);
2043     if( (norm_type & (CV_DIFF|CV_RELATIVE)) && CV_MAT_DEPTH(intype) <= CV_32F )
2044     {
2045         sizes[TEMP][0] = sizes[INPUT][0];
2046         types[TEMP][0] = (intype & ~CV_MAT_DEPTH_MASK)|
2047             (CV_MAT_DEPTH(intype) < CV_32F ? CV_32S : CV_64F);
2048     }
2049 }
2050
2051
2052 void CxCore_NormTest::run_func()
2053 {
2054     /*if( ts->get_current_test_info()->test_case_idx == 268 )
2055     {
2056         cvSave( "_a.xml", &test_mat[INPUT][0] );
2057         cvSave( "_b.xml", &test_mat[INPUT][1] );
2058         putchar('.');
2059     }*/
2060     
2061     test_mat[OUTPUT][0].data.db[0] = cvNorm( test_array[INPUT][0],
2062             test_array[INPUT][1], norm_type, test_array[MASK][0] );
2063 }
2064
2065 void CxCore_NormTest::prepare_to_validation( int /*test_case_idx*/ )
2066 {
2067     double a_norm = 0, b_norm = 0;
2068     CvMat* a = &test_mat[INPUT][0];
2069     CvMat* b = &test_mat[INPUT][1];
2070     CvMat* mask = test_array[MASK][0] ? &test_mat[MASK][0] : 0;
2071     CvMat* diff = a;
2072
2073     if( norm_type & (CV_DIFF|CV_RELATIVE) )
2074     {
2075         diff = &test_mat[TEMP][0] ? &test_mat[TEMP][0] : a;
2076         cvTsAdd( a, cvScalarAll(1.), b, cvScalarAll(-1.),
2077                  cvScalarAll(0.), diff, 0 );
2078     }
2079     a_norm = cvTsNorm( diff, mask, norm_type & CV_NORM_MASK, coi );
2080     if( norm_type & CV_RELATIVE )
2081     {
2082         b_norm = cvTsNorm( b, mask, norm_type & CV_NORM_MASK, coi );
2083         a_norm /= (b_norm + DBL_EPSILON );
2084     }
2085     test_mat[REF_OUTPUT][0].data.db[0] = a_norm;
2086 }
2087
2088 CxCore_NormTest norm_test;
2089
2090
2091 ///////////////// Trace /////////////////////
2092
2093 class CxCore_TraceTest : public CxCore_StatTest
2094 {
2095 public:
2096     CxCore_TraceTest();
2097 protected:
2098     void run_func();
2099     void prepare_to_validation( int test_case_idx );
2100 };
2101
2102
2103 CxCore_TraceTest::CxCore_TraceTest() :
2104     CxCore_StatTest( "matrix-trace", "cvTrace", 4, false, false, false )
2105 {
2106 }
2107
2108
2109 void CxCore_TraceTest::run_func()
2110 {
2111     *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvTrace(test_array[INPUT][0]);
2112 }
2113
2114 void CxCore_TraceTest::prepare_to_validation( int )
2115 {
2116     CvMat* mat = &test_mat[INPUT][0];
2117     int i, j, count = MIN( mat->rows, mat->cols );
2118     CvScalar trace = {0,0,0,0};
2119
2120     for( i = 0; i < count; i++ )
2121     {
2122         CvScalar el = cvGet2D( mat, i, i );
2123         for( j = 0; j < 4; j++ )
2124             trace.val[j] += el.val[j];
2125     }
2126
2127     *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = trace;
2128 }
2129
2130 CxCore_TraceTest trace_test;
2131
2132 // TODO: repeat(?), reshape(?), lut
2133
2134 /* End of file. */