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 );
75 CxCore_MathTestImpl::CxCore_MathTestImpl( const char* test_name, const char* test_funcs )
76 : CvArrTest( test_name, test_funcs, "" )
78 optional_mask = false;
80 test_array[INPUT].push(NULL);
81 test_array[OUTPUT].push(NULL);
82 test_array[REF_OUTPUT].push(NULL);
84 default_timing_param_names = math_param_names;
86 size_list = math_sizes;
88 depth_list = math_depths;
94 double CxCore_MathTestImpl::get_success_error_level( int /*test_case_idx*/, int i, int j )
96 return CV_MAT_DEPTH(test_mat[i][j].type) == CV_32F ? FLT_EPSILON*128 : DBL_EPSILON*1024;
100 void CxCore_MathTestImpl::get_test_array_types_and_sizes( int test_case_idx,
101 CvSize** sizes, int** types )
103 CvRNG* rng = ts->get_rng();
104 int depth = cvTsRandInt(rng)%2 + CV_32F;
105 int cn = cvTsRandInt(rng) % 4 + 1, type = CV_MAKETYPE(depth, cn);
107 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
109 for( i = 0; i < max_arr; i++ )
111 int count = test_array[i].size();
112 for( j = 0; j < count; j++ )
115 test_nd = cvTsRandInt(rng)%3 == 0;
118 CxCore_MathTestImpl math_test( "math", "" );
121 class CxCore_MathTest : public CxCore_MathTestImpl
124 CxCore_MathTest( const char* test_name, const char* test_funcs );
128 CxCore_MathTest::CxCore_MathTest( const char* test_name, const char* test_funcs )
129 : CxCore_MathTestImpl( test_name, test_funcs )
136 ////////// exp /////////////
137 class CxCore_ExpTest : public CxCore_MathTest
142 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
143 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
144 double get_success_error_level( int /*test_case_idx*/, int i, int j );
146 void prepare_to_validation( int test_case_idx );
151 CxCore_ExpTest::CxCore_ExpTest()
152 : CxCore_MathTest( "math-exp", "cvExp" )
158 double CxCore_ExpTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
160 int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
161 int out_depth = CV_MAT_DEPTH(test_mat[OUTPUT][0].type);
162 int min_depth = MIN(in_depth, out_depth);
163 return min_depth == CV_32F ? 1e-5 : 1e-8;
167 void CxCore_ExpTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
169 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
170 out_type = types[OUTPUT][0];
171 /*if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32F && (cvRandInt(ts->get_rng()) & 3) == 0 )
172 types[OUTPUT][0] = types[REF_OUTPUT][0] =
173 out_type = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|CV_64F;*/
176 void CxCore_ExpTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
178 double l = cvTsRandReal(ts->get_rng())*10+1;
179 double u = cvTsRandReal(ts->get_rng())*10+1;
182 *low = cvScalarAll(l);
183 *high = cvScalarAll(CV_MAT_DEPTH(out_type)==CV_64F? u : u*0.5);
187 void CxCore_ExpTest::run_func()
190 cvExp( test_array[INPUT][0], test_array[OUTPUT][0] );
193 cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
194 cv::MatND b = cv::cvarrToMatND(test_array[OUTPUT][0]);
200 void CxCore_ExpTest::prepare_to_validation( int /*test_case_idx*/ )
202 CvMat* a = &test_mat[INPUT][0];
203 CvMat* b = &test_mat[REF_OUTPUT][0];
205 int a_depth = CV_MAT_DEPTH(a->type);
206 int b_depth = CV_MAT_DEPTH(b->type);
207 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
210 for( i = 0; i < a->rows; i++ )
212 uchar* a_data = a->data.ptr + i*a->step;
213 uchar* b_data = b->data.ptr + i*b->step;
215 if( a_depth == CV_32F && b_depth == CV_32F )
217 for( j = 0; j < ncols; j++ )
218 ((float*)b_data)[j] = (float)exp((double)((float*)a_data)[j]);
220 else if( a_depth == CV_32F && b_depth == CV_64F )
222 for( j = 0; j < ncols; j++ )
223 ((double*)b_data)[j] = exp((double)((float*)a_data)[j]);
227 assert( a_depth == CV_64F && b_depth == CV_64F );
228 for( j = 0; j < ncols; j++ )
229 ((double*)b_data)[j] = exp(((double*)a_data)[j]);
234 CxCore_ExpTest exp_test;
237 ////////// log /////////////
238 class CxCore_LogTest : public CxCore_MathTest
243 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
244 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
246 void prepare_to_validation( int test_case_idx );
250 CxCore_LogTest::CxCore_LogTest()
251 : CxCore_MathTest( "math-log", "cvLog" )
256 void CxCore_LogTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
258 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
259 /*if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32F && (cvRandInt(ts->get_rng()) & 3) == 0 )
260 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|CV_64F;*/
264 void CxCore_LogTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
266 double l = cvTsRandReal(ts->get_rng())*15-5;
267 double u = cvTsRandReal(ts->get_rng())*15-5;
273 *low = cvScalarAll(l);
274 *high = cvScalarAll(u);
278 void CxCore_LogTest::run_func()
281 cvLog( test_array[INPUT][0], test_array[OUTPUT][0] );
284 cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
285 cv::MatND b = cv::cvarrToMatND(test_array[OUTPUT][0]);
291 void CxCore_LogTest::prepare_to_validation( int /*test_case_idx*/ )
293 CvMat* a = &test_mat[INPUT][0];
294 CvMat* b = &test_mat[REF_OUTPUT][0];
296 int a_depth = CV_MAT_DEPTH(a->type);
297 int b_depth = CV_MAT_DEPTH(b->type);
298 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
301 for( i = 0; i < a->rows; i++ )
303 uchar* a_data = a->data.ptr + i*a->step;
304 uchar* b_data = b->data.ptr + i*b->step;
306 if( a_depth == CV_32F && b_depth == CV_32F )
308 for( j = 0; j < ncols; j++ )
309 ((float*)b_data)[j] = (float)log((double)((float*)a_data)[j]);
311 else if( a_depth == CV_64F && b_depth == CV_32F )
313 for( j = 0; j < ncols; j++ )
314 ((float*)b_data)[j] = (float)log(((double*)a_data)[j]);
318 assert( a_depth == CV_64F && b_depth == CV_64F );
319 for( j = 0; j < ncols; j++ )
320 ((double*)b_data)[j] = log(((double*)a_data)[j]);
325 CxCore_LogTest log_test;
328 ////////// pow /////////////
330 static const double math_pow_values[] = { 2., 5., 0.5, -0.5, 1./3, -1./3, CV_PI };
331 static const char* math_pow_param_names[] = { "size", "power", "depth", 0 };
332 static const int math_pow_depths[] = { CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, -1 };
334 class CxCore_PowTest : public CxCore_MathTest
339 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
340 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
341 void get_timing_test_array_types_and_sizes( int test_case_idx,
342 CvSize** sizes, int** types,
343 CvSize** whole_sizes, bool* are_images );
344 int write_default_params( CvFileStorage* fs );
345 void print_timing_params( int test_case_idx, char* ptr, int params_left );
347 int prepare_test_case( int test_case_idx );
348 void prepare_to_validation( int test_case_idx );
349 double get_success_error_level( int test_case_idx, int i, int j );
354 CxCore_PowTest::CxCore_PowTest()
355 : CxCore_MathTest( "math-pow", "cvPow" )
358 default_timing_param_names = math_pow_param_names;
359 depth_list = math_pow_depths;
363 void CxCore_PowTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
365 CvRNG* rng = ts->get_rng();
366 int depth = cvTsRandInt(rng) % CV_64F;
367 int cn = cvTsRandInt(rng) % 4 + 1;
369 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
370 depth += depth == CV_8S;
372 if( depth < CV_32F || cvTsRandInt(rng)%8 == 0 )
374 power = (int)(cvTsRandInt(rng)%21 - 10);
377 i = cvTsRandInt(rng)%16;
378 power = i == 15 ? 0.5 : i == 14 ? -0.5 : cvTsRandReal(rng)*10 - 5;
381 for( i = 0; i < max_arr; i++ )
383 int count = test_array[i].size();
384 int type = CV_MAKETYPE(depth, cn);
385 for( j = 0; j < count; j++ )
388 test_nd = cvTsRandInt(rng)%3 == 0;
392 void CxCore_PowTest::get_timing_test_array_types_and_sizes( int test_case_idx,
393 CvSize** sizes, int** types,
394 CvSize** whole_sizes, bool* are_images )
396 CxCore_MathTest::get_timing_test_array_types_and_sizes( test_case_idx,
397 sizes, types, whole_sizes, are_images );
398 power = cvReadReal( find_timing_param( "power" ), 0.2 );
402 int CxCore_PowTest::write_default_params( CvFileStorage* fs )
404 int i, code = CxCore_MathTest::write_default_params(fs);
405 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
407 start_write_param( fs );
408 cvStartWriteStruct( fs, "power", CV_NODE_SEQ + CV_NODE_FLOW );
409 for( i = 0; i < CV_DIM(math_pow_values); i++ )
410 cvWriteReal( fs, 0, math_pow_values[i] );
411 cvEndWriteStruct(fs);
416 int CxCore_PowTest::prepare_test_case( int test_case_idx )
418 int code = CxCore_MathTest::prepare_test_case( test_case_idx );
419 if( code > 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
421 if( cvRound(power) != power && CV_MAT_DEPTH(test_mat[INPUT][0].type) < CV_32F )
428 void CxCore_PowTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
430 sprintf( ptr, "%g,", power );
433 CxCore_MathTest::print_timing_params( test_case_idx, ptr, params_left );
437 double CxCore_PowTest::get_success_error_level( int test_case_idx, int i, int j )
439 int type = cvGetElemType( test_array[i][j] );
440 if( CV_MAT_DEPTH(type) < CV_32F )
441 return power == cvRound(power) && power >= 0 ? 0 : 1;
443 return CxCore_MathTest::get_success_error_level( test_case_idx, i, j );
447 void CxCore_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, CvScalar* low, CvScalar* high )
449 double l, u = cvTsRandInt(ts->get_rng())%1000 + 1;
452 double mval = cvTsMaxVal(type);
453 double u1 = pow(mval,1./power)*2;
457 l = power == cvRound(power) ? -u : FLT_EPSILON;
458 *low = cvScalarAll(l);
459 *high = cvScalarAll(u);
463 void CxCore_PowTest::run_func()
466 cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
469 cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
470 cv::MatND b = cv::cvarrToMatND(test_array[OUTPUT][0]);
474 cv::pow(a, power, b);
479 inline static int ipow( int a, int power )
493 inline static double ipow( double a, int power )
507 void CxCore_PowTest::prepare_to_validation( int /*test_case_idx*/ )
509 CvMat* a = &test_mat[INPUT][0];
510 CvMat* b = &test_mat[REF_OUTPUT][0];
512 int depth = CV_MAT_DEPTH(a->type);
513 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
514 int ipower = cvRound(power), apower = abs(ipower);
517 for( i = 0; i < a->rows; i++ )
519 uchar* a_data = a->data.ptr + i*a->step;
520 uchar* b_data = b->data.ptr + i*b->step;
526 for( j = 0; j < ncols; j++ )
528 int val = ((uchar*)a_data)[j];
529 ((uchar*)b_data)[j] = (uchar)(val <= 1 ? val :
530 val == 2 && ipower == -1 ? 1 : 0);
533 for( j = 0; j < ncols; j++ )
535 int val = ((uchar*)a_data)[j];
536 val = ipow( val, ipower );
537 ((uchar*)b_data)[j] = CV_CAST_8U(val);
542 for( j = 0; j < ncols; j++ )
544 int val = ((char*)a_data)[j];
545 ((char*)b_data)[j] = (char)((val&~1)==0 ? val :
546 val ==-1 ? 1-2*(ipower&1) :
547 val == 2 && ipower == -1 ? 1 : 0);
550 for( j = 0; j < ncols; j++ )
552 int val = ((char*)a_data)[j];
553 val = ipow( val, ipower );
554 ((char*)b_data)[j] = CV_CAST_8S(val);
559 for( j = 0; j < ncols; j++ )
561 int val = ((ushort*)a_data)[j];
562 ((ushort*)b_data)[j] = (ushort)((val&~1)==0 ? val :
563 val ==-1 ? 1-2*(ipower&1) :
564 val == 2 && ipower == -1 ? 1 : 0);
567 for( j = 0; j < ncols; j++ )
569 int val = ((ushort*)a_data)[j];
570 val = ipow( val, ipower );
571 ((ushort*)b_data)[j] = CV_CAST_16U(val);
576 for( j = 0; j < ncols; j++ )
578 int val = ((short*)a_data)[j];
579 ((short*)b_data)[j] = (short)((val&~1)==0 ? val :
580 val ==-1 ? 1-2*(ipower&1) :
581 val == 2 && ipower == -1 ? 1 : 0);
584 for( j = 0; j < ncols; j++ )
586 int val = ((short*)a_data)[j];
587 val = ipow( val, ipower );
588 ((short*)b_data)[j] = CV_CAST_16S(val);
593 for( j = 0; j < ncols; j++ )
595 int val = ((int*)a_data)[j];
596 ((int*)b_data)[j] = (val&~1)==0 ? val :
597 val ==-1 ? 1-2*(ipower&1) :
598 val == 2 && ipower == -1 ? 1 : 0;
601 for( j = 0; j < ncols; j++ )
603 int val = ((int*)a_data)[j];
604 val = ipow( val, ipower );
605 ((int*)b_data)[j] = val;
609 if( power != ipower )
610 for( j = 0; j < ncols; j++ )
612 double val = ((float*)a_data)[j];
613 val = pow( fabs(val), power );
614 ((float*)b_data)[j] = CV_CAST_32F(val);
617 for( j = 0; j < ncols; j++ )
619 double val = ((float*)a_data)[j];
622 val = ipow( val, apower );
623 ((float*)b_data)[j] = (float)val;
627 if( power != ipower )
628 for( j = 0; j < ncols; j++ )
630 double val = ((double*)a_data)[j];
631 val = pow( fabs(val), power );
632 ((double*)b_data)[j] = CV_CAST_64F(val);
635 for( j = 0; j < ncols; j++ )
637 double val = ((double*)a_data)[j];
640 val = ipow( val, apower );
641 ((double*)b_data)[j] = (double)val;
648 CxCore_PowTest pow_test;
652 ////////// cart2polar /////////////
653 class CxCore_CartToPolarTest : public CxCore_MathTest
656 CxCore_CartToPolarTest();
658 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
659 double get_success_error_level( int test_case_idx, int i, int j );
661 void prepare_to_validation( int test_case_idx );
666 CxCore_CartToPolarTest::CxCore_CartToPolarTest()
667 : CxCore_MathTest( "math-cart2polar", "cvCartToPolar" )
670 test_array[INPUT].push(NULL);
671 test_array[OUTPUT].push(NULL);
672 test_array[REF_OUTPUT].push(NULL);
676 void CxCore_CartToPolarTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
678 CvRNG* rng = ts->get_rng();
679 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
681 use_degrees = cvTsRandInt(rng) & 1;
682 if( cvTsRandInt(rng) % 4 == 0 ) // check missing magnitude/angle cases
684 int idx = cvTsRandInt(rng) & 1;
685 sizes[OUTPUT][idx] = sizes[REF_OUTPUT][idx] = cvSize(0,0);
690 void CxCore_CartToPolarTest::run_func()
694 cvCartToPolar( test_array[INPUT][0], test_array[INPUT][1],
695 test_array[OUTPUT][0], test_array[OUTPUT][1], use_degrees );
699 cv::Mat X = cv::cvarrToMat(test_array[INPUT][0]);
700 cv::Mat Y = cv::cvarrToMat(test_array[INPUT][1]);
701 cv::Mat mag = test_array[OUTPUT][0] ? cv::cvarrToMat(test_array[OUTPUT][0]) : cv::Mat();
702 cv::Mat ph = test_array[OUTPUT][1] ? cv::cvarrToMat(test_array[OUTPUT][1]) : cv::Mat();
704 cv::phase(X, Y, ph, use_degrees);
706 cv::magnitude(X, Y, mag);
708 cv::cartToPolar(X, Y, mag, ph, use_degrees);
713 double CxCore_CartToPolarTest::get_success_error_level( int test_case_idx, int i, int j )
715 return j == 1 ? 0.5*(use_degrees ? 1 : CV_PI/180.) :
716 CxCore_MathTest::get_success_error_level( test_case_idx, i, j );
720 void CxCore_CartToPolarTest::prepare_to_validation( int /*test_case_idx*/ )
722 CvMat* x = &test_mat[INPUT][0];
723 CvMat* y = &test_mat[INPUT][1];
724 CvMat* mag = test_array[REF_OUTPUT][0] ? &test_mat[REF_OUTPUT][0] : 0;
725 CvMat* angle = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
726 double C = use_degrees ? 180./CV_PI : 1.;
728 int depth = CV_MAT_DEPTH(x->type);
729 int ncols = x->cols*CV_MAT_CN(x->type);
732 for( i = 0; i < x->rows; i++ )
734 uchar* x_data = x->data.ptr + i*x->step;
735 uchar* y_data = y->data.ptr + i*y->step;
736 uchar* mag_data = mag ? mag->data.ptr + i*mag->step : 0;
737 uchar* angle_data = angle ? angle->data.ptr + i*angle->step : 0;
739 if( depth == CV_32F )
741 for( j = 0; j < ncols; j++ )
743 double xval = ((float*)x_data)[j];
744 double yval = ((float*)y_data)[j];
747 ((float*)mag_data)[j] = (float)sqrt(xval*xval + yval*yval);
750 double a = atan2( yval, xval );
754 ((float*)angle_data)[j] = (float)a;
760 assert( depth == CV_64F );
761 for( j = 0; j < ncols; j++ )
763 double xval = ((double*)x_data)[j];
764 double yval = ((double*)y_data)[j];
767 ((double*)mag_data)[j] = sqrt(xval*xval + yval*yval);
770 double a = atan2( yval, xval );
774 ((double*)angle_data)[j] = a;
782 // hack: increase angle value by 1 (so that alpha becomes 1+alpha)
783 // to hide large relative errors in case of very small angles
784 cvTsAdd( &test_mat[OUTPUT][1], cvScalarAll(1.), 0, cvScalarAll(0.),
785 cvScalarAll(1.), &test_mat[OUTPUT][1], 0 );
786 cvTsAdd( &test_mat[REF_OUTPUT][1], cvScalarAll(1.), 0, cvScalarAll(0.),
787 cvScalarAll(1.), &test_mat[REF_OUTPUT][1], 0 );
791 CxCore_CartToPolarTest cart2polar_test;
795 ////////// polar2cart /////////////
796 class CxCore_PolarToCartTest : public CxCore_MathTest
799 CxCore_PolarToCartTest();
801 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
802 double get_success_error_level( int test_case_idx, int i, int j );
804 void prepare_to_validation( int test_case_idx );
809 CxCore_PolarToCartTest::CxCore_PolarToCartTest()
810 : CxCore_MathTest( "math-polar2cart", "cvPolarToCart" )
813 test_array[INPUT].push(NULL);
814 test_array[OUTPUT].push(NULL);
815 test_array[REF_OUTPUT].push(NULL);
819 void CxCore_PolarToCartTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
821 CvRNG* rng = ts->get_rng();
822 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
824 use_degrees = cvTsRandInt(rng) & 1;
825 if( cvTsRandInt(rng) % 4 == 0 ) // check missing magnitude case
826 sizes[INPUT][1] = cvSize(0,0);
828 if( cvTsRandInt(rng) % 4 == 0 ) // check missing x/y cases
830 int idx = cvTsRandInt(rng) & 1;
831 sizes[OUTPUT][idx] = sizes[REF_OUTPUT][idx] = cvSize(0,0);
836 void CxCore_PolarToCartTest::run_func()
840 cvPolarToCart( test_array[INPUT][1], test_array[INPUT][0],
841 test_array[OUTPUT][0], test_array[OUTPUT][1], use_degrees );
845 cv::Mat X = test_array[OUTPUT][0] ? cv::cvarrToMat(test_array[OUTPUT][0]) : cv::Mat();
846 cv::Mat Y = test_array[OUTPUT][1] ? cv::cvarrToMat(test_array[OUTPUT][1]) : cv::Mat();
847 cv::Mat mag = test_array[INPUT][1] ? cv::cvarrToMat(test_array[INPUT][1]) : cv::Mat();
848 cv::Mat ph = test_array[INPUT][0] ? cv::cvarrToMat(test_array[INPUT][0]) : cv::Mat();
849 cv::polarToCart(mag, ph, X, Y, use_degrees);
854 double CxCore_PolarToCartTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
856 return FLT_EPSILON*100;
860 void CxCore_PolarToCartTest::prepare_to_validation( int /*test_case_idx*/ )
862 CvMat* x = test_array[REF_OUTPUT][0] ? &test_mat[REF_OUTPUT][0] : 0;
863 CvMat* y = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
864 CvMat* angle = &test_mat[INPUT][0];
865 CvMat* mag = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
866 double C = use_degrees ? CV_PI/180. : 1.;
868 int depth = CV_MAT_DEPTH(angle->type);
869 int ncols = angle->cols*CV_MAT_CN(angle->type);
872 for( i = 0; i < angle->rows; i++ )
874 uchar* x_data = x ? x->data.ptr + i*x->step : 0;
875 uchar* y_data = y ? y->data.ptr + i*y->step : 0;
876 uchar* mag_data = mag ? mag->data.ptr + i*mag->step : 0;
877 uchar* angle_data = angle->data.ptr + i*angle->step;
879 if( depth == CV_32F )
881 for( j = 0; j < ncols; j++ )
883 double a = ((float*)angle_data)[j]*C;
884 double m = mag_data ? ((float*)mag_data)[j] : 1.;
887 ((float*)x_data)[j] = (float)(m*cos(a));
889 ((float*)y_data)[j] = (float)(m*sin(a));
894 assert( depth == CV_64F );
895 for( j = 0; j < ncols; j++ )
897 double a = ((double*)angle_data)[j]*C;
898 double m = mag_data ? ((double*)mag_data)[j] : 1.;
901 ((double*)x_data)[j] = m*cos(a);
903 ((double*)y_data)[j] = m*sin(a);
909 CxCore_PolarToCartTest polar2cart_test;
911 ///////////////////////////////////////// matrix tests ////////////////////////////////////////////
913 static const int matrix_all_depths[] = { CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, -1 };
915 class CxCore_MatrixTestImpl : public CvArrTest
918 CxCore_MatrixTestImpl( const char* test_name, const char* test_funcs, int in_count, int out_count,
919 bool allow_int, bool scalar_output, int max_cn );
921 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
922 void get_timing_test_array_types_and_sizes( int test_case_idx,
923 CvSize** sizes, int** types,
924 CvSize** whole_sizes, bool* are_images );
925 double get_success_error_level( int test_case_idx, int i, int j );
932 CxCore_MatrixTestImpl::CxCore_MatrixTestImpl( const char* test_name, const char* test_funcs,
933 int in_count, int out_count,
934 bool _allow_int, bool _scalar_output, int _max_cn )
935 : CvArrTest( test_name, test_funcs, "" ),
936 allow_int(_allow_int), scalar_output(_scalar_output), max_cn(_max_cn)
939 for( i = 0; i < in_count; i++ )
940 test_array[INPUT].push(NULL);
942 for( i = 0; i < out_count; i++ )
944 test_array[OUTPUT].push(NULL);
945 test_array[REF_OUTPUT].push(NULL);
948 element_wise_relative_error = false;
950 default_timing_param_names = math_param_names;
952 size_list = (CvSize*)matrix_sizes;
954 depth_list = (int*)math_depths;
959 void CxCore_MatrixTestImpl::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
961 CvRNG* rng = ts->get_rng();
962 int depth = cvTsRandInt(rng) % (allow_int ? CV_64F+1 : 2);
963 int cn = cvTsRandInt(rng) % max_cn + 1;
967 depth += depth == CV_8S;
971 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
973 for( i = 0; i < max_arr; i++ )
975 int count = test_array[i].size();
976 int flag = (i == OUTPUT || i == REF_OUTPUT) && scalar_output;
977 int type = !flag ? CV_MAKETYPE(depth, cn) : CV_64FC1;
979 for( j = 0; j < count; j++ )
983 sizes[i][j] = cvSize( 4, 1 );
989 void CxCore_MatrixTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
990 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
992 CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx,
993 sizes, types, whole_sizes, are_images );
996 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
997 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( 4, 1 );
998 whole_sizes[OUTPUT][0] = whole_sizes[REF_OUTPUT][0] = cvSize( 4, 1 );
1003 double CxCore_MatrixTestImpl::get_success_error_level( int test_case_idx, int i, int j )
1005 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
1006 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ?
1008 double output_precision = CvArrTest::get_success_error_level( test_case_idx, i, j );
1009 return MAX(input_precision, output_precision);
1012 CxCore_MatrixTestImpl matrix_test( "matrix", "", 0, 0, false, false, 0 );
1015 class CxCore_MatrixTest : public CxCore_MatrixTestImpl
1018 CxCore_MatrixTest( const char* test_name, const char* test_funcs, int in_count, int out_count,
1019 bool allow_int, bool scalar_output, int max_cn );
1023 CxCore_MatrixTest::CxCore_MatrixTest( const char* test_name, const char* test_funcs,
1024 int in_count, int out_count, bool _allow_int,
1025 bool _scalar_output, int _max_cn )
1026 : CxCore_MatrixTestImpl( test_name, test_funcs, in_count, out_count,
1027 _allow_int, _scalar_output, _max_cn )
1034 ///////////////// Trace /////////////////////
1036 class CxCore_TraceTest : public CxCore_MatrixTest
1042 void prepare_to_validation( int test_case_idx );
1046 CxCore_TraceTest::CxCore_TraceTest() :
1047 CxCore_MatrixTest( "matrix-trace", "cvTrace", 1, 1, true, true, 4 )
1052 void CxCore_TraceTest::run_func()
1054 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvTrace(test_array[INPUT][0]);
1058 void CxCore_TraceTest::prepare_to_validation( int )
1060 CvMat* mat = &test_mat[INPUT][0];
1061 int i, j, count = MIN( mat->rows, mat->cols );
1062 CvScalar trace = {{0,0,0,0}};
1064 for( i = 0; i < count; i++ )
1066 CvScalar el = cvGet2D( mat, i, i );
1067 for( j = 0; j < 4; j++ )
1068 trace.val[j] += el.val[j];
1071 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = trace;
1074 CxCore_TraceTest trace_test;
1077 ///////// dotproduct //////////
1079 class CxCore_DotProductTest : public CxCore_MatrixTest
1082 CxCore_DotProductTest();
1085 void prepare_to_validation( int test_case_idx );
1089 CxCore_DotProductTest::CxCore_DotProductTest() :
1090 CxCore_MatrixTest( "matrix-dotproduct", "cvDotProduct", 2, 1, true, true, 4 )
1092 depth_list = matrix_all_depths;
1096 void CxCore_DotProductTest::run_func()
1098 *((CvScalar*)(test_mat[OUTPUT][0].data.ptr)) =
1099 cvRealScalar(cvDotProduct( test_array[INPUT][0], test_array[INPUT][1] ));
1103 void CxCore_DotProductTest::prepare_to_validation( int )
1105 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.ptr)) =
1106 cvRealScalar(cvTsCrossCorr( &test_mat[INPUT][0], &test_mat[INPUT][1] ));
1109 CxCore_DotProductTest dotproduct_test;
1112 ///////// crossproduct //////////
1114 static const CvSize cross_product_sizes[] = {{3,1}, {-1,-1}};
1116 class CxCore_CrossProductTest : public CxCore_MatrixTest
1119 CxCore_CrossProductTest();
1121 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1123 void prepare_to_validation( int test_case_idx );
1127 CxCore_CrossProductTest::CxCore_CrossProductTest() :
1128 CxCore_MatrixTest( "matrix-crossproduct", "cvCrossProduct", 2, 1, false, false, 1 )
1130 size_list = cross_product_sizes;
1134 void CxCore_CrossProductTest::get_test_array_types_and_sizes( int /*test_case_idx*/, CvSize** sizes, int** types )
1136 CvRNG* rng = ts->get_rng();
1137 int depth = cvTsRandInt(rng) % 2 + CV_32F;
1138 int cn = cvTsRandInt(rng) & 1 ? 3 : 1, type = CV_MAKETYPE(depth, cn);
1141 types[INPUT][0] = types[INPUT][1] = types[OUTPUT][0] = types[REF_OUTPUT][0] = type;
1145 else if( cvTsRandInt(rng) & 1 )
1150 sizes[INPUT][0] = sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
1154 void CxCore_CrossProductTest::run_func()
1156 cvCrossProduct( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1160 void CxCore_CrossProductTest::prepare_to_validation( int )
1162 CvScalar a = {{0,0,0,0}}, b = {{0,0,0,0}}, c = {{0,0,0,0}};
1164 if( test_mat[INPUT][0].rows > 1 )
1166 a.val[0] = cvGetReal2D( &test_mat[INPUT][0], 0, 0 );
1167 a.val[1] = cvGetReal2D( &test_mat[INPUT][0], 1, 0 );
1168 a.val[2] = cvGetReal2D( &test_mat[INPUT][0], 2, 0 );
1170 b.val[0] = cvGetReal2D( &test_mat[INPUT][1], 0, 0 );
1171 b.val[1] = cvGetReal2D( &test_mat[INPUT][1], 1, 0 );
1172 b.val[2] = cvGetReal2D( &test_mat[INPUT][1], 2, 0 );
1174 else if( test_mat[INPUT][0].cols > 1 )
1176 a.val[0] = cvGetReal1D( &test_mat[INPUT][0], 0 );
1177 a.val[1] = cvGetReal1D( &test_mat[INPUT][0], 1 );
1178 a.val[2] = cvGetReal1D( &test_mat[INPUT][0], 2 );
1180 b.val[0] = cvGetReal1D( &test_mat[INPUT][1], 0 );
1181 b.val[1] = cvGetReal1D( &test_mat[INPUT][1], 1 );
1182 b.val[2] = cvGetReal1D( &test_mat[INPUT][1], 2 );
1186 a = cvGet1D( &test_mat[INPUT][0], 0 );
1187 b = cvGet1D( &test_mat[INPUT][1], 0 );
1190 c.val[2] = a.val[0]*b.val[1] - a.val[1]*b.val[0];
1191 c.val[1] = -a.val[0]*b.val[2] + a.val[2]*b.val[0];
1192 c.val[0] = a.val[1]*b.val[2] - a.val[2]*b.val[1];
1194 if( test_mat[REF_OUTPUT][0].rows > 1 )
1196 cvSetReal2D( &test_mat[REF_OUTPUT][0], 0, 0, c.val[0] );
1197 cvSetReal2D( &test_mat[REF_OUTPUT][0], 1, 0, c.val[1] );
1198 cvSetReal2D( &test_mat[REF_OUTPUT][0], 2, 0, c.val[2] );
1200 else if( test_mat[REF_OUTPUT][0].cols > 1 )
1202 cvSetReal1D( &test_mat[REF_OUTPUT][0], 0, c.val[0] );
1203 cvSetReal1D( &test_mat[REF_OUTPUT][0], 1, c.val[1] );
1204 cvSetReal1D( &test_mat[REF_OUTPUT][0], 2, c.val[2] );
1208 cvSet1D( &test_mat[REF_OUTPUT][0], 0, c );
1212 CxCore_CrossProductTest crossproduct_test;
1215 ///////////////// scaleadd /////////////////////
1217 class CxCore_ScaleAddTest : public CxCore_MatrixTest
1220 CxCore_ScaleAddTest();
1222 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1223 void get_timing_test_array_types_and_sizes( int test_case_idx,
1224 CvSize** sizes, int** types,
1225 CvSize** whole_sizes, bool* are_images );
1226 int prepare_test_case( int test_case_idx );
1228 void prepare_to_validation( int test_case_idx );
1232 CxCore_ScaleAddTest::CxCore_ScaleAddTest() :
1233 CxCore_MatrixTest( "matrix-scaleadd", "cvScaleAdd", 3, 1, false, false, 4 )
1235 alpha = cvScalarAll(0);
1239 void CxCore_ScaleAddTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1241 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1242 sizes[INPUT][2] = cvSize(1,1);
1243 types[INPUT][2] &= CV_MAT_DEPTH_MASK;
1247 void CxCore_ScaleAddTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1248 CvSize** sizes, int** types,
1249 CvSize** whole_sizes, bool* are_images )
1251 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1252 whole_sizes, are_images );
1253 sizes[INPUT][2] = cvSize(1,1);
1254 types[INPUT][2] &= CV_MAT_DEPTH_MASK;
1258 int CxCore_ScaleAddTest::prepare_test_case( int test_case_idx )
1260 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1262 alpha = cvGet1D( &test_mat[INPUT][2], 0 );
1267 void CxCore_ScaleAddTest::run_func()
1269 cvScaleAdd( test_array[INPUT][0], alpha, test_array[INPUT][1], test_array[OUTPUT][0] );
1273 void CxCore_ScaleAddTest::prepare_to_validation( int )
1275 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(alpha.val[0]),
1276 &test_mat[INPUT][1], cvScalarAll(1.),
1277 cvScalarAll(0.), &test_mat[REF_OUTPUT][0], 0 );
1280 CxCore_ScaleAddTest scaleadd_test;
1283 ///////////////// gemm /////////////////////
1285 static const char* matrix_gemm_param_names[] = { "size", "add_c", "mul_type", "depth", 0 };
1286 static const char* matrix_gemm_mul_types[] = { "AB", "AtB", "ABt", "AtBt", 0 };
1287 static const int matrix_gemm_add_c_flags[] = { 0, 1 };
1289 class CxCore_GEMMTest : public CxCore_MatrixTest
1294 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1295 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1296 void get_timing_test_array_types_and_sizes( int test_case_idx,
1297 CvSize** sizes, int** types,
1298 CvSize** whole_sizes, bool* are_images );
1299 int write_default_params( CvFileStorage* fs );
1300 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1301 int prepare_test_case( int test_case_idx );
1303 void prepare_to_validation( int test_case_idx );
1308 CxCore_GEMMTest::CxCore_GEMMTest() :
1309 CxCore_MatrixTest( "matrix-gemm", "cvGEMM", 5, 1, false, false, 2 )
1311 test_case_count = 100;
1312 default_timing_param_names = matrix_gemm_param_names;
1317 void CxCore_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1319 CvRNG* rng = ts->get_rng();
1321 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1322 sizeA = sizes[INPUT][0];
1323 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1324 sizes[INPUT][0] = sizeA;
1325 sizes[INPUT][2] = sizes[INPUT][3] = cvSize(1,1);
1326 types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK;
1328 tabc_flag = cvTsRandInt(rng) & 7;
1330 switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
1333 sizes[INPUT][1].height = sizes[INPUT][0].width;
1334 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1335 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1338 sizes[INPUT][1].width = sizes[INPUT][0].width;
1339 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1340 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1343 sizes[INPUT][1].height = sizes[INPUT][0].height;
1344 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1345 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1347 case CV_GEMM_A_T | CV_GEMM_B_T:
1348 sizes[INPUT][1].width = sizes[INPUT][0].height;
1349 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1350 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1354 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1356 if( cvTsRandInt(rng) & 1 )
1357 sizes[INPUT][4] = cvSize(0,0);
1358 else if( !(tabc_flag & CV_GEMM_C_T) )
1359 sizes[INPUT][4] = sizes[OUTPUT][0];
1362 sizes[INPUT][4].width = sizes[OUTPUT][0].height;
1363 sizes[INPUT][4].height = sizes[OUTPUT][0].width;
1368 void CxCore_GEMMTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1369 CvSize** sizes, int** types,
1370 CvSize** whole_sizes, bool* are_images )
1372 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1373 sizes, types, whole_sizes, are_images );
1374 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AB" );
1375 if( strcmp( mul_type, "AtB" ) == 0 )
1376 tabc_flag = CV_GEMM_A_T;
1377 else if( strcmp( mul_type, "ABt" ) == 0 )
1378 tabc_flag = CV_GEMM_B_T;
1379 else if( strcmp( mul_type, "AtBt" ) == 0 )
1380 tabc_flag = CV_GEMM_A_T + CV_GEMM_B_T;
1384 if( cvReadInt( find_timing_param( "add_c" ), 0 ) == 0 )
1385 sizes[INPUT][4] = cvSize(0,0);
1389 int CxCore_GEMMTest::write_default_params( CvFileStorage* fs )
1391 int code = CxCore_MatrixTest::write_default_params(fs);
1392 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1394 write_string_list( fs, "mul_type", matrix_gemm_mul_types );
1395 write_int_list( fs, "add_c", matrix_gemm_add_c_flags, CV_DIM(matrix_gemm_add_c_flags) );
1400 void CxCore_GEMMTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1402 sprintf( ptr, "%s%s,%s,",
1403 tabc_flag & CV_GEMM_A_T ? "At" : "A",
1404 tabc_flag & CV_GEMM_B_T ? "Bt" : "B",
1405 test_array[INPUT][4] ? "plusC" : "" );
1408 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1412 int CxCore_GEMMTest::prepare_test_case( int test_case_idx )
1414 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1417 alpha = cvmGet( &test_mat[INPUT][2], 0, 0 );
1418 beta = cvmGet( &test_mat[INPUT][3], 0, 0 );
1424 void CxCore_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1426 *low = cvScalarAll(-10.);
1427 *high = cvScalarAll(10.);
1431 void CxCore_GEMMTest::run_func()
1433 cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
1434 test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
1438 void CxCore_GEMMTest::prepare_to_validation( int )
1440 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][1], alpha,
1441 test_array[INPUT][4] ? &test_mat[INPUT][4] : 0,
1442 beta, &test_mat[REF_OUTPUT][0], tabc_flag );
1445 CxCore_GEMMTest gemm_test;
1448 ///////////////// multransposed /////////////////////
1450 static const char* matrix_multrans_param_names[] = { "size", "use_delta", "mul_type", "depth", 0 };
1451 static const int matrix_multrans_use_delta_flags[] = { 0, 1 };
1452 static const char* matrix_multrans_mul_types[] = { "AAt", "AtA", 0 };
1454 class CxCore_MulTransposedTest : public CxCore_MatrixTest
1457 CxCore_MulTransposedTest();
1459 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1460 void get_timing_test_array_types_and_sizes( int test_case_idx,
1461 CvSize** sizes, int** types,
1462 CvSize** whole_sizes, bool* are_images );
1463 int write_default_params( CvFileStorage* fs );
1464 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1465 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1467 void prepare_to_validation( int test_case_idx );
1472 CxCore_MulTransposedTest::CxCore_MulTransposedTest() :
1473 CxCore_MatrixTest( "matrix-multransposed", "cvMulTransposed, cvRepeat", 2, 1, false, false, 1 )
1475 test_case_count = 100;
1477 test_array[TEMP].push(NULL);
1478 default_timing_param_names = matrix_multrans_param_names;
1482 void CxCore_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1484 CvRNG* rng = ts->get_rng();
1485 int bits = cvTsRandInt(rng);
1486 int src_type = cvTsRandInt(rng) % 5;
1487 int dst_type = cvTsRandInt(rng) % 2;
1489 src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S :
1490 src_type == 3 ? CV_32F : CV_64F;
1491 dst_type = dst_type == 0 ? CV_32F : CV_64F;
1492 dst_type = MAX( dst_type, src_type );
1494 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1497 sizes[INPUT][1] = cvSize(0,0);
1500 sizes[INPUT][1] = sizes[INPUT][0];
1502 sizes[INPUT][1].height = 1;
1504 sizes[INPUT][1].width = 1;
1507 sizes[TEMP][0] = sizes[INPUT][0];
1508 types[INPUT][0] = src_type;
1509 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type;
1511 order = (bits & 8) != 0;
1512 sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ?
1513 sizes[INPUT][0].height : sizes[INPUT][0].width;
1514 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1518 void CxCore_MulTransposedTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1519 CvSize** sizes, int** types,
1520 CvSize** whole_sizes, bool* are_images )
1522 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1523 sizes, types, whole_sizes, are_images );
1524 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AAt" );
1525 order = strcmp( mul_type, "AtA" ) == 0;
1527 if( cvReadInt( find_timing_param( "use_delta" ), 0 ) == 0 )
1528 sizes[INPUT][1] = cvSize(0,0);
1532 int CxCore_MulTransposedTest::write_default_params( CvFileStorage* fs )
1534 int code = CxCore_MatrixTest::write_default_params(fs);
1535 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1537 write_string_list( fs, "mul_type", matrix_multrans_mul_types );
1538 write_int_list( fs, "use_delta", matrix_multrans_use_delta_flags,
1539 CV_DIM(matrix_multrans_use_delta_flags) );
1544 void CxCore_MulTransposedTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1546 sprintf( ptr, "%s,%s,", order == 0 ? "AAt" : "AtA", test_array[INPUT][1] ? "delta" : "" );
1549 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1553 void CxCore_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1555 *low = cvScalarAll(-10.);
1556 *high = cvScalarAll(10.);
1560 void CxCore_MulTransposedTest::run_func()
1562 cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
1563 order, test_array[INPUT][1] );
1567 void CxCore_MulTransposedTest::prepare_to_validation( int )
1569 CvMat* delta = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
1572 if( test_mat[INPUT][1].rows < test_mat[INPUT][0].rows ||
1573 test_mat[INPUT][1].cols < test_mat[INPUT][0].cols )
1575 cvRepeat( delta, &test_mat[TEMP][0] );
1576 delta = &test_mat[TEMP][0];
1578 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.), delta, cvScalarAll(-1.),
1579 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1582 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
1583 delta = &test_mat[TEMP][0];
1585 cvTsGEMM( delta, delta, 1., 0, 0, &test_mat[REF_OUTPUT][0], order == 0 ? CV_GEMM_B_T : CV_GEMM_A_T );
1588 CxCore_MulTransposedTest multransposed_test;
1591 ///////////////// Transform /////////////////////
1593 static const CvSize matrix_transform_sizes[] = {{10,10}, {100,100}, {720,480}, {-1,-1}};
1594 static const CvSize matrix_transform_whole_sizes[] = {{10,10}, {720,480}, {720,480}, {-1,-1}};
1595 static const int matrix_transform_channels[] = { 2, 3, 4, -1 };
1596 static const char* matrix_transform_param_names[] = { "size", "channels", "depth", 0 };
1598 class CxCore_TransformTest : public CxCore_MatrixTest
1601 CxCore_TransformTest();
1603 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1604 double get_success_error_level( int test_case_idx, int i, int j );
1605 void get_timing_test_array_types_and_sizes( int test_case_idx,
1606 CvSize** sizes, int** types,
1607 CvSize** whole_sizes, bool* are_images );
1608 int prepare_test_case( int test_case_idx );
1609 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1611 void prepare_to_validation( int test_case_idx );
1617 CxCore_TransformTest::CxCore_TransformTest() :
1618 CxCore_MatrixTest( "matrix-transform", "cvTransform", 3, 1, true, false, 4 )
1620 default_timing_param_names = matrix_transform_param_names;
1621 cn_list = matrix_transform_channels;
1622 depth_list = matrix_all_depths;
1623 size_list = matrix_transform_sizes;
1624 whole_size_list = matrix_transform_whole_sizes;
1628 void CxCore_TransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1630 CvRNG* rng = ts->get_rng();
1631 int bits = cvTsRandInt(rng);
1632 int depth, dst_cn, mat_cols, mattype;
1633 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1635 mat_cols = CV_MAT_CN(types[INPUT][0]);
1636 depth = CV_MAT_DEPTH(types[INPUT][0]);
1637 dst_cn = cvTsRandInt(rng) % 4 + 1;
1638 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
1640 mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1641 types[INPUT][1] = mattype;
1642 types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
1644 scale = 1./((cvTsRandInt(rng)%4)*50+1);
1648 sizes[INPUT][2] = cvSize(0,0);
1649 mat_cols += (bits & 4) != 0;
1652 sizes[INPUT][2] = cvSize(1,1);
1656 sizes[INPUT][2] = cvSize(dst_cn,1);
1658 sizes[INPUT][2] = cvSize(1,dst_cn);
1659 types[INPUT][2] &= ~CV_MAT_CN_MASK;
1662 sizes[INPUT][1] = cvSize(mat_cols,dst_cn);
1666 void CxCore_TransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1667 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1669 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1670 sizes, types, whole_sizes, are_images );
1671 int cn = CV_MAT_CN(types[INPUT][0]);
1672 sizes[INPUT][1] = cvSize(cn + (cn < 4), cn);
1673 sizes[INPUT][2] = cvSize(0,0);
1674 types[INPUT][1] = types[INPUT][2] = CV_64FC1;
1678 int CxCore_TransformTest::prepare_test_case( int test_case_idx )
1680 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1682 cvTsAdd(&test_mat[INPUT][1], cvScalarAll(scale), &test_mat[INPUT][1],
1683 cvScalarAll(0), cvScalarAll(0), &test_mat[INPUT][1], 0 );
1687 void CxCore_TransformTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1689 CvSize size = cvGetMatSize(&test_mat[INPUT][1]);
1690 sprintf( ptr, "matrix=%dx%d,", size.height, size.width );
1693 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1697 double CxCore_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
1699 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1700 return depth <= CV_8S ? 1 : depth <= CV_32S ? 8 :
1701 CxCore_MatrixTest::get_success_error_level( test_case_idx, i, j );
1704 void CxCore_TransformTest::run_func()
1706 cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1],
1707 test_array[INPUT][2] ? &test_mat[INPUT][2] : 0);
1711 void CxCore_TransformTest::prepare_to_validation( int )
1713 CvMat* transmat = &test_mat[INPUT][1];
1714 CvMat* shift = test_array[INPUT][2] ? &test_mat[INPUT][2] : 0;
1716 cvTsTransform( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], transmat, shift );
1719 CxCore_TransformTest transform_test;
1722 ///////////////// PerspectiveTransform /////////////////////
1724 static const int matrix_perspective_transform_channels[] = { 2, 3, -1 };
1726 class CxCore_PerspectiveTransformTest : public CxCore_MatrixTest
1729 CxCore_PerspectiveTransformTest();
1731 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1732 double get_success_error_level( int test_case_idx, int i, int j );
1733 void get_timing_test_array_types_and_sizes( int test_case_idx,
1734 CvSize** sizes, int** types,
1735 CvSize** whole_sizes, bool* are_images );
1737 void prepare_to_validation( int test_case_idx );
1741 CxCore_PerspectiveTransformTest::CxCore_PerspectiveTransformTest() :
1742 CxCore_MatrixTest( "matrix-perspective", "cvPerspectiveTransform", 2, 1, false, false, 2 )
1744 default_timing_param_names = matrix_transform_param_names;
1745 cn_list = matrix_perspective_transform_channels;
1746 size_list = matrix_transform_sizes;
1747 whole_size_list = matrix_transform_whole_sizes;
1751 void CxCore_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1753 CvRNG* rng = ts->get_rng();
1754 int bits = cvTsRandInt(rng);
1755 int depth, cn, mattype;
1756 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1758 cn = CV_MAT_CN(types[INPUT][0]) + 1;
1759 depth = CV_MAT_DEPTH(types[INPUT][0]);
1760 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1762 mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1763 types[INPUT][1] = mattype;
1764 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1768 double CxCore_PerspectiveTransformTest::get_success_error_level( int test_case_idx, int i, int j )
1770 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1771 return depth == CV_32F ? 1e-4 : depth == CV_64F ? 1e-8 :
1772 CxCore_MatrixTest::get_success_error_level(test_case_idx, i, j);
1776 void CxCore_PerspectiveTransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1777 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1779 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1780 sizes, types, whole_sizes, are_images );
1781 int cn = CV_MAT_CN(types[INPUT][0]);
1782 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1783 types[INPUT][1] = CV_64FC1;
1787 void CxCore_PerspectiveTransformTest::run_func()
1789 cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1] );
1793 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
1796 int cn, depth, mat_depth;
1797 CvMat astub, bstub, *a, *b;
1798 double mat[16], *buf;
1800 a = cvGetMat( _src, &astub, 0, 0 );
1801 b = cvGetMat( _dst, &bstub, 0, 0 );
1803 cn = CV_MAT_CN(a->type);
1804 depth = CV_MAT_DEPTH(a->type);
1805 mat_depth = CV_MAT_DEPTH(transmat->type);
1806 cols = transmat->cols;
1808 // prepare cn x (cn + 1) transform matrix
1809 if( mat_depth == CV_32F )
1811 for( i = 0; i < transmat->rows; i++ )
1812 for( j = 0; j < cols; j++ )
1813 mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
1817 assert( mat_depth == CV_64F );
1818 for( i = 0; i < transmat->rows; i++ )
1819 for( j = 0; j < cols; j++ )
1820 mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
1824 cols = a->cols * cn;
1825 buf = (double*)cvStackAlloc( cols * sizeof(double) );
1827 for( i = 0; i < a->rows; i++ )
1829 uchar* src = a->data.ptr + i*a->step;
1830 uchar* dst = b->data.ptr + i*b->step;
1835 for( j = 0; j < cols; j++ )
1836 buf[j] = ((float*)src)[j];
1839 for( j = 0; j < cols; j++ )
1840 buf[j] = ((double*)src)[j];
1849 for( j = 0; j < cols; j += 2 )
1851 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2];
1852 double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5];
1853 double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8];
1860 for( j = 0; j < cols; j += 3 )
1862 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3];
1863 double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7];
1864 double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11];
1865 double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15];
1879 for( j = 0; j < cols; j++ )
1880 ((float*)dst)[j] = (float)buf[j];
1883 for( j = 0; j < cols; j++ )
1884 ((double*)dst)[j] = buf[j];
1893 void CxCore_PerspectiveTransformTest::prepare_to_validation( int )
1895 CvMat* transmat = &test_mat[INPUT][1];
1896 cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], transmat );
1899 CxCore_PerspectiveTransformTest perspective_test;
1902 ///////////////// Mahalanobis /////////////////////
1904 class CxCore_MahalanobisTest : public CxCore_MatrixTest
1907 CxCore_MahalanobisTest();
1909 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1910 void get_timing_test_array_types_and_sizes( int test_case_idx,
1911 CvSize** sizes, int** types,
1912 CvSize** whole_sizes, bool* are_images );
1913 int prepare_test_case( int test_case_idx );
1915 void prepare_to_validation( int test_case_idx );
1919 CxCore_MahalanobisTest::CxCore_MahalanobisTest() :
1920 CxCore_MatrixTest( "matrix-mahalanobis", "cvMahalanobis", 3, 1, false, true, 1 )
1922 test_case_count = 100;
1923 test_array[TEMP].push(NULL);
1924 test_array[TEMP].push(NULL);
1925 test_array[TEMP].push(NULL);
1929 void CxCore_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1931 CvRNG* rng = ts->get_rng();
1932 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1934 if( cvTsRandInt(rng) & 1 )
1935 sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
1937 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1939 sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0];
1940 sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1;
1941 sizes[TEMP][2] = sizes[INPUT][2];
1942 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
1946 void CxCore_MahalanobisTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1947 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1949 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1950 sizes, types, whole_sizes, are_images );
1951 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1955 int CxCore_MahalanobisTest::prepare_test_case( int test_case_idx )
1957 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1958 if( code > 0 && ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1960 // make sure that the inverted "covariation" matrix is symmetrix and positively defined.
1961 cvTsGEMM( &test_mat[INPUT][2], &test_mat[INPUT][2], 1., 0, 0., &test_mat[TEMP][2], CV_GEMM_B_T );
1962 cvTsCopy( &test_mat[TEMP][2], &test_mat[INPUT][2] );
1969 void CxCore_MahalanobisTest::run_func()
1971 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) =
1972 cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
1975 void CxCore_MahalanobisTest::prepare_to_validation( int )
1977 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
1978 &test_mat[INPUT][1], cvScalarAll(-1.),
1979 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1980 if( test_mat[INPUT][0].rows == 1 )
1981 cvTsGEMM( &test_mat[TEMP][0], &test_mat[INPUT][2], 1.,
1982 0, 0., &test_mat[TEMP][1], 0 );
1984 cvTsGEMM( &test_mat[INPUT][2], &test_mat[TEMP][0], 1.,
1985 0, 0., &test_mat[TEMP][1], 0 );
1987 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) =
1988 cvRealScalar(sqrt(cvTsCrossCorr(&test_mat[TEMP][0], &test_mat[TEMP][1])));
1991 CxCore_MahalanobisTest mahalanobis_test;
1994 ///////////////// covarmatrix /////////////////////
1996 class CxCore_CovarMatrixTest : public CxCore_MatrixTest
1999 CxCore_CovarMatrixTest();
2001 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2002 int prepare_test_case( int test_case_idx );
2004 void prepare_to_validation( int test_case_idx );
2005 CvTestPtrVec temp_hdrs;
2007 int flags, t_flag, len, count;
2012 CxCore_CovarMatrixTest::CxCore_CovarMatrixTest() :
2013 CxCore_MatrixTest( "matrix-covar", "cvCalcCovarMatrix", 1, 1, true, false, 1 ),
2014 flags(0), t_flag(0), are_images(false)
2016 test_case_count = 100;
2017 test_array[INPUT_OUTPUT].push(NULL);
2018 test_array[REF_INPUT_OUTPUT].push(NULL);
2019 test_array[TEMP].push(NULL);
2020 test_array[TEMP].push(NULL);
2022 support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
2026 void CxCore_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2028 CvRNG* rng = ts->get_rng();
2029 int bits = cvTsRandInt(rng);
2030 int i, single_matrix;
2031 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2033 flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS );
2034 single_matrix = flags & CV_COVAR_ROWS;
2035 t_flag = (bits & 256) != 0;
2037 const int min_count = 2;
2041 len = sizes[INPUT][0].width;
2042 count = sizes[INPUT][0].height;
2043 count = MAX(count, min_count);
2044 sizes[INPUT][0] = cvSize(len, count);
2048 len = sizes[INPUT][0].height;
2049 count = sizes[INPUT][0].width;
2050 count = MAX(count, min_count);
2051 sizes[INPUT][0] = cvSize(count, len);
2054 if( single_matrix && t_flag )
2055 flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
2057 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
2058 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
2060 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? cvSize(len,len) : cvSize(count,count);
2061 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? cvSize(len,1) : cvSize(1,len);
2062 sizes[TEMP][0] = sizes[INPUT][0];
2064 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] =
2065 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] =
2066 CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F;
2068 are_images = (bits & 1024) != 0;
2069 for( i = 0; i < (single_matrix ? 1 : count); i++ )
2070 temp_hdrs.push(NULL);
2074 int CxCore_CovarMatrixTest::prepare_test_case( int test_case_idx )
2076 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2080 int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
2081 int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
2083 hdr_data = (uchar*)cvAlloc( count*hdr_size );
2087 *((CvMat*)hdr_data) = test_mat[INPUT][0];
2089 cvGetImage( &test_mat[INPUT][0], (IplImage*)hdr_data );
2090 temp_hdrs[0] = hdr_data;
2093 for( i = 0; i < count; i++ )
2096 void* ptr = hdr_data + i*hdr_size;
2099 cvGetRow( &test_mat[INPUT][0], &part, i );
2101 cvGetCol( &test_mat[INPUT][0], &part, i );
2104 *((CvMat*)ptr) = part;
2106 cvGetImage( &part, (IplImage*)ptr );
2116 void CxCore_CovarMatrixTest::run_func()
2118 cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
2119 test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
2123 void CxCore_CovarMatrixTest::prepare_to_validation( int )
2125 CvMat* avg = &test_mat[REF_INPUT_OUTPUT][0];
2128 if( !(flags & CV_COVAR_USE_AVG) )
2133 for( i = 0; i < count; i++ )
2135 CvMat stub, *vec = 0;
2136 if( flags & CV_COVAR_ROWS )
2137 vec = cvGetRow( temp_hdrs[0], &stub, i );
2138 else if( flags & CV_COVAR_COLS )
2139 vec = cvGetCol( temp_hdrs[0], &stub, i );
2141 vec = cvGetMat( temp_hdrs[i], &stub );
2143 cvTsAdd( avg, cvScalarAll(1.), vec,
2144 cvScalarAll(1.), cvScalarAll(0.), avg, 0 );
2147 cvTsAdd( avg, cvScalarAll(1./count), 0,
2148 cvScalarAll(0.), cvScalarAll(0.), avg, 0 );
2151 if( flags & CV_COVAR_SCALE )
2156 cvRepeat( avg, &test_mat[TEMP][0] );
2157 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
2158 &test_mat[TEMP][0], cvScalarAll(-1.),
2159 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
2161 cvTsGEMM( &test_mat[TEMP][0], &test_mat[TEMP][0],
2162 scale, 0, 0., &test_mat[REF_OUTPUT][0],
2163 t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ?
2164 CV_GEMM_A_T : CV_GEMM_B_T );
2166 cvFree( &hdr_data );
2170 CxCore_CovarMatrixTest covarmatrix_test;
2173 static void cvTsFloodWithZeros( CvMat* mat, CvRNG* rng )
2175 int k, total = mat->rows*mat->cols;
2176 int zero_total = cvTsRandInt(rng) % total;
2177 assert( CV_MAT_TYPE(mat->type) == CV_32FC1 ||
2178 CV_MAT_TYPE(mat->type) == CV_64FC1 );
2180 for( k = 0; k < zero_total; k++ )
2182 int i = cvTsRandInt(rng) % mat->rows;
2183 int j = cvTsRandInt(rng) % mat->cols;
2184 uchar* row = mat->data.ptr + mat->step*i;
2186 if( CV_MAT_DEPTH(mat->type) == CV_32FC1 )
2187 ((float*)row)[j] = 0.f;
2189 ((double*)row)[j] = 0.;
2194 ///////////////// determinant /////////////////////
2196 class CxCore_DetTest : public CxCore_MatrixTest
2201 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2202 double get_success_error_level( int test_case_idx, int i, int j );
2203 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2204 int prepare_test_case( int test_case_idx );
2206 void prepare_to_validation( int test_case_idx );
2210 CxCore_DetTest::CxCore_DetTest() :
2211 CxCore_MatrixTest( "matrix-det", "cvDet", 1, 1, false, true, 1 )
2213 test_case_count = 100;
2214 max_log_array_size = 7;
2215 test_array[TEMP].push(NULL);
2219 void CxCore_DetTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2221 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2223 sizes[INPUT][0].width = sizes[INPUT][0].height = sizes[INPUT][0].height;
2224 sizes[TEMP][0] = sizes[INPUT][0];
2225 types[TEMP][0] = CV_64FC1;
2229 void CxCore_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2231 *low = cvScalarAll(-2.);
2232 *high = cvScalarAll(2.);
2236 double CxCore_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2238 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
2242 int CxCore_DetTest::prepare_test_case( int test_case_idx )
2244 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2246 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2252 void CxCore_DetTest::run_func()
2254 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvRealScalar(cvDet(test_array[INPUT][0]));
2258 // LU method that chooses the optimal in a column pivot element
2259 static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 )
2261 int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double);
2262 int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0;
2263 int x_step = x ? x->step/sizeof(double) : 0;
2264 double *a0 = a->data.db, *b0 = b ? b->data.db : 0;
2265 double *x0 = x ? x->data.db : 0;
2267 assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
2268 (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
2270 for( i = 0; i < Nm; i++ )
2272 double max_val = fabs(a0[i*step + i]);
2273 double *a1, *a2, *b1 = 0, *b2 = 0;
2276 for( j = i+1; j < N; j++ )
2278 t = fabs(a0[j*step + i]);
2288 for( j = i; j < N1; j++ )
2289 CV_SWAP( a0[i*step + j], a0[k*step + j], t );
2291 for( j = 0; j < M; j++ )
2292 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
2308 for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
2311 for( k = i+1; k < N1; k++ )
2314 for( k = 0; k < M; k++ )
2325 for( i = N-1; i >= 0; i-- )
2327 double* a1 = a0 + i*step;
2328 double* b1 = b0 + i*b_step;
2329 for( j = 0; j < M; j++ )
2332 for( k = i+1; k < N1; k++ )
2333 t -= a1[k]*x0[k*x_step + j];
2334 x0[i*x_step + j] = t/a1[i];
2345 void CxCore_DetTest::prepare_to_validation( int )
2347 if( !CV_ARE_TYPES_EQ( &test_mat[INPUT][0], &test_mat[TEMP][0] ))
2348 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
2350 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][0], 0 );
2352 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = cvRealScalar(cvTsLU(&test_mat[TEMP][0], 0, 0));
2355 CxCore_DetTest det_test;
2359 ///////////////// invert /////////////////////
2361 static const char* matrix_solve_invert_param_names[] = { "size", "method", "depth", 0 };
2362 static const char* matrix_solve_invert_methods[] = { "LU", "SVD", 0 };
2364 class CxCore_InvertTest : public CxCore_MatrixTest
2367 CxCore_InvertTest();
2369 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2370 void get_timing_test_array_types_and_sizes( int test_case_idx,
2371 CvSize** sizes, int** types,
2372 CvSize** whole_sizes, bool* are_images );
2373 int write_default_params( CvFileStorage* fs );
2374 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2375 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2376 double get_success_error_level( int test_case_idx, int i, int j );
2377 int prepare_test_case( int test_case_idx );
2379 void prepare_to_validation( int test_case_idx );
2385 CxCore_InvertTest::CxCore_InvertTest() :
2386 CxCore_MatrixTest( "matrix-invert", "cvInvert, cvSVD, cvSVBkSb", 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
2388 test_case_count = 100;
2389 max_log_array_size = 7;
2390 test_array[TEMP].push(NULL);
2391 test_array[TEMP].push(NULL);
2393 default_timing_param_names = matrix_solve_invert_param_names;
2397 void CxCore_InvertTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2399 CvRNG* rng = ts->get_rng();
2400 int bits = cvTsRandInt(rng);
2401 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2402 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2404 if( (bits & 3) == 0 )
2409 sizes[INPUT][0] = cvSize(min_size, min_size);
2411 method = CV_SVD_SYM;
2417 sizes[INPUT][0] = cvSize(min_size, min_size);
2420 sizes[TEMP][0].width = sizes[INPUT][0].height;
2421 sizes[TEMP][0].height = sizes[INPUT][0].width;
2422 sizes[TEMP][1] = sizes[INPUT][0];
2423 types[TEMP][0] = types[INPUT][0];
2424 types[TEMP][1] = CV_64FC1;
2425 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(min_size, min_size);
2429 void CxCore_InvertTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2430 CvSize** sizes, int** types,
2431 CvSize** whole_sizes, bool* are_images )
2433 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2434 sizes, types, whole_sizes, are_images );
2435 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2436 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2440 int CxCore_InvertTest::write_default_params( CvFileStorage* fs )
2442 int code = CxCore_MatrixTest::write_default_params(fs);
2443 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2445 write_string_list( fs, "method", matrix_solve_invert_methods );
2450 void CxCore_InvertTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2452 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2455 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2459 double CxCore_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
2461 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-7;
2464 int CxCore_InvertTest::prepare_test_case( int test_case_idx )
2466 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2469 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2471 if( method == CV_SVD_SYM )
2473 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][0], 1.,
2474 0, 0., &test_mat[TEMP][0], CV_GEMM_B_T );
2475 cvTsCopy( &test_mat[TEMP][0], &test_mat[INPUT][0] );
2484 void CxCore_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2486 *low = cvScalarAll(-2.);
2487 *high = cvScalarAll(2.);
2491 void CxCore_InvertTest::run_func()
2493 result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
2497 static double cvTsSVDet( CvMat* mat )
2499 int type = CV_MAT_TYPE(mat->type);
2500 int i, nm = MIN( mat->rows, mat->cols );
2501 CvMat* w = cvCreateMat( nm, 1, type );
2504 cvSVD( mat, w, 0, 0, 0 );
2506 if( type == CV_32FC1 )
2508 for( i = 0; i < nm; i++ )
2509 det *= w->data.fl[i];
2513 for( i = 0; i < nm; i++ )
2514 det *= w->data.db[i];
2521 void CxCore_InvertTest::prepare_to_validation( int )
2523 CvMat* input = &test_mat[INPUT][0];
2524 double det = cvTsSVDet( input );
2525 double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*500;
2527 if( CV_MAT_TYPE(input->type) == CV_32FC1 )
2528 cvTsConvert( input, &test_mat[TEMP][1] );
2530 cvTsCopy( input, &test_mat[TEMP][1], 0 );
2532 if( (method == CV_LU && result == 0) ||
2533 (det < threshold || result < threshold) )
2535 cvTsZero( &test_mat[OUTPUT][0] );
2536 cvTsZero( &test_mat[REF_OUTPUT][0] );
2537 //cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(fabs(det)>1e-3),
2538 // &test_mat[REF_OUTPUT][0], 0 );
2542 if( input->rows >= input->cols )
2543 cvTsGEMM( &test_mat[TEMP][0], input, 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2545 cvTsGEMM( input, &test_mat[TEMP][0], 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2547 cvTsSetIdentity( &test_mat[REF_OUTPUT][0], cvScalarAll(1.) );
2550 CxCore_InvertTest invert_test;
2553 ///////////////// solve /////////////////////
2555 class CxCore_SolveTest : public CxCore_MatrixTest
2560 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2561 void get_timing_test_array_types_and_sizes( int test_case_idx,
2562 CvSize** sizes, int** types,
2563 CvSize** whole_sizes, bool* are_images );
2564 int write_default_params( CvFileStorage* fs );
2565 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2566 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2567 double get_success_error_level( int test_case_idx, int i, int j );
2568 int prepare_test_case( int test_case_idx );
2570 void prepare_to_validation( int test_case_idx );
2576 CxCore_SolveTest::CxCore_SolveTest() :
2577 CxCore_MatrixTest( "matrix-solve", "cvSolve, cvSVD, cvSVBkSb", 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
2579 test_case_count = 100;
2580 max_log_array_size = 7;
2581 test_array[TEMP].push(NULL);
2582 test_array[TEMP].push(NULL);
2584 default_timing_param_names = matrix_solve_invert_param_names;
2588 void CxCore_SolveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2590 CvRNG* rng = ts->get_rng();
2591 int bits = cvTsRandInt(rng);
2592 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2593 CvSize in_sz = sizes[INPUT][0];
2594 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2595 sizes[INPUT][0] = in_sz;
2596 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2598 if( (bits & 3) == 0 )
2603 sizes[INPUT][0] = cvSize(min_size, min_size);
2605 method = CV_SVD_SYM;*/
2611 sizes[INPUT][0] = cvSize(min_size, min_size);
2614 sizes[INPUT][1].height = sizes[INPUT][0].height;
2615 sizes[TEMP][0].width = sizes[INPUT][1].width;
2616 sizes[TEMP][0].height = sizes[INPUT][0].width;
2617 sizes[TEMP][1] = sizes[INPUT][0];
2618 types[TEMP][0] = types[INPUT][0];
2619 types[TEMP][1] = CV_64FC1;
2620 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][1].width, min_size);
2623 void CxCore_SolveTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2624 CvSize** sizes, int** types,
2625 CvSize** whole_sizes, bool* are_images )
2627 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2628 sizes, types, whole_sizes, are_images );
2629 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2630 sizes[INPUT][1].width = sizes[TEMP][0].width = sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = 1;
2631 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2635 int CxCore_SolveTest::write_default_params( CvFileStorage* fs )
2637 int code = CxCore_MatrixTest::write_default_params(fs);
2638 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2640 write_string_list( fs, "method", matrix_solve_invert_methods );
2645 void CxCore_SolveTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2647 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2650 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2654 int CxCore_SolveTest::prepare_test_case( int test_case_idx )
2656 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2658 /*if( method == CV_SVD_SYM )
2660 cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1.,
2661 0, 0., test_array[TEMP][0], CV_GEMM_B_T );
2662 cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] );
2669 void CxCore_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2671 *low = cvScalarAll(-2.);
2672 *high = cvScalarAll(2.);
2676 double CxCore_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
2678 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 3e-2 : 1e-8;
2682 void CxCore_SolveTest::run_func()
2684 result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
2687 void CxCore_SolveTest::prepare_to_validation( int )
2689 //int rank = test_mat[REF_OUTPUT][0].rows;
2692 if( method == CV_LU && result == 0 )
2694 if( CV_MAT_TYPE(test_mat[INPUT][0].type) == CV_32FC1 )
2695 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][1] );
2697 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][1], 0 );
2699 cvTsZero( &test_mat[OUTPUT][0] );
2700 double det = cvTsLU( &test_mat[TEMP][1], 0, 0 );
2701 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(det != 0),
2702 &test_mat[REF_OUTPUT][0], 0 );
2706 dst = test_mat[INPUT][0].rows <= test_mat[INPUT][0].cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
2708 cvTsGEMM( &test_mat[INPUT][0], &test_mat[TEMP][0], 1., &test_mat[INPUT][1], -1., dst, 0 );
2709 if( dst != &test_mat[OUTPUT][0] )
2710 cvTsGEMM( &test_mat[INPUT][0], dst, 1., 0, 0., &test_mat[OUTPUT][0], CV_GEMM_A_T );
2711 cvTsZero( &test_mat[REF_OUTPUT][0] );
2714 CxCore_SolveTest solve_test;
2717 ///////////////// SVD /////////////////////
2719 static const char* matrix_svd_param_names[] = { "size", "output", "depth", 0 };
2720 static const char* matrix_svd_output_modes[] = { "w", "all", 0 };
2722 class CxCore_SVDTest : public CxCore_MatrixTest
2727 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2728 void get_timing_test_array_types_and_sizes( int test_case_idx,
2729 CvSize** sizes, int** types,
2730 CvSize** whole_sizes, bool* are_images );
2731 double get_success_error_level( int test_case_idx, int i, int j );
2732 int write_default_params( CvFileStorage* fs );
2733 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2734 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2735 int prepare_test_case( int test_case_idx );
2737 void prepare_to_validation( int test_case_idx );
2739 bool have_u, have_v, symmetric, compact, vector_w;
2743 CxCore_SVDTest::CxCore_SVDTest() :
2744 CxCore_MatrixTest( "matrix-svd", "cvSVD", 1, 4, false, false, 1 ),
2745 flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false)
2747 test_case_count = 100;
2748 test_array[TEMP].push(NULL);
2749 test_array[TEMP].push(NULL);
2750 test_array[TEMP].push(NULL);
2751 test_array[TEMP].push(NULL);
2753 default_timing_param_names = matrix_svd_param_names;
2757 void CxCore_SVDTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2759 CvRNG* rng = ts->get_rng();
2760 int bits = cvTsRandInt(rng);
2761 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2762 int min_size, i, m, n;
2764 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2766 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
2767 have_u = (bits & 8) != 0;
2768 have_v = (bits & 16) != 0;
2769 symmetric = (bits & 32) != 0;
2770 compact = (bits & 64) != 0;
2771 vector_w = (bits & 128) != 0;
2774 sizes[INPUT][0] = cvSize(min_size, min_size);
2776 m = sizes[INPUT][0].height;
2777 n = sizes[INPUT][0].width;
2780 sizes[TEMP][0] = cvSize(min_size, min_size);
2782 sizes[TEMP][0] = sizes[INPUT][0];
2783 sizes[TEMP][3] = cvSize(0,0);
2787 sizes[TEMP][3] = sizes[TEMP][0];
2789 sizes[TEMP][0] = cvSize(1, min_size);
2791 sizes[TEMP][0] = cvSize(min_size, 1);
2796 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
2798 if( flags & CV_SVD_U_T )
2799 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
2802 sizes[TEMP][1] = cvSize(0,0);
2806 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
2808 if( !(flags & CV_SVD_V_T) )
2809 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
2812 sizes[TEMP][2] = cvSize(0,0);
2814 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0];
2815 types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0];
2816 types[OUTPUT][3] = CV_8UC1;
2817 sizes[OUTPUT][0] = !have_u || !have_v ? cvSize(0,0) : sizes[INPUT][0];
2818 sizes[OUTPUT][1] = !have_u ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(m,m);
2819 sizes[OUTPUT][2] = !have_v ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(n,n);
2820 sizes[OUTPUT][3] = cvSize(min_size,1);
2822 for( i = 0; i < 4; i++ )
2824 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
2825 types[REF_OUTPUT][i] = types[OUTPUT][i];
2830 void CxCore_SVDTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2831 CvSize** sizes, int** types,
2832 CvSize** whole_sizes, bool* are_images )
2834 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2835 sizes, types, whole_sizes, are_images );
2836 const char* output_str = cvReadString( find_timing_param("output"), "all" );
2837 bool need_all = strcmp( output_str, "all" ) == 0;
2838 int i, count = test_array[OUTPUT].size();
2842 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
2845 have_u = have_v = true;
2849 have_u = have_v = false;
2850 sizes[TEMP][1] = sizes[TEMP][2] = cvSize(0,0);
2853 flags = CV_SVD_U_T + CV_SVD_V_T;
2854 for( i = 0; i < count; i++ )
2855 sizes[OUTPUT][i] = sizes[REF_OUTPUT][i] = cvSize(0,0);
2856 sizes[OUTPUT][0] = cvSize(1,1);
2860 int CxCore_SVDTest::write_default_params( CvFileStorage* fs )
2862 int code = CxCore_MatrixTest::write_default_params(fs);
2863 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2865 write_string_list( fs, "output", matrix_svd_output_modes );
2870 void CxCore_SVDTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2872 sprintf( ptr, "%s,", have_u ? "all" : "w" );
2875 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2879 int CxCore_SVDTest::prepare_test_case( int test_case_idx )
2881 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2884 CvMat* input = &test_mat[INPUT][0];
2885 cvTsFloodWithZeros( input, ts->get_rng() );
2887 if( symmetric && (have_u || have_v) )
2889 CvMat* temp = &test_mat[TEMP][have_u ? 1 : 2];
2890 cvTsGEMM( input, input, 1.,
2891 0, 0., temp, CV_GEMM_B_T );
2892 cvTsCopy( temp, input );
2895 if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
2896 cvTsCopy( input, &test_mat[OUTPUT][0] );
2903 void CxCore_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2905 *low = cvScalarAll(-2.);
2906 *high = cvScalarAll(2.);
2909 double CxCore_SVDTest::get_success_error_level( int test_case_idx, int i, int j )
2911 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
2912 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ?
2914 double output_precision = CvArrTest::get_success_error_level( test_case_idx, i, j );
2915 return MAX(input_precision, output_precision);
2918 void CxCore_SVDTest::run_func()
2920 CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
2922 src = test_array[INPUT][0];
2923 cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
2927 void CxCore_SVDTest::prepare_to_validation( int )
2929 CvMat* input = &test_mat[INPUT][0];
2930 int m = input->rows, n = input->cols, min_size = MIN(m, n);
2931 CvMat *src, *dst, *w;
2932 double prev = 0, threshold = CV_MAT_TYPE(input->type) == CV_32FC1 ? FLT_EPSILON : DBL_EPSILON;
2937 src = &test_mat[TEMP][1];
2938 dst = &test_mat[OUTPUT][1];
2939 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2940 cvTsSetIdentity( &test_mat[REF_OUTPUT][1], cvScalarAll(1.) );
2945 src = &test_mat[TEMP][2];
2946 dst = &test_mat[OUTPUT][2];
2947 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2948 cvTsSetIdentity( &test_mat[REF_OUTPUT][2], cvScalarAll(1.) );
2951 w = &test_mat[TEMP][0];
2952 step = w->rows == 1 ? 1 : w->step/CV_ELEM_SIZE(w->type);
2953 for( i = 0; i < min_size; i++ )
2955 double norm = 0, aii;
2957 if( w->rows > 1 && w->cols > 1 )
2960 cvGetRow( w, &row, i );
2961 norm = cvNorm( &row, 0, CV_L1 );
2963 row_ptr = row.data.ptr;
2967 row_ptr = w->data.ptr;
2971 aii = CV_MAT_TYPE(w->type) == CV_32FC1 ?
2972 (double)((float*)row_ptr)[j] : ((double*)row_ptr)[j];
2973 if( w->rows == 1 || w->cols == 1 )
2975 norm = fabs(norm - aii);
2976 test_mat[OUTPUT][3].data.ptr[i] = aii >= 0 && norm < threshold && (i == 0 || aii <= prev);
2980 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.),
2981 cvScalarAll(1.), &test_mat[REF_OUTPUT][3], 0 );
2983 if( have_u && have_v )
2987 cvTsZero( &test_mat[TEMP][3] );
2988 for( i = 0; i < min_size; i++ )
2990 double val = cvGetReal1D( w, i );
2991 cvSetReal2D( &test_mat[TEMP][3], i, i, val );
2993 w = &test_mat[TEMP][3];
2998 cvTsGEMM( &test_mat[TEMP][1], w, 1., 0, 0., &test_mat[REF_OUTPUT][0],
2999 flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
3000 cvTsGEMM( &test_mat[REF_OUTPUT][0], &test_mat[TEMP][2], 1., 0, 0.,
3001 &test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
3005 cvTsGEMM( w, &test_mat[TEMP][2], 1., 0, 0., &test_mat[REF_OUTPUT][0],
3006 flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
3007 cvTsGEMM( &test_mat[TEMP][1], &test_mat[REF_OUTPUT][0], 1., 0, 0.,
3008 &test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
3011 cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], 0 );
3016 CxCore_SVDTest svd_test;
3019 ///////////////// SVBkSb /////////////////////
3021 class CxCore_SVBkSbTest : public CxCore_MatrixTest
3024 CxCore_SVBkSbTest();
3026 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
3027 void get_timing_test_array_types_and_sizes( int test_case_idx,
3028 CvSize** sizes, int** types,
3029 CvSize** whole_sizes, bool* are_images );
3030 double get_success_error_level( int test_case_idx, int i, int j );
3031 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
3032 int prepare_test_case( int test_case_idx );
3034 void prepare_to_validation( int test_case_idx );
3036 bool have_b, symmetric, compact, vector_w;
3040 CxCore_SVBkSbTest::CxCore_SVBkSbTest() :
3041 CxCore_MatrixTest( "matrix-svbksb", "cvSVBkSb", 2, 1, false, false, 1 ),
3042 flags(0), have_b(false), symmetric(false), compact(false), vector_w(false)
3044 test_case_count = 100;
3045 test_array[TEMP].push(NULL);
3046 test_array[TEMP].push(NULL);
3047 test_array[TEMP].push(NULL);
3051 void CxCore_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
3053 CvRNG* rng = ts->get_rng();
3054 int bits = cvTsRandInt(rng);
3055 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
3056 int min_size, i, m, n;
3059 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
3061 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
3062 have_b = (bits & 16) != 0;
3063 symmetric = (bits & 32) != 0;
3064 compact = (bits & 64) != 0;
3065 vector_w = (bits & 128) != 0;
3068 sizes[INPUT][0] = cvSize(min_size, min_size);
3070 m = sizes[INPUT][0].height;
3071 n = sizes[INPUT][0].width;
3073 sizes[INPUT][1] = cvSize(0,0);
3074 b_size = cvSize(m,m);
3077 sizes[INPUT][1].height = sizes[INPUT][0].height;
3078 sizes[INPUT][1].width = cvTsRandInt(rng) % 100 + 1;
3079 b_size = sizes[INPUT][1];
3083 sizes[TEMP][0] = cvSize(min_size, min_size);
3085 sizes[TEMP][0] = sizes[INPUT][0];
3090 sizes[TEMP][0] = cvSize(1, min_size);
3092 sizes[TEMP][0] = cvSize(min_size, 1);
3095 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
3097 if( flags & CV_SVD_U_T )
3098 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
3100 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
3102 if( !(flags & CV_SVD_V_T) )
3103 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
3105 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
3106 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0];
3107 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( b_size.width, n );
3111 void CxCore_SVBkSbTest::get_timing_test_array_types_and_sizes( int test_case_idx,
3112 CvSize** sizes, int** types,
3113 CvSize** whole_sizes, bool* are_images )
3115 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
3116 sizes, types, whole_sizes, are_images );
3120 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
3121 sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1,sizes[INPUT][0].height);
3122 flags = CV_SVD_U_T + CV_SVD_V_T;
3126 int CxCore_SVBkSbTest::prepare_test_case( int test_case_idx )
3128 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
3131 CvMat* input = &test_mat[INPUT][0];
3132 cvTsFloodWithZeros( input, ts->get_rng() );
3136 CvMat* temp = &test_mat[TEMP][1];
3137 cvTsGEMM( input, input, 1., 0, 0., temp, CV_GEMM_B_T );
3138 cvTsCopy( temp, input );
3141 cvSVD( input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
3148 void CxCore_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
3150 *low = cvScalarAll(-2.);
3151 *high = cvScalarAll(2.);
3155 double CxCore_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
3157 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
3161 void CxCore_SVBkSbTest::run_func()
3163 cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
3164 test_array[INPUT][1], test_array[OUTPUT][0], flags );
3168 void CxCore_SVBkSbTest::prepare_to_validation( int )
3170 CvMat* input = &test_mat[INPUT][0];
3171 int i, m = input->rows, n = input->cols, min_size = MIN(m, n), nb;
3172 bool is_float = CV_MAT_DEPTH(input->type) == CV_32F;
3173 CvSize w_size = compact ? cvSize(min_size,min_size) : cvSize(m,n);
3174 CvMat* w = &test_mat[TEMP][0];
3175 CvMat* wdb = cvCreateMat( w_size.height, w_size.width, CV_64FC1 );
3176 // use exactly the same threshold as in icvSVD... ,
3177 // so the changes in the library and here should be synchronized.
3178 double threshold = cvSum( w ).val[0]*2*(is_float ? FLT_EPSILON : DBL_EPSILON);
3179 CvMat *u, *v, *b, *t0, *t1;
3182 for( i = 0; i < min_size; i++ )
3184 double wii = vector_w ? cvGetReal1D(w,i) : cvGetReal2D(w,i,i);
3185 cvSetReal2D( wdb, i, i, wii > threshold ? 1./wii : 0. );
3188 u = &test_mat[TEMP][1];
3189 v = &test_mat[TEMP][2];
3193 if( test_array[INPUT][1] )
3195 b = &test_mat[INPUT][1];
3201 u = cvCreateMat( u->rows, u->cols, CV_64F );
3202 cvTsConvert( &test_mat[TEMP][1], u );
3205 b = cvCreateMat( b->rows, b->cols, CV_64F );
3206 cvTsConvert( &test_mat[INPUT][1], b );
3210 t0 = cvCreateMat( wdb->cols, nb, CV_64F );
3213 cvTsGEMM( u, b, 1., 0, 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 );
3214 else if( flags & CV_SVD_U_T )
3217 cvTsTranspose( u, t0 );
3226 v = cvCreateMat( v->rows, v->cols, CV_64F );
3233 cvTsConvert( &test_mat[TEMP][2], v );
3236 t1 = cvCreateMat( wdb->rows, nb, CV_64F );
3237 cvTsGEMM( wdb, t0, 1, 0, 0, t1, 0 );
3239 if( !is_float || !symmetric )
3241 cvReleaseMat( &t0 );
3242 t0 = !is_float ? &test_mat[REF_OUTPUT][0] : cvCreateMat( test_mat[REF_OUTPUT][0].rows, nb, CV_64F );
3245 cvTsGEMM( v, t1, 1, 0, 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 );
3246 cvReleaseMat( &t1 );
3248 if( t0 != &test_mat[REF_OUTPUT][0] )
3250 cvTsConvert( t0, &test_mat[REF_OUTPUT][0] );
3251 cvReleaseMat( &t0 );
3254 if( v != &test_mat[TEMP][2] )
3257 cvReleaseMat( &wdb );
3261 CxCore_SVBkSbTest svbksb_test;
3264 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),