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, 4 )
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);
1188 types[INPUT][2] &= CV_MAT_DEPTH_MASK;
1192 void CxCore_ScaleAddTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1193 CvSize** sizes, int** types,
1194 CvSize** whole_sizes, bool* are_images )
1196 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1197 whole_sizes, are_images );
1198 sizes[INPUT][2] = cvSize(1,1);
1199 types[INPUT][2] &= CV_MAT_DEPTH_MASK;
1203 int CxCore_ScaleAddTest::prepare_test_case( int test_case_idx )
1205 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1207 alpha = cvGet1D( &test_mat[INPUT][2], 0 );
1212 void CxCore_ScaleAddTest::run_func()
1214 cvScaleAdd( test_array[INPUT][0], alpha, test_array[INPUT][1], test_array[OUTPUT][0] );
1218 void CxCore_ScaleAddTest::prepare_to_validation( int )
1220 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(alpha.val[0]),
1221 &test_mat[INPUT][1], cvScalarAll(1.),
1222 cvScalarAll(0.), &test_mat[REF_OUTPUT][0], 0 );
1225 CxCore_ScaleAddTest scaleadd_test;
1228 ///////////////// gemm /////////////////////
1230 static const char* matrix_gemm_param_names[] = { "size", "add_c", "mul_type", "depth", 0 };
1231 static const char* matrix_gemm_mul_types[] = { "AB", "AtB", "ABt", "AtBt", 0 };
1232 static const int matrix_gemm_add_c_flags[] = { 0, 1 };
1234 class CxCore_GEMMTest : public CxCore_MatrixTest
1239 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1240 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1241 void get_timing_test_array_types_and_sizes( int test_case_idx,
1242 CvSize** sizes, int** types,
1243 CvSize** whole_sizes, bool* are_images );
1244 int write_default_params( CvFileStorage* fs );
1245 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1246 int prepare_test_case( int test_case_idx );
1248 void prepare_to_validation( int test_case_idx );
1253 CxCore_GEMMTest::CxCore_GEMMTest() :
1254 CxCore_MatrixTest( "matrix-gemm", "cvGEMM", 5, 1, false, false, 2 )
1256 test_case_count = 100;
1257 default_timing_param_names = matrix_gemm_param_names;
1262 void CxCore_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1264 CvRNG* rng = ts->get_rng();
1266 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1267 sizeA = sizes[INPUT][0];
1268 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1269 sizes[INPUT][0] = sizeA;
1270 sizes[INPUT][2] = sizes[INPUT][3] = cvSize(1,1);
1271 types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK;
1273 tabc_flag = cvTsRandInt(rng) & 7;
1275 switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
1278 sizes[INPUT][1].height = sizes[INPUT][0].width;
1279 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1280 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1283 sizes[INPUT][1].width = sizes[INPUT][0].width;
1284 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1285 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1288 sizes[INPUT][1].height = sizes[INPUT][0].height;
1289 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1290 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1292 case CV_GEMM_A_T | CV_GEMM_B_T:
1293 sizes[INPUT][1].width = sizes[INPUT][0].height;
1294 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1295 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1299 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1301 if( cvTsRandInt(rng) & 1 )
1302 sizes[INPUT][4] = cvSize(0,0);
1303 else if( !(tabc_flag & CV_GEMM_C_T) )
1304 sizes[INPUT][4] = sizes[OUTPUT][0];
1307 sizes[INPUT][4].width = sizes[OUTPUT][0].height;
1308 sizes[INPUT][4].height = sizes[OUTPUT][0].width;
1313 void CxCore_GEMMTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1314 CvSize** sizes, int** types,
1315 CvSize** whole_sizes, bool* are_images )
1317 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1318 sizes, types, whole_sizes, are_images );
1319 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AB" );
1320 if( strcmp( mul_type, "AtB" ) == 0 )
1321 tabc_flag = CV_GEMM_A_T;
1322 else if( strcmp( mul_type, "ABt" ) == 0 )
1323 tabc_flag = CV_GEMM_B_T;
1324 else if( strcmp( mul_type, "AtBt" ) == 0 )
1325 tabc_flag = CV_GEMM_A_T + CV_GEMM_B_T;
1329 if( cvReadInt( find_timing_param( "add_c" ), 0 ) == 0 )
1330 sizes[INPUT][4] = cvSize(0,0);
1334 int CxCore_GEMMTest::write_default_params( CvFileStorage* fs )
1336 int code = CxCore_MatrixTest::write_default_params(fs);
1337 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1339 write_string_list( fs, "mul_type", matrix_gemm_mul_types );
1340 write_int_list( fs, "add_c", matrix_gemm_add_c_flags, CV_DIM(matrix_gemm_add_c_flags) );
1345 void CxCore_GEMMTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1347 sprintf( ptr, "%s%s,%s,",
1348 tabc_flag & CV_GEMM_A_T ? "At" : "A",
1349 tabc_flag & CV_GEMM_B_T ? "Bt" : "B",
1350 test_array[INPUT][4] ? "plusC" : "" );
1353 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1357 int CxCore_GEMMTest::prepare_test_case( int test_case_idx )
1359 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1362 alpha = cvmGet( &test_mat[INPUT][2], 0, 0 );
1363 beta = cvmGet( &test_mat[INPUT][3], 0, 0 );
1369 void CxCore_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1371 *low = cvScalarAll(-10.);
1372 *high = cvScalarAll(10.);
1376 void CxCore_GEMMTest::run_func()
1378 cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
1379 test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
1383 void CxCore_GEMMTest::prepare_to_validation( int )
1385 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][1], alpha,
1386 test_array[INPUT][4] ? &test_mat[INPUT][4] : 0,
1387 beta, &test_mat[REF_OUTPUT][0], tabc_flag );
1390 CxCore_GEMMTest gemm_test;
1393 ///////////////// multransposed /////////////////////
1395 static const char* matrix_multrans_param_names[] = { "size", "use_delta", "mul_type", "depth", 0 };
1396 static const int matrix_multrans_use_delta_flags[] = { 0, 1 };
1397 static const char* matrix_multrans_mul_types[] = { "AAt", "AtA", 0 };
1399 class CxCore_MulTransposedTest : public CxCore_MatrixTest
1402 CxCore_MulTransposedTest();
1404 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1405 void get_timing_test_array_types_and_sizes( int test_case_idx,
1406 CvSize** sizes, int** types,
1407 CvSize** whole_sizes, bool* are_images );
1408 int write_default_params( CvFileStorage* fs );
1409 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1410 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1412 void prepare_to_validation( int test_case_idx );
1417 CxCore_MulTransposedTest::CxCore_MulTransposedTest() :
1418 CxCore_MatrixTest( "matrix-multransposed", "cvMulTransposed, cvRepeat", 2, 1, false, false, 1 )
1420 test_case_count = 100;
1422 test_array[TEMP].push(NULL);
1423 default_timing_param_names = matrix_multrans_param_names;
1427 void CxCore_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1429 CvRNG* rng = ts->get_rng();
1430 int bits = cvTsRandInt(rng);
1431 int src_type = cvTsRandInt(rng) % 5;
1432 int dst_type = cvTsRandInt(rng) % 2;
1434 src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S :
1435 src_type == 3 ? CV_32F : CV_64F;
1436 dst_type = dst_type == 0 ? CV_32F : CV_64F;
1437 dst_type = MAX( dst_type, src_type );
1439 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1442 sizes[INPUT][1] = cvSize(0,0);
1445 sizes[INPUT][1] = sizes[INPUT][0];
1447 sizes[INPUT][1].height = 1;
1449 sizes[INPUT][1].width = 1;
1452 sizes[TEMP][0] = sizes[INPUT][0];
1453 types[INPUT][0] = src_type;
1454 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type;
1456 order = (bits & 8) != 0;
1457 sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ?
1458 sizes[INPUT][0].height : sizes[INPUT][0].width;
1459 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1463 void CxCore_MulTransposedTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1464 CvSize** sizes, int** types,
1465 CvSize** whole_sizes, bool* are_images )
1467 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1468 sizes, types, whole_sizes, are_images );
1469 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AAt" );
1470 order = strcmp( mul_type, "AtA" ) == 0;
1472 if( cvReadInt( find_timing_param( "use_delta" ), 0 ) == 0 )
1473 sizes[INPUT][1] = cvSize(0,0);
1477 int CxCore_MulTransposedTest::write_default_params( CvFileStorage* fs )
1479 int code = CxCore_MatrixTest::write_default_params(fs);
1480 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1482 write_string_list( fs, "mul_type", matrix_multrans_mul_types );
1483 write_int_list( fs, "use_delta", matrix_multrans_use_delta_flags,
1484 CV_DIM(matrix_multrans_use_delta_flags) );
1489 void CxCore_MulTransposedTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1491 sprintf( ptr, "%s,%s,", order == 0 ? "AAt" : "AtA", test_array[INPUT][1] ? "delta" : "" );
1494 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1498 void CxCore_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1500 *low = cvScalarAll(-10.);
1501 *high = cvScalarAll(10.);
1505 void CxCore_MulTransposedTest::run_func()
1507 cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
1508 order, test_array[INPUT][1] );
1512 void CxCore_MulTransposedTest::prepare_to_validation( int )
1514 CvMat* delta = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
1517 if( test_mat[INPUT][1].rows < test_mat[INPUT][0].rows ||
1518 test_mat[INPUT][1].cols < test_mat[INPUT][0].cols )
1520 cvRepeat( delta, &test_mat[TEMP][0] );
1521 delta = &test_mat[TEMP][0];
1523 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.), delta, cvScalarAll(-1.),
1524 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1527 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
1528 delta = &test_mat[TEMP][0];
1530 cvTsGEMM( delta, delta, 1., 0, 0, &test_mat[REF_OUTPUT][0], order == 0 ? CV_GEMM_B_T : CV_GEMM_A_T );
1533 CxCore_MulTransposedTest multransposed_test;
1536 ///////////////// Transform /////////////////////
1538 static const CvSize matrix_transform_sizes[] = {{10,10}, {100,100}, {720,480}, {-1,-1}};
1539 static const CvSize matrix_transform_whole_sizes[] = {{10,10}, {720,480}, {720,480}, {-1,-1}};
1540 static const int matrix_transform_channels[] = { 2, 3, 4, -1 };
1541 static const char* matrix_transform_param_names[] = { "size", "channels", "depth", 0 };
1543 class CxCore_TransformTest : public CxCore_MatrixTest
1546 CxCore_TransformTest();
1548 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1549 double get_success_error_level( int test_case_idx, int i, int j );
1550 void get_timing_test_array_types_and_sizes( int test_case_idx,
1551 CvSize** sizes, int** types,
1552 CvSize** whole_sizes, bool* are_images );
1553 int prepare_test_case( int test_case_idx );
1554 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1556 void prepare_to_validation( int test_case_idx );
1562 CxCore_TransformTest::CxCore_TransformTest() :
1563 CxCore_MatrixTest( "matrix-transform", "cvTransform", 3, 1, true, false, 4 )
1565 default_timing_param_names = matrix_transform_param_names;
1566 cn_list = matrix_transform_channels;
1567 depth_list = matrix_all_depths;
1568 size_list = matrix_transform_sizes;
1569 whole_size_list = matrix_transform_whole_sizes;
1573 void CxCore_TransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1575 CvRNG* rng = ts->get_rng();
1576 int bits = cvTsRandInt(rng);
1577 int depth, dst_cn, mat_cols, mattype;
1578 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1580 mat_cols = CV_MAT_CN(types[INPUT][0]);
1581 depth = CV_MAT_DEPTH(types[INPUT][0]);
1582 dst_cn = cvTsRandInt(rng) % 4 + 1;
1583 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
1585 mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1586 types[INPUT][1] = mattype;
1587 types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
1589 scale = 1./((cvTsRandInt(rng)%4)*50+1);
1593 sizes[INPUT][2] = cvSize(0,0);
1594 mat_cols += (bits & 4) != 0;
1597 sizes[INPUT][2] = cvSize(1,1);
1601 sizes[INPUT][2] = cvSize(dst_cn,1);
1603 sizes[INPUT][2] = cvSize(1,dst_cn);
1604 types[INPUT][2] &= ~CV_MAT_CN_MASK;
1607 sizes[INPUT][1] = cvSize(mat_cols,dst_cn);
1611 void CxCore_TransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1612 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1614 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1615 sizes, types, whole_sizes, are_images );
1616 int cn = CV_MAT_CN(types[INPUT][0]);
1617 sizes[INPUT][1] = cvSize(cn + (cn < 4), cn);
1618 sizes[INPUT][2] = cvSize(0,0);
1619 types[INPUT][1] = types[INPUT][2] = CV_64FC1;
1623 int CxCore_TransformTest::prepare_test_case( int test_case_idx )
1625 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1627 cvTsAdd(&test_mat[INPUT][1], cvScalarAll(scale), &test_mat[INPUT][1],
1628 cvScalarAll(0), cvScalarAll(0), &test_mat[INPUT][1], 0 );
1632 void CxCore_TransformTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1634 CvSize size = cvGetMatSize(&test_mat[INPUT][1]);
1635 sprintf( ptr, "matrix=%dx%d,", size.height, size.width );
1638 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1642 double CxCore_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
1644 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1645 return depth <= CV_8S ? 1 : depth <= CV_32S ? 8 :
1646 CxCore_MatrixTest::get_success_error_level( test_case_idx, i, j );
1649 void CxCore_TransformTest::run_func()
1651 cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1],
1652 test_array[INPUT][2] ? &test_mat[INPUT][2] : 0);
1656 void CxCore_TransformTest::prepare_to_validation( int )
1658 CvMat* transmat = &test_mat[INPUT][1];
1659 CvMat* shift = test_array[INPUT][2] ? &test_mat[INPUT][2] : 0;
1661 cvTsTransform( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], transmat, shift );
1664 CxCore_TransformTest transform_test;
1667 ///////////////// PerspectiveTransform /////////////////////
1669 static const int matrix_perspective_transform_channels[] = { 2, 3, -1 };
1671 class CxCore_PerspectiveTransformTest : public CxCore_MatrixTest
1674 CxCore_PerspectiveTransformTest();
1676 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1677 void get_timing_test_array_types_and_sizes( int test_case_idx,
1678 CvSize** sizes, int** types,
1679 CvSize** whole_sizes, bool* are_images );
1681 void prepare_to_validation( int test_case_idx );
1685 CxCore_PerspectiveTransformTest::CxCore_PerspectiveTransformTest() :
1686 CxCore_MatrixTest( "matrix-perspective", "cvPerspectiveTransform", 2, 1, false, false, 2 )
1688 default_timing_param_names = matrix_transform_param_names;
1689 cn_list = matrix_perspective_transform_channels;
1690 size_list = matrix_transform_sizes;
1691 whole_size_list = matrix_transform_whole_sizes;
1695 void CxCore_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1697 CvRNG* rng = ts->get_rng();
1698 int bits = cvTsRandInt(rng);
1699 int depth, cn, mattype;
1700 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1702 cn = CV_MAT_CN(types[INPUT][0]) + 1;
1703 depth = CV_MAT_DEPTH(types[INPUT][0]);
1704 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1706 mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1707 types[INPUT][1] = mattype;
1708 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1712 void CxCore_PerspectiveTransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1713 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1715 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1716 sizes, types, whole_sizes, are_images );
1717 int cn = CV_MAT_CN(types[INPUT][0]);
1718 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1719 types[INPUT][1] = CV_64FC1;
1723 void CxCore_PerspectiveTransformTest::run_func()
1725 cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1] );
1729 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
1732 int cn, depth, mat_depth;
1733 CvMat astub, bstub, *a, *b;
1734 double mat[16], *buf;
1736 a = cvGetMat( _src, &astub, 0, 0 );
1737 b = cvGetMat( _dst, &bstub, 0, 0 );
1739 cn = CV_MAT_CN(a->type);
1740 depth = CV_MAT_DEPTH(a->type);
1741 mat_depth = CV_MAT_DEPTH(transmat->type);
1742 cols = transmat->cols;
1744 // prepare cn x (cn + 1) transform matrix
1745 if( mat_depth == CV_32F )
1747 for( i = 0; i < transmat->rows; i++ )
1748 for( j = 0; j < cols; j++ )
1749 mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
1753 assert( mat_depth == CV_64F );
1754 for( i = 0; i < transmat->rows; i++ )
1755 for( j = 0; j < cols; j++ )
1756 mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
1760 cols = a->cols * cn;
1761 buf = (double*)cvStackAlloc( cols * sizeof(double) );
1763 for( i = 0; i < a->rows; i++ )
1765 uchar* src = a->data.ptr + i*a->step;
1766 uchar* dst = b->data.ptr + i*b->step;
1771 for( j = 0; j < cols; j++ )
1772 buf[j] = ((float*)src)[j];
1775 for( j = 0; j < cols; j++ )
1776 buf[j] = ((double*)src)[j];
1785 for( j = 0; j < cols; j += 2 )
1787 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2];
1788 double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5];
1789 double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8];
1796 for( j = 0; j < cols; j += 3 )
1798 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3];
1799 double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7];
1800 double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11];
1801 double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15];
1815 for( j = 0; j < cols; j++ )
1816 ((float*)dst)[j] = (float)buf[j];
1819 for( j = 0; j < cols; j++ )
1820 ((double*)dst)[j] = buf[j];
1829 void CxCore_PerspectiveTransformTest::prepare_to_validation( int )
1831 CvMat* transmat = &test_mat[INPUT][1];
1832 cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], transmat );
1835 CxCore_PerspectiveTransformTest perspective_test;
1838 ///////////////// Mahalanobis /////////////////////
1840 class CxCore_MahalanobisTest : public CxCore_MatrixTest
1843 CxCore_MahalanobisTest();
1845 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1846 void get_timing_test_array_types_and_sizes( int test_case_idx,
1847 CvSize** sizes, int** types,
1848 CvSize** whole_sizes, bool* are_images );
1849 int prepare_test_case( int test_case_idx );
1851 void prepare_to_validation( int test_case_idx );
1855 CxCore_MahalanobisTest::CxCore_MahalanobisTest() :
1856 CxCore_MatrixTest( "matrix-mahalanobis", "cvMahalanobis", 3, 1, false, true, 1 )
1858 test_case_count = 100;
1859 test_array[TEMP].push(NULL);
1860 test_array[TEMP].push(NULL);
1861 test_array[TEMP].push(NULL);
1865 void CxCore_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1867 CvRNG* rng = ts->get_rng();
1868 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1870 if( cvTsRandInt(rng) & 1 )
1871 sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
1873 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1875 sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0];
1876 sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1;
1877 sizes[TEMP][2] = sizes[INPUT][2];
1878 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
1882 void CxCore_MahalanobisTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1883 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1885 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1886 sizes, types, whole_sizes, are_images );
1887 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1891 int CxCore_MahalanobisTest::prepare_test_case( int test_case_idx )
1893 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1894 if( code > 0 && ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1896 // make sure that the inverted "covariation" matrix is symmetrix and positively defined.
1897 cvTsGEMM( &test_mat[INPUT][2], &test_mat[INPUT][2], 1., 0, 0., &test_mat[TEMP][2], CV_GEMM_B_T );
1898 cvTsCopy( &test_mat[TEMP][2], &test_mat[INPUT][2] );
1905 void CxCore_MahalanobisTest::run_func()
1907 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) =
1908 cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
1911 void CxCore_MahalanobisTest::prepare_to_validation( int )
1913 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
1914 &test_mat[INPUT][1], cvScalarAll(-1.),
1915 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1916 if( test_mat[INPUT][0].rows == 1 )
1917 cvTsGEMM( &test_mat[TEMP][0], &test_mat[INPUT][2], 1.,
1918 0, 0., &test_mat[TEMP][1], 0 );
1920 cvTsGEMM( &test_mat[INPUT][2], &test_mat[TEMP][0], 1.,
1921 0, 0., &test_mat[TEMP][1], 0 );
1923 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) =
1924 cvRealScalar(sqrt(cvTsCrossCorr(&test_mat[TEMP][0], &test_mat[TEMP][1])));
1927 CxCore_MahalanobisTest mahalanobis_test;
1930 ///////////////// covarmatrix /////////////////////
1932 class CxCore_CovarMatrixTest : public CxCore_MatrixTest
1935 CxCore_CovarMatrixTest();
1937 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1938 int prepare_test_case( int test_case_idx );
1940 void prepare_to_validation( int test_case_idx );
1941 CvTestPtrVec temp_hdrs;
1943 int flags, t_flag, len, count;
1948 CxCore_CovarMatrixTest::CxCore_CovarMatrixTest() :
1949 CxCore_MatrixTest( "matrix-covar", "cvCalcCovarMatrix", 1, 1, true, false, 1 ),
1950 flags(0), t_flag(0), are_images(false)
1952 test_case_count = 100;
1953 test_array[INPUT_OUTPUT].push(NULL);
1954 test_array[REF_INPUT_OUTPUT].push(NULL);
1955 test_array[TEMP].push(NULL);
1956 test_array[TEMP].push(NULL);
1958 support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1962 void CxCore_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1964 CvRNG* rng = ts->get_rng();
1965 int bits = cvTsRandInt(rng);
1966 int i, single_matrix;
1967 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1969 flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS );
1970 single_matrix = flags & CV_COVAR_ROWS;
1971 t_flag = (bits & 256) != 0;
1973 const int min_count = 2;
1977 len = sizes[INPUT][0].width;
1978 count = sizes[INPUT][0].height;
1979 count = MAX(count, min_count);
1980 sizes[INPUT][0] = cvSize(len, count);
1984 len = sizes[INPUT][0].height;
1985 count = sizes[INPUT][0].width;
1986 count = MAX(count, min_count);
1987 sizes[INPUT][0] = cvSize(count, len);
1990 if( single_matrix && t_flag )
1991 flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
1993 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
1994 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
1996 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? cvSize(len,len) : cvSize(count,count);
1997 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? cvSize(len,1) : cvSize(1,len);
1998 sizes[TEMP][0] = sizes[INPUT][0];
2000 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] =
2001 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] =
2002 CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F;
2004 are_images = (bits & 1024) != 0;
2005 for( i = 0; i < (single_matrix ? 1 : count); i++ )
2006 temp_hdrs.push(NULL);
2010 int CxCore_CovarMatrixTest::prepare_test_case( int test_case_idx )
2012 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2016 int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
2017 int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
2019 hdr_data = (uchar*)cvAlloc( count*hdr_size );
2023 *((CvMat*)hdr_data) = test_mat[INPUT][0];
2025 cvGetImage( &test_mat[INPUT][0], (IplImage*)hdr_data );
2026 temp_hdrs[0] = hdr_data;
2029 for( i = 0; i < count; i++ )
2032 void* ptr = hdr_data + i*hdr_size;
2035 cvGetRow( &test_mat[INPUT][0], &part, i );
2037 cvGetCol( &test_mat[INPUT][0], &part, i );
2040 *((CvMat*)ptr) = part;
2042 cvGetImage( &part, (IplImage*)ptr );
2052 void CxCore_CovarMatrixTest::run_func()
2054 cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
2055 test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
2059 void CxCore_CovarMatrixTest::prepare_to_validation( int )
2061 CvMat* avg = &test_mat[REF_INPUT_OUTPUT][0];
2064 if( !(flags & CV_COVAR_USE_AVG) )
2069 for( i = 0; i < count; i++ )
2071 CvMat stub, *vec = 0;
2072 if( flags & CV_COVAR_ROWS )
2073 vec = cvGetRow( temp_hdrs[0], &stub, i );
2074 else if( flags & CV_COVAR_COLS )
2075 vec = cvGetCol( temp_hdrs[0], &stub, i );
2077 vec = cvGetMat( temp_hdrs[i], &stub );
2079 cvTsAdd( avg, cvScalarAll(1.), vec,
2080 cvScalarAll(1.), cvScalarAll(0.), avg, 0 );
2083 cvTsAdd( avg, cvScalarAll(1./count), 0,
2084 cvScalarAll(0.), cvScalarAll(0.), avg, 0 );
2087 if( flags & CV_COVAR_SCALE )
2092 cvRepeat( avg, &test_mat[TEMP][0] );
2093 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
2094 &test_mat[TEMP][0], cvScalarAll(-1.),
2095 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
2097 cvTsGEMM( &test_mat[TEMP][0], &test_mat[TEMP][0],
2098 scale, 0, 0., &test_mat[REF_OUTPUT][0],
2099 t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ?
2100 CV_GEMM_A_T : CV_GEMM_B_T );
2102 cvFree( &hdr_data );
2106 CxCore_CovarMatrixTest covarmatrix_test;
2109 static void cvTsFloodWithZeros( CvMat* mat, CvRNG* rng )
2111 int k, total = mat->rows*mat->cols;
2112 int zero_total = cvTsRandInt(rng) % total;
2113 assert( CV_MAT_TYPE(mat->type) == CV_32FC1 ||
2114 CV_MAT_TYPE(mat->type) == CV_64FC1 );
2116 for( k = 0; k < zero_total; k++ )
2118 int i = cvTsRandInt(rng) % mat->rows;
2119 int j = cvTsRandInt(rng) % mat->cols;
2120 uchar* row = mat->data.ptr + mat->step*i;
2122 if( CV_MAT_DEPTH(mat->type) == CV_32FC1 )
2123 ((float*)row)[j] = 0.f;
2125 ((double*)row)[j] = 0.;
2130 ///////////////// determinant /////////////////////
2132 class CxCore_DetTest : public CxCore_MatrixTest
2137 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2138 double get_success_error_level( int test_case_idx, int i, int j );
2139 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2140 int prepare_test_case( int test_case_idx );
2142 void prepare_to_validation( int test_case_idx );
2146 CxCore_DetTest::CxCore_DetTest() :
2147 CxCore_MatrixTest( "matrix-det", "cvDet", 1, 1, false, true, 1 )
2149 test_case_count = 100;
2150 max_log_array_size = 7;
2151 test_array[TEMP].push(NULL);
2155 void CxCore_DetTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2157 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2159 sizes[INPUT][0].width = sizes[INPUT][0].height = sizes[INPUT][0].height;
2160 sizes[TEMP][0] = sizes[INPUT][0];
2161 types[TEMP][0] = CV_64FC1;
2165 void CxCore_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2167 *low = cvScalarAll(-2.);
2168 *high = cvScalarAll(2.);
2172 double CxCore_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2174 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
2178 int CxCore_DetTest::prepare_test_case( int test_case_idx )
2180 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2182 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2188 void CxCore_DetTest::run_func()
2190 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvRealScalar(cvDet(test_array[INPUT][0]));
2194 // LU method that chooses the optimal in a column pivot element
2195 static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 )
2197 int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double);
2198 int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0;
2199 int x_step = x ? x->step/sizeof(double) : 0;
2200 double *a0 = a->data.db, *b0 = b ? b->data.db : 0;
2201 double *x0 = x ? x->data.db : 0;
2203 assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
2204 (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
2206 for( i = 0; i < Nm; i++ )
2208 double max_val = fabs(a0[i*step + i]);
2209 double *a1, *a2, *b1 = 0, *b2 = 0;
2212 for( j = i+1; j < N; j++ )
2214 t = fabs(a0[j*step + i]);
2224 for( j = i; j < N1; j++ )
2225 CV_SWAP( a0[i*step + j], a0[k*step + j], t );
2227 for( j = 0; j < M; j++ )
2228 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
2244 for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
2247 for( k = i+1; k < N1; k++ )
2250 for( k = 0; k < M; k++ )
2261 for( i = N-1; i >= 0; i-- )
2263 double* a1 = a0 + i*step;
2264 double* b1 = b0 + i*b_step;
2265 for( j = 0; j < M; j++ )
2268 for( k = i+1; k < N1; k++ )
2269 t -= a1[k]*x0[k*x_step + j];
2270 x0[i*x_step + j] = t/a1[i];
2281 void CxCore_DetTest::prepare_to_validation( int )
2283 if( !CV_ARE_TYPES_EQ( &test_mat[INPUT][0], &test_mat[TEMP][0] ))
2284 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
2286 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][0], 0 );
2288 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = cvRealScalar(cvTsLU(&test_mat[TEMP][0], 0, 0));
2291 CxCore_DetTest det_test;
2295 ///////////////// invert /////////////////////
2297 static const char* matrix_solve_invert_param_names[] = { "size", "method", "depth", 0 };
2298 static const char* matrix_solve_invert_methods[] = { "LU", "SVD", 0 };
2300 class CxCore_InvertTest : public CxCore_MatrixTest
2303 CxCore_InvertTest();
2305 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2306 void get_timing_test_array_types_and_sizes( int test_case_idx,
2307 CvSize** sizes, int** types,
2308 CvSize** whole_sizes, bool* are_images );
2309 int write_default_params( CvFileStorage* fs );
2310 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2311 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2312 double get_success_error_level( int test_case_idx, int i, int j );
2313 int prepare_test_case( int test_case_idx );
2315 void prepare_to_validation( int test_case_idx );
2321 CxCore_InvertTest::CxCore_InvertTest() :
2322 CxCore_MatrixTest( "matrix-invert", "cvInvert, cvSVD, cvSVBkSb", 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
2324 test_case_count = 100;
2325 max_log_array_size = 7;
2326 test_array[TEMP].push(NULL);
2327 test_array[TEMP].push(NULL);
2329 default_timing_param_names = matrix_solve_invert_param_names;
2333 void CxCore_InvertTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2335 CvRNG* rng = ts->get_rng();
2336 int bits = cvTsRandInt(rng);
2337 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2338 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2340 if( (bits & 3) == 0 )
2345 sizes[INPUT][0] = cvSize(min_size, min_size);
2347 method = CV_SVD_SYM;
2353 sizes[INPUT][0] = cvSize(min_size, min_size);
2356 sizes[TEMP][0].width = sizes[INPUT][0].height;
2357 sizes[TEMP][0].height = sizes[INPUT][0].width;
2358 sizes[TEMP][1] = sizes[INPUT][0];
2359 types[TEMP][0] = types[INPUT][0];
2360 types[TEMP][1] = CV_64FC1;
2361 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(min_size, min_size);
2365 void CxCore_InvertTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2366 CvSize** sizes, int** types,
2367 CvSize** whole_sizes, bool* are_images )
2369 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2370 sizes, types, whole_sizes, are_images );
2371 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2372 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2376 int CxCore_InvertTest::write_default_params( CvFileStorage* fs )
2378 int code = CxCore_MatrixTest::write_default_params(fs);
2379 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2381 write_string_list( fs, "method", matrix_solve_invert_methods );
2386 void CxCore_InvertTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2388 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2391 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2395 double CxCore_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
2397 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-7;
2400 int CxCore_InvertTest::prepare_test_case( int test_case_idx )
2402 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2405 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2407 if( method == CV_SVD_SYM )
2409 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][0], 1.,
2410 0, 0., &test_mat[TEMP][0], CV_GEMM_B_T );
2411 cvTsCopy( &test_mat[TEMP][0], &test_mat[INPUT][0] );
2420 void CxCore_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2422 *low = cvScalarAll(-2.);
2423 *high = cvScalarAll(2.);
2427 void CxCore_InvertTest::run_func()
2429 result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
2433 static double cvTsSVDet( CvMat* mat )
2435 int type = CV_MAT_TYPE(mat->type);
2436 int i, nm = MIN( mat->rows, mat->cols );
2437 CvMat* w = cvCreateMat( nm, 1, type );
2440 cvSVD( mat, w, 0, 0, 0 );
2442 if( type == CV_32FC1 )
2444 for( i = 0; i < nm; i++ )
2445 det *= w->data.fl[i];
2449 for( i = 0; i < nm; i++ )
2450 det *= w->data.db[i];
2457 void CxCore_InvertTest::prepare_to_validation( int )
2459 CvMat* input = &test_mat[INPUT][0];
2460 double det = cvTsSVDet( input );
2461 double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*500;
2463 if( CV_MAT_TYPE(input->type) == CV_32FC1 )
2464 cvTsConvert( input, &test_mat[TEMP][1] );
2466 cvTsCopy( input, &test_mat[TEMP][1], 0 );
2468 if( (method == CV_LU && result == 0) ||
2469 (det < threshold || result < threshold) )
2471 cvTsZero( &test_mat[OUTPUT][0] );
2472 cvTsZero( &test_mat[REF_OUTPUT][0] );
2473 //cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(fabs(det)>1e-3),
2474 // &test_mat[REF_OUTPUT][0], 0 );
2478 if( input->rows >= input->cols )
2479 cvTsGEMM( &test_mat[TEMP][0], input, 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2481 cvTsGEMM( input, &test_mat[TEMP][0], 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2483 cvTsSetIdentity( &test_mat[REF_OUTPUT][0], cvScalarAll(1.) );
2486 CxCore_InvertTest invert_test;
2489 ///////////////// solve /////////////////////
2491 class CxCore_SolveTest : public CxCore_MatrixTest
2496 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2497 void get_timing_test_array_types_and_sizes( int test_case_idx,
2498 CvSize** sizes, int** types,
2499 CvSize** whole_sizes, bool* are_images );
2500 int write_default_params( CvFileStorage* fs );
2501 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2502 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2503 double get_success_error_level( int test_case_idx, int i, int j );
2504 int prepare_test_case( int test_case_idx );
2506 void prepare_to_validation( int test_case_idx );
2512 CxCore_SolveTest::CxCore_SolveTest() :
2513 CxCore_MatrixTest( "matrix-solve", "cvSolve, cvSVD, cvSVBkSb", 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
2515 test_case_count = 100;
2516 max_log_array_size = 7;
2517 test_array[TEMP].push(NULL);
2518 test_array[TEMP].push(NULL);
2520 default_timing_param_names = matrix_solve_invert_param_names;
2524 void CxCore_SolveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2526 CvRNG* rng = ts->get_rng();
2527 int bits = cvTsRandInt(rng);
2528 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2529 CvSize in_sz = sizes[INPUT][0];
2530 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2531 sizes[INPUT][0] = in_sz;
2532 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2534 if( (bits & 3) == 0 )
2539 sizes[INPUT][0] = cvSize(min_size, min_size);
2541 method = CV_SVD_SYM;*/
2547 sizes[INPUT][0] = cvSize(min_size, min_size);
2550 sizes[INPUT][1].height = sizes[INPUT][0].height;
2551 sizes[TEMP][0].width = sizes[INPUT][1].width;
2552 sizes[TEMP][0].height = sizes[INPUT][0].width;
2553 sizes[TEMP][1] = sizes[INPUT][0];
2554 types[TEMP][0] = types[INPUT][0];
2555 types[TEMP][1] = CV_64FC1;
2556 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][1].width, min_size);
2559 void CxCore_SolveTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2560 CvSize** sizes, int** types,
2561 CvSize** whole_sizes, bool* are_images )
2563 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2564 sizes, types, whole_sizes, are_images );
2565 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2566 sizes[INPUT][1].width = sizes[TEMP][0].width = sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = 1;
2567 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2571 int CxCore_SolveTest::write_default_params( CvFileStorage* fs )
2573 int code = CxCore_MatrixTest::write_default_params(fs);
2574 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2576 write_string_list( fs, "method", matrix_solve_invert_methods );
2581 void CxCore_SolveTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2583 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2586 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2590 int CxCore_SolveTest::prepare_test_case( int test_case_idx )
2592 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2594 /*if( method == CV_SVD_SYM )
2596 cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1.,
2597 0, 0., test_array[TEMP][0], CV_GEMM_B_T );
2598 cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] );
2605 void CxCore_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2607 *low = cvScalarAll(-2.);
2608 *high = cvScalarAll(2.);
2612 double CxCore_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
2614 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 3e-2 : 1e-8;
2618 void CxCore_SolveTest::run_func()
2620 result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
2623 void CxCore_SolveTest::prepare_to_validation( int )
2625 //int rank = test_mat[REF_OUTPUT][0].rows;
2628 if( method == CV_LU && result == 0 )
2630 if( CV_MAT_TYPE(test_mat[INPUT][0].type) == CV_32FC1 )
2631 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][1] );
2633 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][1], 0 );
2635 cvTsZero( &test_mat[OUTPUT][0] );
2636 double det = cvTsLU( &test_mat[TEMP][1], 0, 0 );
2637 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(det != 0),
2638 &test_mat[REF_OUTPUT][0], 0 );
2642 dst = test_mat[INPUT][0].rows <= test_mat[INPUT][0].cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
2644 cvTsGEMM( &test_mat[INPUT][0], &test_mat[TEMP][0], 1., &test_mat[INPUT][1], -1., dst, 0 );
2645 if( dst != &test_mat[OUTPUT][0] )
2646 cvTsGEMM( &test_mat[INPUT][0], dst, 1., 0, 0., &test_mat[OUTPUT][0], CV_GEMM_A_T );
2647 cvTsZero( &test_mat[REF_OUTPUT][0] );
2650 CxCore_SolveTest solve_test;
2653 ///////////////// SVD /////////////////////
2655 static const char* matrix_svd_param_names[] = { "size", "output", "depth", 0 };
2656 static const char* matrix_svd_output_modes[] = { "w", "all", 0 };
2658 class CxCore_SVDTest : public CxCore_MatrixTest
2663 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2664 void get_timing_test_array_types_and_sizes( int test_case_idx,
2665 CvSize** sizes, int** types,
2666 CvSize** whole_sizes, bool* are_images );
2667 double get_success_error_level( int test_case_idx, int i, int j );
2668 int write_default_params( CvFileStorage* fs );
2669 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2670 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2671 int prepare_test_case( int test_case_idx );
2673 void prepare_to_validation( int test_case_idx );
2675 bool have_u, have_v, symmetric, compact, vector_w;
2679 CxCore_SVDTest::CxCore_SVDTest() :
2680 CxCore_MatrixTest( "matrix-svd", "cvSVD", 1, 4, false, false, 1 ),
2681 flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false)
2683 test_case_count = 100;
2684 test_array[TEMP].push(NULL);
2685 test_array[TEMP].push(NULL);
2686 test_array[TEMP].push(NULL);
2687 test_array[TEMP].push(NULL);
2689 default_timing_param_names = matrix_svd_param_names;
2693 void CxCore_SVDTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2695 CvRNG* rng = ts->get_rng();
2696 int bits = cvTsRandInt(rng);
2697 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2698 int min_size, i, m, n;
2700 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2702 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
2703 have_u = (bits & 8) != 0;
2704 have_v = (bits & 16) != 0;
2705 symmetric = (bits & 32) != 0;
2706 compact = (bits & 64) != 0;
2707 vector_w = (bits & 128) != 0;
2710 sizes[INPUT][0] = cvSize(min_size, min_size);
2712 m = sizes[INPUT][0].height;
2713 n = sizes[INPUT][0].width;
2716 sizes[TEMP][0] = cvSize(min_size, min_size);
2718 sizes[TEMP][0] = sizes[INPUT][0];
2719 sizes[TEMP][3] = cvSize(0,0);
2723 sizes[TEMP][3] = sizes[TEMP][0];
2725 sizes[TEMP][0] = cvSize(1, min_size);
2727 sizes[TEMP][0] = cvSize(min_size, 1);
2732 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
2734 if( flags & CV_SVD_U_T )
2735 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
2738 sizes[TEMP][1] = cvSize(0,0);
2742 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
2744 if( !(flags & CV_SVD_V_T) )
2745 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
2748 sizes[TEMP][2] = cvSize(0,0);
2750 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0];
2751 types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0];
2752 types[OUTPUT][3] = CV_8UC1;
2753 sizes[OUTPUT][0] = !have_u || !have_v ? cvSize(0,0) : sizes[INPUT][0];
2754 sizes[OUTPUT][1] = !have_u ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(m,m);
2755 sizes[OUTPUT][2] = !have_v ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(n,n);
2756 sizes[OUTPUT][3] = cvSize(min_size,1);
2758 for( i = 0; i < 4; i++ )
2760 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
2761 types[REF_OUTPUT][i] = types[OUTPUT][i];
2766 void CxCore_SVDTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2767 CvSize** sizes, int** types,
2768 CvSize** whole_sizes, bool* are_images )
2770 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2771 sizes, types, whole_sizes, are_images );
2772 const char* output_str = cvReadString( find_timing_param("output"), "all" );
2773 bool need_all = strcmp( output_str, "all" ) == 0;
2774 int i, count = test_array[OUTPUT].size();
2778 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
2781 have_u = have_v = true;
2785 have_u = have_v = false;
2786 sizes[TEMP][1] = sizes[TEMP][2] = cvSize(0,0);
2789 flags = CV_SVD_U_T + CV_SVD_V_T;
2790 for( i = 0; i < count; i++ )
2791 sizes[OUTPUT][i] = sizes[REF_OUTPUT][i] = cvSize(0,0);
2792 sizes[OUTPUT][0] = cvSize(1,1);
2796 int CxCore_SVDTest::write_default_params( CvFileStorage* fs )
2798 int code = CxCore_MatrixTest::write_default_params(fs);
2799 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2801 write_string_list( fs, "output", matrix_svd_output_modes );
2806 void CxCore_SVDTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2808 sprintf( ptr, "%s,", have_u ? "all" : "w" );
2811 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2815 int CxCore_SVDTest::prepare_test_case( int test_case_idx )
2817 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2820 CvMat* input = &test_mat[INPUT][0];
2821 cvTsFloodWithZeros( input, ts->get_rng() );
2823 if( symmetric && (have_u || have_v) )
2825 CvMat* temp = &test_mat[TEMP][have_u ? 1 : 2];
2826 cvTsGEMM( input, input, 1.,
2827 0, 0., temp, CV_GEMM_B_T );
2828 cvTsCopy( temp, input );
2831 if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
2832 cvTsCopy( input, &test_mat[OUTPUT][0] );
2839 void CxCore_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2841 *low = cvScalarAll(-2.);
2842 *high = cvScalarAll(2.);
2845 double CxCore_SVDTest::get_success_error_level( int test_case_idx, int i, int j )
2847 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
2848 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ?
2850 double output_precision = CvArrTest::get_success_error_level( test_case_idx, i, j );
2851 return MAX(input_precision, output_precision);
2854 void CxCore_SVDTest::run_func()
2856 CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
2858 src = test_array[INPUT][0];
2859 cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
2863 void CxCore_SVDTest::prepare_to_validation( int )
2865 CvMat* input = &test_mat[INPUT][0];
2866 int m = input->rows, n = input->cols, min_size = MIN(m, n);
2867 CvMat *src, *dst, *w;
2868 double prev = 0, threshold = CV_MAT_TYPE(input->type) == CV_32FC1 ? FLT_EPSILON : DBL_EPSILON;
2873 src = &test_mat[TEMP][1];
2874 dst = &test_mat[OUTPUT][1];
2875 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2876 cvTsSetIdentity( &test_mat[REF_OUTPUT][1], cvScalarAll(1.) );
2881 src = &test_mat[TEMP][2];
2882 dst = &test_mat[OUTPUT][2];
2883 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2884 cvTsSetIdentity( &test_mat[REF_OUTPUT][2], cvScalarAll(1.) );
2887 w = &test_mat[TEMP][0];
2888 step = w->rows == 1 ? 1 : w->step/CV_ELEM_SIZE(w->type);
2889 for( i = 0; i < min_size; i++ )
2891 double norm = 0, aii;
2893 if( w->rows > 1 && w->cols > 1 )
2896 cvGetRow( w, &row, i );
2897 norm = cvNorm( &row, 0, CV_L1 );
2899 row_ptr = row.data.ptr;
2903 row_ptr = w->data.ptr;
2907 aii = CV_MAT_TYPE(w->type) == CV_32FC1 ?
2908 (double)((float*)row_ptr)[j] : ((double*)row_ptr)[j];
2909 if( w->rows == 1 || w->cols == 1 )
2911 norm = fabs(norm - aii);
2912 test_mat[OUTPUT][3].data.ptr[i] = aii >= 0 && norm < threshold && (i == 0 || aii <= prev);
2916 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.),
2917 cvScalarAll(1.), &test_mat[REF_OUTPUT][3], 0 );
2919 if( have_u && have_v )
2923 cvTsZero( &test_mat[TEMP][3] );
2924 for( i = 0; i < min_size; i++ )
2926 double val = cvGetReal1D( w, i );
2927 cvSetReal2D( &test_mat[TEMP][3], i, i, val );
2929 w = &test_mat[TEMP][3];
2934 cvTsGEMM( &test_mat[TEMP][1], w, 1., 0, 0., &test_mat[REF_OUTPUT][0],
2935 flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
2936 cvTsGEMM( &test_mat[REF_OUTPUT][0], &test_mat[TEMP][2], 1., 0, 0.,
2937 &test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
2941 cvTsGEMM( w, &test_mat[TEMP][2], 1., 0, 0., &test_mat[REF_OUTPUT][0],
2942 flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
2943 cvTsGEMM( &test_mat[TEMP][1], &test_mat[REF_OUTPUT][0], 1., 0, 0.,
2944 &test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
2947 cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], 0 );
2952 CxCore_SVDTest svd_test;
2955 ///////////////// SVBkSb /////////////////////
2957 class CxCore_SVBkSbTest : public CxCore_MatrixTest
2960 CxCore_SVBkSbTest();
2962 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2963 void get_timing_test_array_types_and_sizes( int test_case_idx,
2964 CvSize** sizes, int** types,
2965 CvSize** whole_sizes, bool* are_images );
2966 double get_success_error_level( int test_case_idx, int i, int j );
2967 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2968 int prepare_test_case( int test_case_idx );
2970 void prepare_to_validation( int test_case_idx );
2972 bool have_b, symmetric, compact, vector_w;
2976 CxCore_SVBkSbTest::CxCore_SVBkSbTest() :
2977 CxCore_MatrixTest( "matrix-svbksb", "cvSVBkSb", 2, 1, false, false, 1 ),
2978 flags(0), have_b(false), symmetric(false), compact(false), vector_w(false)
2980 test_case_count = 100;
2981 test_array[TEMP].push(NULL);
2982 test_array[TEMP].push(NULL);
2983 test_array[TEMP].push(NULL);
2987 void CxCore_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2989 CvRNG* rng = ts->get_rng();
2990 int bits = cvTsRandInt(rng);
2991 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2992 int min_size, i, m, n;
2995 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2997 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
2998 have_b = (bits & 16) != 0;
2999 symmetric = (bits & 32) != 0;
3000 compact = (bits & 64) != 0;
3001 vector_w = (bits & 128) != 0;
3004 sizes[INPUT][0] = cvSize(min_size, min_size);
3006 m = sizes[INPUT][0].height;
3007 n = sizes[INPUT][0].width;
3009 sizes[INPUT][1] = cvSize(0,0);
3010 b_size = cvSize(m,m);
3013 sizes[INPUT][1].height = sizes[INPUT][0].height;
3014 sizes[INPUT][1].width = cvTsRandInt(rng) % 100 + 1;
3015 b_size = sizes[INPUT][1];
3019 sizes[TEMP][0] = cvSize(min_size, min_size);
3021 sizes[TEMP][0] = sizes[INPUT][0];
3026 sizes[TEMP][0] = cvSize(1, min_size);
3028 sizes[TEMP][0] = cvSize(min_size, 1);
3031 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
3033 if( flags & CV_SVD_U_T )
3034 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
3036 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
3038 if( !(flags & CV_SVD_V_T) )
3039 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
3041 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
3042 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0];
3043 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( b_size.width, n );
3047 void CxCore_SVBkSbTest::get_timing_test_array_types_and_sizes( int test_case_idx,
3048 CvSize** sizes, int** types,
3049 CvSize** whole_sizes, bool* are_images )
3051 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
3052 sizes, types, whole_sizes, are_images );
3056 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
3057 sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1,sizes[INPUT][0].height);
3058 flags = CV_SVD_U_T + CV_SVD_V_T;
3062 int CxCore_SVBkSbTest::prepare_test_case( int test_case_idx )
3064 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
3067 CvMat* input = &test_mat[INPUT][0];
3068 cvTsFloodWithZeros( input, ts->get_rng() );
3072 CvMat* temp = &test_mat[TEMP][1];
3073 cvTsGEMM( input, input, 1., 0, 0., temp, CV_GEMM_B_T );
3074 cvTsCopy( temp, input );
3077 cvSVD( input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
3084 void CxCore_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
3086 *low = cvScalarAll(-2.);
3087 *high = cvScalarAll(2.);
3091 double CxCore_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
3093 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
3097 void CxCore_SVBkSbTest::run_func()
3099 cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
3100 test_array[INPUT][1], test_array[OUTPUT][0], flags );
3104 void CxCore_SVBkSbTest::prepare_to_validation( int )
3106 CvMat* input = &test_mat[INPUT][0];
3107 int i, m = input->rows, n = input->cols, min_size = MIN(m, n), nb;
3108 bool is_float = CV_MAT_DEPTH(input->type) == CV_32F;
3109 CvSize w_size = compact ? cvSize(min_size,min_size) : cvSize(m,n);
3110 CvMat* w = &test_mat[TEMP][0];
3111 CvMat* wdb = cvCreateMat( w_size.height, w_size.width, CV_64FC1 );
3112 // use exactly the same threshold as in icvSVD... ,
3113 // so the changes in the library and here should be synchronized.
3114 double threshold = cvSum( w ).val[0]*2*(is_float ? FLT_EPSILON : DBL_EPSILON);
3115 CvMat *u, *v, *b, *t0, *t1;
3118 for( i = 0; i < min_size; i++ )
3120 double wii = vector_w ? cvGetReal1D(w,i) : cvGetReal2D(w,i,i);
3121 cvSetReal2D( wdb, i, i, wii > threshold ? 1./wii : 0. );
3124 u = &test_mat[TEMP][1];
3125 v = &test_mat[TEMP][2];
3129 if( test_array[INPUT][1] )
3131 b = &test_mat[INPUT][1];
3137 u = cvCreateMat( u->rows, u->cols, CV_64F );
3138 cvTsConvert( &test_mat[TEMP][1], u );
3141 b = cvCreateMat( b->rows, b->cols, CV_64F );
3142 cvTsConvert( &test_mat[INPUT][1], b );
3146 t0 = cvCreateMat( wdb->cols, nb, CV_64F );
3149 cvTsGEMM( u, b, 1., 0, 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 );
3150 else if( flags & CV_SVD_U_T )
3153 cvTsTranspose( u, t0 );
3162 v = cvCreateMat( v->rows, v->cols, CV_64F );
3169 cvTsConvert( &test_mat[TEMP][2], v );
3172 t1 = cvCreateMat( wdb->rows, nb, CV_64F );
3173 cvTsGEMM( wdb, t0, 1, 0, 0, t1, 0 );
3175 if( !is_float || !symmetric )
3177 cvReleaseMat( &t0 );
3178 t0 = !is_float ? &test_mat[REF_OUTPUT][0] : cvCreateMat( test_mat[REF_OUTPUT][0].rows, nb, CV_64F );
3181 cvTsGEMM( v, t1, 1, 0, 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 );
3182 cvReleaseMat( &t1 );
3184 if( t0 != &test_mat[REF_OUTPUT][0] )
3186 cvTsConvert( t0, &test_mat[REF_OUTPUT][0] );
3187 cvReleaseMat( &t0 );
3190 if( v != &test_mat[TEMP][2] )
3193 cvReleaseMat( &wdb );
3197 CxCore_SVBkSbTest svbksb_test;
3200 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),