1 //////////////////////////////////////////////////////////////////////////////////////////
2 /////////////////// tests for matrix operations and math functions ///////////////////////
3 //////////////////////////////////////////////////////////////////////////////////////////
5 #include "test_precomp.hpp"
12 /// !!! NOTE !!! These tests happily avoid overflow cases & out-of-range arguments
13 /// so that output arrays contain neigher Inf's nor Nan's.
14 /// Handling such cases would require special modification of check function
15 /// (validate_test_results) => TBD.
16 /// Also, need some logarithmic-scale generation of input data. Right now it is done (in some tests)
17 /// by generating min/max boundaries for random data in logarimithic scale, but
18 /// within the same test case all the input array elements are of the same order.
20 class Core_MathTest : public cvtest::ArrayTest
23 typedef cvtest::ArrayTest Base;
26 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes,
27 vector<vector<int> >& types);
28 double get_success_error_level( int /*test_case_idx*/, int i, int j );
33 Core_MathTest::Core_MathTest()
35 optional_mask = false;
37 test_array[INPUT].push_back(NULL);
38 test_array[OUTPUT].push_back(NULL);
39 test_array[REF_OUTPUT].push_back(NULL);
45 double Core_MathTest::get_success_error_level( int /*test_case_idx*/, int i, int j )
47 return test_mat[i][j].depth() == CV_32F ? FLT_EPSILON*128 : DBL_EPSILON*1024;
51 void Core_MathTest::get_test_array_types_and_sizes( int test_case_idx,
52 vector<vector<Size> >& sizes,
53 vector<vector<int> >& types)
55 RNG& rng = ts->get_rng();
56 int depth = cvtest::randInt(rng)%2 + CV_32F;
57 int cn = cvtest::randInt(rng) % 4 + 1, type = CV_MAKETYPE(depth, cn);
59 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
61 for( i = 0; i < test_array.size(); i++ )
63 size_t count = test_array[i].size();
64 for( j = 0; j < count; j++ )
67 test_nd = cvtest::randInt(rng)%3 == 0;
71 ////////// pow /////////////
73 class Core_PowTest : public Core_MathTest
76 typedef Core_MathTest Base;
79 void get_test_array_types_and_sizes( int test_case_idx,
80 vector<vector<Size> >& sizes,
81 vector<vector<int> >& types );
82 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
84 void prepare_to_validation( int test_case_idx );
85 double get_success_error_level( int test_case_idx, int i, int j );
90 Core_PowTest::Core_PowTest()
96 void Core_PowTest::get_test_array_types_and_sizes( int test_case_idx,
97 vector<vector<Size> >& sizes,
98 vector<vector<int> >& types )
100 RNG& rng = ts->get_rng();
101 int depth = cvtest::randInt(rng) % (CV_64F+1);
102 int cn = cvtest::randInt(rng) % 4 + 1;
104 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
105 depth += depth == CV_8S;
107 if( depth < CV_32F || cvtest::randInt(rng)%8 == 0 )
109 power = (int)(cvtest::randInt(rng)%21 - 10);
112 i = cvtest::randInt(rng)%17;
113 power = i == 16 ? 1./3 : i == 15 ? 0.5 : i == 14 ? -0.5 : cvtest::randReal(rng)*10 - 5;
116 for( i = 0; i < test_array.size(); i++ )
118 size_t count = test_array[i].size();
119 int type = CV_MAKETYPE(depth, cn);
120 for( j = 0; j < count; j++ )
123 test_nd = cvtest::randInt(rng)%3 == 0;
127 double Core_PowTest::get_success_error_level( int test_case_idx, int i, int j )
129 int depth = test_mat[i][j].depth();
131 return power == cvRound(power) && power >= 0 ? 0 : 1;
133 return Base::get_success_error_level( test_case_idx, i, j );
137 void Core_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, Scalar& low, Scalar& high )
139 double l, u = cvtest::randInt(ts->get_rng())%1000 + 1;
142 double mval = cvtest::getMaxVal(type);
143 double u1 = pow(mval,1./power)*2;
147 l = power == cvRound(power) ? -u : FLT_EPSILON;
148 low = Scalar::all(l);
149 high = Scalar::all(u);
153 void Core_PowTest::run_func()
157 if( fabs(power-1./3) <= DBL_EPSILON && test_mat[INPUT][0].depth() == CV_32F )
159 Mat a = test_mat[INPUT][0], b = test_mat[OUTPUT][0];
163 for( int i = 0; i < a.rows; i++ )
165 b.at<float>(i,0) = (float)fabs(cvCbrt(a.at<float>(i,0)));
166 for( int j = 1; j < a.cols; j++ )
167 b.at<float>(i,j) = (float)fabs(cv::cubeRoot(a.at<float>(i,j)));
171 cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
175 Mat& a = test_mat[INPUT][0];
176 Mat& b = test_mat[OUTPUT][0];
180 cv::pow(a, power, b);
185 inline static int ipow( int a, int power )
199 inline static double ipow( double a, int power )
213 void Core_PowTest::prepare_to_validation( int /*test_case_idx*/ )
215 const Mat& a = test_mat[INPUT][0];
216 Mat& b = test_mat[REF_OUTPUT][0];
218 int depth = a.depth();
219 int ncols = a.cols*a.channels();
220 int ipower = cvRound(power), apower = abs(ipower);
223 for( i = 0; i < a.rows; i++ )
225 const uchar* a_data = a.ptr(i);
226 uchar* b_data = b.ptr(i);
232 for( j = 0; j < ncols; j++ )
234 int val = ((uchar*)a_data)[j];
235 ((uchar*)b_data)[j] = (uchar)(val <= 1 ? val :
236 val == 2 && ipower == -1 ? 1 : 0);
239 for( j = 0; j < ncols; j++ )
241 int val = ((uchar*)a_data)[j];
242 val = ipow( val, ipower );
243 ((uchar*)b_data)[j] = saturate_cast<uchar>(val);
248 for( j = 0; j < ncols; j++ )
250 int val = ((char*)a_data)[j];
251 ((char*)b_data)[j] = (char)((val&~1)==0 ? val :
252 val ==-1 ? 1-2*(ipower&1) :
253 val == 2 && ipower == -1 ? 1 : 0);
256 for( j = 0; j < ncols; j++ )
258 int val = ((char*)a_data)[j];
259 val = ipow( val, ipower );
260 ((char*)b_data)[j] = saturate_cast<schar>(val);
265 for( j = 0; j < ncols; j++ )
267 int val = ((ushort*)a_data)[j];
268 ((ushort*)b_data)[j] = (ushort)((val&~1)==0 ? val :
269 val ==-1 ? 1-2*(ipower&1) :
270 val == 2 && ipower == -1 ? 1 : 0);
273 for( j = 0; j < ncols; j++ )
275 int val = ((ushort*)a_data)[j];
276 val = ipow( val, ipower );
277 ((ushort*)b_data)[j] = saturate_cast<ushort>(val);
282 for( j = 0; j < ncols; j++ )
284 int val = ((short*)a_data)[j];
285 ((short*)b_data)[j] = (short)((val&~1)==0 ? val :
286 val ==-1 ? 1-2*(ipower&1) :
287 val == 2 && ipower == -1 ? 1 : 0);
290 for( j = 0; j < ncols; j++ )
292 int val = ((short*)a_data)[j];
293 val = ipow( val, ipower );
294 ((short*)b_data)[j] = saturate_cast<short>(val);
299 for( j = 0; j < ncols; j++ )
301 int val = ((int*)a_data)[j];
302 ((int*)b_data)[j] = (val&~1)==0 ? val :
303 val ==-1 ? 1-2*(ipower&1) :
304 val == 2 && ipower == -1 ? 1 : 0;
307 for( j = 0; j < ncols; j++ )
309 int val = ((int*)a_data)[j];
310 val = ipow( val, ipower );
311 ((int*)b_data)[j] = val;
315 if( power != ipower )
316 for( j = 0; j < ncols; j++ )
318 double val = ((float*)a_data)[j];
319 val = pow( fabs(val), power );
320 ((float*)b_data)[j] = (float)val;
323 for( j = 0; j < ncols; j++ )
325 double val = ((float*)a_data)[j];
328 val = ipow( val, apower );
329 ((float*)b_data)[j] = (float)val;
333 if( power != ipower )
334 for( j = 0; j < ncols; j++ )
336 double val = ((double*)a_data)[j];
337 val = pow( fabs(val), power );
338 ((double*)b_data)[j] = (double)val;
341 for( j = 0; j < ncols; j++ )
343 double val = ((double*)a_data)[j];
346 val = ipow( val, apower );
347 ((double*)b_data)[j] = (double)val;
356 ///////////////////////////////////////// matrix tests ////////////////////////////////////////////
358 class Core_MatrixTest : public cvtest::ArrayTest
361 typedef cvtest::ArrayTest Base;
362 Core_MatrixTest( int in_count, int out_count,
363 bool allow_int, bool scalar_output, int max_cn );
365 void get_test_array_types_and_sizes( int test_case_idx,
366 vector<vector<Size> >& sizes,
367 vector<vector<int> >& types );
368 double get_success_error_level( int test_case_idx, int i, int j );
375 Core_MatrixTest::Core_MatrixTest( int in_count, int out_count,
376 bool _allow_int, bool _scalar_output, int _max_cn )
377 : allow_int(_allow_int), scalar_output(_scalar_output), max_cn(_max_cn)
380 for( i = 0; i < in_count; i++ )
381 test_array[INPUT].push_back(NULL);
383 for( i = 0; i < out_count; i++ )
385 test_array[OUTPUT].push_back(NULL);
386 test_array[REF_OUTPUT].push_back(NULL);
389 element_wise_relative_error = false;
393 void Core_MatrixTest::get_test_array_types_and_sizes( int test_case_idx,
394 vector<vector<Size> >& sizes,
395 vector<vector<int> >& types )
397 RNG& rng = ts->get_rng();
398 int depth = cvtest::randInt(rng) % (allow_int ? CV_64F+1 : 2);
399 int cn = cvtest::randInt(rng) % max_cn + 1;
403 depth += depth == CV_8S;
407 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
409 for( i = 0; i < test_array.size(); i++ )
411 size_t count = test_array[i].size();
412 int flag = (i == OUTPUT || i == REF_OUTPUT) && scalar_output;
413 int type = !flag ? CV_MAKETYPE(depth, cn) : CV_64FC1;
415 for( j = 0; j < count; j++ )
419 sizes[i][j] = Size( 4, 1 );
425 double Core_MatrixTest::get_success_error_level( int test_case_idx, int i, int j )
427 int input_depth = test_mat[INPUT][0].depth();
428 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ? 5e-5 : 5e-10;
429 double output_precision = Base::get_success_error_level( test_case_idx, i, j );
430 return MAX(input_precision, output_precision);
434 ///////////////// Trace /////////////////////
436 class Core_TraceTest : public Core_MatrixTest
442 void prepare_to_validation( int test_case_idx );
446 Core_TraceTest::Core_TraceTest() : Core_MatrixTest( 1, 1, true, true, 4 )
451 void Core_TraceTest::run_func()
453 test_mat[OUTPUT][0].at<Scalar>(0,0) = cvTrace(test_array[INPUT][0]);
457 void Core_TraceTest::prepare_to_validation( int )
459 Mat& mat = test_mat[INPUT][0];
460 int count = MIN( mat.rows, mat.cols );
461 Mat diag(count, 1, mat.type(), mat.ptr(), mat.step + mat.elemSize());
462 Scalar r = cvtest::mean(diag);
465 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = r;
469 ///////// dotproduct //////////
471 class Core_DotProductTest : public Core_MatrixTest
474 Core_DotProductTest();
477 void prepare_to_validation( int test_case_idx );
481 Core_DotProductTest::Core_DotProductTest() : Core_MatrixTest( 2, 1, true, true, 4 )
486 void Core_DotProductTest::run_func()
488 test_mat[OUTPUT][0].at<Scalar>(0,0) = Scalar(cvDotProduct( test_array[INPUT][0], test_array[INPUT][1] ));
492 void Core_DotProductTest::prepare_to_validation( int )
494 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = Scalar(cvtest::crossCorr( test_mat[INPUT][0], test_mat[INPUT][1] ));
498 ///////// crossproduct //////////
500 class Core_CrossProductTest : public Core_MatrixTest
503 Core_CrossProductTest();
505 void get_test_array_types_and_sizes( int test_case_idx,
506 vector<vector<Size> >& sizes,
507 vector<vector<int> >& types );
509 void prepare_to_validation( int test_case_idx );
513 Core_CrossProductTest::Core_CrossProductTest() : Core_MatrixTest( 2, 1, false, false, 1 )
518 void Core_CrossProductTest::get_test_array_types_and_sizes( int,
519 vector<vector<Size> >& sizes,
520 vector<vector<int> >& types )
522 RNG& rng = ts->get_rng();
523 int depth = cvtest::randInt(rng) % 2 + CV_32F;
524 int cn = cvtest::randInt(rng) & 1 ? 3 : 1, type = CV_MAKETYPE(depth, cn);
527 types[INPUT][0] = types[INPUT][1] = types[OUTPUT][0] = types[REF_OUTPUT][0] = type;
531 else if( cvtest::randInt(rng) & 1 )
536 sizes[INPUT][0] = sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
540 void Core_CrossProductTest::run_func()
542 cvCrossProduct( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
546 void Core_CrossProductTest::prepare_to_validation( int )
548 CvScalar a(0), b(0), c(0);
550 if( test_mat[INPUT][0].rows > 1 )
552 a.val[0] = cvGetReal2D( test_array[INPUT][0], 0, 0 );
553 a.val[1] = cvGetReal2D( test_array[INPUT][0], 1, 0 );
554 a.val[2] = cvGetReal2D( test_array[INPUT][0], 2, 0 );
556 b.val[0] = cvGetReal2D( test_array[INPUT][1], 0, 0 );
557 b.val[1] = cvGetReal2D( test_array[INPUT][1], 1, 0 );
558 b.val[2] = cvGetReal2D( test_array[INPUT][1], 2, 0 );
560 else if( test_mat[INPUT][0].cols > 1 )
562 a.val[0] = cvGetReal1D( test_array[INPUT][0], 0 );
563 a.val[1] = cvGetReal1D( test_array[INPUT][0], 1 );
564 a.val[2] = cvGetReal1D( test_array[INPUT][0], 2 );
566 b.val[0] = cvGetReal1D( test_array[INPUT][1], 0 );
567 b.val[1] = cvGetReal1D( test_array[INPUT][1], 1 );
568 b.val[2] = cvGetReal1D( test_array[INPUT][1], 2 );
572 a = cvGet1D( test_array[INPUT][0], 0 );
573 b = cvGet1D( test_array[INPUT][1], 0 );
576 c.val[2] = a.val[0]*b.val[1] - a.val[1]*b.val[0];
577 c.val[1] = -a.val[0]*b.val[2] + a.val[2]*b.val[0];
578 c.val[0] = a.val[1]*b.val[2] - a.val[2]*b.val[1];
580 if( test_mat[REF_OUTPUT][0].rows > 1 )
582 cvSetReal2D( test_array[REF_OUTPUT][0], 0, 0, c.val[0] );
583 cvSetReal2D( test_array[REF_OUTPUT][0], 1, 0, c.val[1] );
584 cvSetReal2D( test_array[REF_OUTPUT][0], 2, 0, c.val[2] );
586 else if( test_mat[REF_OUTPUT][0].cols > 1 )
588 cvSetReal1D( test_array[REF_OUTPUT][0], 0, c.val[0] );
589 cvSetReal1D( test_array[REF_OUTPUT][0], 1, c.val[1] );
590 cvSetReal1D( test_array[REF_OUTPUT][0], 2, c.val[2] );
594 cvSet1D( test_array[REF_OUTPUT][0], 0, c );
599 ///////////////// gemm /////////////////////
601 class Core_GEMMTest : public Core_MatrixTest
604 typedef Core_MatrixTest Base;
607 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
608 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
609 int prepare_test_case( int test_case_idx );
611 void prepare_to_validation( int test_case_idx );
616 Core_GEMMTest::Core_GEMMTest() : Core_MatrixTest( 5, 1, false, false, 2 )
618 test_case_count = 100;
619 max_log_array_size = 10;
625 void Core_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
627 RNG& rng = ts->get_rng();
629 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
630 sizeA = sizes[INPUT][0];
631 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
632 sizes[INPUT][0] = sizeA;
633 sizes[INPUT][2] = sizes[INPUT][3] = Size(1,1);
634 types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK;
636 tabc_flag = cvtest::randInt(rng) & 7;
638 switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
641 sizes[INPUT][1].height = sizes[INPUT][0].width;
642 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
643 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
646 sizes[INPUT][1].width = sizes[INPUT][0].width;
647 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
648 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
651 sizes[INPUT][1].height = sizes[INPUT][0].height;
652 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
653 sizes[OUTPUT][0].width = sizes[INPUT][1].width;
655 case CV_GEMM_A_T | CV_GEMM_B_T:
656 sizes[INPUT][1].width = sizes[INPUT][0].height;
657 sizes[OUTPUT][0].height = sizes[INPUT][0].width;
658 sizes[OUTPUT][0].width = sizes[INPUT][1].height;
662 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
664 if( cvtest::randInt(rng) & 1 )
665 sizes[INPUT][4] = Size(0,0);
666 else if( !(tabc_flag & CV_GEMM_C_T) )
667 sizes[INPUT][4] = sizes[OUTPUT][0];
670 sizes[INPUT][4].width = sizes[OUTPUT][0].height;
671 sizes[INPUT][4].height = sizes[OUTPUT][0].width;
676 int Core_GEMMTest::prepare_test_case( int test_case_idx )
678 int code = Base::prepare_test_case( test_case_idx );
681 alpha = cvGetReal2D( test_array[INPUT][2], 0, 0 );
682 beta = cvGetReal2D( test_array[INPUT][3], 0, 0 );
688 void Core_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
690 low = Scalar::all(-10.);
691 high = Scalar::all(10.);
695 void Core_GEMMTest::run_func()
697 cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
698 test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
702 void Core_GEMMTest::prepare_to_validation( int )
704 cvtest::gemm( test_mat[INPUT][0], test_mat[INPUT][1], alpha,
705 test_array[INPUT][4] ? test_mat[INPUT][4] : Mat(),
706 beta, test_mat[REF_OUTPUT][0], tabc_flag );
710 ///////////////// multransposed /////////////////////
712 class Core_MulTransposedTest : public Core_MatrixTest
715 Core_MulTransposedTest();
717 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
718 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
720 void prepare_to_validation( int test_case_idx );
725 Core_MulTransposedTest::Core_MulTransposedTest() : Core_MatrixTest( 2, 1, false, false, 1 )
727 test_case_count = 100;
729 test_array[TEMP].push_back(NULL);
733 void Core_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
735 RNG& rng = ts->get_rng();
736 int bits = cvtest::randInt(rng);
737 int src_type = cvtest::randInt(rng) % 5;
738 int dst_type = cvtest::randInt(rng) % 2;
740 src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S :
741 src_type == 3 ? CV_32F : CV_64F;
742 dst_type = dst_type == 0 ? CV_32F : CV_64F;
743 dst_type = MAX( dst_type, src_type );
745 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
748 sizes[INPUT][1] = Size(0,0);
751 sizes[INPUT][1] = sizes[INPUT][0];
753 sizes[INPUT][1].height = 1;
755 sizes[INPUT][1].width = 1;
758 sizes[TEMP][0] = sizes[INPUT][0];
759 types[INPUT][0] = src_type;
760 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type;
762 order = (bits & 8) != 0;
763 sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ?
764 sizes[INPUT][0].height : sizes[INPUT][0].width;
765 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
769 void Core_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
771 low = cvScalarAll(-10.);
772 high = cvScalarAll(10.);
776 void Core_MulTransposedTest::run_func()
778 cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
779 order, test_array[INPUT][1] );
783 void Core_MulTransposedTest::prepare_to_validation( int )
785 const Mat& src = test_mat[INPUT][0];
786 Mat delta = test_mat[INPUT][1];
787 Mat& temp = test_mat[TEMP][0];
790 if( delta.rows < src.rows || delta.cols < src.cols )
792 cv::repeat( delta, src.rows/delta.rows, src.cols/delta.cols, temp);
795 cvtest::add( src, 1, delta, -1, Scalar::all(0), temp, temp.type());
798 src.convertTo(temp, temp.type());
800 cvtest::gemm( temp, temp, 1., Mat(), 0, test_mat[REF_OUTPUT][0], order == 0 ? GEMM_2_T : GEMM_1_T );
804 ///////////////// Transform /////////////////////
806 class Core_TransformTest : public Core_MatrixTest
809 typedef Core_MatrixTest Base;
810 Core_TransformTest();
812 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
813 double get_success_error_level( int test_case_idx, int i, int j );
814 int prepare_test_case( int test_case_idx );
816 void prepare_to_validation( int test_case_idx );
823 Core_TransformTest::Core_TransformTest() : Core_MatrixTest( 3, 1, true, false, 4 )
830 void Core_TransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
832 RNG& rng = ts->get_rng();
833 int bits = cvtest::randInt(rng);
834 int depth, dst_cn, mat_cols, mattype;
835 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
837 mat_cols = CV_MAT_CN(types[INPUT][0]);
838 depth = CV_MAT_DEPTH(types[INPUT][0]);
839 dst_cn = cvtest::randInt(rng) % 4 + 1;
840 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
842 mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
843 types[INPUT][1] = mattype;
844 types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
846 scale = 1./((cvtest::randInt(rng)%4)*50+1);
850 sizes[INPUT][2] = Size(0,0);
851 mat_cols += (bits & 4) != 0;
854 sizes[INPUT][2] = Size(1,1);
858 sizes[INPUT][2] = Size(dst_cn,1);
860 sizes[INPUT][2] = Size(1,dst_cn);
861 types[INPUT][2] &= ~CV_MAT_CN_MASK;
863 diagMtx = (bits & 16) != 0;
865 sizes[INPUT][1] = Size(mat_cols,dst_cn);
869 int Core_TransformTest::prepare_test_case( int test_case_idx )
871 int code = Base::prepare_test_case( test_case_idx );
874 Mat& m = test_mat[INPUT][1];
875 cvtest::add(m, scale, m, 0, Scalar::all(0), m, m.type() );
878 Mat mask = Mat::eye(m.rows, m.cols, CV_8U)*255;
880 m.setTo(Scalar::all(0), mask);
887 double Core_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
889 int depth = test_mat[INPUT][0].depth();
890 return depth <= CV_8S ? 1 : depth <= CV_32S ? 9 : Base::get_success_error_level( test_case_idx, i, j );
893 void Core_TransformTest::run_func()
895 CvMat _m = test_mat[INPUT][1], _shift = test_mat[INPUT][2];
896 cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &_m, _shift.data.ptr ? &_shift : 0);
900 void Core_TransformTest::prepare_to_validation( int )
902 Mat transmat = test_mat[INPUT][1];
903 Mat shift = test_mat[INPUT][2];
905 cvtest::transform( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], transmat, shift );
909 ///////////////// PerspectiveTransform /////////////////////
911 class Core_PerspectiveTransformTest : public Core_MatrixTest
914 Core_PerspectiveTransformTest();
916 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
917 double get_success_error_level( int test_case_idx, int i, int j );
919 void prepare_to_validation( int test_case_idx );
923 Core_PerspectiveTransformTest::Core_PerspectiveTransformTest() : Core_MatrixTest( 2, 1, false, false, 2 )
928 void Core_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
930 RNG& rng = ts->get_rng();
931 int bits = cvtest::randInt(rng);
932 int depth, cn, mattype;
933 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
935 cn = CV_MAT_CN(types[INPUT][0]) + 1;
936 depth = CV_MAT_DEPTH(types[INPUT][0]);
937 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
939 mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
940 types[INPUT][1] = mattype;
941 sizes[INPUT][1] = Size(cn + 1, cn + 1);
945 double Core_PerspectiveTransformTest::get_success_error_level( int test_case_idx, int i, int j )
947 int depth = test_mat[INPUT][0].depth();
948 return depth == CV_32F ? 1e-4 : depth == CV_64F ? 1e-8 :
949 Core_MatrixTest::get_success_error_level(test_case_idx, i, j);
953 void Core_PerspectiveTransformTest::run_func()
955 CvMat _m = test_mat[INPUT][1];
956 cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &_m );
960 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
963 int cn, depth, mat_depth;
964 CvMat astub, bstub, *a, *b;
967 a = cvGetMat( _src, &astub, 0, 0 );
968 b = cvGetMat( _dst, &bstub, 0, 0 );
970 cn = CV_MAT_CN(a->type);
971 depth = CV_MAT_DEPTH(a->type);
972 mat_depth = CV_MAT_DEPTH(transmat->type);
973 cols = transmat->cols;
975 // prepare cn x (cn + 1) transform matrix
976 if( mat_depth == CV_32F )
978 for( i = 0; i < transmat->rows; i++ )
979 for( j = 0; j < cols; j++ )
980 mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
984 assert( mat_depth == CV_64F );
985 for( i = 0; i < transmat->rows; i++ )
986 for( j = 0; j < cols; j++ )
987 mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
992 vector<double> buf(cols);
994 for( i = 0; i < a->rows; i++ )
996 uchar* src = a->data.ptr + i*a->step;
997 uchar* dst = b->data.ptr + i*b->step;
1002 for( j = 0; j < cols; j++ )
1003 buf[j] = ((float*)src)[j];
1006 for( j = 0; j < cols; j++ )
1007 buf[j] = ((double*)src)[j];
1016 for( j = 0; j < cols; j += 2 )
1018 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2];
1019 double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5];
1020 double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8];
1027 for( j = 0; j < cols; j += 3 )
1029 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3];
1030 double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7];
1031 double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11];
1032 double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15];
1046 for( j = 0; j < cols; j++ )
1047 ((float*)dst)[j] = (float)buf[j];
1050 for( j = 0; j < cols; j++ )
1051 ((double*)dst)[j] = buf[j];
1060 void Core_PerspectiveTransformTest::prepare_to_validation( int )
1062 CvMat transmat = test_mat[INPUT][1];
1063 cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], &transmat );
1066 ///////////////// Mahalanobis /////////////////////
1068 class Core_MahalanobisTest : public Core_MatrixTest
1071 typedef Core_MatrixTest Base;
1072 Core_MahalanobisTest();
1074 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1075 int prepare_test_case( int test_case_idx );
1077 void prepare_to_validation( int test_case_idx );
1081 Core_MahalanobisTest::Core_MahalanobisTest() : Core_MatrixTest( 3, 1, false, true, 1 )
1083 test_case_count = 100;
1084 test_array[TEMP].push_back(NULL);
1085 test_array[TEMP].push_back(NULL);
1086 test_array[TEMP].push_back(NULL);
1090 void Core_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1092 RNG& rng = ts->get_rng();
1093 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1095 if( cvtest::randInt(rng) & 1 )
1096 sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
1098 sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1100 sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0];
1101 sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1;
1102 sizes[TEMP][2] = sizes[INPUT][2];
1103 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
1106 int Core_MahalanobisTest::prepare_test_case( int test_case_idx )
1108 int code = Base::prepare_test_case( test_case_idx );
1111 // make sure that the inverted "covariation" matrix is symmetrix and positively defined.
1112 cvtest::gemm( test_mat[INPUT][2], test_mat[INPUT][2], 1., Mat(), 0., test_mat[TEMP][2], GEMM_2_T );
1113 cvtest::copy( test_mat[TEMP][2], test_mat[INPUT][2] );
1120 void Core_MahalanobisTest::run_func()
1122 test_mat[OUTPUT][0].at<Scalar>(0,0) =
1123 cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
1126 void Core_MahalanobisTest::prepare_to_validation( int )
1128 cvtest::add( test_mat[INPUT][0], 1., test_mat[INPUT][1], -1.,
1129 Scalar::all(0), test_mat[TEMP][0], test_mat[TEMP][0].type() );
1130 if( test_mat[INPUT][0].rows == 1 )
1131 cvtest::gemm( test_mat[TEMP][0], test_mat[INPUT][2], 1.,
1132 Mat(), 0., test_mat[TEMP][1], 0 );
1134 cvtest::gemm( test_mat[INPUT][2], test_mat[TEMP][0], 1.,
1135 Mat(), 0., test_mat[TEMP][1], 0 );
1137 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(sqrt(cvtest::crossCorr(test_mat[TEMP][0], test_mat[TEMP][1])));
1141 ///////////////// covarmatrix /////////////////////
1143 class Core_CovarMatrixTest : public Core_MatrixTest
1146 Core_CovarMatrixTest();
1148 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1149 int prepare_test_case( int test_case_idx );
1151 void prepare_to_validation( int test_case_idx );
1152 vector<void*> temp_hdrs;
1153 vector<uchar> hdr_data;
1154 int flags, t_flag, len, count;
1159 Core_CovarMatrixTest::Core_CovarMatrixTest() : Core_MatrixTest( 1, 1, true, false, 1 ),
1160 flags(0), t_flag(0), len(0), count(0), are_images(false)
1162 test_case_count = 100;
1163 test_array[INPUT_OUTPUT].push_back(NULL);
1164 test_array[REF_INPUT_OUTPUT].push_back(NULL);
1165 test_array[TEMP].push_back(NULL);
1166 test_array[TEMP].push_back(NULL);
1170 void Core_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1172 RNG& rng = ts->get_rng();
1173 int bits = cvtest::randInt(rng);
1174 int i, single_matrix;
1175 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1177 flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS );
1178 single_matrix = flags & CV_COVAR_ROWS;
1179 t_flag = (bits & 256) != 0;
1181 const int min_count = 2;
1185 len = sizes[INPUT][0].width;
1186 count = sizes[INPUT][0].height;
1187 count = MAX(count, min_count);
1188 sizes[INPUT][0] = Size(len, count);
1192 len = sizes[INPUT][0].height;
1193 count = sizes[INPUT][0].width;
1194 count = MAX(count, min_count);
1195 sizes[INPUT][0] = Size(count, len);
1198 if( single_matrix && t_flag )
1199 flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
1201 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
1202 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
1204 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? Size(len,len) : Size(count,count);
1205 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? Size(len,1) : Size(1,len);
1206 sizes[TEMP][0] = sizes[INPUT][0];
1208 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] =
1209 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] =
1210 CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F;
1212 are_images = (bits & 1024) != 0;
1213 for( i = 0; i < (single_matrix ? 1 : count); i++ )
1214 temp_hdrs.push_back(NULL);
1218 int Core_CovarMatrixTest::prepare_test_case( int test_case_idx )
1220 int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1224 int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
1225 int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
1227 hdr_data.resize(count*hdr_size);
1228 uchar* _hdr_data = &hdr_data[0];
1232 *((CvMat*)_hdr_data) = test_mat[INPUT][0];
1234 *((IplImage*)_hdr_data) = test_mat[INPUT][0];
1235 temp_hdrs[0] = _hdr_data;
1238 for( i = 0; i < count; i++ )
1241 void* ptr = _hdr_data + i*hdr_size;
1244 part = test_mat[INPUT][0].row(i);
1246 part = test_mat[INPUT][0].col(i);
1249 *((CvMat*)ptr) = part;
1251 *((IplImage*)ptr) = part;
1261 void Core_CovarMatrixTest::run_func()
1263 cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
1264 test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
1268 void Core_CovarMatrixTest::prepare_to_validation( int )
1270 Mat& avg = test_mat[REF_INPUT_OUTPUT][0];
1273 if( !(flags & CV_COVAR_USE_AVG) )
1275 Mat hdrs0 = cvarrToMat(temp_hdrs[0]);
1278 avg = Scalar::all(0);
1280 for( i = 0; i < count; i++ )
1283 if( flags & CV_COVAR_ROWS )
1285 else if( flags & CV_COVAR_COLS )
1288 vec = cvarrToMat(temp_hdrs[i]);
1290 cvtest::add(avg, 1, vec, 1, Scalar::all(0), avg, avg.type());
1293 cvtest::add(avg, 1./count, avg, 0., Scalar::all(0), avg, avg.type());
1296 if( flags & CV_COVAR_SCALE )
1301 Mat& temp0 = test_mat[TEMP][0];
1302 cv::repeat( avg, temp0.rows/avg.rows, temp0.cols/avg.cols, temp0 );
1303 cvtest::add( test_mat[INPUT][0], 1, temp0, -1, Scalar::all(0), temp0, temp0.type());
1305 cvtest::gemm( temp0, temp0, scale, Mat(), 0., test_mat[REF_OUTPUT][0],
1306 t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ? CV_GEMM_A_T : CV_GEMM_B_T );
1311 static void cvTsFloodWithZeros( Mat& mat, RNG& rng )
1313 int k, total = mat.rows*mat.cols, type = mat.type();
1314 int zero_total = cvtest::randInt(rng) % total;
1315 CV_Assert( type == CV_32FC1 || type == CV_64FC1 );
1317 for( k = 0; k < zero_total; k++ )
1319 int i = cvtest::randInt(rng) % mat.rows;
1320 int j = cvtest::randInt(rng) % mat.cols;
1322 if( type == CV_32FC1 )
1323 mat.at<float>(i,j) = 0.f;
1325 mat.at<double>(i,j) = 0.;
1330 ///////////////// determinant /////////////////////
1332 class Core_DetTest : public Core_MatrixTest
1335 typedef Core_MatrixTest Base;
1338 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1339 double get_success_error_level( int test_case_idx, int i, int j );
1340 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
1341 int prepare_test_case( int test_case_idx );
1343 void prepare_to_validation( int test_case_idx );
1347 Core_DetTest::Core_DetTest() : Core_MatrixTest( 1, 1, false, true, 1 )
1349 test_case_count = 100;
1350 max_log_array_size = 7;
1351 test_array[TEMP].push_back(NULL);
1355 void Core_DetTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1357 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1359 sizes[INPUT][0].width = sizes[INPUT][0].height;
1360 sizes[TEMP][0] = sizes[INPUT][0];
1361 types[TEMP][0] = CV_64FC1;
1365 void Core_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1367 low = cvScalarAll(-2.);
1368 high = cvScalarAll(2.);
1372 double Core_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1374 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
1378 int Core_DetTest::prepare_test_case( int test_case_idx )
1380 int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1382 cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() );
1388 void Core_DetTest::run_func()
1390 test_mat[OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(cvDet(test_array[INPUT][0]));
1394 // LU method that chooses the optimal in a column pivot element
1395 static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 )
1397 int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double);
1398 int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0;
1399 int x_step = x ? x->step/sizeof(double) : 0;
1400 double *a0 = a->data.db, *b0 = b ? b->data.db : 0;
1401 double *x0 = x ? x->data.db : 0;
1403 assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
1404 (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
1406 for( i = 0; i < Nm; i++ )
1408 double max_val = fabs(a0[i*step + i]);
1409 double *a1, *a2, *b1 = 0, *b2 = 0;
1412 for( j = i+1; j < N; j++ )
1414 t = fabs(a0[j*step + i]);
1424 for( j = i; j < N1; j++ )
1425 CV_SWAP( a0[i*step + j], a0[k*step + j], t );
1427 for( j = 0; j < M; j++ )
1428 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
1444 for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
1447 for( k = i+1; k < N1; k++ )
1450 for( k = 0; k < M; k++ )
1461 for( i = N-1; i >= 0; i-- )
1463 double* a1 = a0 + i*step;
1464 double* b1 = b0 + i*b_step;
1465 for( j = 0; j < M; j++ )
1468 for( k = i+1; k < N1; k++ )
1469 t -= a1[k]*x0[k*x_step + j];
1470 x0[i*x_step + j] = t/a1[i];
1481 void Core_DetTest::prepare_to_validation( int )
1483 test_mat[INPUT][0].convertTo(test_mat[TEMP][0], test_mat[TEMP][0].type());
1484 CvMat temp0 = test_mat[TEMP][0];
1485 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(cvTsLU(&temp0, 0, 0));
1489 ///////////////// invert /////////////////////
1491 class Core_InvertTest : public Core_MatrixTest
1494 typedef Core_MatrixTest Base;
1497 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1498 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
1499 double get_success_error_level( int test_case_idx, int i, int j );
1500 int prepare_test_case( int test_case_idx );
1502 void prepare_to_validation( int test_case_idx );
1508 Core_InvertTest::Core_InvertTest()
1509 : Core_MatrixTest( 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
1511 test_case_count = 100;
1512 max_log_array_size = 7;
1513 test_array[TEMP].push_back(NULL);
1514 test_array[TEMP].push_back(NULL);
1518 void Core_InvertTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1520 RNG& rng = ts->get_rng();
1521 int bits = cvtest::randInt(rng);
1522 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1523 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
1525 if( (bits & 3) == 0 )
1530 sizes[INPUT][0] = Size(min_size, min_size);
1532 method = CV_CHOLESKY;
1538 sizes[INPUT][0] = Size(min_size, min_size);
1541 sizes[TEMP][0].width = sizes[INPUT][0].height;
1542 sizes[TEMP][0].height = sizes[INPUT][0].width;
1543 sizes[TEMP][1] = sizes[INPUT][0];
1544 types[TEMP][0] = types[INPUT][0];
1545 types[TEMP][1] = CV_64FC1;
1546 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size(min_size, min_size);
1550 double Core_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
1552 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-6;
1555 int Core_InvertTest::prepare_test_case( int test_case_idx )
1557 int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1560 cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() );
1562 if( method == CV_CHOLESKY )
1564 cvtest::gemm( test_mat[INPUT][0], test_mat[INPUT][0], 1.,
1565 Mat(), 0., test_mat[TEMP][0], CV_GEMM_B_T );
1566 cvtest::copy( test_mat[TEMP][0], test_mat[INPUT][0] );
1575 void Core_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1577 low = cvScalarAll(-1.);
1578 high = cvScalarAll(1.);
1582 void Core_InvertTest::run_func()
1584 result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
1588 static double cvTsSVDet( CvMat* mat, double* ratio )
1590 int type = CV_MAT_TYPE(mat->type);
1591 int i, nm = MIN( mat->rows, mat->cols );
1592 CvMat* w = cvCreateMat( nm, 1, type );
1595 cvSVD( mat, w, 0, 0, 0 );
1597 if( type == CV_32FC1 )
1599 for( i = 0; i < nm; i++ )
1600 det *= w->data.fl[i];
1601 *ratio = w->data.fl[nm-1] < FLT_EPSILON ? 0 : w->data.fl[nm-1]/w->data.fl[0];
1605 for( i = 0; i < nm; i++ )
1606 det *= w->data.db[i];
1607 *ratio = w->data.db[nm-1] < FLT_EPSILON ? 0 : w->data.db[nm-1]/w->data.db[0];
1614 void Core_InvertTest::prepare_to_validation( int )
1616 Mat& input = test_mat[INPUT][0];
1617 Mat& temp0 = test_mat[TEMP][0];
1618 Mat& temp1 = test_mat[TEMP][1];
1619 Mat& dst0 = test_mat[REF_OUTPUT][0];
1620 Mat& dst = test_mat[OUTPUT][0];
1621 CvMat _input = input;
1622 double ratio = 0, det = cvTsSVDet( &_input, &ratio );
1623 double threshold = (input.depth() == CV_32F ? FLT_EPSILON : DBL_EPSILON)*1000;
1625 cvtest::convert( input, temp1, temp1.type() );
1627 if( det < threshold ||
1628 ((method == CV_LU || method == CV_CHOLESKY) && (result == 0 || ratio < threshold)) ||
1629 ((method == CV_SVD || method == CV_SVD_SYM) && result < threshold) )
1631 dst = Scalar::all(0);
1632 dst0 = Scalar::all(0);
1636 if( input.rows >= input.cols )
1637 cvtest::gemm( temp0, input, 1., Mat(), 0., dst, 0 );
1639 cvtest::gemm( input, temp0, 1., Mat(), 0., dst, 0 );
1641 cv::setIdentity( dst0, Scalar::all(1) );
1645 ///////////////// solve /////////////////////
1647 class Core_SolveTest : public Core_MatrixTest
1650 typedef Core_MatrixTest Base;
1653 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1654 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
1655 double get_success_error_level( int test_case_idx, int i, int j );
1656 int prepare_test_case( int test_case_idx );
1658 void prepare_to_validation( int test_case_idx );
1664 Core_SolveTest::Core_SolveTest() : Core_MatrixTest( 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
1666 test_case_count = 100;
1667 max_log_array_size = 7;
1668 test_array[TEMP].push_back(NULL);
1669 test_array[TEMP].push_back(NULL);
1673 void Core_SolveTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1675 RNG& rng = ts->get_rng();
1676 int bits = cvtest::randInt(rng);
1677 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1678 CvSize in_sz = sizes[INPUT][0];
1679 if( in_sz.width > in_sz.height )
1680 in_sz = cvSize(in_sz.height, in_sz.width);
1681 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1682 sizes[INPUT][0] = in_sz;
1683 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
1685 if( (bits & 3) == 0 )
1690 sizes[INPUT][0] = Size(min_size, min_size);
1692 method = CV_SVD_SYM;*/
1698 sizes[INPUT][0] = Size(min_size, min_size);
1701 sizes[INPUT][1].height = sizes[INPUT][0].height;
1702 sizes[TEMP][0].width = sizes[INPUT][1].width;
1703 sizes[TEMP][0].height = sizes[INPUT][0].width;
1704 sizes[TEMP][1] = sizes[INPUT][0];
1705 types[TEMP][0] = types[INPUT][0];
1706 types[TEMP][1] = CV_64FC1;
1707 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size(sizes[INPUT][1].width, min_size);
1711 int Core_SolveTest::prepare_test_case( int test_case_idx )
1713 int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1715 /*if( method == CV_SVD_SYM )
1717 cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1.,
1718 0, 0., test_array[TEMP][0], CV_GEMM_B_T );
1719 cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] );
1726 void Core_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1728 low = cvScalarAll(-1.);
1729 high = cvScalarAll(1.);
1733 double Core_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
1735 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 5e-2 : 1e-8;
1739 void Core_SolveTest::run_func()
1741 result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
1744 void Core_SolveTest::prepare_to_validation( int )
1746 //int rank = test_mat[REF_OUTPUT][0].rows;
1747 Mat& input = test_mat[INPUT][0];
1748 Mat& dst = test_mat[OUTPUT][0];
1749 Mat& dst0 = test_mat[REF_OUTPUT][0];
1751 if( method == CV_LU )
1755 Mat& temp1 = test_mat[TEMP][1];
1756 cvtest::convert(input, temp1, temp1.type());
1757 dst = Scalar::all(0);
1758 CvMat _temp1 = temp1;
1759 double det = cvTsLU( &_temp1, 0, 0 );
1760 dst0 = Scalar::all(det != 0);
1764 double threshold = (input.type() == CV_32F ? FLT_EPSILON : DBL_EPSILON)*1000;
1765 CvMat _input = input;
1766 double ratio = 0, det = cvTsSVDet( &_input, &ratio );
1767 if( det < threshold || ratio < threshold )
1769 dst = Scalar::all(0);
1770 dst0 = Scalar::all(0);
1775 Mat* pdst = input.rows <= input.cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
1777 cvtest::gemm( input, test_mat[TEMP][0], 1., test_mat[INPUT][1], -1., *pdst, 0 );
1779 cvtest::gemm( input, *pdst, 1., Mat(), 0., dst, CV_GEMM_A_T );
1780 dst0 = Scalar::all(0);
1784 ///////////////// SVD /////////////////////
1786 class Core_SVDTest : public Core_MatrixTest
1789 typedef Core_MatrixTest Base;
1792 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1793 double get_success_error_level( int test_case_idx, int i, int j );
1794 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
1795 int prepare_test_case( int test_case_idx );
1797 void prepare_to_validation( int test_case_idx );
1799 bool have_u, have_v, symmetric, compact, vector_w;
1803 Core_SVDTest::Core_SVDTest() :
1804 Core_MatrixTest( 1, 4, false, false, 1 ),
1805 flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false)
1807 test_case_count = 100;
1808 max_log_array_size = 8;
1809 test_array[TEMP].push_back(NULL);
1810 test_array[TEMP].push_back(NULL);
1811 test_array[TEMP].push_back(NULL);
1812 test_array[TEMP].push_back(NULL);
1816 void Core_SVDTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1818 RNG& rng = ts->get_rng();
1819 int bits = cvtest::randInt(rng);
1820 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1821 int min_size, i, m, n;
1823 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
1825 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
1826 have_u = (bits & 8) != 0;
1827 have_v = (bits & 16) != 0;
1828 symmetric = (bits & 32) != 0;
1829 compact = (bits & 64) != 0;
1830 vector_w = (bits & 128) != 0;
1833 sizes[INPUT][0] = Size(min_size, min_size);
1835 m = sizes[INPUT][0].height;
1836 n = sizes[INPUT][0].width;
1839 sizes[TEMP][0] = Size(min_size, min_size);
1841 sizes[TEMP][0] = sizes[INPUT][0];
1842 sizes[TEMP][3] = Size(0,0);
1846 sizes[TEMP][3] = sizes[TEMP][0];
1848 sizes[TEMP][0] = Size(1, min_size);
1850 sizes[TEMP][0] = Size(min_size, 1);
1855 sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m);
1857 if( flags & CV_SVD_U_T )
1858 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
1861 sizes[TEMP][1] = Size(0,0);
1865 sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n);
1867 if( !(flags & CV_SVD_V_T) )
1868 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
1871 sizes[TEMP][2] = Size(0,0);
1873 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0];
1874 types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0];
1875 types[OUTPUT][3] = CV_8UC1;
1876 sizes[OUTPUT][0] = !have_u || !have_v ? Size(0,0) : sizes[INPUT][0];
1877 sizes[OUTPUT][1] = !have_u ? Size(0,0) : compact ? Size(min_size,min_size) : Size(m,m);
1878 sizes[OUTPUT][2] = !have_v ? Size(0,0) : compact ? Size(min_size,min_size) : Size(n,n);
1879 sizes[OUTPUT][3] = Size(min_size,1);
1881 for( i = 0; i < 4; i++ )
1883 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
1884 types[REF_OUTPUT][i] = types[OUTPUT][i];
1889 int Core_SVDTest::prepare_test_case( int test_case_idx )
1891 int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1894 Mat& input = test_mat[INPUT][0];
1895 cvTsFloodWithZeros( input, ts->get_rng() );
1897 if( symmetric && (have_u || have_v) )
1899 Mat& temp = test_mat[TEMP][have_u ? 1 : 2];
1900 cvtest::gemm( input, input, 1., Mat(), 0., temp, CV_GEMM_B_T );
1901 cvtest::copy( temp, input );
1904 if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
1905 cvtest::copy( input, test_mat[OUTPUT][0] );
1912 void Core_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1914 low = cvScalarAll(-2.);
1915 high = cvScalarAll(2.);
1918 double Core_SVDTest::get_success_error_level( int test_case_idx, int i, int j )
1920 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
1921 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ? 1e-5 : 5e-11;
1922 double output_precision = Base::get_success_error_level( test_case_idx, i, j );
1923 return MAX(input_precision, output_precision);
1926 void Core_SVDTest::run_func()
1928 CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
1930 src = test_array[INPUT][0];
1931 cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
1935 void Core_SVDTest::prepare_to_validation( int /*test_case_idx*/ )
1937 Mat& input = test_mat[INPUT][0];
1938 int depth = input.depth();
1939 int i, m = input.rows, n = input.cols, min_size = MIN(m, n);
1941 double prev = 0, threshold = depth == CV_32F ? FLT_EPSILON : DBL_EPSILON;
1945 src = &test_mat[TEMP][1];
1946 dst = &test_mat[OUTPUT][1];
1947 cvtest::gemm( *src, *src, 1., Mat(), 0., *dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
1948 cv::setIdentity( test_mat[REF_OUTPUT][1], Scalar::all(1.) );
1953 src = &test_mat[TEMP][2];
1954 dst = &test_mat[OUTPUT][2];
1955 cvtest::gemm( *src, *src, 1., Mat(), 0., *dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
1956 cv::setIdentity( test_mat[REF_OUTPUT][2], Scalar::all(1.) );
1959 w = &test_mat[TEMP][0];
1960 for( i = 0; i < min_size; i++ )
1962 double normval = 0, aii;
1963 if( w->rows > 1 && w->cols > 1 )
1965 normval = cvtest::norm( w->row(i), NORM_L1 );
1966 aii = depth == CV_32F ? w->at<float>(i,i) : w->at<double>(i,i);
1970 normval = aii = depth == CV_32F ? w->at<float>(i) : w->at<double>(i);
1973 normval = fabs(normval - aii);
1974 test_mat[OUTPUT][3].at<uchar>(i) = aii >= 0 && normval < threshold && (i == 0 || aii <= prev);
1978 test_mat[REF_OUTPUT][3] = Scalar::all(1);
1980 if( have_u && have_v )
1984 test_mat[TEMP][3] = Scalar::all(0);
1985 for( i = 0; i < min_size; i++ )
1987 double val = depth == CV_32F ? w->at<float>(i) : w->at<double>(i);
1988 cvSetReal2D( test_array[TEMP][3], i, i, val );
1990 w = &test_mat[TEMP][3];
1995 cvtest::gemm( test_mat[TEMP][1], *w, 1., Mat(), 0., test_mat[REF_OUTPUT][0],
1996 flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
1997 cvtest::gemm( test_mat[REF_OUTPUT][0], test_mat[TEMP][2], 1., Mat(), 0.,
1998 test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
2002 cvtest::gemm( *w, test_mat[TEMP][2], 1., Mat(), 0., test_mat[REF_OUTPUT][0],
2003 flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
2004 cvtest::gemm( test_mat[TEMP][1], test_mat[REF_OUTPUT][0], 1., Mat(), 0.,
2005 test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
2008 cvtest::copy( test_mat[INPUT][0], test_mat[REF_OUTPUT][0] );
2014 ///////////////// SVBkSb /////////////////////
2016 class Core_SVBkSbTest : public Core_MatrixTest
2019 typedef Core_MatrixTest Base;
2022 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
2023 double get_success_error_level( int test_case_idx, int i, int j );
2024 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
2025 int prepare_test_case( int test_case_idx );
2027 void prepare_to_validation( int test_case_idx );
2029 bool have_b, symmetric, compact, vector_w;
2033 Core_SVBkSbTest::Core_SVBkSbTest() : Core_MatrixTest( 2, 1, false, false, 1 ),
2034 flags(0), have_b(false), symmetric(false), compact(false), vector_w(false)
2036 test_case_count = 100;
2037 test_array[TEMP].push_back(NULL);
2038 test_array[TEMP].push_back(NULL);
2039 test_array[TEMP].push_back(NULL);
2043 void Core_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes,
2044 vector<vector<int> >& types )
2046 RNG& rng = ts->get_rng();
2047 int bits = cvtest::randInt(rng);
2048 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2049 int min_size, i, m, n;
2052 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2054 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
2055 have_b = (bits & 16) != 0;
2056 symmetric = (bits & 32) != 0;
2057 compact = (bits & 64) != 0;
2058 vector_w = (bits & 128) != 0;
2061 sizes[INPUT][0] = Size(min_size, min_size);
2063 m = sizes[INPUT][0].height;
2064 n = sizes[INPUT][0].width;
2066 sizes[INPUT][1] = Size(0,0);
2070 sizes[INPUT][1].height = sizes[INPUT][0].height;
2071 sizes[INPUT][1].width = cvtest::randInt(rng) % 100 + 1;
2072 b_size = sizes[INPUT][1];
2076 sizes[TEMP][0] = Size(min_size, min_size);
2078 sizes[TEMP][0] = sizes[INPUT][0];
2083 sizes[TEMP][0] = Size(1, min_size);
2085 sizes[TEMP][0] = Size(min_size, 1);
2088 sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m);
2090 if( flags & CV_SVD_U_T )
2091 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
2093 sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n);
2095 if( !(flags & CV_SVD_V_T) )
2096 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
2098 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
2099 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0];
2100 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size( b_size.width, n );
2104 int Core_SVBkSbTest::prepare_test_case( int test_case_idx )
2106 int code = Base::prepare_test_case( test_case_idx );
2109 Mat& input = test_mat[INPUT][0];
2110 cvTsFloodWithZeros( input, ts->get_rng() );
2114 Mat& temp = test_mat[TEMP][1];
2115 cvtest::gemm( input, input, 1., Mat(), 0., temp, CV_GEMM_B_T );
2116 cvtest::copy( temp, input );
2119 CvMat _input = input;
2120 cvSVD( &_input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
2127 void Core_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
2129 low = cvScalarAll(-2.);
2130 high = cvScalarAll(2.);
2134 double Core_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2136 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
2140 void Core_SVBkSbTest::run_func()
2142 cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
2143 test_array[INPUT][1], test_array[OUTPUT][0], flags );
2147 void Core_SVBkSbTest::prepare_to_validation( int )
2149 Mat& input = test_mat[INPUT][0];
2150 int i, m = input.rows, n = input.cols, min_size = MIN(m, n);
2151 bool is_float = input.type() == CV_32F;
2152 Size w_size = compact ? Size(min_size,min_size) : Size(m,n);
2153 Mat& w = test_mat[TEMP][0];
2154 Mat wdb( w_size.height, w_size.width, CV_64FC1 );
2155 CvMat _w = w, _wdb = wdb;
2156 // use exactly the same threshold as in icvSVD... ,
2157 // so the changes in the library and here should be synchronized.
2158 double threshold = cv::sum(w)[0]*(DBL_EPSILON*2);//(is_float ? FLT_EPSILON*10 : DBL_EPSILON*2);
2160 wdb = Scalar::all(0);
2161 for( i = 0; i < min_size; i++ )
2163 double wii = vector_w ? cvGetReal1D(&_w,i) : cvGetReal2D(&_w,i,i);
2164 cvSetReal2D( &_wdb, i, i, wii > threshold ? 1./wii : 0. );
2167 Mat u = test_mat[TEMP][1];
2168 Mat v = test_mat[TEMP][2];
2169 Mat b = test_mat[INPUT][1];
2173 test_mat[TEMP][1].convertTo(u, CV_64F);
2174 test_mat[TEMP][2].convertTo(v, CV_64F);
2176 test_mat[INPUT][1].convertTo(b, CV_64F);
2182 cvtest::gemm( u, b, 1., Mat(), 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 );
2183 else if( flags & CV_SVD_U_T )
2184 cvtest::copy( u, t0 );
2186 cvtest::transpose( u, t0 );
2188 cvtest::gemm( wdb, t0, 1, Mat(), 0, t1, 0 );
2190 cvtest::gemm( v, t1, 1, Mat(), 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 );
2191 Mat& dst0 = test_mat[REF_OUTPUT][0];
2192 t0.convertTo(dst0, dst0.type() );
2196 typedef std::complex<double> complex_type;
2200 bool operator() (const complex_type& lhs, const complex_type& rhs) const
2202 return fabs(lhs.real() - rhs.real()) > fabs(rhs.real())*FLT_EPSILON ? lhs.real() < rhs.real() : lhs.imag() < rhs.imag();
2208 bool operator() (const double& lhs, const double& rhs) const
2214 class Core_SolvePolyTest : public cvtest::BaseTest
2217 Core_SolvePolyTest();
2218 ~Core_SolvePolyTest();
2220 virtual void run( int start_from );
2223 Core_SolvePolyTest::Core_SolvePolyTest() {}
2225 Core_SolvePolyTest::~Core_SolvePolyTest() {}
2227 void Core_SolvePolyTest::run( int )
2229 RNG& rng = ts->get_rng();
2232 double err_eps = 1e-4;
2234 for (int idx = 0, max_idx = 1000, progress = 0; idx < max_idx; ++idx)
2236 progress = update_progress(progress, idx-1, max_idx, 0);
2237 int n = cvtest::randInt(rng) % 13 + 1;
2238 std::vector<complex_type> r(n), ar(n), c(n + 1, 0);
2239 std::vector<double> a(n + 1), u(n * 2), ar1(n), ar2(n);
2241 int rr_odds = 3; // odds that we get a real root
2242 for (int j = 0; j < n;)
2244 if (cvtest::randInt(rng) % rr_odds == 0 || j == n - 1)
2245 r[j++] = cvtest::randReal(rng) * range;
2248 r[j] = complex_type(cvtest::randReal(rng) * range,
2249 cvtest::randReal(rng) * range + 1);
2250 r[j + 1] = std::conj(r[j]);
2255 for (int j = 0, k = 1 << n, jj, kk; j < k; ++j)
2259 for (jj = 0, kk = 1; jj < n && !(j & kk); ++jj, ++p, kk <<= 1)
2261 for (; jj < n; ++jj, kk <<= 1)
2272 double div = 0, s = 0;
2273 int cubic_case = idx & 1;
2274 for (int maxiter = 100; !pass && maxiter < 10000; maxiter *= 2, cubic_case = (cubic_case + 1) % 2)
2276 for (int j = 0; j < n + 1; ++j)
2280 cvInitMatHeader(&amat, n + 1, 1, CV_64FC1, &a[0]);
2281 cvInitMatHeader(&umat, n, 1, CV_64FC2, &u[0]);
2282 cvSolvePoly(&amat, &umat, maxiter, fig);
2284 for (int j = 0; j < n; ++j)
2285 ar[j] = complex_type(u[j * 2], u[j * 2 + 1]);
2287 std::sort(r.begin(), r.end(), pred_complex());
2288 std::sort(ar.begin(), ar.end(), pred_complex());
2294 cv::Mat _umat2(3, 1, CV_64F, &ar2[0]), umat2 = _umat2;
2295 cvFlip(&amat, &amat, 0);
2297 if( cubic_case == 0 )
2298 nr2 = cv::solveCubic(cv::cvarrToMat(&amat),umat2);
2300 nr2 = cv::solveCubic(cv::Mat_<float>(cv::cvarrToMat(&amat)), umat2);
2301 cvFlip(&amat, &amat, 0);
2303 std::sort(ar2.begin(), ar2.begin()+nr2, pred_double());
2307 for(int j = 0; j < n; j++)
2308 if( fabs(r[j].imag()) < DBL_EPSILON )
2309 ar1[nr1++] = r[j].real();
2311 pass = pass && nr1 == nr2;
2315 for(int j = 0; j < nr1; j++)
2318 div += fabs(ar1[j] - ar2[j]);
2321 pass = pass && div < err_eps;
2326 for (int j = 0; j < n; ++j)
2328 s += fabs(r[j].real()) + fabs(r[j].imag());
2329 div += sqrt(pow(r[j].real() - ar[j].real(), 2) + pow(r[j].imag() - ar[j].imag(), 2));
2332 pass = pass && div < err_eps;
2337 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
2338 ts->printf( cvtest::TS::LOG, "too big diff = %g\n", div );
2340 for (size_t j=0;j<ar2.size();++j)
2341 ts->printf( cvtest::TS::LOG, "ar2[%d]=%g\n", j, ar2[j]);
2342 ts->printf(cvtest::TS::LOG, "\n");
2344 for (size_t j=0;j<r.size();++j)
2345 ts->printf( cvtest::TS::LOG, "r[%d]=(%g, %g)\n", j, r[j].real(), r[j].imag());
2346 ts->printf( cvtest::TS::LOG, "\n" );
2347 for (size_t j=0;j<ar.size();++j)
2348 ts->printf( cvtest::TS::LOG, "ar[%d]=(%g, %g)\n", j, ar[j].real(), ar[j].imag());
2354 class Core_PhaseTest : public cvtest::BaseTest
2358 ~Core_PhaseTest() {}
2360 virtual void run(int)
2362 const float maxAngleDiff = 0.5; //in degrees
2363 const int axisCount = 8;
2364 const int dim = theRNG().uniform(1,10);
2365 const float scale = theRNG().uniform(1.f, 100.f);
2366 Mat x(axisCount + 1, dim, CV_32FC1),
2367 y(axisCount + 1, dim, CV_32FC1);
2368 Mat anglesInDegrees(axisCount + 1, dim, CV_32FC1);
2371 x.row(0).setTo(Scalar(0));
2372 y.row(0).setTo(Scalar(0));
2373 anglesInDegrees.row(0).setTo(Scalar(0));
2375 x.row(1).setTo(Scalar(scale));
2376 y.row(1).setTo(Scalar(0));
2377 anglesInDegrees.row(1).setTo(Scalar(0));
2379 x.row(2).setTo(Scalar(scale));
2380 y.row(2).setTo(Scalar(scale));
2381 anglesInDegrees.row(2).setTo(Scalar(45));
2383 x.row(3).setTo(Scalar(0));
2384 y.row(3).setTo(Scalar(scale));
2385 anglesInDegrees.row(3).setTo(Scalar(90));
2387 x.row(4).setTo(Scalar(-scale));
2388 y.row(4).setTo(Scalar(scale));
2389 anglesInDegrees.row(4).setTo(Scalar(135));
2391 x.row(5).setTo(Scalar(-scale));
2392 y.row(5).setTo(Scalar(0));
2393 anglesInDegrees.row(5).setTo(Scalar(180));
2395 x.row(6).setTo(Scalar(-scale));
2396 y.row(6).setTo(Scalar(-scale));
2397 anglesInDegrees.row(6).setTo(Scalar(225));
2399 x.row(7).setTo(Scalar(0));
2400 y.row(7).setTo(Scalar(-scale));
2401 anglesInDegrees.row(7).setTo(Scalar(270));
2403 x.row(8).setTo(Scalar(scale));
2404 y.row(8).setTo(Scalar(-scale));
2405 anglesInDegrees.row(8).setTo(Scalar(315));
2407 Mat resInRad, resInDeg;
2408 phase(x, y, resInRad, false);
2409 phase(x, y, resInDeg, true);
2411 CV_Assert(resInRad.size() == x.size());
2412 CV_Assert(resInRad.type() == x.type());
2414 CV_Assert(resInDeg.size() == x.size());
2415 CV_Assert(resInDeg.type() == x.type());
2418 int outOfRangeCount = countNonZero((resInDeg > 360) | (resInDeg < 0));
2419 if(outOfRangeCount > 0)
2421 ts->printf(cvtest::TS::LOG, "There are result angles that are out of range [0, 360] (part of them is %f)\n",
2422 static_cast<float>(outOfRangeCount)/resInDeg.total());
2423 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
2426 Mat diff = abs(anglesInDegrees - resInDeg);
2427 size_t errDegCount = diff.total() - countNonZero((diff < maxAngleDiff) | ((360 - diff) < maxAngleDiff));
2430 ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in degrees) (part of them is %f)\n",
2431 static_cast<float>(errDegCount)/resInDeg.total());
2432 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
2435 Mat convertedRes = resInRad * 180. / CV_PI;
2436 double normDiff = cvtest::norm(convertedRes - resInDeg, NORM_INF);
2437 if(normDiff > FLT_EPSILON * 180.)
2439 ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in radians)\n");
2440 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
2443 ts->set_failed_test_info(cvtest::TS::OK);
2447 class Core_CheckRange_Empty : public cvtest::BaseTest
2450 Core_CheckRange_Empty(){}
2451 ~Core_CheckRange_Empty(){}
2453 virtual void run( int start_from );
2456 void Core_CheckRange_Empty::run( int )
2459 ASSERT_TRUE( cv::checkRange(m) );
2462 TEST(Core_CheckRange_Empty, accuracy) { Core_CheckRange_Empty test; test.safe_run(); }
2464 class Core_CheckRange_INT_MAX : public cvtest::BaseTest
2467 Core_CheckRange_INT_MAX(){}
2468 ~Core_CheckRange_INT_MAX(){}
2470 virtual void run( int start_from );
2473 void Core_CheckRange_INT_MAX::run( int )
2475 cv::Mat m(3, 3, CV_32SC1, cv::Scalar(INT_MAX));
2476 ASSERT_FALSE( cv::checkRange(m, true, 0, 0, INT_MAX) );
2477 ASSERT_TRUE( cv::checkRange(m) );
2480 TEST(Core_CheckRange_INT_MAX, accuracy) { Core_CheckRange_INT_MAX test; test.safe_run(); }
2482 template <typename T> class Core_CheckRange : public testing::Test {};
2484 TYPED_TEST_CASE_P(Core_CheckRange);
2486 TYPED_TEST_P(Core_CheckRange, Negative)
2488 double min_bound = 4.5;
2489 double max_bound = 16.0;
2491 TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14};
2492 cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data);
2494 cv::Point bad_pt(0, 0);
2496 ASSERT_FALSE(checkRange(src, true, &bad_pt, min_bound, max_bound));
2497 ASSERT_EQ(bad_pt.x, 0);
2498 ASSERT_EQ(bad_pt.y, 1);
2501 TYPED_TEST_P(Core_CheckRange, Positive)
2503 double min_bound = -1;
2504 double max_bound = 16.0;
2506 TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14};
2507 cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data);
2509 cv::Point bad_pt(0, 0);
2511 ASSERT_TRUE(checkRange(src, true, &bad_pt, min_bound, max_bound));
2512 ASSERT_EQ(bad_pt.x, 0);
2513 ASSERT_EQ(bad_pt.y, 0);
2516 TYPED_TEST_P(Core_CheckRange, Bounds)
2518 double min_bound = 24.5;
2519 double max_bound = 1.0;
2521 TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14};
2522 cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data);
2524 cv::Point bad_pt(0, 0);
2526 ASSERT_FALSE(checkRange(src, true, &bad_pt, min_bound, max_bound));
2527 ASSERT_EQ(bad_pt.x, 0);
2528 ASSERT_EQ(bad_pt.y, 0);
2531 TYPED_TEST_P(Core_CheckRange, Zero)
2533 double min_bound = 0.0;
2534 double max_bound = 0.1;
2536 cv::Mat src1 = cv::Mat::zeros(3, 3, cv::DataDepth<TypeParam>::value);
2538 int sizes[] = {5, 6, 7};
2539 cv::Mat src2 = cv::Mat::zeros(3, sizes, cv::DataDepth<TypeParam>::value);
2541 ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) );
2542 ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) );
2545 TYPED_TEST_P(Core_CheckRange, One)
2547 double min_bound = 1.0;
2548 double max_bound = 1.1;
2550 cv::Mat src1 = cv::Mat::ones(3, 3, cv::DataDepth<TypeParam>::value);
2552 int sizes[] = {5, 6, 7};
2553 cv::Mat src2 = cv::Mat::ones(3, sizes, cv::DataDepth<TypeParam>::value);
2555 ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) );
2556 ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) );
2559 REGISTER_TYPED_TEST_CASE_P(Core_CheckRange, Negative, Positive, Bounds, Zero, One);
2561 typedef ::testing::Types<signed char,unsigned char, signed short, unsigned short, signed int> mat_data_types;
2562 INSTANTIATE_TYPED_TEST_CASE_P(Negative_Test, Core_CheckRange, mat_data_types);
2564 TEST(Core_Invert, small)
2566 cv::Mat a = (cv::Mat_<float>(3,3) << 2.42104644730331, 1.81444796521479, -3.98072565304758, 0, 7.08389214348967e-3, 5.55326770986007e-3, 0,0, 7.44556154284261e-3);
2567 //cv::randu(a, -1, 1);
2569 cv::Mat b = a.t()*a;
2570 cv::Mat c, i = Mat_<float>::eye(3, 3);
2571 cv::invert(b, c, cv::DECOMP_LU); //std::cout << b*c << std::endl;
2572 ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 );
2573 cv::invert(b, c, cv::DECOMP_SVD); //std::cout << b*c << std::endl;
2574 ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 );
2575 cv::invert(b, c, cv::DECOMP_CHOLESKY); //std::cout << b*c << std::endl;
2576 ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 );
2579 /////////////////////////////////////////////////////////////////////////////////////////////////////
2581 TEST(Core_CovarMatrix, accuracy) { Core_CovarMatrixTest test; test.safe_run(); }
2582 TEST(Core_CrossProduct, accuracy) { Core_CrossProductTest test; test.safe_run(); }
2583 TEST(Core_Determinant, accuracy) { Core_DetTest test; test.safe_run(); }
2584 TEST(Core_DotProduct, accuracy) { Core_DotProductTest test; test.safe_run(); }
2585 TEST(Core_GEMM, accuracy) { Core_GEMMTest test; test.safe_run(); }
2586 TEST(Core_Invert, accuracy) { Core_InvertTest test; test.safe_run(); }
2587 TEST(Core_Mahalanobis, accuracy) { Core_MahalanobisTest test; test.safe_run(); }
2588 TEST(Core_MulTransposed, accuracy) { Core_MulTransposedTest test; test.safe_run(); }
2589 TEST(Core_Transform, accuracy) { Core_TransformTest test; test.safe_run(); }
2590 TEST(Core_PerspectiveTransform, accuracy) { Core_PerspectiveTransformTest test; test.safe_run(); }
2591 TEST(Core_Pow, accuracy) { Core_PowTest test; test.safe_run(); }
2592 TEST(Core_SolveLinearSystem, accuracy) { Core_SolveTest test; test.safe_run(); }
2593 TEST(Core_SVD, accuracy) { Core_SVDTest test; test.safe_run(); }
2594 TEST(Core_SVBkSb, accuracy) { Core_SVBkSbTest test; test.safe_run(); }
2595 TEST(Core_Trace, accuracy) { Core_TraceTest test; test.safe_run(); }
2596 TEST(Core_SolvePoly, accuracy) { Core_SolvePolyTest test; test.safe_run(); }
2597 TEST(Core_Phase, accuracy) { Core_PhaseTest test; test.safe_run(); }
2603 1.23377746e+011f, -7.05490125e+010f, -4.18380882e+010f, -11693456.f,
2604 -39091328.f, 77492224.f, -7.05490125e+010f, 2.36211143e+011f,
2605 -3.51093473e+010f, 70773408.f, -4.83386156e+005f, -129560368.f,
2606 -4.18380882e+010f, -3.51093473e+010f, 9.25311222e+010f, -49052424.f,
2607 43922752.f, 12176842.f, -11693456.f, 70773408.f, -49052424.f, 8.40836094e+004f,
2608 5.17475293e+003f, -1.16122949e+004f, -39091328.f, -4.83386156e+005f,
2609 43922752.f, 5.17475293e+003f, 5.16047969e+004f, 5.68887842e+003f, 77492224.f,
2610 -129560368.f, 12176842.f, -1.16122949e+004f, 5.68887842e+003f,
2615 283751232.f, 2.61604198e+009f, -745033216.f, 2.31125625e+005f,
2616 -4.52429188e+005f, -1.37596525e+006f
2619 Mat A(6, 6, CV_32F, a);
2620 Mat B(6, 1, CV_32F, b);
2622 solve(A, B, X, DECOMP_SVD);
2624 EXPECT_LE(cvtest::norm(B1, B, NORM_L2 + NORM_RELATIVE), FLT_EPSILON*10);
2628 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),
2635 MAT_N_DIM_C1_NONCONT,
2636 MAT_N_1_CDIM_NONCONT,
2640 class CV_KMeansSingularTest : public cvtest::BaseTest
2643 CV_KMeansSingularTest() {}
2644 ~CV_KMeansSingularTest() {}
2646 void run(int inVariant)
2648 int i, iter = 0, N = 0, N0 = 0, K = 0, dims = 0;
2652 RNG& rng = theRNG();
2653 const int MAX_DIM=5;
2654 int MAX_POINTS = 100, maxIter = 100;
2655 for( iter = 0; iter < maxIter; iter++ )
2657 ts->update_context(this, iter, true);
2658 dims = rng.uniform(inVariant == MAT_1_N_CDIM ? 2 : 1, MAX_DIM+1);
2659 N = rng.uniform(1, MAX_POINTS+1);
2660 N0 = rng.uniform(1, MAX(N/10, 2));
2661 K = rng.uniform(1, N+1);
2663 if (inVariant == VECTOR)
2667 std::vector<cv::Point2f> data0(N0);
2668 rng.fill(data0, RNG::UNIFORM, -1, 1);
2670 std::vector<cv::Point2f> data(N);
2671 for( i = 0; i < N; i++ )
2672 data[i] = data0[rng.uniform(0, N0)];
2674 kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
2675 5, KMEANS_PP_CENTERS);
2679 Mat data0(N0, dims, CV_32F);
2680 rng.fill(data0, RNG::UNIFORM, -1, 1);
2687 data.create(N, dims, CV_32F);
2688 for( i = 0; i < N; i++ )
2689 data0.row(rng.uniform(0, N0)).copyTo(data.row(i));
2693 data.create(N, 1, CV_32FC(dims));
2694 for( i = 0; i < N; i++ )
2695 memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
2699 data.create(1, N, CV_32FC(dims));
2700 for( i = 0; i < N; i++ )
2701 memcpy(data.ptr() + i * dims * sizeof(float), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
2704 case MAT_N_DIM_C1_NONCONT:
2705 data.create(N, dims + 5, CV_32F);
2706 data = data(Range(0, N), Range(0, dims));
2707 for( i = 0; i < N; i++ )
2708 data0.row(rng.uniform(0, N0)).copyTo(data.row(i));
2711 case MAT_N_1_CDIM_NONCONT:
2712 data.create(N, 3, CV_32FC(dims));
2713 data = data.colRange(0, 1);
2714 for( i = 0; i < N; i++ )
2715 memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
2719 kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
2720 5, KMEANS_PP_CENTERS);
2723 Mat hist(K, 1, CV_32S, Scalar(0));
2724 for( i = 0; i < N; i++ )
2726 int l = labels.at<int>(i);
2727 CV_Assert(0 <= l && l < K);
2730 for( i = 0; i < K; i++ )
2731 CV_Assert( hist.at<int>(i) != 0 );
2736 ts->printf(cvtest::TS::LOG,
2737 "context: iteration=%d, N=%d, N0=%d, K=%d\n",
2739 std::cout << labels << std::endl;
2740 ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
2745 TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(MAT_N_DIM_C1); }
2747 CV_ENUM(KMeansInputVariant, MAT_N_DIM_C1, MAT_N_1_CDIM, MAT_1_N_CDIM, MAT_N_DIM_C1_NONCONT, MAT_N_1_CDIM_NONCONT, VECTOR)
2749 typedef testing::TestWithParam<KMeansInputVariant> Core_KMeans_InputVariants;
2751 TEST_P(Core_KMeans_InputVariants, singular)
2753 CV_KMeansSingularTest test;
2754 test.safe_run(GetParam());
2757 INSTANTIATE_TEST_CASE_P(AllVariants, Core_KMeans_InputVariants, KMeansInputVariant::all());
2759 TEST(CovariationMatrixVectorOfMat, accuracy)
2761 unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16;
2762 cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F);
2763 int singleMatFlags = CV_COVAR_ROWS;
2767 cv::randu(src,cv::Scalar(-128), cv::Scalar(128));
2768 cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F);
2769 std::vector<cv::Mat> srcVec;
2770 for(size_t i = 0; i < vector_size; i++)
2772 srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size));
2777 cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F);
2780 cv::absdiff(gold, actual, diff);
2781 cv::Scalar s = cv::sum(diff);
2782 ASSERT_EQ(s.dot(s), 0.0);
2785 cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff);
2786 cv::Scalar sDiff = cv::sum(meanDiff);
2787 ASSERT_EQ(sDiff.dot(sDiff), 0.0);
2790 TEST(CovariationMatrixVectorOfMatWithMean, accuracy)
2792 unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16;
2793 cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F);
2794 int singleMatFlags = CV_COVAR_ROWS | CV_COVAR_USE_AVG;
2797 cv::randu(src,cv::Scalar(-128), cv::Scalar(128));
2800 cv::reduce(src,goldMean,0 ,CV_REDUCE_AVG, CV_32F);
2802 cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F);
2804 std::vector<cv::Mat> srcVec;
2805 for(size_t i = 0; i < vector_size; i++)
2807 srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size));
2811 cv::Mat actualMean = goldMean.reshape(0, row_problem_size);
2812 cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F);
2815 cv::absdiff(gold, actual, diff);
2816 cv::Scalar s = cv::sum(diff);
2817 ASSERT_EQ(s.dot(s), 0.0);
2820 cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff);
2821 cv::Scalar sDiff = cv::sum(meanDiff);
2822 ASSERT_EQ(sDiff.dot(sDiff), 0.0);