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+1);
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 max_log_array_size = 10;
1313 default_timing_param_names = matrix_gemm_param_names;
1318 void CxCore_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1320 CvRNG* rng = ts->get_rng();
1322 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1323 sizeA = sizes[INPUT][0];
1324 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1325 sizes[INPUT][0] = sizeA;
1326 sizes[INPUT][2] = sizes[INPUT][3] = cvSize(1,1);
1327 types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK;
1329 tabc_flag = cvTsRandInt(rng) & 7;
1331 switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
1334 sizes[INPUT][1].height = sizes[INPUT][0].width;
1335 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1336 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1339 sizes[INPUT][1].width = sizes[INPUT][0].width;
1340 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1341 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1344 sizes[INPUT][1].height = sizes[INPUT][0].height;
1345 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1346 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1348 case CV_GEMM_A_T | CV_GEMM_B_T:
1349 sizes[INPUT][1].width = sizes[INPUT][0].height;
1350 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1351 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1355 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1357 if( cvTsRandInt(rng) & 1 )
1358 sizes[INPUT][4] = cvSize(0,0);
1359 else if( !(tabc_flag & CV_GEMM_C_T) )
1360 sizes[INPUT][4] = sizes[OUTPUT][0];
1363 sizes[INPUT][4].width = sizes[OUTPUT][0].height;
1364 sizes[INPUT][4].height = sizes[OUTPUT][0].width;
1369 void CxCore_GEMMTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1370 CvSize** sizes, int** types,
1371 CvSize** whole_sizes, bool* are_images )
1373 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1374 sizes, types, whole_sizes, are_images );
1375 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AB" );
1376 if( strcmp( mul_type, "AtB" ) == 0 )
1377 tabc_flag = CV_GEMM_A_T;
1378 else if( strcmp( mul_type, "ABt" ) == 0 )
1379 tabc_flag = CV_GEMM_B_T;
1380 else if( strcmp( mul_type, "AtBt" ) == 0 )
1381 tabc_flag = CV_GEMM_A_T + CV_GEMM_B_T;
1385 if( cvReadInt( find_timing_param( "add_c" ), 0 ) == 0 )
1386 sizes[INPUT][4] = cvSize(0,0);
1390 int CxCore_GEMMTest::write_default_params( CvFileStorage* fs )
1392 int code = CxCore_MatrixTest::write_default_params(fs);
1393 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1395 write_string_list( fs, "mul_type", matrix_gemm_mul_types );
1396 write_int_list( fs, "add_c", matrix_gemm_add_c_flags, CV_DIM(matrix_gemm_add_c_flags) );
1401 void CxCore_GEMMTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1403 sprintf( ptr, "%s%s,%s,",
1404 tabc_flag & CV_GEMM_A_T ? "At" : "A",
1405 tabc_flag & CV_GEMM_B_T ? "Bt" : "B",
1406 test_array[INPUT][4] ? "plusC" : "" );
1409 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1413 int CxCore_GEMMTest::prepare_test_case( int test_case_idx )
1415 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1418 alpha = cvmGet( &test_mat[INPUT][2], 0, 0 );
1419 beta = cvmGet( &test_mat[INPUT][3], 0, 0 );
1425 void CxCore_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1427 *low = cvScalarAll(-10.);
1428 *high = cvScalarAll(10.);
1432 void CxCore_GEMMTest::run_func()
1434 cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
1435 test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
1439 void CxCore_GEMMTest::prepare_to_validation( int )
1441 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][1], alpha,
1442 test_array[INPUT][4] ? &test_mat[INPUT][4] : 0,
1443 beta, &test_mat[REF_OUTPUT][0], tabc_flag );
1446 CxCore_GEMMTest gemm_test;
1449 ///////////////// multransposed /////////////////////
1451 static const char* matrix_multrans_param_names[] = { "size", "use_delta", "mul_type", "depth", 0 };
1452 static const int matrix_multrans_use_delta_flags[] = { 0, 1 };
1453 static const char* matrix_multrans_mul_types[] = { "AAt", "AtA", 0 };
1455 class CxCore_MulTransposedTest : public CxCore_MatrixTest
1458 CxCore_MulTransposedTest();
1460 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1461 void get_timing_test_array_types_and_sizes( int test_case_idx,
1462 CvSize** sizes, int** types,
1463 CvSize** whole_sizes, bool* are_images );
1464 int write_default_params( CvFileStorage* fs );
1465 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1466 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1468 void prepare_to_validation( int test_case_idx );
1473 CxCore_MulTransposedTest::CxCore_MulTransposedTest() :
1474 CxCore_MatrixTest( "matrix-multransposed", "cvMulTransposed, cvRepeat", 2, 1, false, false, 1 )
1476 test_case_count = 100;
1478 test_array[TEMP].push(NULL);
1479 default_timing_param_names = matrix_multrans_param_names;
1483 void CxCore_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1485 CvRNG* rng = ts->get_rng();
1486 int bits = cvTsRandInt(rng);
1487 int src_type = cvTsRandInt(rng) % 5;
1488 int dst_type = cvTsRandInt(rng) % 2;
1490 src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S :
1491 src_type == 3 ? CV_32F : CV_64F;
1492 dst_type = dst_type == 0 ? CV_32F : CV_64F;
1493 dst_type = MAX( dst_type, src_type );
1495 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1498 sizes[INPUT][1] = cvSize(0,0);
1501 sizes[INPUT][1] = sizes[INPUT][0];
1503 sizes[INPUT][1].height = 1;
1505 sizes[INPUT][1].width = 1;
1508 sizes[TEMP][0] = sizes[INPUT][0];
1509 types[INPUT][0] = src_type;
1510 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type;
1512 order = (bits & 8) != 0;
1513 sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ?
1514 sizes[INPUT][0].height : sizes[INPUT][0].width;
1515 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1519 void CxCore_MulTransposedTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1520 CvSize** sizes, int** types,
1521 CvSize** whole_sizes, bool* are_images )
1523 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1524 sizes, types, whole_sizes, are_images );
1525 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AAt" );
1526 order = strcmp( mul_type, "AtA" ) == 0;
1528 if( cvReadInt( find_timing_param( "use_delta" ), 0 ) == 0 )
1529 sizes[INPUT][1] = cvSize(0,0);
1533 int CxCore_MulTransposedTest::write_default_params( CvFileStorage* fs )
1535 int code = CxCore_MatrixTest::write_default_params(fs);
1536 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1538 write_string_list( fs, "mul_type", matrix_multrans_mul_types );
1539 write_int_list( fs, "use_delta", matrix_multrans_use_delta_flags,
1540 CV_DIM(matrix_multrans_use_delta_flags) );
1545 void CxCore_MulTransposedTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1547 sprintf( ptr, "%s,%s,", order == 0 ? "AAt" : "AtA", test_array[INPUT][1] ? "delta" : "" );
1550 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1554 void CxCore_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1556 *low = cvScalarAll(-10.);
1557 *high = cvScalarAll(10.);
1561 void CxCore_MulTransposedTest::run_func()
1563 cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
1564 order, test_array[INPUT][1] );
1568 void CxCore_MulTransposedTest::prepare_to_validation( int )
1570 CvMat* delta = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
1573 if( test_mat[INPUT][1].rows < test_mat[INPUT][0].rows ||
1574 test_mat[INPUT][1].cols < test_mat[INPUT][0].cols )
1576 cvRepeat( delta, &test_mat[TEMP][0] );
1577 delta = &test_mat[TEMP][0];
1579 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.), delta, cvScalarAll(-1.),
1580 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1583 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
1584 delta = &test_mat[TEMP][0];
1586 cvTsGEMM( delta, delta, 1., 0, 0, &test_mat[REF_OUTPUT][0], order == 0 ? CV_GEMM_B_T : CV_GEMM_A_T );
1589 CxCore_MulTransposedTest multransposed_test;
1592 ///////////////// Transform /////////////////////
1594 static const CvSize matrix_transform_sizes[] = {{10,10}, {100,100}, {720,480}, {-1,-1}};
1595 static const CvSize matrix_transform_whole_sizes[] = {{10,10}, {720,480}, {720,480}, {-1,-1}};
1596 static const int matrix_transform_channels[] = { 2, 3, 4, -1 };
1597 static const char* matrix_transform_param_names[] = { "size", "channels", "depth", 0 };
1599 class CxCore_TransformTest : public CxCore_MatrixTest
1602 CxCore_TransformTest();
1604 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1605 double get_success_error_level( int test_case_idx, int i, int j );
1606 void get_timing_test_array_types_and_sizes( int test_case_idx,
1607 CvSize** sizes, int** types,
1608 CvSize** whole_sizes, bool* are_images );
1609 int prepare_test_case( int test_case_idx );
1610 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1612 void prepare_to_validation( int test_case_idx );
1619 CxCore_TransformTest::CxCore_TransformTest() :
1620 CxCore_MatrixTest( "matrix-transform", "cvTransform", 3, 1, true, false, 4 )
1622 default_timing_param_names = matrix_transform_param_names;
1623 cn_list = matrix_transform_channels;
1624 depth_list = matrix_all_depths;
1625 size_list = matrix_transform_sizes;
1626 whole_size_list = matrix_transform_whole_sizes;
1630 void CxCore_TransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1632 CvRNG* rng = ts->get_rng();
1633 int bits = cvTsRandInt(rng);
1634 int depth, dst_cn, mat_cols, mattype;
1635 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1637 mat_cols = CV_MAT_CN(types[INPUT][0]);
1638 depth = CV_MAT_DEPTH(types[INPUT][0]);
1639 dst_cn = cvTsRandInt(rng) % 4 + 1;
1640 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
1642 mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1643 types[INPUT][1] = mattype;
1644 types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
1646 scale = 1./((cvTsRandInt(rng)%4)*50+1);
1650 sizes[INPUT][2] = cvSize(0,0);
1651 mat_cols += (bits & 4) != 0;
1654 sizes[INPUT][2] = cvSize(1,1);
1658 sizes[INPUT][2] = cvSize(dst_cn,1);
1660 sizes[INPUT][2] = cvSize(1,dst_cn);
1661 types[INPUT][2] &= ~CV_MAT_CN_MASK;
1663 diagMtx = (bits & 16) != 0;
1665 sizes[INPUT][1] = cvSize(mat_cols,dst_cn);
1669 void CxCore_TransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1670 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1672 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1673 sizes, types, whole_sizes, are_images );
1674 int cn = CV_MAT_CN(types[INPUT][0]);
1675 sizes[INPUT][1] = cvSize(cn + (cn < 4), cn);
1676 sizes[INPUT][2] = cvSize(0,0);
1677 types[INPUT][1] = types[INPUT][2] = CV_64FC1;
1681 int CxCore_TransformTest::prepare_test_case( int test_case_idx )
1683 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1686 cvTsAdd(&test_mat[INPUT][1], cvScalarAll(scale), &test_mat[INPUT][1],
1687 cvScalarAll(0), cvScalarAll(0), &test_mat[INPUT][1], 0 );
1690 CvMat* w = cvCloneMat(&test_mat[INPUT][1]);
1691 cvSetIdentity(w, cvScalarAll(1));
1692 cvMul(w, &test_mat[INPUT][1], &test_mat[INPUT][1]);
1699 void CxCore_TransformTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1701 CvSize size = cvGetMatSize(&test_mat[INPUT][1]);
1702 sprintf( ptr, "matrix=%dx%d,", size.height, size.width );
1705 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1709 double CxCore_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
1711 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1712 return depth <= CV_8S ? 1 : depth <= CV_32S ? 8 :
1713 CxCore_MatrixTest::get_success_error_level( test_case_idx, i, j );
1716 void CxCore_TransformTest::run_func()
1718 cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1],
1719 test_array[INPUT][2] ? &test_mat[INPUT][2] : 0);
1723 void CxCore_TransformTest::prepare_to_validation( int )
1725 CvMat* transmat = &test_mat[INPUT][1];
1726 CvMat* shift = test_array[INPUT][2] ? &test_mat[INPUT][2] : 0;
1728 cvTsTransform( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], transmat, shift );
1731 CxCore_TransformTest transform_test;
1734 ///////////////// PerspectiveTransform /////////////////////
1736 static const int matrix_perspective_transform_channels[] = { 2, 3, -1 };
1738 class CxCore_PerspectiveTransformTest : public CxCore_MatrixTest
1741 CxCore_PerspectiveTransformTest();
1743 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1744 double get_success_error_level( int test_case_idx, int i, int j );
1745 void get_timing_test_array_types_and_sizes( int test_case_idx,
1746 CvSize** sizes, int** types,
1747 CvSize** whole_sizes, bool* are_images );
1749 void prepare_to_validation( int test_case_idx );
1753 CxCore_PerspectiveTransformTest::CxCore_PerspectiveTransformTest() :
1754 CxCore_MatrixTest( "matrix-perspective", "cvPerspectiveTransform", 2, 1, false, false, 2 )
1756 default_timing_param_names = matrix_transform_param_names;
1757 cn_list = matrix_perspective_transform_channels;
1758 size_list = matrix_transform_sizes;
1759 whole_size_list = matrix_transform_whole_sizes;
1763 void CxCore_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1765 CvRNG* rng = ts->get_rng();
1766 int bits = cvTsRandInt(rng);
1767 int depth, cn, mattype;
1768 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1770 cn = CV_MAT_CN(types[INPUT][0]) + 1;
1771 depth = CV_MAT_DEPTH(types[INPUT][0]);
1772 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1774 mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1775 types[INPUT][1] = mattype;
1776 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1780 double CxCore_PerspectiveTransformTest::get_success_error_level( int test_case_idx, int i, int j )
1782 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1783 return depth == CV_32F ? 1e-4 : depth == CV_64F ? 1e-8 :
1784 CxCore_MatrixTest::get_success_error_level(test_case_idx, i, j);
1788 void CxCore_PerspectiveTransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1789 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1791 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1792 sizes, types, whole_sizes, are_images );
1793 int cn = CV_MAT_CN(types[INPUT][0]);
1794 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1795 types[INPUT][1] = CV_64FC1;
1799 void CxCore_PerspectiveTransformTest::run_func()
1801 cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1] );
1805 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
1808 int cn, depth, mat_depth;
1809 CvMat astub, bstub, *a, *b;
1810 double mat[16], *buf;
1812 a = cvGetMat( _src, &astub, 0, 0 );
1813 b = cvGetMat( _dst, &bstub, 0, 0 );
1815 cn = CV_MAT_CN(a->type);
1816 depth = CV_MAT_DEPTH(a->type);
1817 mat_depth = CV_MAT_DEPTH(transmat->type);
1818 cols = transmat->cols;
1820 // prepare cn x (cn + 1) transform matrix
1821 if( mat_depth == CV_32F )
1823 for( i = 0; i < transmat->rows; i++ )
1824 for( j = 0; j < cols; j++ )
1825 mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
1829 assert( mat_depth == CV_64F );
1830 for( i = 0; i < transmat->rows; i++ )
1831 for( j = 0; j < cols; j++ )
1832 mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
1836 cols = a->cols * cn;
1837 buf = (double*)cvStackAlloc( cols * sizeof(double) );
1839 for( i = 0; i < a->rows; i++ )
1841 uchar* src = a->data.ptr + i*a->step;
1842 uchar* dst = b->data.ptr + i*b->step;
1847 for( j = 0; j < cols; j++ )
1848 buf[j] = ((float*)src)[j];
1851 for( j = 0; j < cols; j++ )
1852 buf[j] = ((double*)src)[j];
1861 for( j = 0; j < cols; j += 2 )
1863 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2];
1864 double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5];
1865 double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8];
1872 for( j = 0; j < cols; j += 3 )
1874 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3];
1875 double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7];
1876 double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11];
1877 double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15];
1891 for( j = 0; j < cols; j++ )
1892 ((float*)dst)[j] = (float)buf[j];
1895 for( j = 0; j < cols; j++ )
1896 ((double*)dst)[j] = buf[j];
1905 void CxCore_PerspectiveTransformTest::prepare_to_validation( int )
1907 CvMat* transmat = &test_mat[INPUT][1];
1908 cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], transmat );
1911 CxCore_PerspectiveTransformTest perspective_test;
1914 ///////////////// Mahalanobis /////////////////////
1916 class CxCore_MahalanobisTest : public CxCore_MatrixTest
1919 CxCore_MahalanobisTest();
1921 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1922 void get_timing_test_array_types_and_sizes( int test_case_idx,
1923 CvSize** sizes, int** types,
1924 CvSize** whole_sizes, bool* are_images );
1925 int prepare_test_case( int test_case_idx );
1927 void prepare_to_validation( int test_case_idx );
1931 CxCore_MahalanobisTest::CxCore_MahalanobisTest() :
1932 CxCore_MatrixTest( "matrix-mahalanobis", "cvMahalanobis", 3, 1, false, true, 1 )
1934 test_case_count = 100;
1935 test_array[TEMP].push(NULL);
1936 test_array[TEMP].push(NULL);
1937 test_array[TEMP].push(NULL);
1941 void CxCore_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1943 CvRNG* rng = ts->get_rng();
1944 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1946 if( cvTsRandInt(rng) & 1 )
1947 sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
1949 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1951 sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0];
1952 sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1;
1953 sizes[TEMP][2] = sizes[INPUT][2];
1954 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
1958 void CxCore_MahalanobisTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1959 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1961 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1962 sizes, types, whole_sizes, are_images );
1963 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1967 int CxCore_MahalanobisTest::prepare_test_case( int test_case_idx )
1969 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1970 if( code > 0 && ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1972 // make sure that the inverted "covariation" matrix is symmetrix and positively defined.
1973 cvTsGEMM( &test_mat[INPUT][2], &test_mat[INPUT][2], 1., 0, 0., &test_mat[TEMP][2], CV_GEMM_B_T );
1974 cvTsCopy( &test_mat[TEMP][2], &test_mat[INPUT][2] );
1981 void CxCore_MahalanobisTest::run_func()
1983 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) =
1984 cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
1987 void CxCore_MahalanobisTest::prepare_to_validation( int )
1989 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
1990 &test_mat[INPUT][1], cvScalarAll(-1.),
1991 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1992 if( test_mat[INPUT][0].rows == 1 )
1993 cvTsGEMM( &test_mat[TEMP][0], &test_mat[INPUT][2], 1.,
1994 0, 0., &test_mat[TEMP][1], 0 );
1996 cvTsGEMM( &test_mat[INPUT][2], &test_mat[TEMP][0], 1.,
1997 0, 0., &test_mat[TEMP][1], 0 );
1999 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) =
2000 cvRealScalar(sqrt(cvTsCrossCorr(&test_mat[TEMP][0], &test_mat[TEMP][1])));
2003 CxCore_MahalanobisTest mahalanobis_test;
2006 ///////////////// covarmatrix /////////////////////
2008 class CxCore_CovarMatrixTest : public CxCore_MatrixTest
2011 CxCore_CovarMatrixTest();
2013 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2014 int prepare_test_case( int test_case_idx );
2016 void prepare_to_validation( int test_case_idx );
2017 CvTestPtrVec temp_hdrs;
2019 int flags, t_flag, len, count;
2024 CxCore_CovarMatrixTest::CxCore_CovarMatrixTest() :
2025 CxCore_MatrixTest( "matrix-covar", "cvCalcCovarMatrix", 1, 1, true, false, 1 ),
2026 flags(0), t_flag(0), are_images(false)
2028 test_case_count = 100;
2029 test_array[INPUT_OUTPUT].push(NULL);
2030 test_array[REF_INPUT_OUTPUT].push(NULL);
2031 test_array[TEMP].push(NULL);
2032 test_array[TEMP].push(NULL);
2034 support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
2038 void CxCore_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2040 CvRNG* rng = ts->get_rng();
2041 int bits = cvTsRandInt(rng);
2042 int i, single_matrix;
2043 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2045 flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS );
2046 single_matrix = flags & CV_COVAR_ROWS;
2047 t_flag = (bits & 256) != 0;
2049 const int min_count = 2;
2053 len = sizes[INPUT][0].width;
2054 count = sizes[INPUT][0].height;
2055 count = MAX(count, min_count);
2056 sizes[INPUT][0] = cvSize(len, count);
2060 len = sizes[INPUT][0].height;
2061 count = sizes[INPUT][0].width;
2062 count = MAX(count, min_count);
2063 sizes[INPUT][0] = cvSize(count, len);
2066 if( single_matrix && t_flag )
2067 flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
2069 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
2070 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
2072 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? cvSize(len,len) : cvSize(count,count);
2073 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? cvSize(len,1) : cvSize(1,len);
2074 sizes[TEMP][0] = sizes[INPUT][0];
2076 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] =
2077 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] =
2078 CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F;
2080 are_images = (bits & 1024) != 0;
2081 for( i = 0; i < (single_matrix ? 1 : count); i++ )
2082 temp_hdrs.push(NULL);
2086 int CxCore_CovarMatrixTest::prepare_test_case( int test_case_idx )
2088 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2092 int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
2093 int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
2095 hdr_data = (uchar*)cvAlloc( count*hdr_size );
2099 *((CvMat*)hdr_data) = test_mat[INPUT][0];
2101 cvGetImage( &test_mat[INPUT][0], (IplImage*)hdr_data );
2102 temp_hdrs[0] = hdr_data;
2105 for( i = 0; i < count; i++ )
2108 void* ptr = hdr_data + i*hdr_size;
2111 cvGetRow( &test_mat[INPUT][0], &part, i );
2113 cvGetCol( &test_mat[INPUT][0], &part, i );
2116 *((CvMat*)ptr) = part;
2118 cvGetImage( &part, (IplImage*)ptr );
2128 void CxCore_CovarMatrixTest::run_func()
2130 cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
2131 test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
2135 void CxCore_CovarMatrixTest::prepare_to_validation( int )
2137 CvMat* avg = &test_mat[REF_INPUT_OUTPUT][0];
2140 if( !(flags & CV_COVAR_USE_AVG) )
2145 for( i = 0; i < count; i++ )
2147 CvMat stub, *vec = 0;
2148 if( flags & CV_COVAR_ROWS )
2149 vec = cvGetRow( temp_hdrs[0], &stub, i );
2150 else if( flags & CV_COVAR_COLS )
2151 vec = cvGetCol( temp_hdrs[0], &stub, i );
2153 vec = cvGetMat( temp_hdrs[i], &stub );
2155 cvTsAdd( avg, cvScalarAll(1.), vec,
2156 cvScalarAll(1.), cvScalarAll(0.), avg, 0 );
2159 cvTsAdd( avg, cvScalarAll(1./count), 0,
2160 cvScalarAll(0.), cvScalarAll(0.), avg, 0 );
2163 if( flags & CV_COVAR_SCALE )
2168 cvRepeat( avg, &test_mat[TEMP][0] );
2169 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
2170 &test_mat[TEMP][0], cvScalarAll(-1.),
2171 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
2173 cvTsGEMM( &test_mat[TEMP][0], &test_mat[TEMP][0],
2174 scale, 0, 0., &test_mat[REF_OUTPUT][0],
2175 t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ?
2176 CV_GEMM_A_T : CV_GEMM_B_T );
2178 cvFree( &hdr_data );
2182 CxCore_CovarMatrixTest covarmatrix_test;
2185 static void cvTsFloodWithZeros( CvMat* mat, CvRNG* rng )
2187 int k, total = mat->rows*mat->cols;
2188 int zero_total = cvTsRandInt(rng) % total;
2189 assert( CV_MAT_TYPE(mat->type) == CV_32FC1 ||
2190 CV_MAT_TYPE(mat->type) == CV_64FC1 );
2192 for( k = 0; k < zero_total; k++ )
2194 int i = cvTsRandInt(rng) % mat->rows;
2195 int j = cvTsRandInt(rng) % mat->cols;
2196 uchar* row = mat->data.ptr + mat->step*i;
2198 if( CV_MAT_DEPTH(mat->type) == CV_32FC1 )
2199 ((float*)row)[j] = 0.f;
2201 ((double*)row)[j] = 0.;
2206 ///////////////// determinant /////////////////////
2208 class CxCore_DetTest : public CxCore_MatrixTest
2213 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2214 double get_success_error_level( int test_case_idx, int i, int j );
2215 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2216 int prepare_test_case( int test_case_idx );
2218 void prepare_to_validation( int test_case_idx );
2222 CxCore_DetTest::CxCore_DetTest() :
2223 CxCore_MatrixTest( "matrix-det", "cvDet", 1, 1, false, true, 1 )
2225 test_case_count = 100;
2226 max_log_array_size = 7;
2227 test_array[TEMP].push(NULL);
2231 void CxCore_DetTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2233 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2235 sizes[INPUT][0].width = sizes[INPUT][0].height = sizes[INPUT][0].height;
2236 sizes[TEMP][0] = sizes[INPUT][0];
2237 types[TEMP][0] = CV_64FC1;
2241 void CxCore_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2243 *low = cvScalarAll(-2.);
2244 *high = cvScalarAll(2.);
2248 double CxCore_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2250 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
2254 int CxCore_DetTest::prepare_test_case( int test_case_idx )
2256 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2258 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2264 void CxCore_DetTest::run_func()
2266 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvRealScalar(cvDet(test_array[INPUT][0]));
2270 // LU method that chooses the optimal in a column pivot element
2271 static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 )
2273 int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double);
2274 int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0;
2275 int x_step = x ? x->step/sizeof(double) : 0;
2276 double *a0 = a->data.db, *b0 = b ? b->data.db : 0;
2277 double *x0 = x ? x->data.db : 0;
2279 assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
2280 (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
2282 for( i = 0; i < Nm; i++ )
2284 double max_val = fabs(a0[i*step + i]);
2285 double *a1, *a2, *b1 = 0, *b2 = 0;
2288 for( j = i+1; j < N; j++ )
2290 t = fabs(a0[j*step + i]);
2300 for( j = i; j < N1; j++ )
2301 CV_SWAP( a0[i*step + j], a0[k*step + j], t );
2303 for( j = 0; j < M; j++ )
2304 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
2320 for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
2323 for( k = i+1; k < N1; k++ )
2326 for( k = 0; k < M; k++ )
2337 for( i = N-1; i >= 0; i-- )
2339 double* a1 = a0 + i*step;
2340 double* b1 = b0 + i*b_step;
2341 for( j = 0; j < M; j++ )
2344 for( k = i+1; k < N1; k++ )
2345 t -= a1[k]*x0[k*x_step + j];
2346 x0[i*x_step + j] = t/a1[i];
2357 void CxCore_DetTest::prepare_to_validation( int )
2359 if( !CV_ARE_TYPES_EQ( &test_mat[INPUT][0], &test_mat[TEMP][0] ))
2360 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
2362 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][0], 0 );
2364 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = cvRealScalar(cvTsLU(&test_mat[TEMP][0], 0, 0));
2367 CxCore_DetTest det_test;
2371 ///////////////// invert /////////////////////
2373 static const char* matrix_solve_invert_param_names[] = { "size", "method", "depth", 0 };
2374 static const char* matrix_solve_invert_methods[] = { "LU", "SVD", 0 };
2376 class CxCore_InvertTest : public CxCore_MatrixTest
2379 CxCore_InvertTest();
2381 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2382 void get_timing_test_array_types_and_sizes( int test_case_idx,
2383 CvSize** sizes, int** types,
2384 CvSize** whole_sizes, bool* are_images );
2385 int write_default_params( CvFileStorage* fs );
2386 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2387 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2388 double get_success_error_level( int test_case_idx, int i, int j );
2389 int prepare_test_case( int test_case_idx );
2391 void prepare_to_validation( int test_case_idx );
2397 CxCore_InvertTest::CxCore_InvertTest() :
2398 CxCore_MatrixTest( "matrix-invert", "cvInvert, cvSVD, cvSVBkSb", 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
2400 test_case_count = 100;
2401 max_log_array_size = 7;
2402 test_array[TEMP].push(NULL);
2403 test_array[TEMP].push(NULL);
2405 default_timing_param_names = matrix_solve_invert_param_names;
2409 void CxCore_InvertTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2411 CvRNG* rng = ts->get_rng();
2412 int bits = cvTsRandInt(rng);
2413 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2414 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2416 if( (bits & 3) == 0 )
2421 sizes[INPUT][0] = cvSize(min_size, min_size);
2423 method = CV_SVD_SYM;
2429 sizes[INPUT][0] = cvSize(min_size, min_size);
2432 sizes[TEMP][0].width = sizes[INPUT][0].height;
2433 sizes[TEMP][0].height = sizes[INPUT][0].width;
2434 sizes[TEMP][1] = sizes[INPUT][0];
2435 types[TEMP][0] = types[INPUT][0];
2436 types[TEMP][1] = CV_64FC1;
2437 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(min_size, min_size);
2441 void CxCore_InvertTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2442 CvSize** sizes, int** types,
2443 CvSize** whole_sizes, bool* are_images )
2445 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2446 sizes, types, whole_sizes, are_images );
2447 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2448 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2452 int CxCore_InvertTest::write_default_params( CvFileStorage* fs )
2454 int code = CxCore_MatrixTest::write_default_params(fs);
2455 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2457 write_string_list( fs, "method", matrix_solve_invert_methods );
2462 void CxCore_InvertTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2464 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2467 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2471 double CxCore_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
2473 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-7;
2476 int CxCore_InvertTest::prepare_test_case( int test_case_idx )
2478 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2481 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2483 if( method == CV_SVD_SYM )
2485 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][0], 1.,
2486 0, 0., &test_mat[TEMP][0], CV_GEMM_B_T );
2487 cvTsCopy( &test_mat[TEMP][0], &test_mat[INPUT][0] );
2496 void CxCore_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2498 *low = cvScalarAll(-2.);
2499 *high = cvScalarAll(2.);
2503 void CxCore_InvertTest::run_func()
2505 result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
2509 static double cvTsSVDet( CvMat* mat )
2511 int type = CV_MAT_TYPE(mat->type);
2512 int i, nm = MIN( mat->rows, mat->cols );
2513 CvMat* w = cvCreateMat( nm, 1, type );
2516 cvSVD( mat, w, 0, 0, 0 );
2518 if( type == CV_32FC1 )
2520 for( i = 0; i < nm; i++ )
2521 det *= w->data.fl[i];
2525 for( i = 0; i < nm; i++ )
2526 det *= w->data.db[i];
2533 void CxCore_InvertTest::prepare_to_validation( int )
2535 CvMat* input = &test_mat[INPUT][0];
2536 double det = cvTsSVDet( input );
2537 double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*500;
2539 if( CV_MAT_TYPE(input->type) == CV_32FC1 )
2540 cvTsConvert( input, &test_mat[TEMP][1] );
2542 cvTsCopy( input, &test_mat[TEMP][1], 0 );
2544 if( (method == CV_LU && result == 0) ||
2545 (det < threshold || result < threshold) )
2547 cvTsZero( &test_mat[OUTPUT][0] );
2548 cvTsZero( &test_mat[REF_OUTPUT][0] );
2549 //cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(fabs(det)>1e-3),
2550 // &test_mat[REF_OUTPUT][0], 0 );
2554 if( input->rows >= input->cols )
2555 cvTsGEMM( &test_mat[TEMP][0], input, 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2557 cvTsGEMM( input, &test_mat[TEMP][0], 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2559 cvTsSetIdentity( &test_mat[REF_OUTPUT][0], cvScalarAll(1.) );
2562 CxCore_InvertTest invert_test;
2565 ///////////////// solve /////////////////////
2567 class CxCore_SolveTest : public CxCore_MatrixTest
2572 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2573 void get_timing_test_array_types_and_sizes( int test_case_idx,
2574 CvSize** sizes, int** types,
2575 CvSize** whole_sizes, bool* are_images );
2576 int write_default_params( CvFileStorage* fs );
2577 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2578 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2579 double get_success_error_level( int test_case_idx, int i, int j );
2580 int prepare_test_case( int test_case_idx );
2582 void prepare_to_validation( int test_case_idx );
2588 CxCore_SolveTest::CxCore_SolveTest() :
2589 CxCore_MatrixTest( "matrix-solve", "cvSolve, cvSVD, cvSVBkSb", 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
2591 test_case_count = 100;
2592 max_log_array_size = 7;
2593 test_array[TEMP].push(NULL);
2594 test_array[TEMP].push(NULL);
2596 default_timing_param_names = matrix_solve_invert_param_names;
2600 void CxCore_SolveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2602 CvRNG* rng = ts->get_rng();
2603 int bits = cvTsRandInt(rng);
2604 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2605 CvSize in_sz = sizes[INPUT][0];
2606 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2607 sizes[INPUT][0] = in_sz;
2608 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2610 if( (bits & 3) == 0 )
2615 sizes[INPUT][0] = cvSize(min_size, min_size);
2617 method = CV_SVD_SYM;*/
2623 sizes[INPUT][0] = cvSize(min_size, min_size);
2626 sizes[INPUT][1].height = sizes[INPUT][0].height;
2627 sizes[TEMP][0].width = sizes[INPUT][1].width;
2628 sizes[TEMP][0].height = sizes[INPUT][0].width;
2629 sizes[TEMP][1] = sizes[INPUT][0];
2630 types[TEMP][0] = types[INPUT][0];
2631 types[TEMP][1] = CV_64FC1;
2632 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][1].width, min_size);
2635 void CxCore_SolveTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2636 CvSize** sizes, int** types,
2637 CvSize** whole_sizes, bool* are_images )
2639 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2640 sizes, types, whole_sizes, are_images );
2641 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2642 sizes[INPUT][1].width = sizes[TEMP][0].width = sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = 1;
2643 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2647 int CxCore_SolveTest::write_default_params( CvFileStorage* fs )
2649 int code = CxCore_MatrixTest::write_default_params(fs);
2650 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2652 write_string_list( fs, "method", matrix_solve_invert_methods );
2657 void CxCore_SolveTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2659 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2662 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2666 int CxCore_SolveTest::prepare_test_case( int test_case_idx )
2668 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2670 /*if( method == CV_SVD_SYM )
2672 cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1.,
2673 0, 0., test_array[TEMP][0], CV_GEMM_B_T );
2674 cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] );
2681 void CxCore_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2683 *low = cvScalarAll(-2.);
2684 *high = cvScalarAll(2.);
2688 double CxCore_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
2690 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 3e-2 : 1e-8;
2694 void CxCore_SolveTest::run_func()
2696 result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
2699 void CxCore_SolveTest::prepare_to_validation( int )
2701 //int rank = test_mat[REF_OUTPUT][0].rows;
2704 if( method == CV_LU && result == 0 )
2706 if( CV_MAT_TYPE(test_mat[INPUT][0].type) == CV_32FC1 )
2707 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][1] );
2709 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][1], 0 );
2711 cvTsZero( &test_mat[OUTPUT][0] );
2712 double det = cvTsLU( &test_mat[TEMP][1], 0, 0 );
2713 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(det != 0),
2714 &test_mat[REF_OUTPUT][0], 0 );
2718 dst = test_mat[INPUT][0].rows <= test_mat[INPUT][0].cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
2720 cvTsGEMM( &test_mat[INPUT][0], &test_mat[TEMP][0], 1., &test_mat[INPUT][1], -1., dst, 0 );
2721 if( dst != &test_mat[OUTPUT][0] )
2722 cvTsGEMM( &test_mat[INPUT][0], dst, 1., 0, 0., &test_mat[OUTPUT][0], CV_GEMM_A_T );
2723 cvTsZero( &test_mat[REF_OUTPUT][0] );
2726 CxCore_SolveTest solve_test;
2729 ///////////////// SVD /////////////////////
2731 static const char* matrix_svd_param_names[] = { "size", "output", "depth", 0 };
2732 static const char* matrix_svd_output_modes[] = { "w", "all", 0 };
2734 class CxCore_SVDTest : public CxCore_MatrixTest
2739 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2740 void get_timing_test_array_types_and_sizes( int test_case_idx,
2741 CvSize** sizes, int** types,
2742 CvSize** whole_sizes, bool* are_images );
2743 double get_success_error_level( int test_case_idx, int i, int j );
2744 int write_default_params( CvFileStorage* fs );
2745 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2746 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2747 int prepare_test_case( int test_case_idx );
2749 void prepare_to_validation( int test_case_idx );
2751 bool have_u, have_v, symmetric, compact, vector_w;
2755 CxCore_SVDTest::CxCore_SVDTest() :
2756 CxCore_MatrixTest( "matrix-svd", "cvSVD", 1, 4, false, false, 1 ),
2757 flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false)
2759 test_case_count = 100;
2760 test_array[TEMP].push(NULL);
2761 test_array[TEMP].push(NULL);
2762 test_array[TEMP].push(NULL);
2763 test_array[TEMP].push(NULL);
2765 default_timing_param_names = matrix_svd_param_names;
2769 void CxCore_SVDTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2771 CvRNG* rng = ts->get_rng();
2772 int bits = cvTsRandInt(rng);
2773 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2774 int min_size, i, m, n;
2776 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2778 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
2779 have_u = (bits & 8) != 0;
2780 have_v = (bits & 16) != 0;
2781 symmetric = (bits & 32) != 0;
2782 compact = (bits & 64) != 0;
2783 vector_w = (bits & 128) != 0;
2786 sizes[INPUT][0] = cvSize(min_size, min_size);
2788 m = sizes[INPUT][0].height;
2789 n = sizes[INPUT][0].width;
2792 sizes[TEMP][0] = cvSize(min_size, min_size);
2794 sizes[TEMP][0] = sizes[INPUT][0];
2795 sizes[TEMP][3] = cvSize(0,0);
2799 sizes[TEMP][3] = sizes[TEMP][0];
2801 sizes[TEMP][0] = cvSize(1, min_size);
2803 sizes[TEMP][0] = cvSize(min_size, 1);
2808 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
2810 if( flags & CV_SVD_U_T )
2811 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
2814 sizes[TEMP][1] = cvSize(0,0);
2818 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
2820 if( !(flags & CV_SVD_V_T) )
2821 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
2824 sizes[TEMP][2] = cvSize(0,0);
2826 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0];
2827 types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0];
2828 types[OUTPUT][3] = CV_8UC1;
2829 sizes[OUTPUT][0] = !have_u || !have_v ? cvSize(0,0) : sizes[INPUT][0];
2830 sizes[OUTPUT][1] = !have_u ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(m,m);
2831 sizes[OUTPUT][2] = !have_v ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(n,n);
2832 sizes[OUTPUT][3] = cvSize(min_size,1);
2834 for( i = 0; i < 4; i++ )
2836 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
2837 types[REF_OUTPUT][i] = types[OUTPUT][i];
2842 void CxCore_SVDTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2843 CvSize** sizes, int** types,
2844 CvSize** whole_sizes, bool* are_images )
2846 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2847 sizes, types, whole_sizes, are_images );
2848 const char* output_str = cvReadString( find_timing_param("output"), "all" );
2849 bool need_all = strcmp( output_str, "all" ) == 0;
2850 int i, count = test_array[OUTPUT].size();
2854 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
2857 have_u = have_v = true;
2861 have_u = have_v = false;
2862 sizes[TEMP][1] = sizes[TEMP][2] = cvSize(0,0);
2865 flags = CV_SVD_U_T + CV_SVD_V_T;
2866 for( i = 0; i < count; i++ )
2867 sizes[OUTPUT][i] = sizes[REF_OUTPUT][i] = cvSize(0,0);
2868 sizes[OUTPUT][0] = cvSize(1,1);
2872 int CxCore_SVDTest::write_default_params( CvFileStorage* fs )
2874 int code = CxCore_MatrixTest::write_default_params(fs);
2875 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2877 write_string_list( fs, "output", matrix_svd_output_modes );
2882 void CxCore_SVDTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2884 sprintf( ptr, "%s,", have_u ? "all" : "w" );
2887 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2891 int CxCore_SVDTest::prepare_test_case( int test_case_idx )
2893 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2896 CvMat* input = &test_mat[INPUT][0];
2897 cvTsFloodWithZeros( input, ts->get_rng() );
2899 if( symmetric && (have_u || have_v) )
2901 CvMat* temp = &test_mat[TEMP][have_u ? 1 : 2];
2902 cvTsGEMM( input, input, 1.,
2903 0, 0., temp, CV_GEMM_B_T );
2904 cvTsCopy( temp, input );
2907 if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
2908 cvTsCopy( input, &test_mat[OUTPUT][0] );
2915 void CxCore_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2917 *low = cvScalarAll(-2.);
2918 *high = cvScalarAll(2.);
2921 double CxCore_SVDTest::get_success_error_level( int test_case_idx, int i, int j )
2923 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
2924 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ?
2926 double output_precision = CvArrTest::get_success_error_level( test_case_idx, i, j );
2927 return MAX(input_precision, output_precision);
2930 void CxCore_SVDTest::run_func()
2932 CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
2934 src = test_array[INPUT][0];
2935 cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
2939 void CxCore_SVDTest::prepare_to_validation( int )
2941 CvMat* input = &test_mat[INPUT][0];
2942 int m = input->rows, n = input->cols, min_size = MIN(m, n);
2943 CvMat *src, *dst, *w;
2944 double prev = 0, threshold = CV_MAT_TYPE(input->type) == CV_32FC1 ? FLT_EPSILON : DBL_EPSILON;
2949 src = &test_mat[TEMP][1];
2950 dst = &test_mat[OUTPUT][1];
2951 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2952 cvTsSetIdentity( &test_mat[REF_OUTPUT][1], cvScalarAll(1.) );
2957 src = &test_mat[TEMP][2];
2958 dst = &test_mat[OUTPUT][2];
2959 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
2960 cvTsSetIdentity( &test_mat[REF_OUTPUT][2], cvScalarAll(1.) );
2963 w = &test_mat[TEMP][0];
2964 step = w->rows == 1 ? 1 : w->step/CV_ELEM_SIZE(w->type);
2965 for( i = 0; i < min_size; i++ )
2967 double norm = 0, aii;
2969 if( w->rows > 1 && w->cols > 1 )
2972 cvGetRow( w, &row, i );
2973 norm = cvNorm( &row, 0, CV_L1 );
2975 row_ptr = row.data.ptr;
2979 row_ptr = w->data.ptr;
2983 aii = CV_MAT_TYPE(w->type) == CV_32FC1 ?
2984 (double)((float*)row_ptr)[j] : ((double*)row_ptr)[j];
2985 if( w->rows == 1 || w->cols == 1 )
2987 norm = fabs(norm - aii);
2988 test_mat[OUTPUT][3].data.ptr[i] = aii >= 0 && norm < threshold && (i == 0 || aii <= prev);
2992 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.),
2993 cvScalarAll(1.), &test_mat[REF_OUTPUT][3], 0 );
2995 if( have_u && have_v )
2999 cvTsZero( &test_mat[TEMP][3] );
3000 for( i = 0; i < min_size; i++ )
3002 double val = cvGetReal1D( w, i );
3003 cvSetReal2D( &test_mat[TEMP][3], i, i, val );
3005 w = &test_mat[TEMP][3];
3010 cvTsGEMM( &test_mat[TEMP][1], w, 1., 0, 0., &test_mat[REF_OUTPUT][0],
3011 flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
3012 cvTsGEMM( &test_mat[REF_OUTPUT][0], &test_mat[TEMP][2], 1., 0, 0.,
3013 &test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
3017 cvTsGEMM( w, &test_mat[TEMP][2], 1., 0, 0., &test_mat[REF_OUTPUT][0],
3018 flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
3019 cvTsGEMM( &test_mat[TEMP][1], &test_mat[REF_OUTPUT][0], 1., 0, 0.,
3020 &test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
3023 cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], 0 );
3028 CxCore_SVDTest svd_test;
3031 ///////////////// SVBkSb /////////////////////
3033 class CxCore_SVBkSbTest : public CxCore_MatrixTest
3036 CxCore_SVBkSbTest();
3038 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
3039 void get_timing_test_array_types_and_sizes( int test_case_idx,
3040 CvSize** sizes, int** types,
3041 CvSize** whole_sizes, bool* are_images );
3042 double get_success_error_level( int test_case_idx, int i, int j );
3043 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
3044 int prepare_test_case( int test_case_idx );
3046 void prepare_to_validation( int test_case_idx );
3048 bool have_b, symmetric, compact, vector_w;
3052 CxCore_SVBkSbTest::CxCore_SVBkSbTest() :
3053 CxCore_MatrixTest( "matrix-svbksb", "cvSVBkSb", 2, 1, false, false, 1 ),
3054 flags(0), have_b(false), symmetric(false), compact(false), vector_w(false)
3056 test_case_count = 100;
3057 test_array[TEMP].push(NULL);
3058 test_array[TEMP].push(NULL);
3059 test_array[TEMP].push(NULL);
3063 void CxCore_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
3065 CvRNG* rng = ts->get_rng();
3066 int bits = cvTsRandInt(rng);
3067 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
3068 int min_size, i, m, n;
3071 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
3073 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
3074 have_b = (bits & 16) != 0;
3075 symmetric = (bits & 32) != 0;
3076 compact = (bits & 64) != 0;
3077 vector_w = (bits & 128) != 0;
3080 sizes[INPUT][0] = cvSize(min_size, min_size);
3082 m = sizes[INPUT][0].height;
3083 n = sizes[INPUT][0].width;
3085 sizes[INPUT][1] = cvSize(0,0);
3086 b_size = cvSize(m,m);
3089 sizes[INPUT][1].height = sizes[INPUT][0].height;
3090 sizes[INPUT][1].width = cvTsRandInt(rng) % 100 + 1;
3091 b_size = sizes[INPUT][1];
3095 sizes[TEMP][0] = cvSize(min_size, min_size);
3097 sizes[TEMP][0] = sizes[INPUT][0];
3102 sizes[TEMP][0] = cvSize(1, min_size);
3104 sizes[TEMP][0] = cvSize(min_size, 1);
3107 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
3109 if( flags & CV_SVD_U_T )
3110 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
3112 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
3114 if( !(flags & CV_SVD_V_T) )
3115 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
3117 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
3118 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0];
3119 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( b_size.width, n );
3123 void CxCore_SVBkSbTest::get_timing_test_array_types_and_sizes( int test_case_idx,
3124 CvSize** sizes, int** types,
3125 CvSize** whole_sizes, bool* are_images )
3127 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
3128 sizes, types, whole_sizes, are_images );
3132 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
3133 sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1,sizes[INPUT][0].height);
3134 flags = CV_SVD_U_T + CV_SVD_V_T;
3138 int CxCore_SVBkSbTest::prepare_test_case( int test_case_idx )
3140 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
3143 CvMat* input = &test_mat[INPUT][0];
3144 cvTsFloodWithZeros( input, ts->get_rng() );
3148 CvMat* temp = &test_mat[TEMP][1];
3149 cvTsGEMM( input, input, 1., 0, 0., temp, CV_GEMM_B_T );
3150 cvTsCopy( temp, input );
3153 cvSVD( input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
3160 void CxCore_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
3162 *low = cvScalarAll(-2.);
3163 *high = cvScalarAll(2.);
3167 double CxCore_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
3169 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
3173 void CxCore_SVBkSbTest::run_func()
3175 cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
3176 test_array[INPUT][1], test_array[OUTPUT][0], flags );
3180 void CxCore_SVBkSbTest::prepare_to_validation( int )
3182 CvMat* input = &test_mat[INPUT][0];
3183 int i, m = input->rows, n = input->cols, min_size = MIN(m, n), nb;
3184 bool is_float = CV_MAT_DEPTH(input->type) == CV_32F;
3185 CvSize w_size = compact ? cvSize(min_size,min_size) : cvSize(m,n);
3186 CvMat* w = &test_mat[TEMP][0];
3187 CvMat* wdb = cvCreateMat( w_size.height, w_size.width, CV_64FC1 );
3188 // use exactly the same threshold as in icvSVD... ,
3189 // so the changes in the library and here should be synchronized.
3190 double threshold = cvSum( w ).val[0]*2*(is_float ? FLT_EPSILON : DBL_EPSILON);
3191 CvMat *u, *v, *b, *t0, *t1;
3194 for( i = 0; i < min_size; i++ )
3196 double wii = vector_w ? cvGetReal1D(w,i) : cvGetReal2D(w,i,i);
3197 cvSetReal2D( wdb, i, i, wii > threshold ? 1./wii : 0. );
3200 u = &test_mat[TEMP][1];
3201 v = &test_mat[TEMP][2];
3205 if( test_array[INPUT][1] )
3207 b = &test_mat[INPUT][1];
3213 u = cvCreateMat( u->rows, u->cols, CV_64F );
3214 cvTsConvert( &test_mat[TEMP][1], u );
3217 b = cvCreateMat( b->rows, b->cols, CV_64F );
3218 cvTsConvert( &test_mat[INPUT][1], b );
3222 t0 = cvCreateMat( wdb->cols, nb, CV_64F );
3225 cvTsGEMM( u, b, 1., 0, 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 );
3226 else if( flags & CV_SVD_U_T )
3229 cvTsTranspose( u, t0 );
3238 v = cvCreateMat( v->rows, v->cols, CV_64F );
3245 cvTsConvert( &test_mat[TEMP][2], v );
3248 t1 = cvCreateMat( wdb->rows, nb, CV_64F );
3249 cvTsGEMM( wdb, t0, 1, 0, 0, t1, 0 );
3251 if( !is_float || !symmetric )
3253 cvReleaseMat( &t0 );
3254 t0 = !is_float ? &test_mat[REF_OUTPUT][0] : cvCreateMat( test_mat[REF_OUTPUT][0].rows, nb, CV_64F );
3257 cvTsGEMM( v, t1, 1, 0, 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 );
3258 cvReleaseMat( &t1 );
3260 if( t0 != &test_mat[REF_OUTPUT][0] )
3262 cvTsConvert( t0, &test_mat[REF_OUTPUT][0] );
3263 cvReleaseMat( &t0 );
3266 if( v != &test_mat[TEMP][2] )
3269 cvReleaseMat( &wdb );
3273 CxCore_SVBkSbTest svbksb_test;
3276 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),