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 );
145 int prepare_test_case( int test_case );
147 void prepare_to_validation( int test_case_idx );
152 CxCore_ExpTest::CxCore_ExpTest()
153 : CxCore_MathTest( "math-exp", "cvExp" )
159 double CxCore_ExpTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
161 int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
162 int out_depth = CV_MAT_DEPTH(test_mat[OUTPUT][0].type);
163 int min_depth = MIN(in_depth, out_depth);
164 return min_depth == CV_32F ? 1e-5 : 1e-8;
168 void CxCore_ExpTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
170 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
171 out_type = types[OUTPUT][0];
172 /*if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32F && (cvRandInt(ts->get_rng()) & 3) == 0 )
173 types[OUTPUT][0] = types[REF_OUTPUT][0] =
174 out_type = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|CV_64F;*/
177 void CxCore_ExpTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
179 double l = cvTsRandReal(ts->get_rng())*10+1;
180 double u = cvTsRandReal(ts->get_rng())*10+1;
183 *low = cvScalarAll(l);
184 *high = cvScalarAll(CV_MAT_DEPTH(out_type)==CV_64F? u : u*0.5);
187 int CxCore_ExpTest::prepare_test_case( int test_case )
189 int code = CxCore_MathTest::prepare_test_case(test_case);
193 CvRNG* rng = ts->get_rng();
195 int i, j, k, count = cvTsRandInt(rng) % 10;
196 CvMat* src = &test_mat[INPUT][0];
197 int depth = CV_MAT_DEPTH(src->type);
199 // add some extremal values
200 for( k = 0; k < count; k++ )
202 i = cvTsRandInt(rng) % src->rows;
203 j = cvTsRandInt(rng) % (src->cols*CV_MAT_CN(src->type));
204 int sign = cvTsRandInt(rng) % 2 ? 1 : -1;
205 if( depth == CV_32F )
206 ((float*)(src->data.ptr + src->step*i))[j] = FLT_MAX*sign;
208 ((double*)(src->data.ptr + src->step*i))[j] = DBL_MAX*sign;
215 void CxCore_ExpTest::run_func()
218 cvExp( test_array[INPUT][0], test_array[OUTPUT][0] );
221 cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
222 cv::MatND b = cv::cvarrToMatND(test_array[OUTPUT][0]);
228 void CxCore_ExpTest::prepare_to_validation( int /*test_case_idx*/ )
230 CvMat* a = &test_mat[INPUT][0];
231 CvMat* b = &test_mat[REF_OUTPUT][0];
233 int a_depth = CV_MAT_DEPTH(a->type);
234 int b_depth = CV_MAT_DEPTH(b->type);
235 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
238 for( i = 0; i < a->rows; i++ )
240 uchar* a_data = a->data.ptr + i*a->step;
241 uchar* b_data = b->data.ptr + i*b->step;
243 if( a_depth == CV_32F && b_depth == CV_32F )
245 for( j = 0; j < ncols; j++ )
246 ((float*)b_data)[j] = (float)exp((double)((float*)a_data)[j]);
248 else if( a_depth == CV_32F && b_depth == CV_64F )
250 for( j = 0; j < ncols; j++ )
251 ((double*)b_data)[j] = exp((double)((float*)a_data)[j]);
255 assert( a_depth == CV_64F && b_depth == CV_64F );
256 for( j = 0; j < ncols; j++ )
257 ((double*)b_data)[j] = exp(((double*)a_data)[j]);
262 CxCore_ExpTest exp_test;
265 ////////// log /////////////
266 class CxCore_LogTest : public CxCore_MathTest
271 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
272 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
274 void prepare_to_validation( int test_case_idx );
278 CxCore_LogTest::CxCore_LogTest()
279 : CxCore_MathTest( "math-log", "cvLog" )
284 void CxCore_LogTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
286 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
287 /*if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32F && (cvRandInt(ts->get_rng()) & 3) == 0 )
288 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK)|CV_64F;*/
292 void CxCore_LogTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
294 double l = cvTsRandReal(ts->get_rng())*15-5;
295 double u = cvTsRandReal(ts->get_rng())*15-5;
301 *low = cvScalarAll(l);
302 *high = cvScalarAll(u);
306 void CxCore_LogTest::run_func()
309 cvLog( test_array[INPUT][0], test_array[OUTPUT][0] );
312 cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
313 cv::MatND b = cv::cvarrToMatND(test_array[OUTPUT][0]);
319 void CxCore_LogTest::prepare_to_validation( int /*test_case_idx*/ )
321 CvMat* a = &test_mat[INPUT][0];
322 CvMat* b = &test_mat[REF_OUTPUT][0];
324 int a_depth = CV_MAT_DEPTH(a->type);
325 int b_depth = CV_MAT_DEPTH(b->type);
326 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
329 for( i = 0; i < a->rows; i++ )
331 uchar* a_data = a->data.ptr + i*a->step;
332 uchar* b_data = b->data.ptr + i*b->step;
334 if( a_depth == CV_32F && b_depth == CV_32F )
336 for( j = 0; j < ncols; j++ )
337 ((float*)b_data)[j] = (float)log((double)((float*)a_data)[j]);
339 else if( a_depth == CV_64F && b_depth == CV_32F )
341 for( j = 0; j < ncols; j++ )
342 ((float*)b_data)[j] = (float)log(((double*)a_data)[j]);
346 assert( a_depth == CV_64F && b_depth == CV_64F );
347 for( j = 0; j < ncols; j++ )
348 ((double*)b_data)[j] = log(((double*)a_data)[j]);
353 CxCore_LogTest log_test;
356 ////////// pow /////////////
358 static const double math_pow_values[] = { 2., 5., 0.5, -0.5, 1./3, -1./3, CV_PI };
359 static const char* math_pow_param_names[] = { "size", "power", "depth", 0 };
360 static const int math_pow_depths[] = { CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, -1 };
362 class CxCore_PowTest : public CxCore_MathTest
367 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
368 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
369 void get_timing_test_array_types_and_sizes( int test_case_idx,
370 CvSize** sizes, int** types,
371 CvSize** whole_sizes, bool* are_images );
372 int write_default_params( CvFileStorage* fs );
373 void print_timing_params( int test_case_idx, char* ptr, int params_left );
375 int prepare_test_case( int test_case_idx );
376 void prepare_to_validation( int test_case_idx );
377 double get_success_error_level( int test_case_idx, int i, int j );
382 CxCore_PowTest::CxCore_PowTest()
383 : CxCore_MathTest( "math-pow", "cvPow" )
386 default_timing_param_names = math_pow_param_names;
387 depth_list = math_pow_depths;
391 void CxCore_PowTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
393 CvRNG* rng = ts->get_rng();
394 int depth = cvTsRandInt(rng) % (CV_64F+1);
395 int cn = cvTsRandInt(rng) % 4 + 1;
397 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
398 depth += depth == CV_8S;
400 if( depth < CV_32F || cvTsRandInt(rng)%8 == 0 )
402 power = (int)(cvTsRandInt(rng)%21 - 10);
405 i = cvTsRandInt(rng)%17;
406 power = i == 16 ? 1./3 : i == 15 ? 0.5 : i == 14 ? -0.5 : cvTsRandReal(rng)*10 - 5;
409 for( i = 0; i < max_arr; i++ )
411 int count = test_array[i].size();
412 int type = CV_MAKETYPE(depth, cn);
413 for( j = 0; j < count; j++ )
416 test_nd = cvTsRandInt(rng)%3 == 0;
420 void CxCore_PowTest::get_timing_test_array_types_and_sizes( int test_case_idx,
421 CvSize** sizes, int** types,
422 CvSize** whole_sizes, bool* are_images )
424 CxCore_MathTest::get_timing_test_array_types_and_sizes( test_case_idx,
425 sizes, types, whole_sizes, are_images );
426 power = cvReadReal( find_timing_param( "power" ), 0.2 );
430 int CxCore_PowTest::write_default_params( CvFileStorage* fs )
432 int i, code = CxCore_MathTest::write_default_params(fs);
433 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
435 start_write_param( fs );
436 cvStartWriteStruct( fs, "power", CV_NODE_SEQ + CV_NODE_FLOW );
437 for( i = 0; i < CV_DIM(math_pow_values); i++ )
438 cvWriteReal( fs, 0, math_pow_values[i] );
439 cvEndWriteStruct(fs);
444 int CxCore_PowTest::prepare_test_case( int test_case_idx )
446 int code = CxCore_MathTest::prepare_test_case( test_case_idx );
447 if( code > 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
449 if( cvRound(power) != power && CV_MAT_DEPTH(test_mat[INPUT][0].type) < CV_32F )
456 void CxCore_PowTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
458 sprintf( ptr, "%g,", power );
461 CxCore_MathTest::print_timing_params( test_case_idx, ptr, params_left );
465 double CxCore_PowTest::get_success_error_level( int test_case_idx, int i, int j )
467 int type = cvGetElemType( test_array[i][j] );
468 if( CV_MAT_DEPTH(type) < CV_32F )
469 return power == cvRound(power) && power >= 0 ? 0 : 1;
471 return CxCore_MathTest::get_success_error_level( test_case_idx, i, j );
475 void CxCore_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, CvScalar* low, CvScalar* high )
477 double l, u = cvTsRandInt(ts->get_rng())%1000 + 1;
480 double mval = cvTsMaxVal(type);
481 double u1 = pow(mval,1./power)*2;
485 l = power == cvRound(power) ? -u : FLT_EPSILON;
486 *low = cvScalarAll(l);
487 *high = cvScalarAll(u);
491 void CxCore_PowTest::run_func()
495 if( fabs(power-1./3) <= DBL_EPSILON && CV_MAT_DEPTH(test_mat[INPUT][0].type) == CV_32F )
497 cv::Mat a(&test_mat[INPUT][0]), b(&test_mat[OUTPUT][0]);
501 for( int i = 0; i < a.rows; i++ )
503 b.at<float>(i,0) = (float)fabs(cvCbrt(a.at<float>(i,0)));
504 for( int j = 1; j < a.cols; j++ )
505 b.at<float>(i,j) = (float)fabs(cv::cubeRoot(a.at<float>(i,j)));
509 cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
513 cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
514 cv::MatND b = cv::cvarrToMatND(test_array[OUTPUT][0]);
518 cv::pow(a, power, b);
523 inline static int ipow( int a, int power )
537 inline static double ipow( double a, int power )
551 void CxCore_PowTest::prepare_to_validation( int /*test_case_idx*/ )
553 CvMat* a = &test_mat[INPUT][0];
554 CvMat* b = &test_mat[REF_OUTPUT][0];
556 int depth = CV_MAT_DEPTH(a->type);
557 int ncols = test_mat[INPUT][0].cols*CV_MAT_CN(a->type);
558 int ipower = cvRound(power), apower = abs(ipower);
561 for( i = 0; i < a->rows; i++ )
563 uchar* a_data = a->data.ptr + i*a->step;
564 uchar* b_data = b->data.ptr + i*b->step;
570 for( j = 0; j < ncols; j++ )
572 int val = ((uchar*)a_data)[j];
573 ((uchar*)b_data)[j] = (uchar)(val <= 1 ? val :
574 val == 2 && ipower == -1 ? 1 : 0);
577 for( j = 0; j < ncols; j++ )
579 int val = ((uchar*)a_data)[j];
580 val = ipow( val, ipower );
581 ((uchar*)b_data)[j] = CV_CAST_8U(val);
586 for( j = 0; j < ncols; j++ )
588 int val = ((char*)a_data)[j];
589 ((char*)b_data)[j] = (char)((val&~1)==0 ? val :
590 val ==-1 ? 1-2*(ipower&1) :
591 val == 2 && ipower == -1 ? 1 : 0);
594 for( j = 0; j < ncols; j++ )
596 int val = ((char*)a_data)[j];
597 val = ipow( val, ipower );
598 ((char*)b_data)[j] = CV_CAST_8S(val);
603 for( j = 0; j < ncols; j++ )
605 int val = ((ushort*)a_data)[j];
606 ((ushort*)b_data)[j] = (ushort)((val&~1)==0 ? val :
607 val ==-1 ? 1-2*(ipower&1) :
608 val == 2 && ipower == -1 ? 1 : 0);
611 for( j = 0; j < ncols; j++ )
613 int val = ((ushort*)a_data)[j];
614 val = ipow( val, ipower );
615 ((ushort*)b_data)[j] = CV_CAST_16U(val);
620 for( j = 0; j < ncols; j++ )
622 int val = ((short*)a_data)[j];
623 ((short*)b_data)[j] = (short)((val&~1)==0 ? val :
624 val ==-1 ? 1-2*(ipower&1) :
625 val == 2 && ipower == -1 ? 1 : 0);
628 for( j = 0; j < ncols; j++ )
630 int val = ((short*)a_data)[j];
631 val = ipow( val, ipower );
632 ((short*)b_data)[j] = CV_CAST_16S(val);
637 for( j = 0; j < ncols; j++ )
639 int val = ((int*)a_data)[j];
640 ((int*)b_data)[j] = (val&~1)==0 ? val :
641 val ==-1 ? 1-2*(ipower&1) :
642 val == 2 && ipower == -1 ? 1 : 0;
645 for( j = 0; j < ncols; j++ )
647 int val = ((int*)a_data)[j];
648 val = ipow( val, ipower );
649 ((int*)b_data)[j] = val;
653 if( power != ipower )
654 for( j = 0; j < ncols; j++ )
656 double val = ((float*)a_data)[j];
657 val = pow( fabs(val), power );
658 ((float*)b_data)[j] = CV_CAST_32F(val);
661 for( j = 0; j < ncols; j++ )
663 double val = ((float*)a_data)[j];
666 val = ipow( val, apower );
667 ((float*)b_data)[j] = (float)val;
671 if( power != ipower )
672 for( j = 0; j < ncols; j++ )
674 double val = ((double*)a_data)[j];
675 val = pow( fabs(val), power );
676 ((double*)b_data)[j] = CV_CAST_64F(val);
679 for( j = 0; j < ncols; j++ )
681 double val = ((double*)a_data)[j];
684 val = ipow( val, apower );
685 ((double*)b_data)[j] = (double)val;
692 CxCore_PowTest pow_test;
696 ////////// cart2polar /////////////
697 class CxCore_CartToPolarTest : public CxCore_MathTest
700 CxCore_CartToPolarTest();
702 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
703 double get_success_error_level( int test_case_idx, int i, int j );
705 void prepare_to_validation( int test_case_idx );
710 CxCore_CartToPolarTest::CxCore_CartToPolarTest()
711 : CxCore_MathTest( "math-cart2polar", "cvCartToPolar" )
714 test_array[INPUT].push(NULL);
715 test_array[OUTPUT].push(NULL);
716 test_array[REF_OUTPUT].push(NULL);
720 void CxCore_CartToPolarTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
722 CvRNG* rng = ts->get_rng();
723 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
725 use_degrees = cvTsRandInt(rng) & 1;
726 if( cvTsRandInt(rng) % 4 == 0 ) // check missing magnitude/angle cases
728 int idx = cvTsRandInt(rng) & 1;
729 sizes[OUTPUT][idx] = sizes[REF_OUTPUT][idx] = cvSize(0,0);
734 void CxCore_CartToPolarTest::run_func()
738 cvCartToPolar( test_array[INPUT][0], test_array[INPUT][1],
739 test_array[OUTPUT][0], test_array[OUTPUT][1], use_degrees );
743 cv::Mat X = cv::cvarrToMat(test_array[INPUT][0]);
744 cv::Mat Y = cv::cvarrToMat(test_array[INPUT][1]);
745 cv::Mat mag = test_array[OUTPUT][0] ? cv::cvarrToMat(test_array[OUTPUT][0]) : cv::Mat();
746 cv::Mat ph = test_array[OUTPUT][1] ? cv::cvarrToMat(test_array[OUTPUT][1]) : cv::Mat();
748 cv::phase(X, Y, ph, use_degrees != 0);
750 cv::magnitude(X, Y, mag);
752 cv::cartToPolar(X, Y, mag, ph, use_degrees != 0);
757 double CxCore_CartToPolarTest::get_success_error_level( int test_case_idx, int i, int j )
759 return j == 1 ? 0.5*(use_degrees ? 1 : CV_PI/180.) :
760 CxCore_MathTest::get_success_error_level( test_case_idx, i, j );
764 void CxCore_CartToPolarTest::prepare_to_validation( int /*test_case_idx*/ )
766 CvMat* x = &test_mat[INPUT][0];
767 CvMat* y = &test_mat[INPUT][1];
768 CvMat* mag = test_array[REF_OUTPUT][0] ? &test_mat[REF_OUTPUT][0] : 0;
769 CvMat* angle = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
770 double C = use_degrees ? 180./CV_PI : 1.;
772 int depth = CV_MAT_DEPTH(x->type);
773 int ncols = x->cols*CV_MAT_CN(x->type);
776 for( i = 0; i < x->rows; i++ )
778 uchar* x_data = x->data.ptr + i*x->step;
779 uchar* y_data = y->data.ptr + i*y->step;
780 uchar* mag_data = mag ? mag->data.ptr + i*mag->step : 0;
781 uchar* angle_data = angle ? angle->data.ptr + i*angle->step : 0;
783 if( depth == CV_32F )
785 for( j = 0; j < ncols; j++ )
787 double xval = ((float*)x_data)[j];
788 double yval = ((float*)y_data)[j];
791 ((float*)mag_data)[j] = (float)sqrt(xval*xval + yval*yval);
794 double a = atan2( yval, xval );
798 ((float*)angle_data)[j] = (float)a;
804 assert( depth == CV_64F );
805 for( j = 0; j < ncols; j++ )
807 double xval = ((double*)x_data)[j];
808 double yval = ((double*)y_data)[j];
811 ((double*)mag_data)[j] = sqrt(xval*xval + yval*yval);
814 double a = atan2( yval, xval );
818 ((double*)angle_data)[j] = a;
826 // hack: increase angle value by 1 (so that alpha becomes 1+alpha)
827 // to hide large relative errors in case of very small angles
828 cvTsAdd( &test_mat[OUTPUT][1], cvScalarAll(1.), 0, cvScalarAll(0.),
829 cvScalarAll(1.), &test_mat[OUTPUT][1], 0 );
830 cvTsAdd( &test_mat[REF_OUTPUT][1], cvScalarAll(1.), 0, cvScalarAll(0.),
831 cvScalarAll(1.), &test_mat[REF_OUTPUT][1], 0 );
835 CxCore_CartToPolarTest cart2polar_test;
839 ////////// polar2cart /////////////
840 class CxCore_PolarToCartTest : public CxCore_MathTest
843 CxCore_PolarToCartTest();
845 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
846 double get_success_error_level( int test_case_idx, int i, int j );
848 void prepare_to_validation( int test_case_idx );
853 CxCore_PolarToCartTest::CxCore_PolarToCartTest()
854 : CxCore_MathTest( "math-polar2cart", "cvPolarToCart" )
857 test_array[INPUT].push(NULL);
858 test_array[OUTPUT].push(NULL);
859 test_array[REF_OUTPUT].push(NULL);
863 void CxCore_PolarToCartTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
865 CvRNG* rng = ts->get_rng();
866 CxCore_MathTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
868 use_degrees = cvTsRandInt(rng) & 1;
869 if( cvTsRandInt(rng) % 4 == 0 ) // check missing magnitude case
870 sizes[INPUT][1] = cvSize(0,0);
872 if( cvTsRandInt(rng) % 4 == 0 ) // check missing x/y cases
874 int idx = cvTsRandInt(rng) & 1;
875 sizes[OUTPUT][idx] = sizes[REF_OUTPUT][idx] = cvSize(0,0);
880 void CxCore_PolarToCartTest::run_func()
884 cvPolarToCart( test_array[INPUT][1], test_array[INPUT][0],
885 test_array[OUTPUT][0], test_array[OUTPUT][1], use_degrees );
889 cv::Mat X = test_array[OUTPUT][0] ? cv::cvarrToMat(test_array[OUTPUT][0]) : cv::Mat();
890 cv::Mat Y = test_array[OUTPUT][1] ? cv::cvarrToMat(test_array[OUTPUT][1]) : cv::Mat();
891 cv::Mat mag = test_array[INPUT][1] ? cv::cvarrToMat(test_array[INPUT][1]) : cv::Mat();
892 cv::Mat ph = test_array[INPUT][0] ? cv::cvarrToMat(test_array[INPUT][0]) : cv::Mat();
893 cv::polarToCart(mag, ph, X, Y, use_degrees != 0);
898 double CxCore_PolarToCartTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
900 return FLT_EPSILON*100;
904 void CxCore_PolarToCartTest::prepare_to_validation( int /*test_case_idx*/ )
906 CvMat* x = test_array[REF_OUTPUT][0] ? &test_mat[REF_OUTPUT][0] : 0;
907 CvMat* y = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
908 CvMat* angle = &test_mat[INPUT][0];
909 CvMat* mag = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
910 double C = use_degrees ? CV_PI/180. : 1.;
912 int depth = CV_MAT_DEPTH(angle->type);
913 int ncols = angle->cols*CV_MAT_CN(angle->type);
916 for( i = 0; i < angle->rows; i++ )
918 uchar* x_data = x ? x->data.ptr + i*x->step : 0;
919 uchar* y_data = y ? y->data.ptr + i*y->step : 0;
920 uchar* mag_data = mag ? mag->data.ptr + i*mag->step : 0;
921 uchar* angle_data = angle->data.ptr + i*angle->step;
923 if( depth == CV_32F )
925 for( j = 0; j < ncols; j++ )
927 double a = ((float*)angle_data)[j]*C;
928 double m = mag_data ? ((float*)mag_data)[j] : 1.;
931 ((float*)x_data)[j] = (float)(m*cos(a));
933 ((float*)y_data)[j] = (float)(m*sin(a));
938 assert( depth == CV_64F );
939 for( j = 0; j < ncols; j++ )
941 double a = ((double*)angle_data)[j]*C;
942 double m = mag_data ? ((double*)mag_data)[j] : 1.;
945 ((double*)x_data)[j] = m*cos(a);
947 ((double*)y_data)[j] = m*sin(a);
953 CxCore_PolarToCartTest polar2cart_test;
955 ///////////////////////////////////////// matrix tests ////////////////////////////////////////////
957 static const int matrix_all_depths[] = { CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, -1 };
959 class CxCore_MatrixTestImpl : public CvArrTest
962 CxCore_MatrixTestImpl( const char* test_name, const char* test_funcs, int in_count, int out_count,
963 bool allow_int, bool scalar_output, int max_cn );
965 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
966 void get_timing_test_array_types_and_sizes( int test_case_idx,
967 CvSize** sizes, int** types,
968 CvSize** whole_sizes, bool* are_images );
969 double get_success_error_level( int test_case_idx, int i, int j );
976 CxCore_MatrixTestImpl::CxCore_MatrixTestImpl( const char* test_name, const char* test_funcs,
977 int in_count, int out_count,
978 bool _allow_int, bool _scalar_output, int _max_cn )
979 : CvArrTest( test_name, test_funcs, "" ),
980 allow_int(_allow_int), scalar_output(_scalar_output), max_cn(_max_cn)
983 for( i = 0; i < in_count; i++ )
984 test_array[INPUT].push(NULL);
986 for( i = 0; i < out_count; i++ )
988 test_array[OUTPUT].push(NULL);
989 test_array[REF_OUTPUT].push(NULL);
992 element_wise_relative_error = false;
994 default_timing_param_names = math_param_names;
996 size_list = (CvSize*)matrix_sizes;
998 depth_list = (int*)math_depths;
1003 void CxCore_MatrixTestImpl::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1005 CvRNG* rng = ts->get_rng();
1006 int depth = cvTsRandInt(rng) % (allow_int ? CV_64F+1 : 2);
1007 int cn = cvTsRandInt(rng) % max_cn + 1;
1011 depth += depth == CV_8S;
1015 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1017 for( i = 0; i < max_arr; i++ )
1019 int count = test_array[i].size();
1020 int flag = (i == OUTPUT || i == REF_OUTPUT) && scalar_output;
1021 int type = !flag ? CV_MAKETYPE(depth, cn) : CV_64FC1;
1023 for( j = 0; j < count; j++ )
1027 sizes[i][j] = cvSize( 4, 1 );
1033 void CxCore_MatrixTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
1034 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1036 CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx,
1037 sizes, types, whole_sizes, are_images );
1040 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
1041 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( 4, 1 );
1042 whole_sizes[OUTPUT][0] = whole_sizes[REF_OUTPUT][0] = cvSize( 4, 1 );
1047 double CxCore_MatrixTestImpl::get_success_error_level( int test_case_idx, int i, int j )
1049 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
1050 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ?
1052 double output_precision = CvArrTest::get_success_error_level( test_case_idx, i, j );
1053 return MAX(input_precision, output_precision);
1056 CxCore_MatrixTestImpl matrix_test( "matrix", "", 0, 0, false, false, 0 );
1059 class CxCore_MatrixTest : public CxCore_MatrixTestImpl
1062 CxCore_MatrixTest( const char* test_name, const char* test_funcs, int in_count, int out_count,
1063 bool allow_int, bool scalar_output, int max_cn );
1067 CxCore_MatrixTest::CxCore_MatrixTest( const char* test_name, const char* test_funcs,
1068 int in_count, int out_count, bool _allow_int,
1069 bool _scalar_output, int _max_cn )
1070 : CxCore_MatrixTestImpl( test_name, test_funcs, in_count, out_count,
1071 _allow_int, _scalar_output, _max_cn )
1078 ///////////////// Trace /////////////////////
1080 class CxCore_TraceTest : public CxCore_MatrixTest
1086 void prepare_to_validation( int test_case_idx );
1090 CxCore_TraceTest::CxCore_TraceTest() :
1091 CxCore_MatrixTest( "matrix-trace", "cvTrace", 1, 1, true, true, 4 )
1096 void CxCore_TraceTest::run_func()
1098 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvTrace(test_array[INPUT][0]);
1102 void CxCore_TraceTest::prepare_to_validation( int )
1104 CvMat* mat = &test_mat[INPUT][0];
1105 int i, j, count = MIN( mat->rows, mat->cols );
1106 CvScalar trace = {{0,0,0,0}};
1108 for( i = 0; i < count; i++ )
1110 CvScalar el = cvGet2D( mat, i, i );
1111 for( j = 0; j < 4; j++ )
1112 trace.val[j] += el.val[j];
1115 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = trace;
1118 CxCore_TraceTest trace_test;
1121 ///////// dotproduct //////////
1123 class CxCore_DotProductTest : public CxCore_MatrixTest
1126 CxCore_DotProductTest();
1129 void prepare_to_validation( int test_case_idx );
1133 CxCore_DotProductTest::CxCore_DotProductTest() :
1134 CxCore_MatrixTest( "matrix-dotproduct", "cvDotProduct", 2, 1, true, true, 4 )
1136 depth_list = matrix_all_depths;
1140 void CxCore_DotProductTest::run_func()
1142 *((CvScalar*)(test_mat[OUTPUT][0].data.ptr)) =
1143 cvRealScalar(cvDotProduct( test_array[INPUT][0], test_array[INPUT][1] ));
1147 void CxCore_DotProductTest::prepare_to_validation( int )
1149 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.ptr)) =
1150 cvRealScalar(cvTsCrossCorr( &test_mat[INPUT][0], &test_mat[INPUT][1] ));
1153 CxCore_DotProductTest dotproduct_test;
1156 ///////// crossproduct //////////
1158 static const CvSize cross_product_sizes[] = {{3,1}, {-1,-1}};
1160 class CxCore_CrossProductTest : public CxCore_MatrixTest
1163 CxCore_CrossProductTest();
1165 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1167 void prepare_to_validation( int test_case_idx );
1171 CxCore_CrossProductTest::CxCore_CrossProductTest() :
1172 CxCore_MatrixTest( "matrix-crossproduct", "cvCrossProduct", 2, 1, false, false, 1 )
1174 size_list = cross_product_sizes;
1178 void CxCore_CrossProductTest::get_test_array_types_and_sizes( int /*test_case_idx*/, CvSize** sizes, int** types )
1180 CvRNG* rng = ts->get_rng();
1181 int depth = cvTsRandInt(rng) % 2 + CV_32F;
1182 int cn = cvTsRandInt(rng) & 1 ? 3 : 1, type = CV_MAKETYPE(depth, cn);
1185 types[INPUT][0] = types[INPUT][1] = types[OUTPUT][0] = types[REF_OUTPUT][0] = type;
1189 else if( cvTsRandInt(rng) & 1 )
1194 sizes[INPUT][0] = sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
1198 void CxCore_CrossProductTest::run_func()
1200 cvCrossProduct( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
1204 void CxCore_CrossProductTest::prepare_to_validation( int )
1206 CvScalar a = {{0,0,0,0}}, b = {{0,0,0,0}}, c = {{0,0,0,0}};
1208 if( test_mat[INPUT][0].rows > 1 )
1210 a.val[0] = cvGetReal2D( &test_mat[INPUT][0], 0, 0 );
1211 a.val[1] = cvGetReal2D( &test_mat[INPUT][0], 1, 0 );
1212 a.val[2] = cvGetReal2D( &test_mat[INPUT][0], 2, 0 );
1214 b.val[0] = cvGetReal2D( &test_mat[INPUT][1], 0, 0 );
1215 b.val[1] = cvGetReal2D( &test_mat[INPUT][1], 1, 0 );
1216 b.val[2] = cvGetReal2D( &test_mat[INPUT][1], 2, 0 );
1218 else if( test_mat[INPUT][0].cols > 1 )
1220 a.val[0] = cvGetReal1D( &test_mat[INPUT][0], 0 );
1221 a.val[1] = cvGetReal1D( &test_mat[INPUT][0], 1 );
1222 a.val[2] = cvGetReal1D( &test_mat[INPUT][0], 2 );
1224 b.val[0] = cvGetReal1D( &test_mat[INPUT][1], 0 );
1225 b.val[1] = cvGetReal1D( &test_mat[INPUT][1], 1 );
1226 b.val[2] = cvGetReal1D( &test_mat[INPUT][1], 2 );
1230 a = cvGet1D( &test_mat[INPUT][0], 0 );
1231 b = cvGet1D( &test_mat[INPUT][1], 0 );
1234 c.val[2] = a.val[0]*b.val[1] - a.val[1]*b.val[0];
1235 c.val[1] = -a.val[0]*b.val[2] + a.val[2]*b.val[0];
1236 c.val[0] = a.val[1]*b.val[2] - a.val[2]*b.val[1];
1238 if( test_mat[REF_OUTPUT][0].rows > 1 )
1240 cvSetReal2D( &test_mat[REF_OUTPUT][0], 0, 0, c.val[0] );
1241 cvSetReal2D( &test_mat[REF_OUTPUT][0], 1, 0, c.val[1] );
1242 cvSetReal2D( &test_mat[REF_OUTPUT][0], 2, 0, c.val[2] );
1244 else if( test_mat[REF_OUTPUT][0].cols > 1 )
1246 cvSetReal1D( &test_mat[REF_OUTPUT][0], 0, c.val[0] );
1247 cvSetReal1D( &test_mat[REF_OUTPUT][0], 1, c.val[1] );
1248 cvSetReal1D( &test_mat[REF_OUTPUT][0], 2, c.val[2] );
1252 cvSet1D( &test_mat[REF_OUTPUT][0], 0, c );
1256 CxCore_CrossProductTest crossproduct_test;
1259 ///////////////// scaleadd /////////////////////
1261 class CxCore_ScaleAddTest : public CxCore_MatrixTest
1264 CxCore_ScaleAddTest();
1266 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1267 void get_timing_test_array_types_and_sizes( int test_case_idx,
1268 CvSize** sizes, int** types,
1269 CvSize** whole_sizes, bool* are_images );
1270 int prepare_test_case( int test_case_idx );
1272 void prepare_to_validation( int test_case_idx );
1277 CxCore_ScaleAddTest::CxCore_ScaleAddTest() :
1278 CxCore_MatrixTest( "matrix-scaleadd", "cvScaleAdd", 3, 1, false, false, 4 )
1280 alpha = cvScalarAll(0);
1285 void CxCore_ScaleAddTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1287 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1288 sizes[INPUT][2] = cvSize(1,1);
1289 types[INPUT][2] &= CV_MAT_DEPTH_MASK;
1290 test_nd = cvTsRandInt(ts->get_rng()) % 2 != 0;
1294 void CxCore_ScaleAddTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1295 CvSize** sizes, int** types,
1296 CvSize** whole_sizes, bool* are_images )
1298 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1299 whole_sizes, are_images );
1300 sizes[INPUT][2] = cvSize(1,1);
1301 types[INPUT][2] &= CV_MAT_DEPTH_MASK;
1305 int CxCore_ScaleAddTest::prepare_test_case( int test_case_idx )
1307 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1309 alpha = cvGet1D( &test_mat[INPUT][2], 0 );
1316 void CxCore_ScaleAddTest::run_func()
1319 cvScaleAdd( test_array[INPUT][0], alpha, test_array[INPUT][1], test_array[OUTPUT][0] );
1322 cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
1323 cv::scaleAdd( cv::cvarrToMatND(test_array[INPUT][0]), alpha.val[0],
1324 cv::cvarrToMatND(test_array[INPUT][1]), c);
1329 void CxCore_ScaleAddTest::prepare_to_validation( int )
1331 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(alpha.val[0]),
1332 &test_mat[INPUT][1], cvScalarAll(1.),
1333 cvScalarAll(0.), &test_mat[REF_OUTPUT][0], 0 );
1336 CxCore_ScaleAddTest scaleadd_test;
1339 ///////////////// gemm /////////////////////
1341 static const char* matrix_gemm_param_names[] = { "size", "add_c", "mul_type", "depth", 0 };
1342 static const char* matrix_gemm_mul_types[] = { "AB", "AtB", "ABt", "AtBt", 0 };
1343 static const int matrix_gemm_add_c_flags[] = { 0, 1 };
1345 class CxCore_GEMMTest : public CxCore_MatrixTest
1350 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1351 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1352 void get_timing_test_array_types_and_sizes( int test_case_idx,
1353 CvSize** sizes, int** types,
1354 CvSize** whole_sizes, bool* are_images );
1355 int write_default_params( CvFileStorage* fs );
1356 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1357 int prepare_test_case( int test_case_idx );
1359 void prepare_to_validation( int test_case_idx );
1364 CxCore_GEMMTest::CxCore_GEMMTest() :
1365 CxCore_MatrixTest( "matrix-gemm", "cvGEMM", 5, 1, false, false, 2 )
1367 test_case_count = 100;
1368 max_log_array_size = 10;
1369 default_timing_param_names = matrix_gemm_param_names;
1374 void CxCore_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1376 CvRNG* rng = ts->get_rng();
1378 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1379 sizeA = sizes[INPUT][0];
1380 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1381 sizes[INPUT][0] = sizeA;
1382 sizes[INPUT][2] = sizes[INPUT][3] = cvSize(1,1);
1383 types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK;
1385 tabc_flag = cvTsRandInt(rng) & 7;
1387 switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
1390 sizes[INPUT][1].height = sizes[INPUT][0].width;
1391 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1392 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1395 sizes[INPUT][1].width = sizes[INPUT][0].width;
1396 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
1397 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1400 sizes[INPUT][1].height = sizes[INPUT][0].height;
1401 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1402 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
1404 case CV_GEMM_A_T | CV_GEMM_B_T:
1405 sizes[INPUT][1].width = sizes[INPUT][0].height;
1406 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
1407 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
1411 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1413 if( cvTsRandInt(rng) & 1 )
1414 sizes[INPUT][4] = cvSize(0,0);
1415 else if( !(tabc_flag & CV_GEMM_C_T) )
1416 sizes[INPUT][4] = sizes[OUTPUT][0];
1419 sizes[INPUT][4].width = sizes[OUTPUT][0].height;
1420 sizes[INPUT][4].height = sizes[OUTPUT][0].width;
1425 void CxCore_GEMMTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1426 CvSize** sizes, int** types,
1427 CvSize** whole_sizes, bool* are_images )
1429 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1430 sizes, types, whole_sizes, are_images );
1431 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AB" );
1432 if( strcmp( mul_type, "AtB" ) == 0 )
1433 tabc_flag = CV_GEMM_A_T;
1434 else if( strcmp( mul_type, "ABt" ) == 0 )
1435 tabc_flag = CV_GEMM_B_T;
1436 else if( strcmp( mul_type, "AtBt" ) == 0 )
1437 tabc_flag = CV_GEMM_A_T + CV_GEMM_B_T;
1441 if( cvReadInt( find_timing_param( "add_c" ), 0 ) == 0 )
1442 sizes[INPUT][4] = cvSize(0,0);
1446 int CxCore_GEMMTest::write_default_params( CvFileStorage* fs )
1448 int code = CxCore_MatrixTest::write_default_params(fs);
1449 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1451 write_string_list( fs, "mul_type", matrix_gemm_mul_types );
1452 write_int_list( fs, "add_c", matrix_gemm_add_c_flags, CV_DIM(matrix_gemm_add_c_flags) );
1457 void CxCore_GEMMTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1459 sprintf( ptr, "%s%s,%s,",
1460 tabc_flag & CV_GEMM_A_T ? "At" : "A",
1461 tabc_flag & CV_GEMM_B_T ? "Bt" : "B",
1462 test_array[INPUT][4] ? "plusC" : "" );
1465 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1469 int CxCore_GEMMTest::prepare_test_case( int test_case_idx )
1471 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1474 alpha = cvmGet( &test_mat[INPUT][2], 0, 0 );
1475 beta = cvmGet( &test_mat[INPUT][3], 0, 0 );
1481 void CxCore_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1483 *low = cvScalarAll(-10.);
1484 *high = cvScalarAll(10.);
1488 void CxCore_GEMMTest::run_func()
1490 cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
1491 test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
1495 void CxCore_GEMMTest::prepare_to_validation( int )
1497 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][1], alpha,
1498 test_array[INPUT][4] ? &test_mat[INPUT][4] : 0,
1499 beta, &test_mat[REF_OUTPUT][0], tabc_flag );
1502 CxCore_GEMMTest gemm_test;
1505 ///////////////// multransposed /////////////////////
1507 static const char* matrix_multrans_param_names[] = { "size", "use_delta", "mul_type", "depth", 0 };
1508 static const int matrix_multrans_use_delta_flags[] = { 0, 1 };
1509 static const char* matrix_multrans_mul_types[] = { "AAt", "AtA", 0 };
1511 class CxCore_MulTransposedTest : public CxCore_MatrixTest
1514 CxCore_MulTransposedTest();
1516 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1517 void get_timing_test_array_types_and_sizes( int test_case_idx,
1518 CvSize** sizes, int** types,
1519 CvSize** whole_sizes, bool* are_images );
1520 int write_default_params( CvFileStorage* fs );
1521 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1522 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
1524 void prepare_to_validation( int test_case_idx );
1529 CxCore_MulTransposedTest::CxCore_MulTransposedTest() :
1530 CxCore_MatrixTest( "matrix-multransposed", "cvMulTransposed, cvRepeat", 2, 1, false, false, 1 )
1532 test_case_count = 100;
1534 test_array[TEMP].push(NULL);
1535 default_timing_param_names = matrix_multrans_param_names;
1539 void CxCore_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1541 CvRNG* rng = ts->get_rng();
1542 int bits = cvTsRandInt(rng);
1543 int src_type = cvTsRandInt(rng) % 5;
1544 int dst_type = cvTsRandInt(rng) % 2;
1546 src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S :
1547 src_type == 3 ? CV_32F : CV_64F;
1548 dst_type = dst_type == 0 ? CV_32F : CV_64F;
1549 dst_type = MAX( dst_type, src_type );
1551 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1554 sizes[INPUT][1] = cvSize(0,0);
1557 sizes[INPUT][1] = sizes[INPUT][0];
1559 sizes[INPUT][1].height = 1;
1561 sizes[INPUT][1].width = 1;
1564 sizes[TEMP][0] = sizes[INPUT][0];
1565 types[INPUT][0] = src_type;
1566 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type;
1568 order = (bits & 8) != 0;
1569 sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ?
1570 sizes[INPUT][0].height : sizes[INPUT][0].width;
1571 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
1575 void CxCore_MulTransposedTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1576 CvSize** sizes, int** types,
1577 CvSize** whole_sizes, bool* are_images )
1579 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1580 sizes, types, whole_sizes, are_images );
1581 const char* mul_type = cvReadString( find_timing_param("mul_type"), "AAt" );
1582 order = strcmp( mul_type, "AtA" ) == 0;
1584 if( cvReadInt( find_timing_param( "use_delta" ), 0 ) == 0 )
1585 sizes[INPUT][1] = cvSize(0,0);
1589 int CxCore_MulTransposedTest::write_default_params( CvFileStorage* fs )
1591 int code = CxCore_MatrixTest::write_default_params(fs);
1592 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
1594 write_string_list( fs, "mul_type", matrix_multrans_mul_types );
1595 write_int_list( fs, "use_delta", matrix_multrans_use_delta_flags,
1596 CV_DIM(matrix_multrans_use_delta_flags) );
1601 void CxCore_MulTransposedTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1603 sprintf( ptr, "%s,%s,", order == 0 ? "AAt" : "AtA", test_array[INPUT][1] ? "delta" : "" );
1606 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1610 void CxCore_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
1612 *low = cvScalarAll(-10.);
1613 *high = cvScalarAll(10.);
1617 void CxCore_MulTransposedTest::run_func()
1619 cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
1620 order, test_array[INPUT][1] );
1624 void CxCore_MulTransposedTest::prepare_to_validation( int )
1626 CvMat* delta = test_array[INPUT][1] ? &test_mat[INPUT][1] : 0;
1629 if( test_mat[INPUT][1].rows < test_mat[INPUT][0].rows ||
1630 test_mat[INPUT][1].cols < test_mat[INPUT][0].cols )
1632 cvRepeat( delta, &test_mat[TEMP][0] );
1633 delta = &test_mat[TEMP][0];
1635 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.), delta, cvScalarAll(-1.),
1636 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
1639 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
1640 delta = &test_mat[TEMP][0];
1642 cvTsGEMM( delta, delta, 1., 0, 0, &test_mat[REF_OUTPUT][0], order == 0 ? CV_GEMM_B_T : CV_GEMM_A_T );
1645 CxCore_MulTransposedTest multransposed_test;
1648 ///////////////// Transform /////////////////////
1650 static const CvSize matrix_transform_sizes[] = {{10,10}, {100,100}, {720,480}, {-1,-1}};
1651 static const CvSize matrix_transform_whole_sizes[] = {{10,10}, {720,480}, {720,480}, {-1,-1}};
1652 static const int matrix_transform_channels[] = { 2, 3, 4, -1 };
1653 static const char* matrix_transform_param_names[] = { "size", "channels", "depth", 0 };
1655 class CxCore_TransformTest : public CxCore_MatrixTest
1658 CxCore_TransformTest();
1660 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1661 double get_success_error_level( int test_case_idx, int i, int j );
1662 void get_timing_test_array_types_and_sizes( int test_case_idx,
1663 CvSize** sizes, int** types,
1664 CvSize** whole_sizes, bool* are_images );
1665 int prepare_test_case( int test_case_idx );
1666 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1668 void prepare_to_validation( int test_case_idx );
1675 CxCore_TransformTest::CxCore_TransformTest() :
1676 CxCore_MatrixTest( "matrix-transform", "cvTransform", 3, 1, true, false, 4 )
1678 default_timing_param_names = matrix_transform_param_names;
1679 cn_list = matrix_transform_channels;
1680 depth_list = matrix_all_depths;
1681 size_list = matrix_transform_sizes;
1682 whole_size_list = matrix_transform_whole_sizes;
1686 void CxCore_TransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1688 CvRNG* rng = ts->get_rng();
1689 int bits = cvTsRandInt(rng);
1690 int depth, dst_cn, mat_cols, mattype;
1691 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1693 mat_cols = CV_MAT_CN(types[INPUT][0]);
1694 depth = CV_MAT_DEPTH(types[INPUT][0]);
1695 dst_cn = cvTsRandInt(rng) % 4 + 1;
1696 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
1698 mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1699 types[INPUT][1] = mattype;
1700 types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
1702 scale = 1./((cvTsRandInt(rng)%4)*50+1);
1706 sizes[INPUT][2] = cvSize(0,0);
1707 mat_cols += (bits & 4) != 0;
1710 sizes[INPUT][2] = cvSize(1,1);
1714 sizes[INPUT][2] = cvSize(dst_cn,1);
1716 sizes[INPUT][2] = cvSize(1,dst_cn);
1717 types[INPUT][2] &= ~CV_MAT_CN_MASK;
1719 diagMtx = (bits & 16) != 0;
1721 sizes[INPUT][1] = cvSize(mat_cols,dst_cn);
1725 void CxCore_TransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1726 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1728 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1729 sizes, types, whole_sizes, are_images );
1730 int cn = CV_MAT_CN(types[INPUT][0]);
1731 sizes[INPUT][1] = cvSize(cn + (cn < 4), cn);
1732 sizes[INPUT][2] = cvSize(0,0);
1733 types[INPUT][1] = types[INPUT][2] = CV_64FC1;
1737 int CxCore_TransformTest::prepare_test_case( int test_case_idx )
1739 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
1742 cvTsAdd(&test_mat[INPUT][1], cvScalarAll(scale), &test_mat[INPUT][1],
1743 cvScalarAll(0), cvScalarAll(0), &test_mat[INPUT][1], 0 );
1746 CvMat* w = cvCloneMat(&test_mat[INPUT][1]);
1747 cvSetIdentity(w, cvScalarAll(1));
1748 cvMul(w, &test_mat[INPUT][1], &test_mat[INPUT][1]);
1755 void CxCore_TransformTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1757 CvSize size = cvGetMatSize(&test_mat[INPUT][1]);
1758 sprintf( ptr, "matrix=%dx%d,", size.height, size.width );
1761 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
1765 double CxCore_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
1767 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1768 return depth <= CV_8S ? 1 : depth <= CV_32S ? 8 :
1769 CxCore_MatrixTest::get_success_error_level( test_case_idx, i, j );
1772 void CxCore_TransformTest::run_func()
1774 cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1],
1775 test_array[INPUT][2] ? &test_mat[INPUT][2] : 0);
1779 void CxCore_TransformTest::prepare_to_validation( int )
1781 CvMat* transmat = &test_mat[INPUT][1];
1782 CvMat* shift = test_array[INPUT][2] ? &test_mat[INPUT][2] : 0;
1784 cvTsTransform( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], transmat, shift );
1787 CxCore_TransformTest transform_test;
1790 ///////////////// PerspectiveTransform /////////////////////
1792 static const int matrix_perspective_transform_channels[] = { 2, 3, -1 };
1794 class CxCore_PerspectiveTransformTest : public CxCore_MatrixTest
1797 CxCore_PerspectiveTransformTest();
1799 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1800 double get_success_error_level( int test_case_idx, int i, int j );
1801 void get_timing_test_array_types_and_sizes( int test_case_idx,
1802 CvSize** sizes, int** types,
1803 CvSize** whole_sizes, bool* are_images );
1805 void prepare_to_validation( int test_case_idx );
1809 CxCore_PerspectiveTransformTest::CxCore_PerspectiveTransformTest() :
1810 CxCore_MatrixTest( "matrix-perspective", "cvPerspectiveTransform", 2, 1, false, false, 2 )
1812 default_timing_param_names = matrix_transform_param_names;
1813 cn_list = matrix_perspective_transform_channels;
1814 size_list = matrix_transform_sizes;
1815 whole_size_list = matrix_transform_whole_sizes;
1819 void CxCore_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1821 CvRNG* rng = ts->get_rng();
1822 int bits = cvTsRandInt(rng);
1823 int depth, cn, mattype;
1824 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1826 cn = CV_MAT_CN(types[INPUT][0]) + 1;
1827 depth = CV_MAT_DEPTH(types[INPUT][0]);
1828 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1830 mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
1831 types[INPUT][1] = mattype;
1832 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1836 double CxCore_PerspectiveTransformTest::get_success_error_level( int test_case_idx, int i, int j )
1838 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1839 return depth == CV_32F ? 1e-4 : depth == CV_64F ? 1e-8 :
1840 CxCore_MatrixTest::get_success_error_level(test_case_idx, i, j);
1844 void CxCore_PerspectiveTransformTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1845 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
1847 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
1848 sizes, types, whole_sizes, are_images );
1849 int cn = CV_MAT_CN(types[INPUT][0]);
1850 sizes[INPUT][1] = cvSize(cn + 1, cn + 1);
1851 types[INPUT][1] = CV_64FC1;
1855 void CxCore_PerspectiveTransformTest::run_func()
1857 cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &test_mat[INPUT][1] );
1861 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
1864 int cn, depth, mat_depth;
1865 CvMat astub, bstub, *a, *b;
1866 double mat[16], *buf;
1868 a = cvGetMat( _src, &astub, 0, 0 );
1869 b = cvGetMat( _dst, &bstub, 0, 0 );
1871 cn = CV_MAT_CN(a->type);
1872 depth = CV_MAT_DEPTH(a->type);
1873 mat_depth = CV_MAT_DEPTH(transmat->type);
1874 cols = transmat->cols;
1876 // prepare cn x (cn + 1) transform matrix
1877 if( mat_depth == CV_32F )
1879 for( i = 0; i < transmat->rows; i++ )
1880 for( j = 0; j < cols; j++ )
1881 mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
1885 assert( mat_depth == CV_64F );
1886 for( i = 0; i < transmat->rows; i++ )
1887 for( j = 0; j < cols; j++ )
1888 mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
1892 cols = a->cols * cn;
1893 buf = (double*)cvStackAlloc( cols * sizeof(double) );
1895 for( i = 0; i < a->rows; i++ )
1897 uchar* src = a->data.ptr + i*a->step;
1898 uchar* dst = b->data.ptr + i*b->step;
1903 for( j = 0; j < cols; j++ )
1904 buf[j] = ((float*)src)[j];
1907 for( j = 0; j < cols; j++ )
1908 buf[j] = ((double*)src)[j];
1917 for( j = 0; j < cols; j += 2 )
1919 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2];
1920 double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5];
1921 double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8];
1928 for( j = 0; j < cols; j += 3 )
1930 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3];
1931 double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7];
1932 double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11];
1933 double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15];
1947 for( j = 0; j < cols; j++ )
1948 ((float*)dst)[j] = (float)buf[j];
1951 for( j = 0; j < cols; j++ )
1952 ((double*)dst)[j] = buf[j];
1961 void CxCore_PerspectiveTransformTest::prepare_to_validation( int )
1963 CvMat* transmat = &test_mat[INPUT][1];
1964 cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], transmat );
1967 CxCore_PerspectiveTransformTest perspective_test;
1970 ///////////////// Mahalanobis /////////////////////
1972 class CxCore_MahalanobisTest : public CxCore_MatrixTest
1975 CxCore_MahalanobisTest();
1977 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1978 void get_timing_test_array_types_and_sizes( int test_case_idx,
1979 CvSize** sizes, int** types,
1980 CvSize** whole_sizes, bool* are_images );
1981 int prepare_test_case( int test_case_idx );
1983 void prepare_to_validation( int test_case_idx );
1987 CxCore_MahalanobisTest::CxCore_MahalanobisTest() :
1988 CxCore_MatrixTest( "matrix-mahalanobis", "cvMahalanobis", 3, 1, false, true, 1 )
1990 test_case_count = 100;
1991 test_array[TEMP].push(NULL);
1992 test_array[TEMP].push(NULL);
1993 test_array[TEMP].push(NULL);
1997 void CxCore_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1999 CvRNG* rng = ts->get_rng();
2000 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2002 if( cvTsRandInt(rng) & 1 )
2003 sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
2005 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
2007 sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0];
2008 sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1;
2009 sizes[TEMP][2] = sizes[INPUT][2];
2010 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
2014 void CxCore_MahalanobisTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2015 CvSize** sizes, int** types, CvSize** whole_sizes, bool* are_images )
2017 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2018 sizes, types, whole_sizes, are_images );
2019 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
2023 int CxCore_MahalanobisTest::prepare_test_case( int test_case_idx )
2025 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2026 if( code > 0 && ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
2028 // make sure that the inverted "covariation" matrix is symmetrix and positively defined.
2029 cvTsGEMM( &test_mat[INPUT][2], &test_mat[INPUT][2], 1., 0, 0., &test_mat[TEMP][2], CV_GEMM_B_T );
2030 cvTsCopy( &test_mat[TEMP][2], &test_mat[INPUT][2] );
2037 void CxCore_MahalanobisTest::run_func()
2039 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) =
2040 cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
2043 void CxCore_MahalanobisTest::prepare_to_validation( int )
2045 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
2046 &test_mat[INPUT][1], cvScalarAll(-1.),
2047 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
2048 if( test_mat[INPUT][0].rows == 1 )
2049 cvTsGEMM( &test_mat[TEMP][0], &test_mat[INPUT][2], 1.,
2050 0, 0., &test_mat[TEMP][1], 0 );
2052 cvTsGEMM( &test_mat[INPUT][2], &test_mat[TEMP][0], 1.,
2053 0, 0., &test_mat[TEMP][1], 0 );
2055 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) =
2056 cvRealScalar(sqrt(cvTsCrossCorr(&test_mat[TEMP][0], &test_mat[TEMP][1])));
2059 CxCore_MahalanobisTest mahalanobis_test;
2062 ///////////////// covarmatrix /////////////////////
2064 class CxCore_CovarMatrixTest : public CxCore_MatrixTest
2067 CxCore_CovarMatrixTest();
2069 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2070 int prepare_test_case( int test_case_idx );
2072 void prepare_to_validation( int test_case_idx );
2073 CvTestPtrVec temp_hdrs;
2075 int flags, t_flag, len, count;
2080 CxCore_CovarMatrixTest::CxCore_CovarMatrixTest() :
2081 CxCore_MatrixTest( "matrix-covar", "cvCalcCovarMatrix", 1, 1, true, false, 1 ),
2082 flags(0), t_flag(0), are_images(false)
2084 test_case_count = 100;
2085 test_array[INPUT_OUTPUT].push(NULL);
2086 test_array[REF_INPUT_OUTPUT].push(NULL);
2087 test_array[TEMP].push(NULL);
2088 test_array[TEMP].push(NULL);
2090 support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
2094 void CxCore_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2096 CvRNG* rng = ts->get_rng();
2097 int bits = cvTsRandInt(rng);
2098 int i, single_matrix;
2099 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2101 flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS );
2102 single_matrix = flags & CV_COVAR_ROWS;
2103 t_flag = (bits & 256) != 0;
2105 const int min_count = 2;
2109 len = sizes[INPUT][0].width;
2110 count = sizes[INPUT][0].height;
2111 count = MAX(count, min_count);
2112 sizes[INPUT][0] = cvSize(len, count);
2116 len = sizes[INPUT][0].height;
2117 count = sizes[INPUT][0].width;
2118 count = MAX(count, min_count);
2119 sizes[INPUT][0] = cvSize(count, len);
2122 if( single_matrix && t_flag )
2123 flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
2125 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
2126 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
2128 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? cvSize(len,len) : cvSize(count,count);
2129 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? cvSize(len,1) : cvSize(1,len);
2130 sizes[TEMP][0] = sizes[INPUT][0];
2132 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] =
2133 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] =
2134 CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F;
2136 are_images = (bits & 1024) != 0;
2137 for( i = 0; i < (single_matrix ? 1 : count); i++ )
2138 temp_hdrs.push(NULL);
2142 int CxCore_CovarMatrixTest::prepare_test_case( int test_case_idx )
2144 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2148 int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
2149 int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
2151 hdr_data = (uchar*)cvAlloc( count*hdr_size );
2155 *((CvMat*)hdr_data) = test_mat[INPUT][0];
2157 cvGetImage( &test_mat[INPUT][0], (IplImage*)hdr_data );
2158 temp_hdrs[0] = hdr_data;
2161 for( i = 0; i < count; i++ )
2164 void* ptr = hdr_data + i*hdr_size;
2167 cvGetRow( &test_mat[INPUT][0], &part, i );
2169 cvGetCol( &test_mat[INPUT][0], &part, i );
2172 *((CvMat*)ptr) = part;
2174 cvGetImage( &part, (IplImage*)ptr );
2184 void CxCore_CovarMatrixTest::run_func()
2186 cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
2187 test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
2191 void CxCore_CovarMatrixTest::prepare_to_validation( int )
2193 CvMat* avg = &test_mat[REF_INPUT_OUTPUT][0];
2196 if( !(flags & CV_COVAR_USE_AVG) )
2201 for( i = 0; i < count; i++ )
2203 CvMat stub, *vec = 0;
2204 if( flags & CV_COVAR_ROWS )
2205 vec = cvGetRow( temp_hdrs[0], &stub, i );
2206 else if( flags & CV_COVAR_COLS )
2207 vec = cvGetCol( temp_hdrs[0], &stub, i );
2209 vec = cvGetMat( temp_hdrs[i], &stub );
2211 cvTsAdd( avg, cvScalarAll(1.), vec,
2212 cvScalarAll(1.), cvScalarAll(0.), avg, 0 );
2215 cvTsAdd( avg, cvScalarAll(1./count), 0,
2216 cvScalarAll(0.), cvScalarAll(0.), avg, 0 );
2219 if( flags & CV_COVAR_SCALE )
2224 cvRepeat( avg, &test_mat[TEMP][0] );
2225 cvTsAdd( &test_mat[INPUT][0], cvScalarAll(1.),
2226 &test_mat[TEMP][0], cvScalarAll(-1.),
2227 cvScalarAll(0.), &test_mat[TEMP][0], 0 );
2229 cvTsGEMM( &test_mat[TEMP][0], &test_mat[TEMP][0],
2230 scale, 0, 0., &test_mat[REF_OUTPUT][0],
2231 t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ?
2232 CV_GEMM_A_T : CV_GEMM_B_T );
2234 cvFree( &hdr_data );
2238 CxCore_CovarMatrixTest covarmatrix_test;
2241 static void cvTsFloodWithZeros( CvMat* mat, CvRNG* rng )
2243 int k, total = mat->rows*mat->cols;
2244 int zero_total = cvTsRandInt(rng) % total;
2245 assert( CV_MAT_TYPE(mat->type) == CV_32FC1 ||
2246 CV_MAT_TYPE(mat->type) == CV_64FC1 );
2248 for( k = 0; k < zero_total; k++ )
2250 int i = cvTsRandInt(rng) % mat->rows;
2251 int j = cvTsRandInt(rng) % mat->cols;
2252 uchar* row = mat->data.ptr + mat->step*i;
2254 if( CV_MAT_DEPTH(mat->type) == CV_32FC1 )
2255 ((float*)row)[j] = 0.f;
2257 ((double*)row)[j] = 0.;
2262 ///////////////// determinant /////////////////////
2264 class CxCore_DetTest : public CxCore_MatrixTest
2269 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2270 double get_success_error_level( int test_case_idx, int i, int j );
2271 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2272 int prepare_test_case( int test_case_idx );
2274 void prepare_to_validation( int test_case_idx );
2278 CxCore_DetTest::CxCore_DetTest() :
2279 CxCore_MatrixTest( "matrix-det", "cvDet", 1, 1, false, true, 1 )
2281 test_case_count = 100;
2282 max_log_array_size = 7;
2283 test_array[TEMP].push(NULL);
2287 void CxCore_DetTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2289 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2291 sizes[INPUT][0].width = sizes[INPUT][0].height = sizes[INPUT][0].height;
2292 sizes[TEMP][0] = sizes[INPUT][0];
2293 types[TEMP][0] = CV_64FC1;
2297 void CxCore_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2299 *low = cvScalarAll(-2.);
2300 *high = cvScalarAll(2.);
2304 double CxCore_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2306 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
2310 int CxCore_DetTest::prepare_test_case( int test_case_idx )
2312 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2314 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2320 void CxCore_DetTest::run_func()
2322 *((CvScalar*)(test_mat[OUTPUT][0].data.db)) = cvRealScalar(cvDet(test_array[INPUT][0]));
2326 // LU method that chooses the optimal in a column pivot element
2327 static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 )
2329 int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double);
2330 int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0;
2331 int x_step = x ? x->step/sizeof(double) : 0;
2332 double *a0 = a->data.db, *b0 = b ? b->data.db : 0;
2333 double *x0 = x ? x->data.db : 0;
2335 assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
2336 (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
2338 for( i = 0; i < Nm; i++ )
2340 double max_val = fabs(a0[i*step + i]);
2341 double *a1, *a2, *b1 = 0, *b2 = 0;
2344 for( j = i+1; j < N; j++ )
2346 t = fabs(a0[j*step + i]);
2356 for( j = i; j < N1; j++ )
2357 CV_SWAP( a0[i*step + j], a0[k*step + j], t );
2359 for( j = 0; j < M; j++ )
2360 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
2376 for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
2379 for( k = i+1; k < N1; k++ )
2382 for( k = 0; k < M; k++ )
2393 for( i = N-1; i >= 0; i-- )
2395 double* a1 = a0 + i*step;
2396 double* b1 = b0 + i*b_step;
2397 for( j = 0; j < M; j++ )
2400 for( k = i+1; k < N1; k++ )
2401 t -= a1[k]*x0[k*x_step + j];
2402 x0[i*x_step + j] = t/a1[i];
2413 void CxCore_DetTest::prepare_to_validation( int )
2415 if( !CV_ARE_TYPES_EQ( &test_mat[INPUT][0], &test_mat[TEMP][0] ))
2416 cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][0] );
2418 cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][0], 0 );
2420 *((CvScalar*)(test_mat[REF_OUTPUT][0].data.db)) = cvRealScalar(cvTsLU(&test_mat[TEMP][0], 0, 0));
2423 CxCore_DetTest det_test;
2427 ///////////////// invert /////////////////////
2429 static const char* matrix_solve_invert_param_names[] = { "size", "method", "depth", 0 };
2430 static const char* matrix_solve_invert_methods[] = { "LU", "SVD", 0 };
2432 class CxCore_InvertTest : public CxCore_MatrixTest
2435 CxCore_InvertTest();
2437 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2438 void get_timing_test_array_types_and_sizes( int test_case_idx,
2439 CvSize** sizes, int** types,
2440 CvSize** whole_sizes, bool* are_images );
2441 int write_default_params( CvFileStorage* fs );
2442 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2443 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2444 double get_success_error_level( int test_case_idx, int i, int j );
2445 int prepare_test_case( int test_case_idx );
2447 void prepare_to_validation( int test_case_idx );
2453 CxCore_InvertTest::CxCore_InvertTest() :
2454 CxCore_MatrixTest( "matrix-invert", "cvInvert, cvSVD, cvSVBkSb", 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
2456 test_case_count = 100;
2457 max_log_array_size = 7;
2458 test_array[TEMP].push(NULL);
2459 test_array[TEMP].push(NULL);
2461 default_timing_param_names = matrix_solve_invert_param_names;
2465 void CxCore_InvertTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2467 CvRNG* rng = ts->get_rng();
2468 int bits = cvTsRandInt(rng);
2469 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2470 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2472 if( (bits & 3) == 0 )
2477 sizes[INPUT][0] = cvSize(min_size, min_size);
2479 method = CV_SVD_SYM;
2485 sizes[INPUT][0] = cvSize(min_size, min_size);
2488 sizes[TEMP][0].width = sizes[INPUT][0].height;
2489 sizes[TEMP][0].height = sizes[INPUT][0].width;
2490 sizes[TEMP][1] = sizes[INPUT][0];
2491 types[TEMP][0] = types[INPUT][0];
2492 types[TEMP][1] = CV_64FC1;
2493 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(min_size, min_size);
2497 void CxCore_InvertTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2498 CvSize** sizes, int** types,
2499 CvSize** whole_sizes, bool* are_images )
2501 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2502 sizes, types, whole_sizes, are_images );
2503 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2504 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2508 int CxCore_InvertTest::write_default_params( CvFileStorage* fs )
2510 int code = CxCore_MatrixTest::write_default_params(fs);
2511 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2513 write_string_list( fs, "method", matrix_solve_invert_methods );
2518 void CxCore_InvertTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2520 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2523 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2527 double CxCore_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
2529 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-7;
2532 int CxCore_InvertTest::prepare_test_case( int test_case_idx )
2534 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2537 cvTsFloodWithZeros( &test_mat[INPUT][0], ts->get_rng() );
2539 if( method == CV_SVD_SYM )
2541 cvTsGEMM( &test_mat[INPUT][0], &test_mat[INPUT][0], 1.,
2542 0, 0., &test_mat[TEMP][0], CV_GEMM_B_T );
2543 cvTsCopy( &test_mat[TEMP][0], &test_mat[INPUT][0] );
2552 void CxCore_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2554 *low = cvScalarAll(-1.);
2555 *high = cvScalarAll(1.);
2559 void CxCore_InvertTest::run_func()
2561 result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
2565 static double cvTsSVDet( CvMat* mat, double* ratio )
2567 int type = CV_MAT_TYPE(mat->type);
2568 int i, nm = MIN( mat->rows, mat->cols );
2569 CvMat* w = cvCreateMat( nm, 1, type );
2572 cvSVD( mat, w, 0, 0, 0 );
2574 if( type == CV_32FC1 )
2576 for( i = 0; i < nm; i++ )
2577 det *= w->data.fl[i];
2578 *ratio = w->data.fl[nm-1] < FLT_EPSILON ? FLT_MAX : w->data.fl[0]/w->data.fl[nm-1];
2582 for( i = 0; i < nm; i++ )
2583 det *= w->data.db[i];
2584 *ratio = w->data.db[nm-1] < FLT_EPSILON ? DBL_MAX : w->data.db[0]/w->data.db[nm-1];
2591 void CxCore_InvertTest::prepare_to_validation( int )
2593 CvMat* input = &test_mat[INPUT][0];
2594 double ratio = 0, det = cvTsSVDet( input, &ratio );
2595 double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*500;
2596 double rthreshold = CV_MAT_DEPTH(input->type) == CV_32F ? 1e6 : 1e12;
2598 if( CV_MAT_TYPE(input->type) == CV_32FC1 )
2599 cvTsConvert( input, &test_mat[TEMP][1] );
2601 cvTsCopy( input, &test_mat[TEMP][1], 0 );
2603 if( (method == CV_LU && result == 0) ||
2605 (method == CV_LU && ratio > rthreshold) ||
2606 (method == CV_SVD && result < threshold) )
2608 cvTsZero( &test_mat[OUTPUT][0] );
2609 cvTsZero( &test_mat[REF_OUTPUT][0] );
2610 //cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(fabs(det)>1e-3),
2611 // &test_mat[REF_OUTPUT][0], 0 );
2615 if( input->rows >= input->cols )
2616 cvTsGEMM( &test_mat[TEMP][0], input, 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2618 cvTsGEMM( input, &test_mat[TEMP][0], 1., 0, 0., &test_mat[OUTPUT][0], 0 );
2620 cvTsSetIdentity( &test_mat[REF_OUTPUT][0], cvScalarAll(1.) );
2623 CxCore_InvertTest invert_test;
2626 ///////////////// solve /////////////////////
2628 class CxCore_SolveTest : public CxCore_MatrixTest
2633 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2634 void get_timing_test_array_types_and_sizes( int test_case_idx,
2635 CvSize** sizes, int** types,
2636 CvSize** whole_sizes, bool* are_images );
2637 int write_default_params( CvFileStorage* fs );
2638 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2639 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2640 double get_success_error_level( int test_case_idx, int i, int j );
2641 int prepare_test_case( int test_case_idx );
2643 void prepare_to_validation( int test_case_idx );
2649 CxCore_SolveTest::CxCore_SolveTest() :
2650 CxCore_MatrixTest( "matrix-solve", "cvSolve, cvSVD, cvSVBkSb", 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
2652 test_case_count = 100;
2653 max_log_array_size = 7;
2654 test_array[TEMP].push(NULL);
2655 test_array[TEMP].push(NULL);
2657 default_timing_param_names = matrix_solve_invert_param_names;
2661 void CxCore_SolveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2663 CvRNG* rng = ts->get_rng();
2664 int bits = cvTsRandInt(rng);
2665 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2666 CvSize in_sz = sizes[INPUT][0];
2667 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2668 sizes[INPUT][0] = in_sz;
2669 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2671 if( (bits & 3) == 0 )
2676 sizes[INPUT][0] = cvSize(min_size, min_size);
2678 method = CV_SVD_SYM;*/
2684 sizes[INPUT][0] = cvSize(min_size, min_size);
2687 sizes[INPUT][1].height = sizes[INPUT][0].height;
2688 sizes[TEMP][0].width = sizes[INPUT][1].width;
2689 sizes[TEMP][0].height = sizes[INPUT][0].width;
2690 sizes[TEMP][1] = sizes[INPUT][0];
2691 types[TEMP][0] = types[INPUT][0];
2692 types[TEMP][1] = CV_64FC1;
2693 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][1].width, min_size);
2696 void CxCore_SolveTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2697 CvSize** sizes, int** types,
2698 CvSize** whole_sizes, bool* are_images )
2700 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2701 sizes, types, whole_sizes, are_images );
2702 const char* method_str = cvReadString( find_timing_param("method"), "LU" );
2703 sizes[INPUT][1].width = sizes[TEMP][0].width = sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = 1;
2704 method = strcmp( method_str, "LU" ) == 0 ? CV_LU : CV_SVD;
2708 int CxCore_SolveTest::write_default_params( CvFileStorage* fs )
2710 int code = CxCore_MatrixTest::write_default_params(fs);
2711 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2713 write_string_list( fs, "method", matrix_solve_invert_methods );
2718 void CxCore_SolveTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2720 sprintf( ptr, "%s,", method == CV_LU ? "LU" : "SVD" );
2723 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2727 int CxCore_SolveTest::prepare_test_case( int test_case_idx )
2729 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2731 /*if( method == CV_SVD_SYM )
2733 cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1.,
2734 0, 0., test_array[TEMP][0], CV_GEMM_B_T );
2735 cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] );
2742 void CxCore_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2744 *low = cvScalarAll(-1.);
2745 *high = cvScalarAll(1.);
2749 double CxCore_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
2751 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-8;
2755 void CxCore_SolveTest::run_func()
2757 result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
2760 void CxCore_SolveTest::prepare_to_validation( int )
2762 //int rank = test_mat[REF_OUTPUT][0].rows;
2764 CvMat* input = &test_mat[INPUT][0];
2766 if( method == CV_LU )
2770 if( CV_MAT_TYPE(input->type) == CV_32FC1 )
2771 cvTsConvert( input, &test_mat[TEMP][1] );
2773 cvTsCopy( input, &test_mat[TEMP][1], 0 );
2775 cvTsZero( &test_mat[OUTPUT][0] );
2776 double det = cvTsLU( &test_mat[TEMP][1], 0, 0 );
2777 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(det != 0),
2778 &test_mat[REF_OUTPUT][0], 0 );
2782 double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*500;
2783 double rthreshold = CV_MAT_DEPTH(input->type) == CV_32F ? 1e6 : 1e12;
2784 double ratio = 0, det = cvTsSVDet( input, &ratio );
2785 if( det < threshold || ratio > rthreshold )
2787 cvTsZero( &test_mat[OUTPUT][0] );
2788 cvTsZero( &test_mat[REF_OUTPUT][0] );
2794 dst = input->rows <= input->cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
2796 cvTsGEMM( input, &test_mat[TEMP][0], 1., &test_mat[INPUT][1], -1., dst, 0 );
2797 if( dst != &test_mat[OUTPUT][0] )
2798 cvTsGEMM( input, dst, 1., 0, 0., &test_mat[OUTPUT][0], CV_GEMM_A_T );
2799 cvTsZero( &test_mat[REF_OUTPUT][0] );
2802 CxCore_SolveTest solve_test;
2805 ///////////////// SVD /////////////////////
2807 static const char* matrix_svd_param_names[] = { "size", "output", "depth", 0 };
2808 static const char* matrix_svd_output_modes[] = { "w", "all", 0 };
2810 class CxCore_SVDTest : public CxCore_MatrixTest
2815 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2816 void get_timing_test_array_types_and_sizes( int test_case_idx,
2817 CvSize** sizes, int** types,
2818 CvSize** whole_sizes, bool* are_images );
2819 double get_success_error_level( int test_case_idx, int i, int j );
2820 int write_default_params( CvFileStorage* fs );
2821 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2822 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
2823 int prepare_test_case( int test_case_idx );
2825 void prepare_to_validation( int test_case_idx );
2827 bool have_u, have_v, symmetric, compact, vector_w;
2831 CxCore_SVDTest::CxCore_SVDTest() :
2832 CxCore_MatrixTest( "matrix-svd", "cvSVD", 1, 4, false, false, 1 ),
2833 flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false)
2835 test_case_count = 100;
2836 test_array[TEMP].push(NULL);
2837 test_array[TEMP].push(NULL);
2838 test_array[TEMP].push(NULL);
2839 test_array[TEMP].push(NULL);
2841 default_timing_param_names = matrix_svd_param_names;
2845 void CxCore_SVDTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
2847 CvRNG* rng = ts->get_rng();
2848 int bits = cvTsRandInt(rng);
2849 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2850 int min_size, i, m, n;
2852 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2854 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
2855 have_u = (bits & 8) != 0;
2856 have_v = (bits & 16) != 0;
2857 symmetric = (bits & 32) != 0;
2858 compact = (bits & 64) != 0;
2859 vector_w = (bits & 128) != 0;
2862 sizes[INPUT][0] = cvSize(min_size, min_size);
2864 m = sizes[INPUT][0].height;
2865 n = sizes[INPUT][0].width;
2868 sizes[TEMP][0] = cvSize(min_size, min_size);
2870 sizes[TEMP][0] = sizes[INPUT][0];
2871 sizes[TEMP][3] = cvSize(0,0);
2875 sizes[TEMP][3] = sizes[TEMP][0];
2877 sizes[TEMP][0] = cvSize(1, min_size);
2879 sizes[TEMP][0] = cvSize(min_size, 1);
2884 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
2886 if( flags & CV_SVD_U_T )
2887 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
2890 sizes[TEMP][1] = cvSize(0,0);
2894 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
2896 if( !(flags & CV_SVD_V_T) )
2897 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
2900 sizes[TEMP][2] = cvSize(0,0);
2902 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0];
2903 types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0];
2904 types[OUTPUT][3] = CV_8UC1;
2905 sizes[OUTPUT][0] = !have_u || !have_v ? cvSize(0,0) : sizes[INPUT][0];
2906 sizes[OUTPUT][1] = !have_u ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(m,m);
2907 sizes[OUTPUT][2] = !have_v ? cvSize(0,0) : compact ? cvSize(min_size,min_size) : cvSize(n,n);
2908 sizes[OUTPUT][3] = cvSize(min_size,1);
2910 for( i = 0; i < 4; i++ )
2912 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
2913 types[REF_OUTPUT][i] = types[OUTPUT][i];
2918 void CxCore_SVDTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2919 CvSize** sizes, int** types,
2920 CvSize** whole_sizes, bool* are_images )
2922 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
2923 sizes, types, whole_sizes, are_images );
2924 const char* output_str = cvReadString( find_timing_param("output"), "all" );
2925 bool need_all = strcmp( output_str, "all" ) == 0;
2926 int i, count = test_array[OUTPUT].size();
2930 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
2933 have_u = have_v = true;
2937 have_u = have_v = false;
2938 sizes[TEMP][1] = sizes[TEMP][2] = cvSize(0,0);
2941 flags = CV_SVD_U_T + CV_SVD_V_T;
2942 for( i = 0; i < count; i++ )
2943 sizes[OUTPUT][i] = sizes[REF_OUTPUT][i] = cvSize(0,0);
2944 sizes[OUTPUT][0] = cvSize(1,1);
2948 int CxCore_SVDTest::write_default_params( CvFileStorage* fs )
2950 int code = CxCore_MatrixTest::write_default_params(fs);
2951 if( code < 0 || ts->get_testing_mode() != CvTS::TIMING_MODE )
2953 write_string_list( fs, "output", matrix_svd_output_modes );
2958 void CxCore_SVDTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2960 sprintf( ptr, "%s,", have_u ? "all" : "w" );
2963 CxCore_MatrixTest::print_timing_params( test_case_idx, ptr, params_left );
2967 int CxCore_SVDTest::prepare_test_case( int test_case_idx )
2969 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
2972 CvMat* input = &test_mat[INPUT][0];
2973 cvTsFloodWithZeros( input, ts->get_rng() );
2975 if( symmetric && (have_u || have_v) )
2977 CvMat* temp = &test_mat[TEMP][have_u ? 1 : 2];
2978 cvTsGEMM( input, input, 1.,
2979 0, 0., temp, CV_GEMM_B_T );
2980 cvTsCopy( temp, input );
2983 if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
2984 cvTsCopy( input, &test_mat[OUTPUT][0] );
2991 void CxCore_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
2993 *low = cvScalarAll(-2.);
2994 *high = cvScalarAll(2.);
2997 double CxCore_SVDTest::get_success_error_level( int test_case_idx, int i, int j )
2999 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
3000 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ?
3002 double output_precision = CvArrTest::get_success_error_level( test_case_idx, i, j );
3003 return MAX(input_precision, output_precision);
3006 void CxCore_SVDTest::run_func()
3008 CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
3010 src = test_array[INPUT][0];
3011 cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
3015 void CxCore_SVDTest::prepare_to_validation( int )
3017 CvMat* input = &test_mat[INPUT][0];
3018 int m = input->rows, n = input->cols, min_size = MIN(m, n);
3019 CvMat *src, *dst, *w;
3020 double prev = 0, threshold = CV_MAT_TYPE(input->type) == CV_32FC1 ? FLT_EPSILON : DBL_EPSILON;
3025 src = &test_mat[TEMP][1];
3026 dst = &test_mat[OUTPUT][1];
3027 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
3028 cvTsSetIdentity( &test_mat[REF_OUTPUT][1], cvScalarAll(1.) );
3033 src = &test_mat[TEMP][2];
3034 dst = &test_mat[OUTPUT][2];
3035 cvTsGEMM( src, src, 1., 0, 0., dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
3036 cvTsSetIdentity( &test_mat[REF_OUTPUT][2], cvScalarAll(1.) );
3039 w = &test_mat[TEMP][0];
3040 step = w->rows == 1 ? 1 : w->step/CV_ELEM_SIZE(w->type);
3041 for( i = 0; i < min_size; i++ )
3043 double norm = 0, aii;
3045 if( w->rows > 1 && w->cols > 1 )
3048 cvGetRow( w, &row, i );
3049 norm = cvNorm( &row, 0, CV_L1 );
3051 row_ptr = row.data.ptr;
3055 row_ptr = w->data.ptr;
3059 aii = CV_MAT_TYPE(w->type) == CV_32FC1 ?
3060 (double)((float*)row_ptr)[j] : ((double*)row_ptr)[j];
3061 if( w->rows == 1 || w->cols == 1 )
3063 norm = fabs(norm - aii);
3064 test_mat[OUTPUT][3].data.ptr[i] = aii >= 0 && norm < threshold && (i == 0 || aii <= prev);
3068 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.),
3069 cvScalarAll(1.), &test_mat[REF_OUTPUT][3], 0 );
3071 if( have_u && have_v )
3075 cvTsZero( &test_mat[TEMP][3] );
3076 for( i = 0; i < min_size; i++ )
3078 double val = cvGetReal1D( w, i );
3079 cvSetReal2D( &test_mat[TEMP][3], i, i, val );
3081 w = &test_mat[TEMP][3];
3086 cvTsGEMM( &test_mat[TEMP][1], w, 1., 0, 0., &test_mat[REF_OUTPUT][0],
3087 flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
3088 cvTsGEMM( &test_mat[REF_OUTPUT][0], &test_mat[TEMP][2], 1., 0, 0.,
3089 &test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
3093 cvTsGEMM( w, &test_mat[TEMP][2], 1., 0, 0., &test_mat[REF_OUTPUT][0],
3094 flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
3095 cvTsGEMM( &test_mat[TEMP][1], &test_mat[REF_OUTPUT][0], 1., 0, 0.,
3096 &test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
3099 cvTsCopy( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], 0 );
3104 CxCore_SVDTest svd_test;
3107 ///////////////// SVBkSb /////////////////////
3109 class CxCore_SVBkSbTest : public CxCore_MatrixTest
3112 CxCore_SVBkSbTest();
3114 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
3115 void get_timing_test_array_types_and_sizes( int test_case_idx,
3116 CvSize** sizes, int** types,
3117 CvSize** whole_sizes, bool* are_images );
3118 double get_success_error_level( int test_case_idx, int i, int j );
3119 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high );
3120 int prepare_test_case( int test_case_idx );
3122 void prepare_to_validation( int test_case_idx );
3124 bool have_b, symmetric, compact, vector_w;
3128 CxCore_SVBkSbTest::CxCore_SVBkSbTest() :
3129 CxCore_MatrixTest( "matrix-svbksb", "cvSVBkSb", 2, 1, false, false, 1 ),
3130 flags(0), have_b(false), symmetric(false), compact(false), vector_w(false)
3132 test_case_count = 100;
3133 test_array[TEMP].push(NULL);
3134 test_array[TEMP].push(NULL);
3135 test_array[TEMP].push(NULL);
3139 void CxCore_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
3141 CvRNG* rng = ts->get_rng();
3142 int bits = cvTsRandInt(rng);
3143 CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
3144 int min_size, i, m, n;
3147 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
3149 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
3150 have_b = (bits & 16) != 0;
3151 symmetric = (bits & 32) != 0;
3152 compact = (bits & 64) != 0;
3153 vector_w = (bits & 128) != 0;
3156 sizes[INPUT][0] = cvSize(min_size, min_size);
3158 m = sizes[INPUT][0].height;
3159 n = sizes[INPUT][0].width;
3161 sizes[INPUT][1] = cvSize(0,0);
3162 b_size = cvSize(m,m);
3165 sizes[INPUT][1].height = sizes[INPUT][0].height;
3166 sizes[INPUT][1].width = cvTsRandInt(rng) % 100 + 1;
3167 b_size = sizes[INPUT][1];
3171 sizes[TEMP][0] = cvSize(min_size, min_size);
3173 sizes[TEMP][0] = sizes[INPUT][0];
3178 sizes[TEMP][0] = cvSize(1, min_size);
3180 sizes[TEMP][0] = cvSize(min_size, 1);
3183 sizes[TEMP][1] = compact ? cvSize(min_size, m) : cvSize(m, m);
3185 if( flags & CV_SVD_U_T )
3186 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
3188 sizes[TEMP][2] = compact ? cvSize(n, min_size) : cvSize(n, n);
3190 if( !(flags & CV_SVD_V_T) )
3191 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
3193 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
3194 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0];
3195 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize( b_size.width, n );
3199 void CxCore_SVBkSbTest::get_timing_test_array_types_and_sizes( int test_case_idx,
3200 CvSize** sizes, int** types,
3201 CvSize** whole_sizes, bool* are_images )
3203 CxCore_MatrixTest::get_timing_test_array_types_and_sizes( test_case_idx,
3204 sizes, types, whole_sizes, are_images );
3208 sizes[TEMP][0] = cvSize(1,sizes[INPUT][0].height);
3209 sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1,sizes[INPUT][0].height);
3210 flags = CV_SVD_U_T + CV_SVD_V_T;
3214 int CxCore_SVBkSbTest::prepare_test_case( int test_case_idx )
3216 int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
3219 CvMat* input = &test_mat[INPUT][0];
3220 cvTsFloodWithZeros( input, ts->get_rng() );
3224 CvMat* temp = &test_mat[TEMP][1];
3225 cvTsGEMM( input, input, 1., 0, 0., temp, CV_GEMM_B_T );
3226 cvTsCopy( temp, input );
3229 cvSVD( input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
3236 void CxCore_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
3238 *low = cvScalarAll(-2.);
3239 *high = cvScalarAll(2.);
3243 double CxCore_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
3245 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
3249 void CxCore_SVBkSbTest::run_func()
3251 cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
3252 test_array[INPUT][1], test_array[OUTPUT][0], flags );
3256 void CxCore_SVBkSbTest::prepare_to_validation( int )
3258 CvMat* input = &test_mat[INPUT][0];
3259 int i, m = input->rows, n = input->cols, min_size = MIN(m, n), nb;
3260 bool is_float = CV_MAT_DEPTH(input->type) == CV_32F;
3261 CvSize w_size = compact ? cvSize(min_size,min_size) : cvSize(m,n);
3262 CvMat* w = &test_mat[TEMP][0];
3263 CvMat* wdb = cvCreateMat( w_size.height, w_size.width, CV_64FC1 );
3264 // use exactly the same threshold as in icvSVD... ,
3265 // so the changes in the library and here should be synchronized.
3266 double threshold = cvSum( w ).val[0]*2*(is_float ? FLT_EPSILON : DBL_EPSILON);
3267 CvMat *u, *v, *b, *t0, *t1;
3270 for( i = 0; i < min_size; i++ )
3272 double wii = vector_w ? cvGetReal1D(w,i) : cvGetReal2D(w,i,i);
3273 cvSetReal2D( wdb, i, i, wii > threshold ? 1./wii : 0. );
3276 u = &test_mat[TEMP][1];
3277 v = &test_mat[TEMP][2];
3281 if( test_array[INPUT][1] )
3283 b = &test_mat[INPUT][1];
3289 u = cvCreateMat( u->rows, u->cols, CV_64F );
3290 cvTsConvert( &test_mat[TEMP][1], u );
3293 b = cvCreateMat( b->rows, b->cols, CV_64F );
3294 cvTsConvert( &test_mat[INPUT][1], b );
3298 t0 = cvCreateMat( wdb->cols, nb, CV_64F );
3301 cvTsGEMM( u, b, 1., 0, 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 );
3302 else if( flags & CV_SVD_U_T )
3305 cvTsTranspose( u, t0 );
3314 v = cvCreateMat( v->rows, v->cols, CV_64F );
3321 cvTsConvert( &test_mat[TEMP][2], v );
3324 t1 = cvCreateMat( wdb->rows, nb, CV_64F );
3325 cvTsGEMM( wdb, t0, 1, 0, 0, t1, 0 );
3327 if( !is_float || !symmetric )
3329 cvReleaseMat( &t0 );
3330 t0 = !is_float ? &test_mat[REF_OUTPUT][0] : cvCreateMat( test_mat[REF_OUTPUT][0].rows, nb, CV_64F );
3333 cvTsGEMM( v, t1, 1, 0, 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 );
3334 cvReleaseMat( &t1 );
3336 if( t0 != &test_mat[REF_OUTPUT][0] )
3338 cvTsConvert( t0, &test_mat[REF_OUTPUT][0] );
3339 cvReleaseMat( &t0 );
3342 if( v != &test_mat[TEMP][2] )
3345 cvReleaseMat( &wdb );
3349 CxCore_SVBkSbTest svbksb_test;
3352 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),