1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
42 //////////////////////////////////////////////////////////////////////////////////////////
43 /////////////////// tests for matrix operations and math functions ///////////////////////
44 //////////////////////////////////////////////////////////////////////////////////////////
46 #include "cxcoretest.h"
50 /// !!! NOTE !!! These tests happily avoid overflow cases & out-of-range arguments
51 /// so that output arrays contain neigher Inf's nor Nan's.
52 /// Handling such cases would require special modification of check function
53 /// (validate_test_results) => TBD.
54 /// Also, need some logarithmic-scale generation of input data. Right now it is done (in some tests)
55 /// by generating min/max boundaries for random data in logarimithic scale, but
56 /// within the same test case all the input array elements are of the same order.
58 static const CvSize math_sizes[] = {{10,1}, {100,1}, {10000,1}, {-1,-1}};
59 static const int math_depths[] = { CV_32F, CV_64F, -1 };
60 static const char* math_param_names[] = { "size", "depth", 0 };
62 static const CvSize matrix_sizes[] = {{3,3}, {4,4}, {10,10}, {30,30}, {100,100}, {500,500}, {-1,-1}};
64 class CxCore_MathTestImpl : public CvArrTest
67 CxCore_MathTestImpl( const char* test_name, const char* test_funcs );
69 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
70 double get_success_error_level( int /*test_case_idx*/, int i, int j );
74 CxCore_MathTestImpl::CxCore_MathTestImpl( const char* test_name, const char* test_funcs )
75 : CvArrTest( test_name, test_funcs, "" )
77 optional_mask = false;
79 test_array[INPUT].push(NULL);
80 test_array[OUTPUT].push(NULL);
81 test_array[REF_OUTPUT].push(NULL);
83 default_timing_param_names = math_param_names;
85 size_list = math_sizes;
87 depth_list = math_depths;
92 double CxCore_MathTestImpl::get_success_error_level( int /*test_case_idx*/, int i, int j )
94 return CV_MAT_DEPTH(test_mat[i][j].type) == CV_32F ? FLT_EPSILON*128 : DBL_EPSILON*1024;
98 void CxCore_MathTestImpl::get_test_array_types_and_sizes( int test_case_idx,
99 CvSize** sizes, int** types )
101 CvRNG* rng = ts->get_rng();
102 int depth = cvTsRandInt(rng)%2 + CV_32F;
103 int cn = cvTsRandInt(rng) % 4 + 1, type = CV_MAKETYPE(depth, cn);
105 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
107 for( i = 0; i < max_arr; i++ )
109 int count = test_array[i].size();
110 for( j = 0; j < count; j++ )
115 CxCore_MathTestImpl math_test( "math", "" );
118 class CxCore_MathTest : public CxCore_MathTestImpl
121 CxCore_MathTest( const char* test_name, const char* test_funcs );
125 CxCore_MathTest::CxCore_MathTest( const char* test_name, const char* test_funcs )
126 : CxCore_MathTestImpl( test_name, test_funcs )
133 ////////// exp /////////////
134 class CxCore_ExpTest : public CxCore_MathTest
139 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
140 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
141 double get_success_error_level( int /*test_case_idx*/, int i, int j );
143 void prepare_to_validation( int test_case_idx );
148 CxCore_ExpTest::CxCore_ExpTest()
149 : CxCore_MathTest( "math-exp", "cvExp" )
155 double CxCore_ExpTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
157 int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
158 int out_depth = CV_MAT_DEPTH(test_mat[OUTPUT][0].type);
159 int min_depth = MIN(in_depth, out_depth);
160 return min_depth == CV_32F ? 1e-5 : 1e-8;
164 void CxCore_ExpTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
166 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
167 out_type = types[OUTPUT][0];
168 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32F && (cvRandInt(ts->get_rng()) & 3) == 0 )
169 types[OUTPUT][0] = types[REF_OUTPUT][0] =
170 out_type = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|CV_64F;
173 void CxCore_ExpTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
175 double l = cvTsRandReal(ts->get_rng())*10+1;
176 double u = cvTsRandReal(ts->get_rng())*10+1;
179 *low = cvScalarAll(l);
180 *high = cvScalarAll(CV_MAT_DEPTH(out_type)==CV_64F? u : u*0.5);
184 void CxCore_ExpTest::run_func()
186 cvExp( test_array[INPUT][0], test_array[OUTPUT][0] );
190 void CxCore_ExpTest::prepare_to_validation( int /*test_case_idx*/ )
192 CvMat* a = &test_mat[INPUT][0];
193 CvMat* b = &test_mat[REF_OUTPUT][0];
195 int a_depth = CV_MAT_DEPTH(a->type);
196 int b_depth = CV_MAT_DEPTH(b->type);
197 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
200 for( i = 0; i < a->rows; i++ )
202 uchar* a_data = a->data.ptr + i*a->step;
203 uchar* b_data = b->data.ptr + i*b->step;
205 if( a_depth == CV_32F && b_depth == CV_32F )
207 for( j = 0; j < ncols; j++ )
208 ((float*)b_data)[j] = (float)exp((double)((float*)a_data)[j]);
210 else if( a_depth == CV_32F && b_depth == CV_64F )
212 for( j = 0; j < ncols; j++ )
213 ((double*)b_data)[j] = exp((double)((float*)a_data)[j]);
217 assert( a_depth == CV_64F && b_depth == CV_64F );
218 for( j = 0; j < ncols; j++ )
219 ((double*)b_data)[j] = exp(((double*)a_data)[j]);
224 CxCore_ExpTest exp_test;
227 ////////// log /////////////
228 class CxCore_LogTest : public CxCore_MathTest
233 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
234 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
236 void prepare_to_validation( int test_case_idx );
240 CxCore_LogTest::CxCore_LogTest()
241 : CxCore_MathTest( "math-log", "cvLog" )
246 void CxCore_LogTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
248 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
249 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32F && (cvRandInt(ts->get_rng()) & 3) == 0 )
250 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|CV_64F;
254 void CxCore_LogTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
256 double l = cvTsRandReal(ts->get_rng())*15-5;
257 double u = cvTsRandReal(ts->get_rng())*15-5;
263 *low = cvScalarAll(l);
264 *high = cvScalarAll(u);
268 void CxCore_LogTest::run_func()
270 cvLog( test_array[INPUT][0], test_array[OUTPUT][0] );
274 void CxCore_LogTest::prepare_to_validation( int /*test_case_idx*/ )
276 CvMat* a = &test_mat[INPUT][0];
277 CvMat* b = &test_mat[REF_OUTPUT][0];
279 int a_depth = CV_MAT_DEPTH(a->type);
280 int b_depth = CV_MAT_DEPTH(b->type);
281 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
284 for( i = 0; i < a->rows; i++ )
286 uchar* a_data = a->data.ptr + i*a->step;
287 uchar* b_data = b->data.ptr + i*b->step;
289 if( a_depth == CV_32F && b_depth == CV_32F )
291 for( j = 0; j < ncols; j++ )
292 ((float*)b_data)[j] = (float)log((double)((float*)a_data)[j]);
294 else if( a_depth == CV_64F && b_depth == CV_32F )
296 for( j = 0; j < ncols; j++ )
297 ((float*)b_data)[j] = (float)log(((double*)a_data)[j]);
301 assert( a_depth == CV_64F && b_depth == CV_64F );
302 for( j = 0; j < ncols; j++ )
303 ((double*)b_data)[j] = log(((double*)a_data)[j]);
308 CxCore_LogTest log_test;
311 ////////// pow /////////////
313 static const double math_pow_values[] = { 2., 5., 0.5, -0.5, 1./3, -1./3, CV_PI };
314 static const char* math_pow_param_names[] = { "size", "power", "depth", 0 };
315 static const int math_pow_depths[] = { CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, -1 };
317 class CxCore_PowTest : public CxCore_MathTest
322 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
323 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
324 void get_timing_test_array_types_and_sizes( int test_case_idx,
325 CvSize** sizes, int** types,
326 CvSize** whole_sizes, bool* are_images );
327 int write_default_params( CvFileStorage* fs );
328 void print_timing_params( int test_case_idx, char* ptr, int params_left );
330 int prepare_test_case( int test_case_idx );
331 void prepare_to_validation( int test_case_idx );
332 double get_success_error_level( int test_case_idx, int i, int j );
337 CxCore_PowTest::CxCore_PowTest()
338 : CxCore_MathTest( "math-pow", "cvPow" )
341 default_timing_param_names = math_pow_param_names;
342 depth_list = math_pow_depths;
346 void CxCore_PowTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
348 CvRNG* rng = ts->get_rng();
349 int depth = cvTsRandInt(rng) % CV_64F;
350 int cn = cvTsRandInt(rng) % 4 + 1;
352 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
353 depth += depth == CV_8S;
355 if( depth < CV_32F || cvTsRandInt(rng)%8 == 0 )
357 power = (int)(cvTsRandInt(rng)%21 - 10);
360 i = cvTsRandInt(rng)%16;
361 power = i == 15 ? 0.5 : i == 14 ? -0.5 : cvTsRandReal(rng)*10 - 5;
364 for( i = 0; i < max_arr; i++ )
366 int count = test_array[i].size();
367 int type = CV_MAKETYPE(depth, cn);
368 for( j = 0; j < count; j++ )
374 void CxCore_PowTest::get_timing_test_array_types_and_sizes( int test_case_idx,
375 CvSize** sizes, int** types,
376 CvSize** whole_sizes, bool* are_images )
378 CxCore_MathTest::get_timing_test_array_types_and_sizes( test_case_idx,
379 sizes, types, whole_sizes, are_images );
380 power = cvReadReal( find_timing_param( "power" ), 0.2 );
384 int CxCore_PowTest::write_default_params( CvFileStorage* fs )
386 int i, code = CxCore_MathTest::write_default_params(fs);
387 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
389 start_write_param( fs );
390 cvStartWriteStruct( fs, "power", CV_NODE_SEQ + CV_NODE_FLOW );
391 for( i = 0; i < CV_DIM(math_pow_values); i++ )
392 cvWriteReal( fs, 0, math_pow_values[i] );
393 cvEndWriteStruct(fs);
398 int CxCore_PowTest::prepare_test_case( int test_case_idx )
400 int code = CxCore_MathTest::prepare_test_case( test_case_idx );
401 if( code > 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
403 if( cvRound(power) != power && CV_MAT_DEPTH(test_mat[INPUT][0].type) < CV_32F )
410 void CxCore_PowTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
412 sprintf( ptr, "%g,", power );
415 CxCore_MathTest::print_timing_params( test_case_idx, ptr, params_left );
419 double CxCore_PowTest::get_success_error_level( int test_case_idx, int i, int j )
421 int type = cvGetElemType( test_array[i][j] );
422 if( CV_MAT_DEPTH(type) < CV_32F )
423 return power == cvRound(power) && power >= 0 ? 0 : 1;
425 return CxCore_MathTest::get_success_error_level( test_case_idx, i, j );
429 void CxCore_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, CvScalar* low, CvScalar* high )
431 double l, u = cvTsRandInt(ts->get_rng())%1000 + 1;
434 double mval = cvTsMaxVal(type);
435 double u1 = pow(mval,1./power)*2;
439 l = power == cvRound(power) ? -u : FLT_EPSILON;
440 *low = cvScalarAll(l);
441 *high = cvScalarAll(u);
445 void CxCore_PowTest::run_func()
447 cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
451 inline static int ipow( int a, int power )
465 inline static double ipow( double a, int power )
479 void CxCore_PowTest::prepare_to_validation( int /*test_case_idx*/ )
481 CvMat* a = &test_mat[INPUT][0];
482 CvMat* b = &test_mat[REF_OUTPUT][0];
484 int depth = CV_MAT_DEPTH(a->type);
485 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
486 int ipower = cvRound(power), apower = abs(ipower);
489 for( i = 0; i < a->rows; i++ )
491 uchar* a_data = a->data.ptr + i*a->step;
492 uchar* b_data = b->data.ptr + i*b->step;
498 for( j = 0; j < ncols; j++ )
500 int val = ((uchar*)a_data)[j];
501 ((uchar*)b_data)[j] = (uchar)(val <= 1 ? val :
502 val == 2 && ipower == -1 ? 1 : 0);
505 for( j = 0; j < ncols; j++ )
507 int val = ((uchar*)a_data)[j];
508 val = ipow( val, ipower );
509 ((uchar*)b_data)[j] = CV_CAST_8U(val);
514 for( j = 0; j < ncols; j++ )
516 int val = ((char*)a_data)[j];
517 ((char*)b_data)[j] = (char)((val&~1)==0 ? val :
518 val ==-1 ? 1-2*(ipower&1) :
519 val == 2 && ipower == -1 ? 1 : 0);
522 for( j = 0; j < ncols; j++ )
524 int val = ((char*)a_data)[j];
525 val = ipow( val, ipower );
526 ((char*)b_data)[j] = CV_CAST_8S(val);
531 for( j = 0; j < ncols; j++ )
533 int val = ((ushort*)a_data)[j];
534 ((ushort*)b_data)[j] = (ushort)((val&~1)==0 ? val :
535 val ==-1 ? 1-2*(ipower&1) :
536 val == 2 && ipower == -1 ? 1 : 0);
539 for( j = 0; j < ncols; j++ )
541 int val = ((ushort*)a_data)[j];
542 val = ipow( val, ipower );
543 ((ushort*)b_data)[j] = CV_CAST_16U(val);
548 for( j = 0; j < ncols; j++ )
550 int val = ((short*)a_data)[j];
551 ((short*)b_data)[j] = (short)((val&~1)==0 ? val :
552 val ==-1 ? 1-2*(ipower&1) :
553 val == 2 && ipower == -1 ? 1 : 0);
556 for( j = 0; j < ncols; j++ )
558 int val = ((short*)a_data)[j];
559 val = ipow( val, ipower );
560 ((short*)b_data)[j] = CV_CAST_16S(val);
565 for( j = 0; j < ncols; j++ )
567 int val = ((int*)a_data)[j];
568 ((int*)b_data)[j] = (val&~1)==0 ? val :
569 val ==-1 ? 1-2*(ipower&1) :
570 val == 2 && ipower == -1 ? 1 : 0;
573 for( j = 0; j < ncols; j++ )
575 int val = ((int*)a_data)[j];
576 val = ipow( val, ipower );
577 ((int*)b_data)[j] = val;
581 if( power != ipower )
582 for( j = 0; j < ncols; j++ )
584 double val = ((float*)a_data)[j];
585 val = pow( fabs(val), power );
586 ((float*)b_data)[j] = CV_CAST_32F(val);
589 for( j = 0; j < ncols; j++ )
591 double val = ((float*)a_data)[j];
594 val = ipow( val, apower );
595 ((float*)b_data)[j] = (float)val;
599 if( power != ipower )
600 for( j = 0; j < ncols; j++ )
602 double val = ((double*)a_data)[j];
603 val = pow( fabs(val), power );
604 ((double*)b_data)[j] = CV_CAST_64F(val);
607 for( j = 0; j < ncols; j++ )
609 double val = ((double*)a_data)[j];
612 val = ipow( val, apower );
613 ((double*)b_data)[j] = (double)val;
620 CxCore_PowTest pow_test;
624 ////////// cart2polar /////////////
625 class CxCore_CartToPolarTest : public CxCore_MathTest
628 CxCore_CartToPolarTest();
630 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
631 double get_success_error_level( int test_case_idx, int i, int j );
633 void prepare_to_validation( int test_case_idx );
638 CxCore_CartToPolarTest::CxCore_CartToPolarTest()
639 : CxCore_MathTest( "math-cart2polar", "cvCartToPolar" )
642 test_array[INPUT].push(NULL);
643 test_array[OUTPUT].push(NULL);
644 test_array[REF_OUTPUT].push(NULL);
648 void CxCore_CartToPolarTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
650 CvRNG* rng = ts->get_rng();
651 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
653 use_degrees = cvTsRandInt(rng) & 1;
654 if( cvTsRandInt(rng) % 4 == 0 ) // check missing magnitude/angle cases
656 int idx = cvTsRandInt(rng) & 1;
657 sizes[OUTPUT][idx] = sizes[REF_OUTPUT][idx] = cvSize(0,0);
662 void CxCore_CartToPolarTest::run_func()
664 cvCartToPolar( test_array[INPUT][0], test_array[INPUT][1],
665 test_array[OUTPUT][0], test_array[OUTPUT][1], use_degrees );
669 double CxCore_CartToPolarTest::get_success_error_level( int test_case_idx, int i, int j )
671 return j == 1 ? 0.5*(use_degrees ? 1 : CV_PI/180.) :
672 CxCore_MathTest::get_success_error_level( test_case_idx, i, j );
676 void CxCore_CartToPolarTest::prepare_to_validation( int /*test_case_idx*/ )
678 CvMat* x = &test_mat[INPUT][0];
679 CvMat* y = &test_mat[INPUT][1];
680 CvMat* mag = test_array[REF_OUTPUT][0] ? &test_mat[REF_OUTPUT][0] : 0;
681 CvMat* angle = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
682 double C = use_degrees ? 180./CV_PI : 1.;
684 int depth = CV_MAT_DEPTH(x->type);
685 int ncols = x->cols*CV_MAT_CN(x->type);
688 for( i = 0; i < x->rows; i++ )
690 uchar* x_data = x->data.ptr + i*x->step;
691 uchar* y_data = y->data.ptr + i*y->step;
692 uchar* mag_data = mag ? mag->data.ptr + i*mag->step : 0;
693 uchar* angle_data = angle ? angle->data.ptr + i*angle->step : 0;
695 if( depth == CV_32F )
697 for( j = 0; j < ncols; j++ )
699 double xval = ((float*)x_data)[j];
700 double yval = ((float*)y_data)[j];
703 ((float*)mag_data)[j] = (float)sqrt(xval*xval + yval*yval);
706 double a = atan2( yval, xval );
710 ((float*)angle_data)[j] = (float)a;
716 assert( depth == CV_64F );
717 for( j = 0; j < ncols; j++ )
719 double xval = ((double*)x_data)[j];
720 double yval = ((double*)y_data)[j];
723 ((double*)mag_data)[j] = sqrt(xval*xval + yval*yval);
726 double a = atan2( yval, xval );
730 ((double*)angle_data)[j] = a;
738 // hack: increase angle value by 1 (so that alpha becomes 1+alpha)
739 // to hide large relative errors in case of very small angles
740 cvTsAdd( &test_mat[OUTPUT][1], cvScalarAll(1.), 0, cvScalarAll(0.),
741 cvScalarAll(1.), &test_mat[OUTPUT][1], 0 );
742 cvTsAdd( &test_mat[REF_OUTPUT][1], cvScalarAll(1.), 0, cvScalarAll(0.),
743 cvScalarAll(1.), &test_mat[REF_OUTPUT][1], 0 );
747 CxCore_CartToPolarTest cart2polar_test;
751 ////////// polar2cart /////////////
752 class CxCore_PolarToCartTest : public CxCore_MathTest
755 CxCore_PolarToCartTest();
757 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
758 double get_success_error_level( int test_case_idx, int i, int j );
760 void prepare_to_validation( int test_case_idx );
765 CxCore_PolarToCartTest::CxCore_PolarToCartTest()
766 : CxCore_MathTest( "math-polar2cart", "cvPolarToCart" )
769 test_array[INPUT].push(NULL);
770 test_array[OUTPUT].push(NULL);
771 test_array[REF_OUTPUT].push(NULL);
775 void CxCore_PolarToCartTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
777 CvRNG* rng = ts->get_rng();
778 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
780 use_degrees = cvTsRandInt(rng) & 1;
781 if( cvTsRandInt(rng) % 4 == 0 ) // check missing magnitude case
782 sizes[INPUT][1] = cvSize(0,0);
784 if( cvTsRandInt(rng) % 4 == 0 ) // check missing x/y cases
786 int idx = cvTsRandInt(rng) & 1;
787 sizes[OUTPUT][idx] = sizes[REF_OUTPUT][idx] = cvSize(0,0);
792 void CxCore_PolarToCartTest::run_func()
794 cvPolarToCart( test_array[INPUT][1], test_array[INPUT][0],
795 test_array[OUTPUT][0], test_array[OUTPUT][1], use_degrees );
799 double CxCore_PolarToCartTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
801 return FLT_EPSILON*100;
805 void CxCore_PolarToCartTest::prepare_to_validation( int /*test_case_idx*/ )
807 CvMat* x = test_array[REF_OUTPUT][0] ? &test_mat[REF_OUTPUT][0] : 0;
808 CvMat* y = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
809 CvMat* angle = &test_mat[INPUT][0];
810 CvMat* mag = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
811 double C = use_degrees ? CV_PI/180. : 1.;
813 int depth = CV_MAT_DEPTH(angle->type);
814 int ncols = angle->cols*CV_MAT_CN(angle->type);
817 for( i = 0; i < angle->rows; i++ )
819 uchar* x_data = x ? x->data.ptr + i*x->step : 0;
820 uchar* y_data = y ? y->data.ptr + i*y->step : 0;
821 uchar* mag_data = mag ? mag->data.ptr + i*mag->step : 0;
822 uchar* angle_data = angle->data.ptr + i*angle->step;
824 if( depth == CV_32F )
826 for( j = 0; j < ncols; j++ )
828 double a = ((float*)angle_data)[j]*C;
829 double m = mag_data ? ((float*)mag_data)[j] : 1.;
832 ((float*)x_data)[j] = (float)(m*cos(a));
834 ((float*)y_data)[j] = (float)(m*sin(a));
839 assert( depth == CV_64F );
840 for( j = 0; j < ncols; j++ )
842 double a = ((double*)angle_data)[j]*C;
843 double m = mag_data ? ((double*)mag_data)[j] : 1.;
846 ((double*)x_data)[j] = m*cos(a);
848 ((double*)y_data)[j] = m*sin(a);
854 CxCore_PolarToCartTest polar2cart_test;
856 ///////////////////////////////////////// matrix tests ////////////////////////////////////////////
858 static const int matrix_all_depths[] = { CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, -1 };
860 class CxCore_MatrixTestImpl : public CvArrTest
863 CxCore_MatrixTestImpl( const char* test_name, const char* test_funcs, int in_count, int out_count,
864 bool allow_int, bool scalar_output, int max_cn );
866 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
867 void get_timing_test_array_types_and_sizes( int test_case_idx,
868 CvSize** sizes, int** types,
869 CvSize** whole_sizes, bool* are_images );
870 double get_success_error_level( int test_case_idx, int i, int j );
877 CxCore_MatrixTestImpl::CxCore_MatrixTestImpl( const char* test_name, const char* test_funcs,
878 int in_count, int out_count,
879 bool _allow_int, bool _scalar_output, int _max_cn )
880 : CvArrTest( test_name, test_funcs, "" ),
881 allow_int(_allow_int), scalar_output(_scalar_output), max_cn(_max_cn)
884 for( i = 0; i < in_count; i++ )
885 test_array[INPUT].push(NULL);
887 for( i = 0; i < out_count; i++ )
889 test_array[OUTPUT].push(NULL);
890 test_array[REF_OUTPUT].push(NULL);
893 element_wise_relative_error = false;
895 default_timing_param_names = math_param_names;
897 size_list = (CvSize*)matrix_sizes;
899 depth_list = (int*)math_depths;
904 void CxCore_MatrixTestImpl::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
906 CvRNG* rng = ts->get_rng();
907 int depth = cvTsRandInt(rng) % (allow_int ? CV_64F+1 : 2);
908 int cn = cvTsRandInt(rng) % max_cn + 1;
912 depth += depth == CV_8S;
916 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
918 for( i = 0; i < max_arr; i++ )
920 int count = test_array[i].size();
921 int flag = (i == OUTPUT || i == REF_OUTPUT) && scalar_output;
922 int type = !flag ? CV_MAKETYPE(depth, cn) : CV_64FC1;
924 for( j = 0; j < count; j++ )
928 sizes[i][j] = cvSize( 4, 1 );
934 void CxCore_MatrixTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
935 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
937 CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx,
938 sizes, types, whole_sizes, are_images );
941 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
942 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( 4, 1 );
943 whole_sizes[OUTPUT][0] = whole_sizes[REF_OUTPUT][0] = cvSize( 4, 1 );
948 double CxCore_MatrixTestImpl::get_success_error_level( int test_case_idx, int i, int j )
950 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
951 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ?
953 double output_precision = CvArrTest::get_success_error_level( test_case_idx, i, j );
954 return MAX(input_precision, output_precision);
957 CxCore_MatrixTestImpl matrix_test( "matrix", "", 0, 0, false, false, 0 );
960 class CxCore_MatrixTest : public CxCore_MatrixTestImpl
963 CxCore_MatrixTest( const char* test_name, const char* test_funcs, int in_count, int out_count,
964 bool allow_int, bool scalar_output, int max_cn );
968 CxCore_MatrixTest::CxCore_MatrixTest( const char* test_name, const char* test_funcs,
969 int in_count, int out_count, bool _allow_int,
970 bool _scalar_output, int _max_cn )
971 : CxCore_MatrixTestImpl( test_name, test_funcs, in_count, out_count,
972 _allow_int, _scalar_output, _max_cn )
979 ///////////////// Trace /////////////////////
981 class CxCore_TraceTest : public CxCore_MatrixTest
987 void prepare_to_validation( int test_case_idx );
991 CxCore_TraceTest::CxCore_TraceTest() :
992 CxCore_MatrixTest( "matrix-trace", "cvTrace", 1, 1, true, true, 4 )
997 void CxCore_TraceTest::run_func()
999 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvTrace(test_array[INPUT][0]);
1003 void CxCore_TraceTest::prepare_to_validation( int )
1005 CvMat* mat = &test_mat[INPUT][0];
1006 int i, j, count = MIN( mat->rows, mat->cols );
1007 CvScalar trace = {{0,0,0,0}};
1009 for( i = 0; i < count; i++ )
1011 CvScalar el = cvGet2D( mat, i, i );
1012 for( j = 0; j < 4; j++ )
1013 trace.val[j] += el.val[j];
1016 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = trace;
1019 CxCore_TraceTest trace_test;
1022 ///////// dotproduct //////////
1024 class CxCore_DotProductTest : public CxCore_MatrixTest
1027 CxCore_DotProductTest();
1030 void prepare_to_validation( int test_case_idx );
1034 CxCore_DotProductTest::CxCore_DotProductTest() :
1035 CxCore_MatrixTest( "matrix-dotproduct", "cvDotProduct", 2, 1, true, true, 4 )
1037 depth_list = matrix_all_depths;
1041 void CxCore_DotProductTest::run_func()
1043 *((CvScalar*)(test_mat[OUTPUT][0].data.ptr)) =
1044 cvRealScalar(cvDotProduct( test_array[INPUT][0], test_array[INPUT][1] ));
1048 void CxCore_DotProductTest::prepare_to_validation( int )
1050 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.ptr)) =
1051 cvRealScalar(cvTsCrossCorr( &test_mat[INPUT][0], &test_mat[INPUT][1] ));
1054 CxCore_DotProductTest dotproduct_test;
1057 ///////// crossproduct //////////
1059 static const CvSize cross_product_sizes[] = {{3,1}, {-1,-1}};
1061 class CxCore_CrossProductTest : public CxCore_MatrixTest
1064 CxCore_CrossProductTest();
1066 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1068 void prepare_to_validation( int test_case_idx );
1072 CxCore_CrossProductTest::CxCore_CrossProductTest() :
1073 CxCore_MatrixTest( "matrix-crossproduct", "cvCrossProduct", 2, 1, false, false, 1 )
1075 size_list = cross_product_sizes;
1079 void CxCore_CrossProductTest::get_test_array_types_and_sizes( int /*test_case_idx*/, CvSize** sizes, int** types )
1081 CvRNG* rng = ts->get_rng();
1082 int depth = cvTsRandInt(rng) % 2 + CV_32F;
1083 int cn = cvTsRandInt(rng) & 1 ? 3 : 1, type = CV_MAKETYPE(depth, cn);
1086 types[INPUT][0] = types[INPUT][1] = types[OUTPUT][0] = types[REF_OUTPUT][0] = type;
1090 else if( cvTsRandInt(rng) & 1 )
1095 sizes[INPUT][0] = sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
1099 void CxCore_CrossProductTest::run_func()
1101 cvCrossProduct( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1105 void CxCore_CrossProductTest::prepare_to_validation( int )
1107 CvScalar a = {{0,0,0,0}}, b = {{0,0,0,0}}, c = {{0,0,0,0}};
1109 if( test_mat[INPUT][0].rows > 1 )
1111 a.val[0] = cvGetReal2D( &test_mat[INPUT][0], 0, 0 );
1112 a.val[1] = cvGetReal2D( &test_mat[INPUT][0], 1, 0 );
1113 a.val[2] = cvGetReal2D( &test_mat[INPUT][0], 2, 0 );
1115 b.val[0] = cvGetReal2D( &test_mat[INPUT][1], 0, 0 );
1116 b.val[1] = cvGetReal2D( &test_mat[INPUT][1], 1, 0 );
1117 b.val[2] = cvGetReal2D( &test_mat[INPUT][1], 2, 0 );
1119 else if( test_mat[INPUT][0].cols > 1 )
1121 a.val[0] = cvGetReal1D( &test_mat[INPUT][0], 0 );
1122 a.val[1] = cvGetReal1D( &test_mat[INPUT][0], 1 );
1123 a.val[2] = cvGetReal1D( &test_mat[INPUT][0], 2 );
1125 b.val[0] = cvGetReal1D( &test_mat[INPUT][1], 0 );
1126 b.val[1] = cvGetReal1D( &test_mat[INPUT][1], 1 );
1127 b.val[2] = cvGetReal1D( &test_mat[INPUT][1], 2 );
1131 a = cvGet1D( &test_mat[INPUT][0], 0 );
1132 b = cvGet1D( &test_mat[INPUT][1], 0 );
1135 c.val[2] = a.val[0]*b.val[1] - a.val[1]*b.val[0];
1136 c.val[1] = -a.val[0]*b.val[2] + a.val[2]*b.val[0];
1137 c.val[0] = a.val[1]*b.val[2] - a.val[2]*b.val[1];
1139 if( test_mat[REF_OUTPUT][0].rows > 1 )
1141 cvSetReal2D( &test_mat[REF_OUTPUT][0], 0, 0, c.val[0] );
1142 cvSetReal2D( &test_mat[REF_OUTPUT][0], 1, 0, c.val[1] );
1143 cvSetReal2D( &test_mat[REF_OUTPUT][0], 2, 0, c.val[2] );
1145 else if( test_mat[REF_OUTPUT][0].cols > 1 )
1147 cvSetReal1D( &test_mat[REF_OUTPUT][0], 0, c.val[0] );
1148 cvSetReal1D( &test_mat[REF_OUTPUT][0], 1, c.val[1] );
1149 cvSetReal1D( &test_mat[REF_OUTPUT][0], 2, c.val[2] );
1153 cvSet1D( &test_mat[REF_OUTPUT][0], 0, c );
1157 CxCore_CrossProductTest crossproduct_test;
1160 ///////////////// scaleadd /////////////////////
1162 class CxCore_ScaleAddTest : public CxCore_MatrixTest
1165 CxCore_ScaleAddTest();
1167 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1168 void get_timing_test_array_types_and_sizes( int test_case_idx,
1169 CvSize** sizes, int** types,
1170 CvSize** whole_sizes, bool* are_images );
1171 int prepare_test_case( int test_case_idx );
1173 void prepare_to_validation( int test_case_idx );
1177 CxCore_ScaleAddTest::CxCore_ScaleAddTest() :
1178 CxCore_MatrixTest( "matrix-scaleadd", "cvScaleAdd", 3, 1, false, false, 2 )
1180 alpha = cvScalarAll(0);
1184 void CxCore_ScaleAddTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1186 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1187 sizes[INPUT][2] = cvSize(1,1);
1191 void CxCore_ScaleAddTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1192 CvSize** sizes, int** types,
1193 CvSize** whole_sizes, bool* are_images )
1195 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1196 whole_sizes, are_images );
1197 sizes[INPUT][2] = cvSize(1,1);
1201 int CxCore_ScaleAddTest::prepare_test_case( int test_case_idx )
1203 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1205 alpha = cvGet1D( &test_mat[INPUT][2], 0 );
1210 void CxCore_ScaleAddTest::run_func()
1212 cvScaleAdd( test_array[INPUT][0], alpha, test_array[INPUT][1], test_array[OUTPUT][0] );
1216 void CxCore_ScaleAddTest::prepare_to_validation( int )
1218 int rows = test_mat[INPUT][0].rows;
1219 int type = CV_MAT_TYPE(test_mat[INPUT][0].type);
1220 int cn = CV_MAT_CN(type);
1221 int ncols = test_mat[INPUT][0].cols*cn;
1224 for( i = 0; i < rows; i++ )
1226 uchar* src1 = test_mat[INPUT][0].data.ptr + test_mat[INPUT][0].step*i;
1227 uchar* src2 = test_mat[INPUT][1].data.ptr + test_mat[INPUT][1].step*i;
1228 uchar* dst = test_mat[REF_OUTPUT][0].data.ptr + test_mat[REF_OUTPUT][0].step*i;
1233 for( j = 0; j < ncols; j++ )
1234 ((float*)dst)[j] = (float)(((float*)src1)[j]*alpha.val[0] + ((float*)src2)[j]);
1237 for( j = 0; j < ncols; j += 2 )
1239 double re = ((float*)src1)[j];
1240 double im = ((float*)src1)[j+1];
1241 ((float*)dst)[j] = (float)(re*alpha.val[0] - im*alpha.val[1] + ((float*)src2)[j]);
1242 ((float*)dst)[j+1] = (float)(re*alpha.val[1] + im*alpha.val[0] + ((float*)src2)[j+1]);
1246 for( j = 0; j < ncols; j++ )
1247 ((double*)dst)[j] = ((double*)src1)[j]*alpha.val[0] + ((double*)src2)[j];
1250 for( j = 0; j < ncols; j += 2 )
1252 double re = ((double*)src1)[j];
1253 double im = ((double*)src1)[j+1];
1254 ((double*)dst)[j] = (double)(re*alpha.val[0] - im*alpha.val[1] + ((double*)src2)[j]);
1255 ((double*)dst)[j+1] = (double)(re*alpha.val[1] + im*alpha.val[0] + ((double*)src2)[j+1]);
1264 CxCore_ScaleAddTest scaleadd_test;
1267 ///////////////// gemm /////////////////////
1269 static const char* matrix_gemm_param_names[] = { "size", "add_c", "mul_type", "depth", 0 };
1270 static const char* matrix_gemm_mul_types[] = { "AB", "AtB", "ABt", "AtBt", 0 };
1271 static const int matrix_gemm_add_c_flags[] = { 0, 1 };
1273 class CxCore_GEMMTest : public CxCore_MatrixTest
1278 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1279 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1280 void get_timing_test_array_types_and_sizes( int test_case_idx,
1281 CvSize** sizes, int** types,
1282 CvSize** whole_sizes, bool* are_images );
1283 int write_default_params( CvFileStorage* fs );
1284 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1285 int prepare_test_case( int test_case_idx );
1287 void prepare_to_validation( int test_case_idx );
1292 CxCore_GEMMTest::CxCore_GEMMTest() :
1293 CxCore_MatrixTest( "matrix-gemm", "cvGEMM", 5, 1, false, false, 2 )
1295 test_case_count = 100;
1296 default_timing_param_names = matrix_gemm_param_names;
1301 void CxCore_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1303 CvRNG* rng = ts->get_rng();
1305 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1306 sizeA = sizes[INPUT][0];
1307 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1308 sizes[INPUT][0] = sizeA;
1309 sizes[INPUT][2] = sizes[INPUT][3] = cvSize(1,1);
1310 types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK;
1312 tabc_flag = cvTsRandInt(rng) & 7;
1314 switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
1317 sizes[INPUT][1].height = sizes[INPUT][0].width;
1318 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1319 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1322 sizes[INPUT][1].width = sizes[INPUT][0].width;
1323 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1324 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1327 sizes[INPUT][1].height = sizes[INPUT][0].height;
1328 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1329 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1331 case CV_GEMM_A_T | CV_GEMM_B_T:
1332 sizes[INPUT][1].width = sizes[INPUT][0].height;
1333 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1334 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1338 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1340 if( cvTsRandInt(rng) & 1 )
1341 sizes[INPUT][4] = cvSize(0,0);
1342 else if( !(tabc_flag & CV_GEMM_C_T) )
1343 sizes[INPUT][4] = sizes[OUTPUT][0];
1346 sizes[INPUT][4].width = sizes[OUTPUT][0].height;
1347 sizes[INPUT][4].height = sizes[OUTPUT][0].width;
1352 void CxCore_GEMMTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1353 CvSize** sizes, int** types,
1354 CvSize** whole_sizes, bool* are_images )
1356 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1357 sizes, types, whole_sizes, are_images );
1358 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AB" );
1359 if( strcmp( mul_type, "AtB" ) == 0 )
1360 tabc_flag = CV_GEMM_A_T;
1361 else if( strcmp( mul_type, "ABt" ) == 0 )
1362 tabc_flag = CV_GEMM_B_T;
1363 else if( strcmp( mul_type, "AtBt" ) == 0 )
1364 tabc_flag = CV_GEMM_A_T + CV_GEMM_B_T;
1368 if( cvReadInt( find_timing_param( "add_c" ), 0 ) == 0 )
1369 sizes[INPUT][4] = cvSize(0,0);
1373 int CxCore_GEMMTest::write_default_params( CvFileStorage* fs )
1375 int code = CxCore_MatrixTest::write_default_params(fs);
1376 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1378 write_string_list( fs, "mul_type", matrix_gemm_mul_types );
1379 write_int_list( fs, "add_c", matrix_gemm_add_c_flags, CV_DIM(matrix_gemm_add_c_flags) );
1384 void CxCore_GEMMTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1386 sprintf( ptr, "%s%s,%s,",
1387 tabc_flag & CV_GEMM_A_T ? "At" : "A",
1388 tabc_flag & CV_GEMM_B_T ? "Bt" : "B",
1389 test_array[INPUT][4] ? "plusC" : "" );
1392 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1396 int CxCore_GEMMTest::prepare_test_case( int test_case_idx )
1398 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1401 alpha = cvmGet( &test_mat[INPUT][2], 0, 0 );
1402 beta = cvmGet( &test_mat[INPUT][3], 0, 0 );
1408 void CxCore_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1410 *low = cvScalarAll(-10.);
1411 *high = cvScalarAll(10.);
1415 void CxCore_GEMMTest::run_func()
1417 cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
1418 test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
1422 void CxCore_GEMMTest::prepare_to_validation( int )
1424 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][1], alpha,
1425 test_array[INPUT][4] ? &test_mat[INPUT][4] : 0,
1426 beta, &test_mat[REF_OUTPUT][0], tabc_flag );
1429 CxCore_GEMMTest gemm_test;
1432 ///////////////// multransposed /////////////////////
1434 static const char* matrix_multrans_param_names[] = { "size", "use_delta", "mul_type", "depth", 0 };
1435 static const int matrix_multrans_use_delta_flags[] = { 0, 1 };
1436 static const char* matrix_multrans_mul_types[] = { "AAt", "AtA", 0 };
1438 class CxCore_MulTransposedTest : public CxCore_MatrixTest
1441 CxCore_MulTransposedTest();
1443 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1444 void get_timing_test_array_types_and_sizes( int test_case_idx,
1445 CvSize** sizes, int** types,
1446 CvSize** whole_sizes, bool* are_images );
1447 int write_default_params( CvFileStorage* fs );
1448 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1449 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1451 void prepare_to_validation( int test_case_idx );
1456 CxCore_MulTransposedTest::CxCore_MulTransposedTest() :
1457 CxCore_MatrixTest( "matrix-multransposed", "cvMulTransposed, cvRepeat", 2, 1, false, false, 1 )
1459 test_case_count = 100;
1461 test_array[TEMP].push(NULL);
1462 default_timing_param_names = matrix_multrans_param_names;
1466 void CxCore_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1468 CvRNG* rng = ts->get_rng();
1469 int bits = cvTsRandInt(rng);
1470 int src_type = cvTsRandInt(rng) % 5;
1471 int dst_type = cvTsRandInt(rng) % 2;
1473 src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S :
1474 src_type == 3 ? CV_32F : CV_64F;
1475 dst_type = dst_type == 0 ? CV_32F : CV_64F;
1476 dst_type = MAX( dst_type, src_type );
1478 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1481 sizes[INPUT][1] = cvSize(0,0);
1484 sizes[INPUT][1] = sizes[INPUT][0];
1486 sizes[INPUT][1].height = 1;
1488 sizes[INPUT][1].width = 1;
1491 sizes[TEMP][0] = sizes[INPUT][0];
1492 types[INPUT][0] = src_type;
1493 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type;
1495 order = (bits & 8) != 0;
1496 sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ?
1497 sizes[INPUT][0].height : sizes[INPUT][0].width;
1498 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1502 void CxCore_MulTransposedTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1503 CvSize** sizes, int** types,
1504 CvSize** whole_sizes, bool* are_images )
1506 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1507 sizes, types, whole_sizes, are_images );
1508 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AAt" );
1509 order = strcmp( mul_type, "AtA" ) == 0;
1511 if( cvReadInt( find_timing_param( "use_delta" ), 0 ) == 0 )
1512 sizes[INPUT][1] = cvSize(0,0);
1516 int CxCore_MulTransposedTest::write_default_params( CvFileStorage* fs )
1518 int code = CxCore_MatrixTest::write_default_params(fs);
1519 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1521 write_string_list( fs, "mul_type", matrix_multrans_mul_types );
1522 write_int_list( fs, "use_delta", matrix_multrans_use_delta_flags,
1523 CV_DIM(matrix_multrans_use_delta_flags) );
1528 void CxCore_MulTransposedTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1530 sprintf( ptr, "%s,%s,", order == 0 ? "AAt" : "AtA", test_array[INPUT][1] ? "delta" : "" );
1533 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1537 void CxCore_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1539 *low = cvScalarAll(-10.);
1540 *high = cvScalarAll(10.);
1544 void CxCore_MulTransposedTest::run_func()
1546 cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
1547 order, test_array[INPUT][1] );
1551 void CxCore_MulTransposedTest::prepare_to_validation( int )
1553 CvMat* delta = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
1556 if( test_mat[INPUT][1].rows < test_mat[INPUT][0].rows ||
1557 test_mat[INPUT][1].cols < test_mat[INPUT][0].cols )
1559 cvRepeat( delta, &test_mat[TEMP][0] );
1560 delta = &test_mat[TEMP][0];
1562 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.), delta, cvScalarAll(-1.),
1563 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1566 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
1567 delta = &test_mat[TEMP][0];
1569 cvTsGEMM( delta, delta, 1., 0, 0, &test_mat[REF_OUTPUT][0], order == 0 ? CV_GEMM_B_T : CV_GEMM_A_T );
1572 CxCore_MulTransposedTest multransposed_test;
1575 ///////////////// Transform /////////////////////
1577 static const CvSize matrix_transform_sizes[] = {{10,10}, {100,100}, {720,480}, {-1,-1}};
1578 static const CvSize matrix_transform_whole_sizes[] = {{10,10}, {720,480}, {720,480}, {-1,-1}};
1579 static const int matrix_transform_channels[] = { 2, 3, 4, -1 };
1580 static const char* matrix_transform_param_names[] = { "size", "channels", "depth", 0 };
1582 class CxCore_TransformTest : public CxCore_MatrixTest
1585 CxCore_TransformTest();
1587 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1588 double get_success_error_level( int test_case_idx, int i, int j );
1589 void get_timing_test_array_types_and_sizes( int test_case_idx,
1590 CvSize** sizes, int** types,
1591 CvSize** whole_sizes, bool* are_images );
1592 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1594 void prepare_to_validation( int test_case_idx );
1598 CxCore_TransformTest::CxCore_TransformTest() :
1599 CxCore_MatrixTest( "matrix-transform", "cvTransform", 3, 1, true, false, 4 )
1601 default_timing_param_names = matrix_transform_param_names;
1602 cn_list = matrix_transform_channels;
1603 depth_list = matrix_all_depths;
1604 size_list = matrix_transform_sizes;
1605 whole_size_list = matrix_transform_whole_sizes;
1609 void CxCore_TransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1611 CvRNG* rng = ts->get_rng();
1612 int bits = cvTsRandInt(rng);
1613 int depth, dst_cn, mat_cols, mattype;
1614 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1616 mat_cols = CV_MAT_CN(types[INPUT][0]);
1617 depth = CV_MAT_DEPTH(types[INPUT][0]);
1618 dst_cn = cvTsRandInt(rng) % 4 + 1;
1619 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
1621 mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1622 types[INPUT][1] = mattype;
1623 types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
1627 sizes[INPUT][2] = cvSize(0,0);
1628 mat_cols += (bits & 4) != 0;
1631 sizes[INPUT][2] = cvSize(1,1);
1635 sizes[INPUT][2] = cvSize(dst_cn,1);
1637 sizes[INPUT][2] = cvSize(1,dst_cn);
1638 types[INPUT][2] &= ~CV_MAT_CN_MASK;
1641 sizes[INPUT][1] = cvSize(mat_cols,dst_cn);
1645 void CxCore_TransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1646 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1648 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1649 sizes, types, whole_sizes, are_images );
1650 int cn = CV_MAT_CN(types[INPUT][0]);
1651 sizes[INPUT][1] = cvSize(cn + (cn < 4), cn);
1652 sizes[INPUT][2] = cvSize(0,0);
1653 types[INPUT][1] = types[INPUT][2] = CV_64FC1;
1657 void CxCore_TransformTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1659 CvSize size = cvGetMatSize(&test_mat[INPUT][1]);
1660 sprintf( ptr, "matrix=%dx%d,", size.height, size.width );
1663 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1667 double CxCore_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
1669 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1670 return depth <= CV_8S ? 1 : depth <= CV_32S ? 8 :
1671 CxCore_MatrixTest::get_success_error_level( test_case_idx, i, j );
1674 void CxCore_TransformTest::run_func()
1676 cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1],
1677 test_array[INPUT][2] ? &test_mat[INPUT][2] : 0);
1681 void CxCore_TransformTest::prepare_to_validation( int )
1683 CvMat* transmat = &test_mat[INPUT][1];
1684 CvMat* shift = test_array[INPUT][2] ? &test_mat[INPUT][2] : 0;
1686 cvTsTransform( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], transmat, shift );
1689 CxCore_TransformTest transform_test;
1692 ///////////////// PerspectiveTransform /////////////////////
1694 static const int matrix_perspective_transform_channels[] = { 2, 3, -1 };
1696 class CxCore_PerspectiveTransformTest : public CxCore_MatrixTest
1699 CxCore_PerspectiveTransformTest();
1701 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1702 void get_timing_test_array_types_and_sizes( int test_case_idx,
1703 CvSize** sizes, int** types,
1704 CvSize** whole_sizes, bool* are_images );
1706 void prepare_to_validation( int test_case_idx );
1710 CxCore_PerspectiveTransformTest::CxCore_PerspectiveTransformTest() :
1711 CxCore_MatrixTest( "matrix-perspective", "cvPerspectiveTransform", 2, 1, false, false, 2 )
1713 default_timing_param_names = matrix_transform_param_names;
1714 cn_list = matrix_perspective_transform_channels;
1715 size_list = matrix_transform_sizes;
1716 whole_size_list = matrix_transform_whole_sizes;
1720 void CxCore_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1722 CvRNG* rng = ts->get_rng();
1723 int bits = cvTsRandInt(rng);
1724 int depth, cn, mattype;
1725 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1727 cn = CV_MAT_CN(types[INPUT][0]) + 1;
1728 depth = CV_MAT_DEPTH(types[INPUT][0]);
1729 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1731 mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1732 types[INPUT][1] = mattype;
1733 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1737 void CxCore_PerspectiveTransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1738 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1740 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1741 sizes, types, whole_sizes, are_images );
1742 int cn = CV_MAT_CN(types[INPUT][0]);
1743 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1744 types[INPUT][1] = CV_64FC1;
1748 void CxCore_PerspectiveTransformTest::run_func()
1750 cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1] );
1754 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
1757 int cn, depth, mat_depth;
1758 CvMat astub, bstub, *a, *b;
1759 double mat[16], *buf;
1761 a = cvGetMat( _src, &astub, 0, 0 );
1762 b = cvGetMat( _dst, &bstub, 0, 0 );
1764 cn = CV_MAT_CN(a->type);
1765 depth = CV_MAT_DEPTH(a->type);
1766 mat_depth = CV_MAT_DEPTH(transmat->type);
1767 cols = transmat->cols;
1769 // prepare cn x (cn + 1) transform matrix
1770 if( mat_depth == CV_32F )
1772 for( i = 0; i < transmat->rows; i++ )
1773 for( j = 0; j < cols; j++ )
1774 mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
1778 assert( mat_depth == CV_64F );
1779 for( i = 0; i < transmat->rows; i++ )
1780 for( j = 0; j < cols; j++ )
1781 mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
1785 cols = a->cols * cn;
1786 buf = (double*)cvStackAlloc( cols * sizeof(double) );
1788 for( i = 0; i < a->rows; i++ )
1790 uchar* src = a->data.ptr + i*a->step;
1791 uchar* dst = b->data.ptr + i*b->step;
1796 for( j = 0; j < cols; j++ )
1797 buf[j] = ((float*)src)[j];
1800 for( j = 0; j < cols; j++ )
1801 buf[j] = ((double*)src)[j];
1810 for( j = 0; j < cols; j += 2 )
1812 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2];
1813 double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5];
1814 double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8];
1821 for( j = 0; j < cols; j += 3 )
1823 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3];
1824 double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7];
1825 double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11];
1826 double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15];
1840 for( j = 0; j < cols; j++ )
1841 ((float*)dst)[j] = (float)buf[j];
1844 for( j = 0; j < cols; j++ )
1845 ((double*)dst)[j] = buf[j];
1854 void CxCore_PerspectiveTransformTest::prepare_to_validation( int )
1856 CvMat* transmat = &test_mat[INPUT][1];
1857 cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], transmat );
1860 CxCore_PerspectiveTransformTest perspective_test;
1863 ///////////////// Mahalanobis /////////////////////
1865 class CxCore_MahalanobisTest : public CxCore_MatrixTest
1868 CxCore_MahalanobisTest();
1870 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1871 void get_timing_test_array_types_and_sizes( int test_case_idx,
1872 CvSize** sizes, int** types,
1873 CvSize** whole_sizes, bool* are_images );
1874 int prepare_test_case( int test_case_idx );
1876 void prepare_to_validation( int test_case_idx );
1880 CxCore_MahalanobisTest::CxCore_MahalanobisTest() :
1881 CxCore_MatrixTest( "matrix-mahalanobis", "cvMahalanobis", 3, 1, false, true, 1 )
1883 test_case_count = 100;
1884 test_array[TEMP].push(NULL);
1885 test_array[TEMP].push(NULL);
1886 test_array[TEMP].push(NULL);
1890 void CxCore_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1892 CvRNG* rng = ts->get_rng();
1893 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1895 if( cvTsRandInt(rng) & 1 )
1896 sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
1898 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1900 sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0];
1901 sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1;
1902 sizes[TEMP][2] = sizes[INPUT][2];
1903 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
1907 void CxCore_MahalanobisTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1908 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1910 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1911 sizes, types, whole_sizes, are_images );
1912 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1916 int CxCore_MahalanobisTest::prepare_test_case( int test_case_idx )
1918 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1919 if( code > 0 && ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1921 // make sure that the inverted "covariation" matrix is symmetrix and positively defined.
1922 cvTsGEMM( &test_mat[INPUT][2], &test_mat[INPUT][2], 1., 0, 0., &test_mat[TEMP][2], CV_GEMM_B_T );
1923 cvTsCopy( &test_mat[TEMP][2], &test_mat[INPUT][2] );
1930 void CxCore_MahalanobisTest::run_func()
1932 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) =
1933 cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
1936 void CxCore_MahalanobisTest::prepare_to_validation( int )
1938 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
1939 &test_mat[INPUT][1], cvScalarAll(-1.),
1940 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1941 if( test_mat[INPUT][0].rows == 1 )
1942 cvTsGEMM( &test_mat[TEMP][0], &test_mat[INPUT][2], 1.,
1943 0, 0., &test_mat[TEMP][1], 0 );
1945 cvTsGEMM( &test_mat[INPUT][2], &test_mat[TEMP][0], 1.,
1946 0, 0., &test_mat[TEMP][1], 0 );
1948 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) =
1949 cvRealScalar(sqrt(cvTsCrossCorr(&test_mat[TEMP][0], &test_mat[TEMP][1])));
1952 CxCore_MahalanobisTest mahalanobis_test;
1955 ///////////////// covarmatrix /////////////////////
1957 class CxCore_CovarMatrixTest : public CxCore_MatrixTest
1960 CxCore_CovarMatrixTest();
1962 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1963 int prepare_test_case( int test_case_idx );
1965 void prepare_to_validation( int test_case_idx );
1966 CvTestPtrVec temp_hdrs;
1968 int flags, t_flag, len, count;
1973 CxCore_CovarMatrixTest::CxCore_CovarMatrixTest() :
1974 CxCore_MatrixTest( "matrix-covar", "cvCalcCovarMatrix", 1, 1, true, false, 1 ),
1975 flags(0), t_flag(0), are_images(false)
1977 test_case_count = 100;
1978 test_array[INPUT_OUTPUT].push(NULL);
1979 test_array[REF_INPUT_OUTPUT].push(NULL);
1980 test_array[TEMP].push(NULL);
1981 test_array[TEMP].push(NULL);
1983 support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1987 void CxCore_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1989 CvRNG* rng = ts->get_rng();
1990 int bits = cvTsRandInt(rng);
1991 int i, single_matrix;
1992 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1994 flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS );
1995 single_matrix = flags & CV_COVAR_ROWS;
1996 t_flag = (bits & 256) != 0;
1999 len = sizes[INPUT][0].width, count = sizes[INPUT][0].height;
2001 len = sizes[INPUT][0].height, count = sizes[INPUT][0].width;
2003 if( single_matrix && t_flag )
2004 flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
2006 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
2007 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
2009 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? cvSize(len,len) : cvSize(count,count);
2010 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? cvSize(len,1) : cvSize(1,len);
2011 sizes[TEMP][0] = sizes[INPUT][0];
2013 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] =
2014 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] =
2015 CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F;
2017 are_images = (bits & 1024) != 0;
2018 for( i = 0; i < (single_matrix ? 1 : count); i++ )
2019 temp_hdrs.push(NULL);
2023 int CxCore_CovarMatrixTest::prepare_test_case( int test_case_idx )
2025 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2029 int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
2030 int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
2032 hdr_data = (uchar*)cvAlloc( count*hdr_size );
2036 *((CvMat*)hdr_data) = test_mat[INPUT][0];
2038 cvGetImage( &test_mat[INPUT][0], (IplImage*)hdr_data );
2039 temp_hdrs[0] = hdr_data;
2042 for( i = 0; i < count; i++ )
2045 void* ptr = hdr_data + i*hdr_size;
2048 cvGetRow( &test_mat[INPUT][0], &part, i );
2050 cvGetCol( &test_mat[INPUT][0], &part, i );
2053 *((CvMat*)ptr) = part;
2055 cvGetImage( &part, (IplImage*)ptr );
2065 void CxCore_CovarMatrixTest::run_func()
2067 cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
2068 test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
2072 void CxCore_CovarMatrixTest::prepare_to_validation( int )
2074 CvMat* avg = &test_mat[REF_INPUT_OUTPUT][0];
2077 if( !(flags & CV_COVAR_USE_AVG) )
2082 for( i = 0; i < count; i++ )
2084 CvMat stub, *vec = 0;
2085 if( flags & CV_COVAR_ROWS )
2086 vec = cvGetRow( temp_hdrs[0], &stub, i );
2087 else if( flags & CV_COVAR_COLS )
2088 vec = cvGetCol( temp_hdrs[0], &stub, i );
2090 vec = cvGetMat( temp_hdrs[i], &stub );
2092 cvTsAdd( avg, cvScalarAll(1.), vec,
2093 cvScalarAll(1.), cvScalarAll(0.), avg, 0 );
2096 cvTsAdd( avg, cvScalarAll(1./count), 0,
2097 cvScalarAll(0.), cvScalarAll(0.), avg, 0 );
2100 if( flags & CV_COVAR_SCALE )
2105 cvRepeat( avg, &test_mat[TEMP][0] );
2106 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
2107 &test_mat[TEMP][0], cvScalarAll(-1.),
2108 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
2110 cvTsGEMM( &test_mat[TEMP][0], &test_mat[TEMP][0],
2111 scale, 0, 0., &test_mat[REF_OUTPUT][0],
2112 t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ?
2113 CV_GEMM_A_T : CV_GEMM_B_T );
2115 cvFree( &hdr_data );
2119 CxCore_CovarMatrixTest covarmatrix_test;
2122 static void cvTsFloodWithZeros( CvMat* mat, CvRNG* rng )
2124 int k, total = mat->rows*mat->cols;
2125 int zero_total = cvTsRandInt(rng) % total;
2126 assert( CV_MAT_TYPE(mat->type) == CV_32FC1 ||
2127 CV_MAT_TYPE(mat->type) == CV_64FC1 );
2129 for( k = 0; k < zero_total; k++ )
2131 int i = cvTsRandInt(rng) % mat->rows;
2132 int j = cvTsRandInt(rng) % mat->cols;
2133 uchar* row = mat->data.ptr + mat->step*i;
2135 if( CV_MAT_DEPTH(mat->type) == CV_32FC1 )
2136 ((float*)row)[j] = 0.f;
2138 ((double*)row)[j] = 0.;
2143 ///////////////// determinant /////////////////////
2145 class CxCore_DetTest : public CxCore_MatrixTest
2150 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2151 double get_success_error_level( int test_case_idx, int i, int j );
2152 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2153 int prepare_test_case( int test_case_idx );
2155 void prepare_to_validation( int test_case_idx );
2159 CxCore_DetTest::CxCore_DetTest() :
2160 CxCore_MatrixTest( "matrix-det", "cvDet", 1, 1, false, true, 1 )
2162 test_case_count = 100;
2163 max_log_array_size = 7;
2164 test_array[TEMP].push(NULL);
2168 void CxCore_DetTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2170 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2172 sizes[INPUT][0].width = sizes[INPUT][0].height = sizes[INPUT][0].height;
2173 sizes[TEMP][0] = sizes[INPUT][0];
2174 types[TEMP][0] = CV_64FC1;
2178 void CxCore_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2180 *low = cvScalarAll(-2.);
2181 *high = cvScalarAll(2.);
2185 double CxCore_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2187 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
2191 int CxCore_DetTest::prepare_test_case( int test_case_idx )
2193 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2195 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2201 void CxCore_DetTest::run_func()
2203 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvRealScalar(cvDet(test_array[INPUT][0]));
2207 // LU method that chooses the optimal in a column pivot element
2208 static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 )
2210 int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double);
2211 int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0;
2212 int x_step = x ? x->step/sizeof(double) : 0;
2213 double *a0 = a->data.db, *b0 = b ? b->data.db : 0;
2214 double *x0 = x ? x->data.db : 0;
2216 assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
2217 (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
2219 for( i = 0; i < Nm; i++ )
2221 double max_val = fabs(a0[i*step + i]);
2222 double *a1, *a2, *b1 = 0, *b2 = 0;
2225 for( j = i+1; j < N; j++ )
2227 t = fabs(a0[j*step + i]);
2237 for( j = i; j < N1; j++ )
2238 CV_SWAP( a0[i*step + j], a0[k*step + j], t );
2240 for( j = 0; j < M; j++ )
2241 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
2257 for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
2260 for( k = i+1; k < N1; k++ )
2263 for( k = 0; k < M; k++ )
2274 for( i = N-1; i >= 0; i-- )
2276 double* a1 = a0 + i*step;
2277 double* b1 = b0 + i*b_step;
2278 for( j = 0; j < M; j++ )
2281 for( k = i+1; k < N1; k++ )
2282 t -= a1[k]*x0[k*x_step + j];
2283 x0[i*x_step + j] = t/a1[i];
2294 void CxCore_DetTest::prepare_to_validation( int )
2296 if( !CV_ARE_TYPES_EQ( &test_mat[INPUT][0], &test_mat[TEMP][0] ))
2297 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
2299 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][0], 0 );
2301 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = cvRealScalar(cvTsLU(&test_mat[TEMP][0], 0, 0));
2304 CxCore_DetTest det_test;
2308 ///////////////// invert /////////////////////
2310 static const char* matrix_solve_invert_param_names[] = { "size", "method", "depth", 0 };
2311 static const char* matrix_solve_invert_methods[] = { "LU", "SVD", 0 };
2313 class CxCore_InvertTest : public CxCore_MatrixTest
2316 CxCore_InvertTest();
2318 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2319 void get_timing_test_array_types_and_sizes( int test_case_idx,
2320 CvSize** sizes, int** types,
2321 CvSize** whole_sizes, bool* are_images );
2322 int write_default_params( CvFileStorage* fs );
2323 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2324 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2325 double get_success_error_level( int test_case_idx, int i, int j );
2326 int prepare_test_case( int test_case_idx );
2328 void prepare_to_validation( int test_case_idx );
2334 CxCore_InvertTest::CxCore_InvertTest() :
2335 CxCore_MatrixTest( "matrix-invert", "cvInvert, cvSVD, cvSVBkSb", 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
2337 test_case_count = 100;
2338 max_log_array_size = 7;
2339 test_array[TEMP].push(NULL);
2340 test_array[TEMP].push(NULL);
2342 default_timing_param_names = matrix_solve_invert_param_names;
2346 void CxCore_InvertTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2348 CvRNG* rng = ts->get_rng();
2349 int bits = cvTsRandInt(rng);
2350 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2351 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2353 if( (bits & 3) == 0 )
2358 sizes[INPUT][0] = cvSize(min_size, min_size);
2360 method = CV_SVD_SYM;
2366 sizes[INPUT][0] = cvSize(min_size, min_size);
2369 sizes[TEMP][0].width = sizes[INPUT][0].height;
2370 sizes[TEMP][0].height = sizes[INPUT][0].width;
2371 sizes[TEMP][1] = sizes[INPUT][0];
2372 types[TEMP][0] = types[INPUT][0];
2373 types[TEMP][1] = CV_64FC1;
2374 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(min_size, min_size);
2378 void CxCore_InvertTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2379 CvSize** sizes, int** types,
2380 CvSize** whole_sizes, bool* are_images )
2382 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2383 sizes, types, whole_sizes, are_images );
2384 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2385 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2389 int CxCore_InvertTest::write_default_params( CvFileStorage* fs )
2391 int code = CxCore_MatrixTest::write_default_params(fs);
2392 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2394 write_string_list( fs, "method", matrix_solve_invert_methods );
2399 void CxCore_InvertTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2401 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2404 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2408 double CxCore_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
2410 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-7;
2413 int CxCore_InvertTest::prepare_test_case( int test_case_idx )
2415 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2418 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2420 if( method == CV_SVD_SYM )
2422 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][0], 1.,
2423 0, 0., &test_mat[TEMP][0], CV_GEMM_B_T );
2424 cvTsCopy( &test_mat[TEMP][0], &test_mat[INPUT][0] );
2433 void CxCore_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2435 *low = cvScalarAll(-2.);
2436 *high = cvScalarAll(2.);
2440 void CxCore_InvertTest::run_func()
2442 result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
2446 static double cvTsSVDet( CvMat* mat )
2448 int type = CV_MAT_TYPE(mat->type);
2449 int i, nm = MIN( mat->rows, mat->cols );
2450 CvMat* w = cvCreateMat( nm, 1, type );
2453 cvSVD( mat, w, 0, 0, 0 );
2455 if( type == CV_32FC1 )
2457 for( i = 0; i < nm; i++ )
2458 det *= w->data.fl[i];
2462 for( i = 0; i < nm; i++ )
2463 det *= w->data.db[i];
2470 void CxCore_InvertTest::prepare_to_validation( int )
2472 CvMat* input = &test_mat[INPUT][0];
2473 double det = method != CV_LU ? cvTsSVDet( input ) : 0;
2474 double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*100;
2476 if( CV_MAT_TYPE(input->type) == CV_32FC1 )
2477 cvTsConvert( input, &test_mat[TEMP][1] );
2479 cvTsCopy( input, &test_mat[TEMP][1], 0 );
2481 if( method == CV_LU && result == 0 || method != CV_LU &&
2482 det < threshold || result < threshold )
2484 cvTsZero( &test_mat[OUTPUT][0] );
2485 cvTsZero( &test_mat[REF_OUTPUT][0] );
2486 //cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(fabs(det)>1e-3),
2487 // &test_mat[REF_OUTPUT][0], 0 );
2491 if( input->rows >= input->cols )
2492 cvTsGEMM( &test_mat[TEMP][0], input, 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2494 cvTsGEMM( input, &test_mat[TEMP][0], 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2496 cvTsSetIdentity( &test_mat[REF_OUTPUT][0], cvScalarAll(1.) );
2499 CxCore_InvertTest invert_test;
2502 ///////////////// solve /////////////////////
2504 class CxCore_SolveTest : public CxCore_MatrixTest
2509 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2510 void get_timing_test_array_types_and_sizes( int test_case_idx,
2511 CvSize** sizes, int** types,
2512 CvSize** whole_sizes, bool* are_images );
2513 int write_default_params( CvFileStorage* fs );
2514 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2515 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2516 double get_success_error_level( int test_case_idx, int i, int j );
2517 int prepare_test_case( int test_case_idx );
2519 void prepare_to_validation( int test_case_idx );
2525 CxCore_SolveTest::CxCore_SolveTest() :
2526 CxCore_MatrixTest( "matrix-solve", "cvSolve, cvSVD, cvSVBkSb", 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
2528 test_case_count = 100;
2529 max_log_array_size = 7;
2530 test_array[TEMP].push(NULL);
2531 test_array[TEMP].push(NULL);
2533 default_timing_param_names = matrix_solve_invert_param_names;
2537 void CxCore_SolveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2539 CvRNG* rng = ts->get_rng();
2540 int bits = cvTsRandInt(rng);
2541 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2542 CvSize in_sz = sizes[INPUT][0];
2543 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2544 sizes[INPUT][0] = in_sz;
2545 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2547 if( (bits & 3) == 0 )
2552 sizes[INPUT][0] = cvSize(min_size, min_size);
2554 method = CV_SVD_SYM;*/
2560 sizes[INPUT][0] = cvSize(min_size, min_size);
2563 sizes[INPUT][1].height = sizes[INPUT][0].height;
2564 sizes[TEMP][0].width = sizes[INPUT][1].width;
2565 sizes[TEMP][0].height = sizes[INPUT][0].width;
2566 sizes[TEMP][1] = sizes[INPUT][0];
2567 types[TEMP][0] = types[INPUT][0];
2568 types[TEMP][1] = CV_64FC1;
2569 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][1].width, min_size);
2572 void CxCore_SolveTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2573 CvSize** sizes, int** types,
2574 CvSize** whole_sizes, bool* are_images )
2576 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2577 sizes, types, whole_sizes, are_images );
2578 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2579 sizes[INPUT][1].width = sizes[TEMP][0].width = sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = 1;
2580 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2584 int CxCore_SolveTest::write_default_params( CvFileStorage* fs )
2586 int code = CxCore_MatrixTest::write_default_params(fs);
2587 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2589 write_string_list( fs, "method", matrix_solve_invert_methods );
2594 void CxCore_SolveTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2596 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2599 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2603 int CxCore_SolveTest::prepare_test_case( int test_case_idx )
2605 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2607 /*if( method == CV_SVD_SYM )
2609 cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1.,
2610 0, 0., test_array[TEMP][0], CV_GEMM_B_T );
2611 cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] );
2618 void CxCore_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2620 *low = cvScalarAll(-2.);
2621 *high = cvScalarAll(2.);
2625 double CxCore_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
2627 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 3e-2 : 1e-8;
2631 void CxCore_SolveTest::run_func()
2633 result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
2636 void CxCore_SolveTest::prepare_to_validation( int )
2638 //int rank = test_mat[REF_OUTPUT][0].rows;
2641 if( method == CV_LU && result == 0 )
2643 if( CV_MAT_TYPE(test_mat[INPUT][0].type) == CV_32FC1 )
2644 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][1] );
2646 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][1], 0 );
2648 cvTsZero( &test_mat[OUTPUT][0] );
2649 double det = cvTsLU( &test_mat[TEMP][1], 0, 0 );
2650 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(det != 0),
2651 &test_mat[REF_OUTPUT][0], 0 );
2655 dst = test_mat[INPUT][0].rows <= test_mat[INPUT][0].cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
2657 cvTsGEMM( &test_mat[INPUT][0], &test_mat[TEMP][0], 1., &test_mat[INPUT][1], -1., dst, 0 );
2658 if( dst != &test_mat[OUTPUT][0] )
2659 cvTsGEMM( &test_mat[INPUT][0], dst, 1., 0, 0., &test_mat[OUTPUT][0], CV_GEMM_A_T );
2660 cvTsZero( &test_mat[REF_OUTPUT][0] );
2663 CxCore_SolveTest solve_test;
2666 ///////////////// SVD /////////////////////
2668 static const char* matrix_svd_param_names[] = { "size", "output", "depth", 0 };
2669 static const char* matrix_svd_output_modes[] = { "w", "all", 0 };
2671 class CxCore_SVDTest : public CxCore_MatrixTest
2676 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2677 void get_timing_test_array_types_and_sizes( int test_case_idx,
2678 CvSize** sizes, int** types,
2679 CvSize** whole_sizes, bool* are_images );
2680 int write_default_params( CvFileStorage* fs );
2681 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2682 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2683 int prepare_test_case( int test_case_idx );
2685 void prepare_to_validation( int test_case_idx );
2687 bool have_u, have_v, symmetric, compact, vector_w;
2691 CxCore_SVDTest::CxCore_SVDTest() :
2692 CxCore_MatrixTest( "matrix-svd", "cvSVD", 1, 4, false, false, 1 ),
2693 flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false)
2695 test_case_count = 100;
2696 test_array[TEMP].push(NULL);
2697 test_array[TEMP].push(NULL);
2698 test_array[TEMP].push(NULL);
2699 test_array[TEMP].push(NULL);
2701 default_timing_param_names = matrix_svd_param_names;
2705 void CxCore_SVDTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2707 CvRNG* rng = ts->get_rng();
2708 int bits = cvTsRandInt(rng);
2709 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2710 int min_size, i, m, n;
2712 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2714 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
2715 have_u = (bits & 8) != 0;
2716 have_v = (bits & 16) != 0;
2717 symmetric = (bits & 32) != 0;
2718 compact = (bits & 64) != 0;
2719 vector_w = (bits & 128) != 0;
2722 sizes[INPUT][0] = cvSize(min_size, min_size);
2724 m = sizes[INPUT][0].height;
2725 n = sizes[INPUT][0].width;
2728 sizes[TEMP][0] = cvSize(min_size, min_size);
2730 sizes[TEMP][0] = sizes[INPUT][0];
2731 sizes[TEMP][3] = cvSize(0,0);
2735 sizes[TEMP][3] = sizes[TEMP][0];
2737 sizes[TEMP][0] = cvSize(1, min_size);
2739 sizes[TEMP][0] = cvSize(min_size, 1);
2744 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
2746 if( flags & CV_SVD_U_T )
2747 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
2750 sizes[TEMP][1] = cvSize(0,0);
2754 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
2756 if( !(flags & CV_SVD_V_T) )
2757 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
2760 sizes[TEMP][2] = cvSize(0,0);
2762 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0];
2763 types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0];
2764 types[OUTPUT][3] = CV_8UC1;
2765 sizes[OUTPUT][0] = !have_u || !have_v ? cvSize(0,0) : sizes[INPUT][0];
2766 sizes[OUTPUT][1] = !have_u ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(m,m);
2767 sizes[OUTPUT][2] = !have_v ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(n,n);
2768 sizes[OUTPUT][3] = cvSize(min_size,1);
2770 for( i = 0; i < 4; i++ )
2772 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
2773 types[REF_OUTPUT][i] = types[OUTPUT][i];
2778 void CxCore_SVDTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2779 CvSize** sizes, int** types,
2780 CvSize** whole_sizes, bool* are_images )
2782 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2783 sizes, types, whole_sizes, are_images );
2784 const char* output_str = cvReadString( find_timing_param("output"), "all" );
2785 bool need_all = strcmp( output_str, "all" ) == 0;
2786 int i, count = test_array[OUTPUT].size();
2790 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
2793 have_u = have_v = true;
2797 have_u = have_v = false;
2798 sizes[TEMP][1] = sizes[TEMP][2] = cvSize(0,0);
2801 flags = CV_SVD_U_T + CV_SVD_V_T;
2802 for( i = 0; i < count; i++ )
2803 sizes[OUTPUT][i] = sizes[REF_OUTPUT][i] = cvSize(0,0);
2804 sizes[OUTPUT][0] = cvSize(1,1);
2808 int CxCore_SVDTest::write_default_params( CvFileStorage* fs )
2810 int code = CxCore_MatrixTest::write_default_params(fs);
2811 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2813 write_string_list( fs, "output", matrix_svd_output_modes );
2818 void CxCore_SVDTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2820 sprintf( ptr, "%s,", have_u ? "all" : "w" );
2823 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2827 int CxCore_SVDTest::prepare_test_case( int test_case_idx )
2829 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2832 CvMat* input = &test_mat[INPUT][0];
2833 cvTsFloodWithZeros( input, ts->get_rng() );
2835 if( symmetric && (have_u || have_v) )
2837 CvMat* temp = &test_mat[TEMP][have_u ? 1 : 2];
2838 cvTsGEMM( input, input, 1.,
2839 0, 0., temp, CV_GEMM_B_T );
2840 cvTsCopy( temp, input );
2843 if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
2844 cvTsCopy( input, &test_mat[OUTPUT][0] );
2851 void CxCore_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2853 *low = cvScalarAll(-2.);
2854 *high = cvScalarAll(2.);
2858 void CxCore_SVDTest::run_func()
2860 CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
2862 src = test_array[INPUT][0];
2863 cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
2867 void CxCore_SVDTest::prepare_to_validation( int )
2869 CvMat* input = &test_mat[INPUT][0];
2870 int m = input->rows, n = input->cols, min_size = MIN(m, n);
2871 CvMat *src, *dst, *w;
2872 double prev = 0, threshold = CV_MAT_TYPE(input->type) == CV_32FC1 ? FLT_EPSILON : DBL_EPSILON;
2877 src = &test_mat[TEMP][1];
2878 dst = &test_mat[OUTPUT][1];
2879 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2880 cvTsSetIdentity( &test_mat[REF_OUTPUT][1], cvScalarAll(1.) );
2885 src = &test_mat[TEMP][2];
2886 dst = &test_mat[OUTPUT][2];
2887 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2888 cvTsSetIdentity( &test_mat[REF_OUTPUT][2], cvScalarAll(1.) );
2891 w = &test_mat[TEMP][0];
2892 step = w->rows == 1 ? 1 : w->step/CV_ELEM_SIZE(w->type);
2893 for( i = 0; i < min_size; i++ )
2895 double norm = 0, aii;
2897 if( w->rows > 1 && w->cols > 1 )
2900 cvGetRow( w, &row, i );
2901 norm = cvNorm( &row, 0, CV_L1 );
2903 row_ptr = row.data.ptr;
2907 row_ptr = w->data.ptr;
2911 aii = CV_MAT_TYPE(w->type) == CV_32FC1 ?
2912 (double)((float*)row_ptr)[j] : ((double*)row_ptr)[j];
2913 if( w->rows == 1 || w->cols == 1 )
2915 norm = fabs(norm - aii);
2916 test_mat[OUTPUT][3].data.ptr[i] = aii >= 0 && norm < threshold && (i == 0 || aii <= prev);
2920 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.),
2921 cvScalarAll(1.), &test_mat[REF_OUTPUT][3], 0 );
2923 if( have_u && have_v )
2927 cvTsZero( &test_mat[TEMP][3] );
2928 for( i = 0; i < min_size; i++ )
2930 double val = cvGetReal1D( w, i );
2931 cvSetReal2D( &test_mat[TEMP][3], i, i, val );
2933 w = &test_mat[TEMP][3];
2938 cvTsGEMM( &test_mat[TEMP][1], w, 1., 0, 0., &test_mat[REF_OUTPUT][0],
2939 flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
2940 cvTsGEMM( &test_mat[REF_OUTPUT][0], &test_mat[TEMP][2], 1., 0, 0.,
2941 &test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
2945 cvTsGEMM( w, &test_mat[TEMP][2], 1., 0, 0., &test_mat[REF_OUTPUT][0],
2946 flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
2947 cvTsGEMM( &test_mat[TEMP][1], &test_mat[REF_OUTPUT][0], 1., 0, 0.,
2948 &test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
2951 cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], 0 );
2956 CxCore_SVDTest svd_test;
2959 ///////////////// SVBkSb /////////////////////
2961 class CxCore_SVBkSbTest : public CxCore_MatrixTest
2964 CxCore_SVBkSbTest();
2966 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2967 void get_timing_test_array_types_and_sizes( int test_case_idx,
2968 CvSize** sizes, int** types,
2969 CvSize** whole_sizes, bool* are_images );
2970 double get_success_error_level( int test_case_idx, int i, int j );
2971 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2972 int prepare_test_case( int test_case_idx );
2974 void prepare_to_validation( int test_case_idx );
2976 bool have_b, symmetric, compact, vector_w;
2980 CxCore_SVBkSbTest::CxCore_SVBkSbTest() :
2981 CxCore_MatrixTest( "matrix-svbksb", "cvSVBkSb", 2, 1, false, false, 1 ),
2982 flags(0), have_b(false), symmetric(false), compact(false), vector_w(false)
2984 test_case_count = 100;
2985 test_array[TEMP].push(NULL);
2986 test_array[TEMP].push(NULL);
2987 test_array[TEMP].push(NULL);
2991 void CxCore_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2993 CvRNG* rng = ts->get_rng();
2994 int bits = cvTsRandInt(rng);
2995 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2996 int min_size, i, m, n;
2999 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
3001 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
3002 have_b = (bits & 16) != 0;
3003 symmetric = (bits & 32) != 0;
3004 compact = (bits & 64) != 0;
3005 vector_w = (bits & 128) != 0;
3008 sizes[INPUT][0] = cvSize(min_size, min_size);
3010 m = sizes[INPUT][0].height;
3011 n = sizes[INPUT][0].width;
3013 sizes[INPUT][1] = cvSize(0,0);
3014 b_size = cvSize(m,m);
3017 sizes[INPUT][1].height = sizes[INPUT][0].height;
3018 sizes[INPUT][1].width = cvTsRandInt(rng) % 100 + 1;
3019 b_size = sizes[INPUT][1];
3023 sizes[TEMP][0] = cvSize(min_size, min_size);
3025 sizes[TEMP][0] = sizes[INPUT][0];
3030 sizes[TEMP][0] = cvSize(1, min_size);
3032 sizes[TEMP][0] = cvSize(min_size, 1);
3035 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
3037 if( flags & CV_SVD_U_T )
3038 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
3040 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
3042 if( !(flags & CV_SVD_V_T) )
3043 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
3045 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
3046 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0];
3047 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( b_size.width, n );
3051 void CxCore_SVBkSbTest::get_timing_test_array_types_and_sizes( int test_case_idx,
3052 CvSize** sizes, int** types,
3053 CvSize** whole_sizes, bool* are_images )
3055 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
3056 sizes, types, whole_sizes, are_images );
3060 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
3061 sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1,sizes[INPUT][0].height);
3062 flags = CV_SVD_U_T + CV_SVD_V_T;
3066 int CxCore_SVBkSbTest::prepare_test_case( int test_case_idx )
3068 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
3071 CvMat* input = &test_mat[INPUT][0];
3072 cvTsFloodWithZeros( input, ts->get_rng() );
3076 CvMat* temp = &test_mat[TEMP][1];
3077 cvTsGEMM( input, input, 1., 0, 0., temp, CV_GEMM_B_T );
3078 cvTsCopy( temp, input );
3081 cvSVD( input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
3088 void CxCore_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
3090 *low = cvScalarAll(-2.);
3091 *high = cvScalarAll(2.);
3095 double CxCore_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
3097 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
3101 void CxCore_SVBkSbTest::run_func()
3103 cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
3104 test_array[INPUT][1], test_array[OUTPUT][0], flags );
3108 void CxCore_SVBkSbTest::prepare_to_validation( int )
3110 CvMat* input = &test_mat[INPUT][0];
3111 int i, m = input->rows, n = input->cols, min_size = MIN(m, n), nb;
3112 bool is_float = CV_MAT_DEPTH(input->type) == CV_32F;
3113 CvSize w_size = compact ? cvSize(min_size,min_size) : cvSize(m,n);
3114 CvMat* w = &test_mat[TEMP][0];
3115 CvMat* wdb = cvCreateMat( w_size.height, w_size.width, CV_64FC1 );
3116 // use exactly the same threshold as in icvSVD... ,
3117 // so the changes in the library and here should be synchronized.
3118 double threshold = cvSum( w ).val[0]*2*(is_float ? FLT_EPSILON : DBL_EPSILON);
3119 CvMat *u, *v, *b, *t0, *t1;
3122 for( i = 0; i < min_size; i++ )
3124 double wii = vector_w ? cvGetReal1D(w,i) : cvGetReal2D(w,i,i);
3125 cvSetReal2D( wdb, i, i, wii > threshold ? 1./wii : 0. );
3128 u = &test_mat[TEMP][1];
3129 v = &test_mat[TEMP][2];
3133 if( test_array[INPUT][1] )
3135 b = &test_mat[INPUT][1];
3141 u = cvCreateMat( u->rows, u->cols, CV_64F );
3142 cvTsConvert( &test_mat[TEMP][1], u );
3145 b = cvCreateMat( b->rows, b->cols, CV_64F );
3146 cvTsConvert( &test_mat[INPUT][1], b );
3150 t0 = cvCreateMat( wdb->cols, nb, CV_64F );
3153 cvTsGEMM( u, b, 1., 0, 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 );
3154 else if( flags & CV_SVD_U_T )
3157 cvTsTranspose( u, t0 );
3166 v = cvCreateMat( v->rows, v->cols, CV_64F );
3173 cvTsConvert( &test_mat[TEMP][2], v );
3176 t1 = cvCreateMat( wdb->rows, nb, CV_64F );
3177 cvTsGEMM( wdb, t0, 1, 0, 0, t1, 0 );
3179 if( !is_float || !symmetric )
3181 cvReleaseMat( &t0 );
3182 t0 = !is_float ? &test_mat[REF_OUTPUT][0] : cvCreateMat( test_mat[REF_OUTPUT][0].rows, nb, CV_64F );
3185 cvTsGEMM( v, t1, 1, 0, 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 );
3186 cvReleaseMat( &t1 );
3188 if( t0 != &test_mat[REF_OUTPUT][0] )
3190 cvTsConvert( t0, &test_mat[REF_OUTPUT][0] );
3191 cvReleaseMat( &t0 );
3194 if( v != &test_mat[TEMP][2] )
3197 cvReleaseMat( &wdb );
3201 CxCore_SVBkSbTest svbksb_test;
3204 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),