enabled gst
[profile/ivi/opencv.git] / modules / core / test / test_math.cpp
1 //////////////////////////////////////////////////////////////////////////////////////////
2 /////////////////// tests for matrix operations and math functions ///////////////////////
3 //////////////////////////////////////////////////////////////////////////////////////////
4
5 #include "test_precomp.hpp"
6 #include <float.h>
7 #include <math.h>
8
9 using namespace cv;
10 using namespace std;
11
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.
19
20 class Core_MathTest : public cvtest::ArrayTest
21 {
22 public:
23     typedef cvtest::ArrayTest Base;
24     Core_MathTest();
25 protected:
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 );
29     bool test_nd;
30 };
31
32
33 Core_MathTest::Core_MathTest()
34 {
35     optional_mask = false;
36
37     test_array[INPUT].push_back(NULL);
38     test_array[OUTPUT].push_back(NULL);
39     test_array[REF_OUTPUT].push_back(NULL);
40
41     test_nd = false;
42 }
43
44
45 double Core_MathTest::get_success_error_level( int /*test_case_idx*/, int i, int j )
46 {
47     return test_mat[i][j].depth() == CV_32F ? FLT_EPSILON*128 : DBL_EPSILON*1024;
48 }
49
50
51 void Core_MathTest::get_test_array_types_and_sizes( int test_case_idx,
52                                                      vector<vector<Size> >& sizes,
53                                                      vector<vector<int> >& types)
54 {
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);
58     size_t i, j;
59     Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
60
61     for( i = 0; i < test_array.size(); i++ )
62     {
63         size_t count = test_array[i].size();
64         for( j = 0; j < count; j++ )
65             types[i][j] = type;
66     }
67     test_nd = cvtest::randInt(rng)%3 == 0;
68 }
69
70
71 ////////// pow /////////////
72
73 class Core_PowTest : public Core_MathTest
74 {
75 public:
76     typedef Core_MathTest Base;
77     Core_PowTest();
78 protected:
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 );
83     void run_func();
84     void prepare_to_validation( int test_case_idx );
85     double get_success_error_level( int test_case_idx, int i, int j );
86     double power;
87 };
88
89
90 Core_PowTest::Core_PowTest()
91 {
92     power = 0;
93 }
94
95
96 void Core_PowTest::get_test_array_types_and_sizes( int test_case_idx,
97                                                     vector<vector<Size> >& sizes,
98                                                     vector<vector<int> >& types )
99 {
100     RNG& rng = ts->get_rng();
101     int depth = cvtest::randInt(rng) % (CV_64F+1);
102     int cn = cvtest::randInt(rng) % 4 + 1;
103     size_t i, j;
104     Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
105     depth += depth == CV_8S;
106
107     if( depth < CV_32F || cvtest::randInt(rng)%8 == 0 )
108         // integer power
109         power = (int)(cvtest::randInt(rng)%21 - 10);
110     else
111     {
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;
114     }
115
116     for( i = 0; i < test_array.size(); i++ )
117     {
118         size_t count = test_array[i].size();
119         int type = CV_MAKETYPE(depth, cn);
120         for( j = 0; j < count; j++ )
121             types[i][j] = type;
122     }
123     test_nd = cvtest::randInt(rng)%3 == 0;
124 }
125
126
127 double Core_PowTest::get_success_error_level( int test_case_idx, int i, int j )
128 {
129     int depth = test_mat[i][j].depth();
130     if( depth < CV_32F )
131         return power == cvRound(power) && power >= 0 ? 0 : 1;
132     else
133         return Base::get_success_error_level( test_case_idx, i, j );
134 }
135
136
137 void Core_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, Scalar& low, Scalar& high )
138 {
139     double l, u = cvtest::randInt(ts->get_rng())%1000 + 1;
140     if( power > 0 )
141     {
142         double mval = cvtest::getMaxVal(type);
143         double u1 = pow(mval,1./power)*2;
144         u = MIN(u,u1);
145     }
146
147     l = power == cvRound(power) ? -u : FLT_EPSILON;
148     low = Scalar::all(l);
149     high = Scalar::all(u);
150 }
151
152
153 void Core_PowTest::run_func()
154 {
155     if(!test_nd)
156     {
157         if( fabs(power-1./3) <= DBL_EPSILON && test_mat[INPUT][0].depth() == CV_32F )
158         {
159             Mat a = test_mat[INPUT][0], b = test_mat[OUTPUT][0];
160
161             a = a.reshape(1);
162             b = b.reshape(1);
163             for( int i = 0; i < a.rows; i++ )
164             {
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)));
168             }
169         }
170         else
171             cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
172     }
173     else
174     {
175         Mat& a = test_mat[INPUT][0];
176         Mat& b = test_mat[OUTPUT][0];
177         if(power == 0.5)
178             cv::sqrt(a, b);
179         else
180             cv::pow(a, power, b);
181     }
182 }
183
184
185 inline static int ipow( int a, int power )
186 {
187     int b = 1;
188     while( power > 0 )
189     {
190         if( power&1 )
191             b *= a, power--;
192         else
193             a *= a, power >>= 1;
194     }
195     return b;
196 }
197
198
199 inline static double ipow( double a, int power )
200 {
201     double b = 1.;
202     while( power > 0 )
203     {
204         if( power&1 )
205             b *= a, power--;
206         else
207             a *= a, power >>= 1;
208     }
209     return b;
210 }
211
212
213 void Core_PowTest::prepare_to_validation( int /*test_case_idx*/ )
214 {
215     const Mat& a = test_mat[INPUT][0];
216     Mat& b = test_mat[REF_OUTPUT][0];
217
218     int depth = a.depth();
219     int ncols = a.cols*a.channels();
220     int ipower = cvRound(power), apower = abs(ipower);
221     int i, j;
222
223     for( i = 0; i < a.rows; i++ )
224     {
225         const uchar* a_data = a.ptr(i);
226         uchar* b_data = b.ptr(i);
227
228         switch( depth )
229         {
230             case CV_8U:
231                 if( ipower < 0 )
232                     for( j = 0; j < ncols; j++ )
233                     {
234                         int val = ((uchar*)a_data)[j];
235                         ((uchar*)b_data)[j] = (uchar)(val <= 1 ? val :
236                                                       val == 2 && ipower == -1 ? 1 : 0);
237                     }
238                 else
239                     for( j = 0; j < ncols; j++ )
240                     {
241                         int val = ((uchar*)a_data)[j];
242                         val = ipow( val, ipower );
243                         ((uchar*)b_data)[j] = saturate_cast<uchar>(val);
244                     }
245                 break;
246             case CV_8S:
247                 if( ipower < 0 )
248                     for( j = 0; j < ncols; j++ )
249                     {
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);
254                     }
255                 else
256                     for( j = 0; j < ncols; j++ )
257                     {
258                         int val = ((char*)a_data)[j];
259                         val = ipow( val, ipower );
260                         ((char*)b_data)[j] = saturate_cast<schar>(val);
261                     }
262                 break;
263             case CV_16U:
264                 if( ipower < 0 )
265                     for( j = 0; j < ncols; j++ )
266                     {
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);
271                     }
272                 else
273                     for( j = 0; j < ncols; j++ )
274                     {
275                         int val = ((ushort*)a_data)[j];
276                         val = ipow( val, ipower );
277                         ((ushort*)b_data)[j] = saturate_cast<ushort>(val);
278                     }
279                 break;
280             case CV_16S:
281                 if( ipower < 0 )
282                     for( j = 0; j < ncols; j++ )
283                     {
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);
288                     }
289                 else
290                     for( j = 0; j < ncols; j++ )
291                     {
292                         int val = ((short*)a_data)[j];
293                         val = ipow( val, ipower );
294                         ((short*)b_data)[j] = saturate_cast<short>(val);
295                     }
296                 break;
297             case CV_32S:
298                 if( ipower < 0 )
299                     for( j = 0; j < ncols; j++ )
300                     {
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;
305                     }
306                 else
307                     for( j = 0; j < ncols; j++ )
308                     {
309                         int val = ((int*)a_data)[j];
310                         val = ipow( val, ipower );
311                         ((int*)b_data)[j] = val;
312                     }
313                 break;
314             case CV_32F:
315                 if( power != ipower )
316                     for( j = 0; j < ncols; j++ )
317                     {
318                         double val = ((float*)a_data)[j];
319                         val = pow( fabs(val), power );
320                         ((float*)b_data)[j] = (float)val;
321                     }
322                 else
323                     for( j = 0; j < ncols; j++ )
324                     {
325                         double val = ((float*)a_data)[j];
326                         if( ipower < 0 )
327                             val = 1./val;
328                         val = ipow( val, apower );
329                         ((float*)b_data)[j] = (float)val;
330                     }
331                 break;
332             case CV_64F:
333                 if( power != ipower )
334                     for( j = 0; j < ncols; j++ )
335                     {
336                         double val = ((double*)a_data)[j];
337                         val = pow( fabs(val), power );
338                         ((double*)b_data)[j] = (double)val;
339                     }
340                 else
341                     for( j = 0; j < ncols; j++ )
342                     {
343                         double val = ((double*)a_data)[j];
344                         if( ipower < 0 )
345                             val = 1./val;
346                         val = ipow( val, apower );
347                         ((double*)b_data)[j] = (double)val;
348                     }
349                 break;
350         }
351     }
352 }
353
354
355
356 ///////////////////////////////////////// matrix tests ////////////////////////////////////////////
357
358 class Core_MatrixTest : public cvtest::ArrayTest
359 {
360 public:
361     typedef cvtest::ArrayTest Base;
362     Core_MatrixTest( int in_count, int out_count,
363                        bool allow_int, bool scalar_output, int max_cn );
364 protected:
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 );
369     bool allow_int;
370     bool scalar_output;
371     int max_cn;
372 };
373
374
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)
378 {
379     int i;
380     for( i = 0; i < in_count; i++ )
381         test_array[INPUT].push_back(NULL);
382
383     for( i = 0; i < out_count; i++ )
384     {
385         test_array[OUTPUT].push_back(NULL);
386         test_array[REF_OUTPUT].push_back(NULL);
387     }
388
389     element_wise_relative_error = false;
390 }
391
392
393 void Core_MatrixTest::get_test_array_types_and_sizes( int test_case_idx,
394                                                        vector<vector<Size> >& sizes,
395                                                        vector<vector<int> >& types )
396 {
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;
400     size_t i, j;
401
402     if( allow_int )
403         depth += depth == CV_8S;
404     else
405         depth += CV_32F;
406
407     Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
408
409     for( i = 0; i < test_array.size(); i++ )
410     {
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;
414
415         for( j = 0; j < count; j++ )
416         {
417             types[i][j] = type;
418             if( flag )
419                 sizes[i][j] = Size( 4, 1 );
420         }
421     }
422 }
423
424
425 double Core_MatrixTest::get_success_error_level( int test_case_idx, int i, int j )
426 {
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);
431 }
432
433
434 ///////////////// Trace /////////////////////
435
436 class Core_TraceTest : public Core_MatrixTest
437 {
438 public:
439     Core_TraceTest();
440 protected:
441     void run_func();
442     void prepare_to_validation( int test_case_idx );
443 };
444
445
446 Core_TraceTest::Core_TraceTest() : Core_MatrixTest( 1, 1, true, true, 4 )
447 {
448 }
449
450
451 void Core_TraceTest::run_func()
452 {
453     test_mat[OUTPUT][0].at<Scalar>(0,0) = cvTrace(test_array[INPUT][0]);
454 }
455
456
457 void Core_TraceTest::prepare_to_validation( int )
458 {
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);
463     r *= (double)count;
464
465     test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = r;
466 }
467
468
469 ///////// dotproduct //////////
470
471 class Core_DotProductTest : public Core_MatrixTest
472 {
473 public:
474     Core_DotProductTest();
475 protected:
476     void run_func();
477     void prepare_to_validation( int test_case_idx );
478 };
479
480
481 Core_DotProductTest::Core_DotProductTest() : Core_MatrixTest( 2, 1, true, true, 4 )
482 {
483 }
484
485
486 void Core_DotProductTest::run_func()
487 {
488     test_mat[OUTPUT][0].at<Scalar>(0,0) = Scalar(cvDotProduct( test_array[INPUT][0], test_array[INPUT][1] ));
489 }
490
491
492 void Core_DotProductTest::prepare_to_validation( int )
493 {
494     test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = Scalar(cvtest::crossCorr( test_mat[INPUT][0], test_mat[INPUT][1] ));
495 }
496
497
498 ///////// crossproduct //////////
499
500 class Core_CrossProductTest : public Core_MatrixTest
501 {
502 public:
503     Core_CrossProductTest();
504 protected:
505     void get_test_array_types_and_sizes( int test_case_idx,
506                                         vector<vector<Size> >& sizes,
507                                         vector<vector<int> >& types );
508     void run_func();
509     void prepare_to_validation( int test_case_idx );
510 };
511
512
513 Core_CrossProductTest::Core_CrossProductTest() : Core_MatrixTest( 2, 1, false, false, 1 )
514 {
515 }
516
517
518 void Core_CrossProductTest::get_test_array_types_and_sizes( int,
519                                                              vector<vector<Size> >& sizes,
520                                                              vector<vector<int> >& types )
521 {
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);
525     CvSize sz;
526
527     types[INPUT][0] = types[INPUT][1] = types[OUTPUT][0] = types[REF_OUTPUT][0] = type;
528
529     if( cn == 3 )
530         sz = Size(1,1);
531     else if( cvtest::randInt(rng) & 1 )
532         sz = Size(3,1);
533     else
534         sz = Size(1,3);
535
536     sizes[INPUT][0] = sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
537 }
538
539
540 void Core_CrossProductTest::run_func()
541 {
542     cvCrossProduct( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
543 }
544
545
546 void Core_CrossProductTest::prepare_to_validation( int )
547 {
548     CvScalar a(0), b(0), c(0);
549
550     if( test_mat[INPUT][0].rows > 1 )
551     {
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 );
555
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 );
559     }
560     else if( test_mat[INPUT][0].cols > 1 )
561     {
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 );
565
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 );
569     }
570     else
571     {
572         a = cvGet1D( test_array[INPUT][0], 0 );
573         b = cvGet1D( test_array[INPUT][1], 0 );
574     }
575
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];
579
580     if( test_mat[REF_OUTPUT][0].rows > 1 )
581     {
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] );
585     }
586     else if( test_mat[REF_OUTPUT][0].cols > 1 )
587     {
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] );
591     }
592     else
593     {
594         cvSet1D( test_array[REF_OUTPUT][0], 0, c );
595     }
596 }
597
598
599 ///////////////// gemm /////////////////////
600
601 class Core_GEMMTest : public Core_MatrixTest
602 {
603 public:
604     typedef Core_MatrixTest Base;
605     Core_GEMMTest();
606 protected:
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 );
610     void run_func();
611     void prepare_to_validation( int test_case_idx );
612     int tabc_flag;
613     double alpha, beta;
614 };
615
616 Core_GEMMTest::Core_GEMMTest() : Core_MatrixTest( 5, 1, false, false, 2 )
617 {
618     test_case_count = 100;
619     max_log_array_size = 10;
620     tabc_flag = 0;
621     alpha = beta = 0;
622 }
623
624
625 void Core_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
626 {
627     RNG& rng = ts->get_rng();
628     Size sizeA;
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;
635
636     tabc_flag = cvtest::randInt(rng) & 7;
637
638     switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
639     {
640         case 0:
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;
644             break;
645         case CV_GEMM_B_T:
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;
649             break;
650         case CV_GEMM_A_T:
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;
654             break;
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;
659             break;
660     }
661
662     sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
663
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];
668     else
669     {
670         sizes[INPUT][4].width = sizes[OUTPUT][0].height;
671         sizes[INPUT][4].height = sizes[OUTPUT][0].width;
672     }
673 }
674
675
676 int Core_GEMMTest::prepare_test_case( int test_case_idx )
677 {
678     int code = Base::prepare_test_case( test_case_idx );
679     if( code > 0 )
680     {
681         alpha = cvGetReal2D( test_array[INPUT][2], 0, 0 );
682         beta = cvGetReal2D( test_array[INPUT][3], 0, 0 );
683     }
684     return code;
685 }
686
687
688 void Core_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
689 {
690     low = Scalar::all(-10.);
691     high = Scalar::all(10.);
692 }
693
694
695 void Core_GEMMTest::run_func()
696 {
697     cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
698            test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
699 }
700
701
702 void Core_GEMMTest::prepare_to_validation( int )
703 {
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 );
707 }
708
709
710 ///////////////// multransposed /////////////////////
711
712 class Core_MulTransposedTest : public Core_MatrixTest
713 {
714 public:
715     Core_MulTransposedTest();
716 protected:
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 );
719     void run_func();
720     void prepare_to_validation( int test_case_idx );
721     int order;
722 };
723
724
725 Core_MulTransposedTest::Core_MulTransposedTest() : Core_MatrixTest( 2, 1, false, false, 1 )
726 {
727     test_case_count = 100;
728     order = 0;
729     test_array[TEMP].push_back(NULL);
730 }
731
732
733 void Core_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
734 {
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;
739
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 );
744
745     Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
746
747     if( bits & 1 )
748         sizes[INPUT][1] = Size(0,0);
749     else
750     {
751         sizes[INPUT][1] = sizes[INPUT][0];
752         if( bits & 2 )
753             sizes[INPUT][1].height = 1;
754         if( bits & 4 )
755             sizes[INPUT][1].width = 1;
756     }
757
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;
761
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];
766 }
767
768
769 void Core_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
770 {
771     low = cvScalarAll(-10.);
772     high = cvScalarAll(10.);
773 }
774
775
776 void Core_MulTransposedTest::run_func()
777 {
778     cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
779                     order, test_array[INPUT][1] );
780 }
781
782
783 void Core_MulTransposedTest::prepare_to_validation( int )
784 {
785     const Mat& src = test_mat[INPUT][0];
786     Mat delta = test_mat[INPUT][1];
787     Mat& temp = test_mat[TEMP][0];
788     if( !delta.empty() )
789     {
790         if( delta.rows < src.rows || delta.cols < src.cols )
791         {
792             cv::repeat( delta, src.rows/delta.rows, src.cols/delta.cols, temp);
793             delta = temp;
794         }
795         cvtest::add( src, 1, delta, -1, Scalar::all(0), temp, temp.type());
796     }
797     else
798         src.convertTo(temp, temp.type());
799
800     cvtest::gemm( temp, temp, 1., Mat(), 0, test_mat[REF_OUTPUT][0], order == 0 ? GEMM_2_T : GEMM_1_T );
801 }
802
803
804 ///////////////// Transform /////////////////////
805
806 class Core_TransformTest : public Core_MatrixTest
807 {
808 public:
809     typedef Core_MatrixTest Base;
810     Core_TransformTest();
811 protected:
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 );
815     void run_func();
816     void prepare_to_validation( int test_case_idx );
817
818     double scale;
819     bool diagMtx;
820 };
821
822
823 Core_TransformTest::Core_TransformTest() : Core_MatrixTest( 3, 1, true, false, 4 )
824 {
825     scale = 1;
826     diagMtx = false;
827 }
828
829
830 void Core_TransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
831 {
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 );
836
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);
841
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);
845
846     scale = 1./((cvtest::randInt(rng)%4)*50+1);
847
848     if( bits & 2 )
849     {
850         sizes[INPUT][2] = Size(0,0);
851         mat_cols += (bits & 4) != 0;
852     }
853     else if( bits & 4 )
854         sizes[INPUT][2] = Size(1,1);
855     else
856     {
857         if( bits & 8 )
858             sizes[INPUT][2] = Size(dst_cn,1);
859         else
860             sizes[INPUT][2] = Size(1,dst_cn);
861         types[INPUT][2] &= ~CV_MAT_CN_MASK;
862     }
863     diagMtx = (bits & 16) != 0;
864
865     sizes[INPUT][1] = Size(mat_cols,dst_cn);
866 }
867
868
869 int Core_TransformTest::prepare_test_case( int test_case_idx )
870 {
871     int code = Base::prepare_test_case( test_case_idx );
872     if( code > 0 )
873     {
874         Mat& m = test_mat[INPUT][1];
875         cvtest::add(m, scale, m, 0, Scalar::all(0), m, m.type() );
876         if(diagMtx)
877         {
878             Mat mask = Mat::eye(m.rows, m.cols, CV_8U)*255;
879             mask = ~mask;
880             m.setTo(Scalar::all(0), mask);
881         }
882     }
883     return code;
884 }
885
886
887 double Core_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
888 {
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 );
891 }
892
893 void Core_TransformTest::run_func()
894 {
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);
897 }
898
899
900 void Core_TransformTest::prepare_to_validation( int )
901 {
902     Mat transmat = test_mat[INPUT][1];
903     Mat shift = test_mat[INPUT][2];
904
905     cvtest::transform( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], transmat, shift );
906 }
907
908
909 ///////////////// PerspectiveTransform /////////////////////
910
911 class Core_PerspectiveTransformTest : public Core_MatrixTest
912 {
913 public:
914     Core_PerspectiveTransformTest();
915 protected:
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 );
918     void run_func();
919     void prepare_to_validation( int test_case_idx );
920 };
921
922
923 Core_PerspectiveTransformTest::Core_PerspectiveTransformTest() : Core_MatrixTest( 2, 1, false, false, 2 )
924 {
925 }
926
927
928 void Core_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
929 {
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 );
934
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);
938
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);
942 }
943
944
945 double Core_PerspectiveTransformTest::get_success_error_level( int test_case_idx, int i, int j )
946 {
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);
950 }
951
952
953 void Core_PerspectiveTransformTest::run_func()
954 {
955     CvMat _m = test_mat[INPUT][1];
956     cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &_m );
957 }
958
959
960 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
961 {
962     int i, j, cols;
963     int cn, depth, mat_depth;
964     CvMat astub, bstub, *a, *b;
965     double mat[16];
966
967     a = cvGetMat( _src, &astub, 0, 0 );
968     b = cvGetMat( _dst, &bstub, 0, 0 );
969
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;
974
975     // prepare cn x (cn + 1) transform matrix
976     if( mat_depth == CV_32F )
977     {
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];
981     }
982     else
983     {
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];
988     }
989
990     // transform data
991     cols = a->cols * cn;
992     vector<double> buf(cols);
993
994     for( i = 0; i < a->rows; i++ )
995     {
996         uchar* src = a->data.ptr + i*a->step;
997         uchar* dst = b->data.ptr + i*b->step;
998
999         switch( depth )
1000         {
1001             case CV_32F:
1002                 for( j = 0; j < cols; j++ )
1003                     buf[j] = ((float*)src)[j];
1004                 break;
1005             case CV_64F:
1006                 for( j = 0; j < cols; j++ )
1007                     buf[j] = ((double*)src)[j];
1008                 break;
1009             default:
1010                 assert(0);
1011         }
1012
1013         switch( cn )
1014         {
1015             case 2:
1016                 for( j = 0; j < cols; j += 2 )
1017                 {
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];
1021                     w = w ? 1./w : 0;
1022                     buf[j] = t0*w;
1023                     buf[j+1] = t1*w;
1024                 }
1025                 break;
1026             case 3:
1027                 for( j = 0; j < cols; j += 3 )
1028                 {
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];
1033                     w = w ? 1./w : 0;
1034                     buf[j] = t0*w;
1035                     buf[j+1] = t1*w;
1036                     buf[j+2] = t2*w;
1037                 }
1038                 break;
1039             default:
1040                 assert(0);
1041         }
1042
1043         switch( depth )
1044         {
1045             case CV_32F:
1046                 for( j = 0; j < cols; j++ )
1047                     ((float*)dst)[j] = (float)buf[j];
1048                 break;
1049             case CV_64F:
1050                 for( j = 0; j < cols; j++ )
1051                     ((double*)dst)[j] = buf[j];
1052                 break;
1053             default:
1054                 assert(0);
1055         }
1056     }
1057 }
1058
1059
1060 void Core_PerspectiveTransformTest::prepare_to_validation( int )
1061 {
1062     CvMat transmat = test_mat[INPUT][1];
1063     cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], &transmat );
1064 }
1065
1066 ///////////////// Mahalanobis /////////////////////
1067
1068 class Core_MahalanobisTest : public Core_MatrixTest
1069 {
1070 public:
1071     typedef Core_MatrixTest Base;
1072     Core_MahalanobisTest();
1073 protected:
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 );
1076     void run_func();
1077     void prepare_to_validation( int test_case_idx );
1078 };
1079
1080
1081 Core_MahalanobisTest::Core_MahalanobisTest() : Core_MatrixTest( 3, 1, false, true, 1 )
1082 {
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);
1087 }
1088
1089
1090 void Core_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1091 {
1092     RNG& rng = ts->get_rng();
1093     Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1094
1095     if( cvtest::randInt(rng) & 1 )
1096         sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
1097     else
1098         sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
1099
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];
1104 }
1105
1106 int Core_MahalanobisTest::prepare_test_case( int test_case_idx )
1107 {
1108     int code = Base::prepare_test_case( test_case_idx );
1109     if( code > 0 )
1110     {
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] );
1114     }
1115
1116     return code;
1117 }
1118
1119
1120 void Core_MahalanobisTest::run_func()
1121 {
1122     test_mat[OUTPUT][0].at<Scalar>(0,0) =
1123     cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
1124 }
1125
1126 void Core_MahalanobisTest::prepare_to_validation( int )
1127 {
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 );
1133     else
1134         cvtest::gemm( test_mat[INPUT][2], test_mat[TEMP][0], 1.,
1135                  Mat(), 0., test_mat[TEMP][1], 0 );
1136
1137     test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(sqrt(cvtest::crossCorr(test_mat[TEMP][0], test_mat[TEMP][1])));
1138 }
1139
1140
1141 ///////////////// covarmatrix /////////////////////
1142
1143 class Core_CovarMatrixTest : public Core_MatrixTest
1144 {
1145 public:
1146     Core_CovarMatrixTest();
1147 protected:
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 );
1150     void run_func();
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;
1155     bool are_images;
1156 };
1157
1158
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)
1161 {
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);
1167 }
1168
1169
1170 void Core_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1171 {
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 );
1176
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;
1180
1181     const int min_count = 2;
1182
1183     if( !t_flag )
1184     {
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);
1189     }
1190     else
1191     {
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);
1196     }
1197
1198     if( single_matrix && t_flag )
1199         flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
1200
1201     if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
1202         types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
1203
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];
1207
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;
1211
1212     are_images = (bits & 1024) != 0;
1213     for( i = 0; i < (single_matrix ? 1 : count); i++ )
1214         temp_hdrs.push_back(NULL);
1215 }
1216
1217
1218 int Core_CovarMatrixTest::prepare_test_case( int test_case_idx )
1219 {
1220     int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1221     if( code > 0 )
1222     {
1223         int i;
1224         int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
1225         int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
1226
1227         hdr_data.resize(count*hdr_size);
1228         uchar* _hdr_data = &hdr_data[0];
1229         if( single_matrix )
1230         {
1231             if( !are_images )
1232                 *((CvMat*)_hdr_data) = test_mat[INPUT][0];
1233             else
1234                 *((IplImage*)_hdr_data) = test_mat[INPUT][0];
1235             temp_hdrs[0] = _hdr_data;
1236         }
1237         else
1238             for( i = 0; i < count; i++ )
1239             {
1240                 Mat part;
1241                 void* ptr = _hdr_data + i*hdr_size;
1242
1243                 if( !t_flag )
1244                     part = test_mat[INPUT][0].row(i);
1245                 else
1246                     part = test_mat[INPUT][0].col(i);
1247
1248                 if( !are_images )
1249                     *((CvMat*)ptr) = part;
1250                 else
1251                     *((IplImage*)ptr) = part;
1252
1253                 temp_hdrs[i] = ptr;
1254             }
1255     }
1256
1257     return code;
1258 }
1259
1260
1261 void Core_CovarMatrixTest::run_func()
1262 {
1263     cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
1264                       test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
1265 }
1266
1267
1268 void Core_CovarMatrixTest::prepare_to_validation( int )
1269 {
1270     Mat& avg = test_mat[REF_INPUT_OUTPUT][0];
1271     double scale = 1.;
1272
1273     if( !(flags & CV_COVAR_USE_AVG) )
1274     {
1275         Mat hdrs0 = cvarrToMat(temp_hdrs[0]);
1276
1277         int i;
1278         avg = Scalar::all(0);
1279
1280         for( i = 0; i < count; i++ )
1281         {
1282             Mat vec;
1283             if( flags & CV_COVAR_ROWS )
1284                 vec = hdrs0.row(i);
1285             else if( flags & CV_COVAR_COLS )
1286                 vec = hdrs0.col(i);
1287             else
1288                 vec = cvarrToMat(temp_hdrs[i]);
1289
1290             cvtest::add(avg, 1, vec, 1, Scalar::all(0), avg, avg.type());
1291         }
1292
1293         cvtest::add(avg, 1./count, avg, 0., Scalar::all(0), avg, avg.type());
1294     }
1295
1296     if( flags & CV_COVAR_SCALE )
1297     {
1298         scale = 1./count;
1299     }
1300
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());
1304
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 );
1307     temp_hdrs.clear();
1308 }
1309
1310
1311 static void cvTsFloodWithZeros( Mat& mat, RNG& rng )
1312 {
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 );
1316
1317     for( k = 0; k < zero_total; k++ )
1318     {
1319         int i = cvtest::randInt(rng) % mat.rows;
1320         int j = cvtest::randInt(rng) % mat.cols;
1321
1322         if( type == CV_32FC1 )
1323             mat.at<float>(i,j) = 0.f;
1324         else
1325             mat.at<double>(i,j) = 0.;
1326     }
1327 }
1328
1329
1330 ///////////////// determinant /////////////////////
1331
1332 class Core_DetTest : public Core_MatrixTest
1333 {
1334 public:
1335     typedef Core_MatrixTest Base;
1336     Core_DetTest();
1337 protected:
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 );
1342     void run_func();
1343     void prepare_to_validation( int test_case_idx );
1344 };
1345
1346
1347 Core_DetTest::Core_DetTest() : Core_MatrixTest( 1, 1, false, true, 1 )
1348 {
1349     test_case_count = 100;
1350     max_log_array_size = 7;
1351     test_array[TEMP].push_back(NULL);
1352 }
1353
1354
1355 void Core_DetTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1356 {
1357     Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1358
1359     sizes[INPUT][0].width = sizes[INPUT][0].height;
1360     sizes[TEMP][0] = sizes[INPUT][0];
1361     types[TEMP][0] = CV_64FC1;
1362 }
1363
1364
1365 void Core_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1366 {
1367     low = cvScalarAll(-2.);
1368     high = cvScalarAll(2.);
1369 }
1370
1371
1372 double Core_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1373 {
1374     return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
1375 }
1376
1377
1378 int Core_DetTest::prepare_test_case( int test_case_idx )
1379 {
1380     int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1381     if( code > 0 )
1382         cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() );
1383
1384     return code;
1385 }
1386
1387
1388 void Core_DetTest::run_func()
1389 {
1390     test_mat[OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(cvDet(test_array[INPUT][0]));
1391 }
1392
1393
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 )
1396 {
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;
1402     double t, det = 1.;
1403     assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
1404            (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
1405
1406     for( i = 0; i < Nm; i++ )
1407     {
1408         double max_val = fabs(a0[i*step + i]);
1409         double *a1, *a2, *b1 = 0, *b2 = 0;
1410         k = i;
1411
1412         for( j = i+1; j < N; j++ )
1413         {
1414             t = fabs(a0[j*step + i]);
1415             if( max_val < t )
1416             {
1417                 max_val = t;
1418                 k = j;
1419             }
1420         }
1421
1422         if( k != i )
1423         {
1424             for( j = i; j < N1; j++ )
1425                 CV_SWAP( a0[i*step + j], a0[k*step + j], t );
1426
1427             for( j = 0; j < M; j++ )
1428                 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
1429             det = -det;
1430         }
1431
1432         if( max_val == 0 )
1433         {
1434             if( rank )
1435                 *rank = i;
1436             return 0.;
1437         }
1438
1439         a1 = a0 + i*step;
1440         a2 = a1 + step;
1441         b1 = b0 + i*b_step;
1442         b2 = b1 + b_step;
1443
1444         for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
1445         {
1446             t = a2[i]/a1[i];
1447             for( k = i+1; k < N1; k++ )
1448                 a2[k] -= t*a1[k];
1449
1450             for( k = 0; k < M; k++ )
1451                 b2[k] -= t*b1[k];
1452         }
1453
1454         det *= a1[i];
1455     }
1456
1457     if( x )
1458     {
1459         assert( b );
1460
1461         for( i = N-1; i >= 0; i-- )
1462         {
1463             double* a1 = a0 + i*step;
1464             double* b1 = b0 + i*b_step;
1465             for( j = 0; j < M; j++ )
1466             {
1467                 t = b1[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];
1471             }
1472         }
1473     }
1474
1475     if( rank )
1476         *rank = i;
1477     return det;
1478 }
1479
1480
1481 void Core_DetTest::prepare_to_validation( int )
1482 {
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));
1486 }
1487
1488
1489 ///////////////// invert /////////////////////
1490
1491 class Core_InvertTest : public Core_MatrixTest
1492 {
1493 public:
1494     typedef Core_MatrixTest Base;
1495     Core_InvertTest();
1496 protected:
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 );
1501     void run_func();
1502     void prepare_to_validation( int test_case_idx );
1503     int method, rank;
1504     double result;
1505 };
1506
1507
1508 Core_InvertTest::Core_InvertTest()
1509 : Core_MatrixTest( 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
1510 {
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);
1515 }
1516
1517
1518 void Core_InvertTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1519 {
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 );
1524
1525     if( (bits & 3) == 0 )
1526     {
1527         method = CV_SVD;
1528         if( bits & 4 )
1529         {
1530             sizes[INPUT][0] = Size(min_size, min_size);
1531             if( bits & 16 )
1532                 method = CV_CHOLESKY;
1533         }
1534     }
1535     else
1536     {
1537         method = CV_LU;
1538         sizes[INPUT][0] = Size(min_size, min_size);
1539     }
1540
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);
1547 }
1548
1549
1550 double Core_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
1551 {
1552     return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-6;
1553 }
1554
1555 int Core_InvertTest::prepare_test_case( int test_case_idx )
1556 {
1557     int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1558     if( code > 0 )
1559     {
1560         cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() );
1561
1562         if( method == CV_CHOLESKY )
1563         {
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] );
1567         }
1568     }
1569
1570     return code;
1571 }
1572
1573
1574
1575 void Core_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1576 {
1577     low = cvScalarAll(-1.);
1578     high = cvScalarAll(1.);
1579 }
1580
1581
1582 void Core_InvertTest::run_func()
1583 {
1584     result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
1585 }
1586
1587
1588 static double cvTsSVDet( CvMat* mat, double* ratio )
1589 {
1590     int type = CV_MAT_TYPE(mat->type);
1591     int i, nm = MIN( mat->rows, mat->cols );
1592     CvMat* w = cvCreateMat( nm, 1, type );
1593     double det = 1.;
1594
1595     cvSVD( mat, w, 0, 0, 0 );
1596
1597     if( type == CV_32FC1 )
1598     {
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];
1602     }
1603     else
1604     {
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];
1608     }
1609
1610     cvReleaseMat( &w );
1611     return det;
1612 }
1613
1614 void Core_InvertTest::prepare_to_validation( int )
1615 {
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;
1624
1625     cvtest::convert( input, temp1, temp1.type() );
1626
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) )
1630     {
1631         dst = Scalar::all(0);
1632         dst0 = Scalar::all(0);
1633         return;
1634     }
1635
1636     if( input.rows >= input.cols )
1637         cvtest::gemm( temp0, input, 1., Mat(), 0., dst, 0 );
1638     else
1639         cvtest::gemm( input, temp0, 1., Mat(), 0., dst, 0 );
1640
1641     cv::setIdentity( dst0, Scalar::all(1) );
1642 }
1643
1644
1645 ///////////////// solve /////////////////////
1646
1647 class Core_SolveTest : public Core_MatrixTest
1648 {
1649 public:
1650     typedef Core_MatrixTest Base;
1651     Core_SolveTest();
1652 protected:
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 );
1657     void run_func();
1658     void prepare_to_validation( int test_case_idx );
1659     int method, rank;
1660     double result;
1661 };
1662
1663
1664 Core_SolveTest::Core_SolveTest() : Core_MatrixTest( 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
1665 {
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);
1670 }
1671
1672
1673 void Core_SolveTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1674 {
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 );
1684
1685     if( (bits & 3) == 0 )
1686     {
1687         method = CV_SVD;
1688         if( bits & 4 )
1689         {
1690             sizes[INPUT][0] = Size(min_size, min_size);
1691             /*if( bits & 8 )
1692              method = CV_SVD_SYM;*/
1693         }
1694     }
1695     else
1696     {
1697         method = CV_LU;
1698         sizes[INPUT][0] = Size(min_size, min_size);
1699     }
1700
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);
1708 }
1709
1710
1711 int Core_SolveTest::prepare_test_case( int test_case_idx )
1712 {
1713     int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1714
1715     /*if( method == CV_SVD_SYM )
1716      {
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] );
1720      }*/
1721
1722     return code;
1723 }
1724
1725
1726 void Core_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1727 {
1728     low = cvScalarAll(-1.);
1729     high = cvScalarAll(1.);
1730 }
1731
1732
1733 double Core_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
1734 {
1735     return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 5e-2 : 1e-8;
1736 }
1737
1738
1739 void Core_SolveTest::run_func()
1740 {
1741     result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
1742 }
1743
1744 void Core_SolveTest::prepare_to_validation( int )
1745 {
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];
1750
1751     if( method == CV_LU )
1752     {
1753         if( result == 0 )
1754         {
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);
1761             return;
1762         }
1763
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 )
1768         {
1769             dst = Scalar::all(0);
1770             dst0 = Scalar::all(0);
1771             return;
1772         }
1773     }
1774
1775     Mat* pdst = input.rows <= input.cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
1776
1777     cvtest::gemm( input, test_mat[TEMP][0], 1., test_mat[INPUT][1], -1., *pdst, 0 );
1778     if( pdst != &dst )
1779         cvtest::gemm( input, *pdst, 1., Mat(), 0., dst, CV_GEMM_A_T );
1780     dst0 = Scalar::all(0);
1781 }
1782
1783
1784 ///////////////// SVD /////////////////////
1785
1786 class Core_SVDTest : public Core_MatrixTest
1787 {
1788 public:
1789     typedef Core_MatrixTest Base;
1790     Core_SVDTest();
1791 protected:
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 );
1796     void run_func();
1797     void prepare_to_validation( int test_case_idx );
1798     int flags;
1799     bool have_u, have_v, symmetric, compact, vector_w;
1800 };
1801
1802
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)
1806 {
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);
1813 }
1814
1815
1816 void Core_SVDTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1817 {
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;
1822
1823     min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
1824
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;
1831
1832     if( symmetric )
1833         sizes[INPUT][0] = Size(min_size, min_size);
1834
1835     m = sizes[INPUT][0].height;
1836     n = sizes[INPUT][0].width;
1837
1838     if( compact )
1839         sizes[TEMP][0] = Size(min_size, min_size);
1840     else
1841         sizes[TEMP][0] = sizes[INPUT][0];
1842     sizes[TEMP][3] = Size(0,0);
1843
1844     if( vector_w )
1845     {
1846         sizes[TEMP][3] = sizes[TEMP][0];
1847         if( bits & 256 )
1848             sizes[TEMP][0] = Size(1, min_size);
1849         else
1850             sizes[TEMP][0] = Size(min_size, 1);
1851     }
1852
1853     if( have_u )
1854     {
1855         sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m);
1856
1857         if( flags & CV_SVD_U_T )
1858             CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
1859     }
1860     else
1861         sizes[TEMP][1] = Size(0,0);
1862
1863     if( have_v )
1864     {
1865         sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n);
1866
1867         if( !(flags & CV_SVD_V_T) )
1868             CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
1869     }
1870     else
1871         sizes[TEMP][2] = Size(0,0);
1872
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);
1880
1881     for( i = 0; i < 4; i++ )
1882     {
1883         sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
1884         types[REF_OUTPUT][i] = types[OUTPUT][i];
1885     }
1886 }
1887
1888
1889 int Core_SVDTest::prepare_test_case( int test_case_idx )
1890 {
1891     int code = Core_MatrixTest::prepare_test_case( test_case_idx );
1892     if( code > 0 )
1893     {
1894         Mat& input = test_mat[INPUT][0];
1895         cvTsFloodWithZeros( input, ts->get_rng() );
1896
1897         if( symmetric && (have_u || have_v) )
1898         {
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 );
1902         }
1903
1904         if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
1905             cvtest::copy( input, test_mat[OUTPUT][0] );
1906     }
1907
1908     return code;
1909 }
1910
1911
1912 void Core_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
1913 {
1914     low = cvScalarAll(-2.);
1915     high = cvScalarAll(2.);
1916 }
1917
1918 double Core_SVDTest::get_success_error_level( int test_case_idx, int i, int j )
1919 {
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);
1924 }
1925
1926 void Core_SVDTest::run_func()
1927 {
1928     CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
1929     if( !src )
1930         src = test_array[INPUT][0];
1931     cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
1932 }
1933
1934
1935 void Core_SVDTest::prepare_to_validation( int /*test_case_idx*/ )
1936 {
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);
1940     Mat *src, *dst, *w;
1941     double prev = 0, threshold = depth == CV_32F ? FLT_EPSILON : DBL_EPSILON;
1942
1943     if( have_u )
1944     {
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.) );
1949     }
1950
1951     if( have_v )
1952     {
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.) );
1957     }
1958
1959     w = &test_mat[TEMP][0];
1960     for( i = 0; i < min_size; i++ )
1961     {
1962         double normval = 0, aii;
1963         if( w->rows > 1 && w->cols > 1 )
1964         {
1965             normval = cvtest::norm( w->row(i), NORM_L1 );
1966             aii = depth == CV_32F ? w->at<float>(i,i) : w->at<double>(i,i);
1967         }
1968         else
1969         {
1970             normval = aii = depth == CV_32F ? w->at<float>(i) : w->at<double>(i);
1971         }
1972
1973         normval = fabs(normval - aii);
1974         test_mat[OUTPUT][3].at<uchar>(i) = aii >= 0 && normval < threshold && (i == 0 || aii <= prev);
1975         prev = aii;
1976     }
1977
1978     test_mat[REF_OUTPUT][3] = Scalar::all(1);
1979
1980     if( have_u && have_v )
1981     {
1982         if( vector_w )
1983         {
1984             test_mat[TEMP][3] = Scalar::all(0);
1985             for( i = 0; i < min_size; i++ )
1986             {
1987                 double val = depth == CV_32F ? w->at<float>(i) : w->at<double>(i);
1988                 cvSetReal2D( test_array[TEMP][3], i, i, val );
1989             }
1990             w = &test_mat[TEMP][3];
1991         }
1992
1993         if( m >= n )
1994         {
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 );
1999         }
2000         else
2001         {
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 );
2006         }
2007
2008         cvtest::copy( test_mat[INPUT][0], test_mat[REF_OUTPUT][0] );
2009     }
2010 }
2011
2012
2013
2014 ///////////////// SVBkSb /////////////////////
2015
2016 class Core_SVBkSbTest : public Core_MatrixTest
2017 {
2018 public:
2019     typedef Core_MatrixTest Base;
2020     Core_SVBkSbTest();
2021 protected:
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 );
2026     void run_func();
2027     void prepare_to_validation( int test_case_idx );
2028     int flags;
2029     bool have_b, symmetric, compact, vector_w;
2030 };
2031
2032
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)
2035 {
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);
2040 }
2041
2042
2043 void Core_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes,
2044                                                       vector<vector<int> >& types )
2045 {
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;
2050     CvSize b_size;
2051
2052     min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
2053
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;
2059
2060     if( symmetric )
2061         sizes[INPUT][0] = Size(min_size, min_size);
2062
2063     m = sizes[INPUT][0].height;
2064     n = sizes[INPUT][0].width;
2065
2066     sizes[INPUT][1] = Size(0,0);
2067     b_size = Size(m,m);
2068     if( have_b )
2069     {
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];
2073     }
2074
2075     if( compact )
2076         sizes[TEMP][0] = Size(min_size, min_size);
2077     else
2078         sizes[TEMP][0] = sizes[INPUT][0];
2079
2080     if( vector_w )
2081     {
2082         if( bits & 256 )
2083             sizes[TEMP][0] = Size(1, min_size);
2084         else
2085             sizes[TEMP][0] = Size(min_size, 1);
2086     }
2087
2088     sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m);
2089
2090     if( flags & CV_SVD_U_T )
2091         CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
2092
2093     sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n);
2094
2095     if( !(flags & CV_SVD_V_T) )
2096         CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
2097
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 );
2101 }
2102
2103
2104 int Core_SVBkSbTest::prepare_test_case( int test_case_idx )
2105 {
2106     int code = Base::prepare_test_case( test_case_idx );
2107     if( code > 0 )
2108     {
2109         Mat& input = test_mat[INPUT][0];
2110         cvTsFloodWithZeros( input, ts->get_rng() );
2111
2112         if( symmetric )
2113         {
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 );
2117         }
2118
2119         CvMat _input = input;
2120         cvSVD( &_input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
2121     }
2122
2123     return code;
2124 }
2125
2126
2127 void Core_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
2128 {
2129     low = cvScalarAll(-2.);
2130     high = cvScalarAll(2.);
2131 }
2132
2133
2134 double Core_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
2135 {
2136     return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
2137 }
2138
2139
2140 void Core_SVBkSbTest::run_func()
2141 {
2142     cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
2143              test_array[INPUT][1], test_array[OUTPUT][0], flags );
2144 }
2145
2146
2147 void Core_SVBkSbTest::prepare_to_validation( int )
2148 {
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);
2159
2160     wdb = Scalar::all(0);
2161     for( i = 0; i < min_size; i++ )
2162     {
2163         double wii = vector_w ? cvGetReal1D(&_w,i) : cvGetReal2D(&_w,i,i);
2164         cvSetReal2D( &_wdb, i, i, wii > threshold ? 1./wii : 0. );
2165     }
2166
2167     Mat u = test_mat[TEMP][1];
2168     Mat v = test_mat[TEMP][2];
2169     Mat b = test_mat[INPUT][1];
2170
2171     if( is_float )
2172     {
2173         test_mat[TEMP][1].convertTo(u, CV_64F);
2174         test_mat[TEMP][2].convertTo(v, CV_64F);
2175         if( !b.empty() )
2176             test_mat[INPUT][1].convertTo(b, CV_64F);
2177     }
2178
2179     Mat t0, t1;
2180
2181     if( !b.empty() )
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 );
2185     else
2186         cvtest::transpose( u, t0 );
2187
2188     cvtest::gemm( wdb, t0, 1, Mat(), 0, t1, 0 );
2189
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() );
2193 }
2194
2195
2196 typedef std::complex<double> complex_type;
2197
2198 struct pred_complex
2199 {
2200     bool operator() (const complex_type& lhs, const complex_type& rhs) const
2201     {
2202         return fabs(lhs.real() - rhs.real()) > fabs(rhs.real())*FLT_EPSILON ? lhs.real() < rhs.real() : lhs.imag() < rhs.imag();
2203     }
2204 };
2205
2206 struct pred_double
2207 {
2208     bool operator() (const double& lhs, const double& rhs) const
2209     {
2210         return lhs < rhs;
2211     }
2212 };
2213
2214 class Core_SolvePolyTest : public cvtest::BaseTest
2215 {
2216 public:
2217     Core_SolvePolyTest();
2218     ~Core_SolvePolyTest();
2219 protected:
2220     virtual void run( int start_from );
2221 };
2222
2223 Core_SolvePolyTest::Core_SolvePolyTest() {}
2224
2225 Core_SolvePolyTest::~Core_SolvePolyTest() {}
2226
2227 void Core_SolvePolyTest::run( int )
2228 {
2229     RNG& rng = ts->get_rng();
2230     int fig = 100;
2231     double range = 50;
2232     double err_eps = 1e-4;
2233
2234     for (int idx = 0, max_idx = 1000, progress = 0; idx < max_idx; ++idx)
2235     {
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);
2240
2241         int rr_odds = 3; // odds that we get a real root
2242         for (int j = 0; j < n;)
2243         {
2244             if (cvtest::randInt(rng) % rr_odds == 0 || j == n - 1)
2245                 r[j++] = cvtest::randReal(rng) * range;
2246             else
2247             {
2248                 r[j] = complex_type(cvtest::randReal(rng) * range,
2249                                     cvtest::randReal(rng) * range + 1);
2250                 r[j + 1] = std::conj(r[j]);
2251                 j += 2;
2252             }
2253         }
2254
2255         for (int j = 0, k = 1 << n, jj, kk; j < k; ++j)
2256         {
2257             int p = 0;
2258             complex_type v(1);
2259             for (jj = 0, kk = 1; jj < n && !(j & kk); ++jj, ++p, kk <<= 1)
2260                 ;
2261             for (; jj < n; ++jj, kk <<= 1)
2262             {
2263                 if (j & kk)
2264                     v *= -r[jj];
2265                 else
2266                     ++p;
2267             }
2268             c[p] += v;
2269         }
2270
2271         bool pass = false;
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)
2275         {
2276             for (int j = 0; j < n + 1; ++j)
2277                 a[j] = c[j].real();
2278
2279             CvMat amat, umat;
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);
2283
2284             for (int j = 0; j < n; ++j)
2285                 ar[j] = complex_type(u[j * 2], u[j * 2 + 1]);
2286
2287             std::sort(r.begin(), r.end(), pred_complex());
2288             std::sort(ar.begin(), ar.end(), pred_complex());
2289
2290             pass = true;
2291             if( n == 3 )
2292             {
2293                 ar2.resize(n);
2294                 cv::Mat _umat2(3, 1, CV_64F, &ar2[0]), umat2 = _umat2;
2295                 cvFlip(&amat, &amat, 0);
2296                 int nr2;
2297                 if( cubic_case == 0 )
2298                     nr2 = cv::solveCubic(cv::cvarrToMat(&amat),umat2);
2299                 else
2300                     nr2 = cv::solveCubic(cv::Mat_<float>(cv::cvarrToMat(&amat)), umat2);
2301                 cvFlip(&amat, &amat, 0);
2302                 if(nr2 > 0)
2303                     std::sort(ar2.begin(), ar2.begin()+nr2, pred_double());
2304                 ar2.resize(nr2);
2305
2306                 int nr1 = 0;
2307                 for(int j = 0; j < n; j++)
2308                     if( fabs(r[j].imag()) < DBL_EPSILON )
2309                         ar1[nr1++] = r[j].real();
2310
2311                 pass = pass && nr1 == nr2;
2312                 if( nr2 > 0 )
2313                 {
2314                     div = s = 0;
2315                     for(int j = 0; j < nr1; j++)
2316                     {
2317                         s += fabs(ar1[j]);
2318                         div += fabs(ar1[j] - ar2[j]);
2319                     }
2320                     div /= s;
2321                     pass = pass && div < err_eps;
2322                 }
2323             }
2324
2325             div = s = 0;
2326             for (int j = 0; j < n; ++j)
2327             {
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));
2330             }
2331             div /= s;
2332             pass = pass && div < err_eps;
2333         }
2334
2335         if (!pass)
2336         {
2337             ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
2338             ts->printf( cvtest::TS::LOG, "too big diff = %g\n", div );
2339
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");
2343
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());
2349             break;
2350         }
2351     }
2352 }
2353
2354 class Core_PhaseTest : public cvtest::BaseTest
2355 {
2356 public:
2357     Core_PhaseTest() {}
2358     ~Core_PhaseTest() {}
2359 protected:
2360     virtual void run(int)
2361     {
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);
2369
2370         // fill the data
2371         x.row(0).setTo(Scalar(0));
2372         y.row(0).setTo(Scalar(0));
2373         anglesInDegrees.row(0).setTo(Scalar(0));
2374
2375         x.row(1).setTo(Scalar(scale));
2376         y.row(1).setTo(Scalar(0));
2377         anglesInDegrees.row(1).setTo(Scalar(0));
2378
2379         x.row(2).setTo(Scalar(scale));
2380         y.row(2).setTo(Scalar(scale));
2381         anglesInDegrees.row(2).setTo(Scalar(45));
2382
2383         x.row(3).setTo(Scalar(0));
2384         y.row(3).setTo(Scalar(scale));
2385         anglesInDegrees.row(3).setTo(Scalar(90));
2386
2387         x.row(4).setTo(Scalar(-scale));
2388         y.row(4).setTo(Scalar(scale));
2389         anglesInDegrees.row(4).setTo(Scalar(135));
2390
2391         x.row(5).setTo(Scalar(-scale));
2392         y.row(5).setTo(Scalar(0));
2393         anglesInDegrees.row(5).setTo(Scalar(180));
2394
2395         x.row(6).setTo(Scalar(-scale));
2396         y.row(6).setTo(Scalar(-scale));
2397         anglesInDegrees.row(6).setTo(Scalar(225));
2398
2399         x.row(7).setTo(Scalar(0));
2400         y.row(7).setTo(Scalar(-scale));
2401         anglesInDegrees.row(7).setTo(Scalar(270));
2402
2403         x.row(8).setTo(Scalar(scale));
2404         y.row(8).setTo(Scalar(-scale));
2405         anglesInDegrees.row(8).setTo(Scalar(315));
2406
2407         Mat resInRad, resInDeg;
2408         phase(x, y, resInRad, false);
2409         phase(x, y, resInDeg, true);
2410
2411         CV_Assert(resInRad.size() == x.size());
2412         CV_Assert(resInRad.type() == x.type());
2413
2414         CV_Assert(resInDeg.size() == x.size());
2415         CV_Assert(resInDeg.type() == x.type());
2416
2417         // check the result
2418         int outOfRangeCount = countNonZero((resInDeg > 360) | (resInDeg < 0));
2419         if(outOfRangeCount > 0)
2420         {
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);
2424         }
2425
2426         Mat diff = abs(anglesInDegrees - resInDeg);
2427         size_t errDegCount = diff.total() - countNonZero((diff < maxAngleDiff) | ((360 - diff) < maxAngleDiff));
2428         if(errDegCount > 0)
2429         {
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);
2433         }
2434
2435         Mat convertedRes = resInRad * 180. / CV_PI;
2436         double normDiff = cvtest::norm(convertedRes - resInDeg, NORM_INF);
2437         if(normDiff > FLT_EPSILON * 180.)
2438         {
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);
2441         }
2442
2443         ts->set_failed_test_info(cvtest::TS::OK);
2444     }
2445 };
2446
2447 class Core_CheckRange_Empty : public cvtest::BaseTest
2448 {
2449 public:
2450     Core_CheckRange_Empty(){}
2451     ~Core_CheckRange_Empty(){}
2452 protected:
2453     virtual void run( int start_from );
2454 };
2455
2456 void Core_CheckRange_Empty::run( int )
2457 {
2458     cv::Mat m;
2459     ASSERT_TRUE( cv::checkRange(m) );
2460 }
2461
2462 TEST(Core_CheckRange_Empty, accuracy) { Core_CheckRange_Empty test; test.safe_run(); }
2463
2464 class Core_CheckRange_INT_MAX : public cvtest::BaseTest
2465 {
2466 public:
2467     Core_CheckRange_INT_MAX(){}
2468     ~Core_CheckRange_INT_MAX(){}
2469 protected:
2470     virtual void run( int start_from );
2471 };
2472
2473 void Core_CheckRange_INT_MAX::run( int )
2474 {
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) );
2478 }
2479
2480 TEST(Core_CheckRange_INT_MAX, accuracy) { Core_CheckRange_INT_MAX test; test.safe_run(); }
2481
2482 template <typename T> class Core_CheckRange : public testing::Test {};
2483
2484 TYPED_TEST_CASE_P(Core_CheckRange);
2485
2486 TYPED_TEST_P(Core_CheckRange, Negative)
2487 {
2488     double min_bound = 4.5;
2489     double max_bound = 16.0;
2490
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);
2493
2494     cv::Point bad_pt(0, 0);
2495
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);
2499 }
2500
2501 TYPED_TEST_P(Core_CheckRange, Positive)
2502 {
2503     double min_bound = -1;
2504     double max_bound = 16.0;
2505
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);
2508
2509     cv::Point bad_pt(0, 0);
2510
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);
2514 }
2515
2516 TYPED_TEST_P(Core_CheckRange, Bounds)
2517 {
2518     double min_bound = 24.5;
2519     double max_bound = 1.0;
2520
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);
2523
2524     cv::Point bad_pt(0, 0);
2525
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);
2529 }
2530
2531 TYPED_TEST_P(Core_CheckRange, Zero)
2532 {
2533     double min_bound = 0.0;
2534     double max_bound = 0.1;
2535
2536     cv::Mat src1 = cv::Mat::zeros(3, 3, cv::DataDepth<TypeParam>::value);
2537
2538     int sizes[] = {5, 6, 7};
2539     cv::Mat src2 = cv::Mat::zeros(3, sizes, cv::DataDepth<TypeParam>::value);
2540
2541     ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) );
2542     ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) );
2543 }
2544
2545 TYPED_TEST_P(Core_CheckRange, One)
2546 {
2547     double min_bound = 1.0;
2548     double max_bound = 1.1;
2549
2550     cv::Mat src1 = cv::Mat::ones(3, 3, cv::DataDepth<TypeParam>::value);
2551
2552     int sizes[] = {5, 6, 7};
2553     cv::Mat src2 = cv::Mat::ones(3, sizes, cv::DataDepth<TypeParam>::value);
2554
2555     ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) );
2556     ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) );
2557 }
2558
2559 REGISTER_TYPED_TEST_CASE_P(Core_CheckRange, Negative, Positive, Bounds, Zero, One);
2560
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);
2563
2564 TEST(Core_Invert, small)
2565 {
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);
2568
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 );
2577 }
2578
2579 /////////////////////////////////////////////////////////////////////////////////////////////////////
2580
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(); }
2598
2599
2600 TEST(Core_SVD, flt)
2601 {
2602     float a[] = {
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,
2611     1.28060578e+005f
2612     };
2613
2614     float b[] = {
2615     283751232.f, 2.61604198e+009f, -745033216.f, 2.31125625e+005f,
2616     -4.52429188e+005f, -1.37596525e+006f
2617     };
2618
2619     Mat A(6, 6, CV_32F, a);
2620     Mat B(6, 1, CV_32F, b);
2621     Mat X, B1;
2622     solve(A, B, X, DECOMP_SVD);
2623     B1 = A*X;
2624     EXPECT_LE(cvtest::norm(B1, B, NORM_L2 + NORM_RELATIVE), FLT_EPSILON*10);
2625 }
2626
2627
2628 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),
2629
2630 enum
2631 {
2632     MAT_N_DIM_C1,
2633     MAT_N_1_CDIM,
2634     MAT_1_N_CDIM,
2635     MAT_N_DIM_C1_NONCONT,
2636     MAT_N_1_CDIM_NONCONT,
2637     VECTOR
2638 };
2639
2640 class CV_KMeansSingularTest : public cvtest::BaseTest
2641 {
2642 public:
2643     CV_KMeansSingularTest() {}
2644     ~CV_KMeansSingularTest() {}
2645 protected:
2646     void run(int inVariant)
2647     {
2648         int i, iter = 0, N = 0, N0 = 0, K = 0, dims = 0;
2649         Mat labels;
2650         try
2651         {
2652             RNG& rng = theRNG();
2653             const int MAX_DIM=5;
2654             int MAX_POINTS = 100, maxIter = 100;
2655             for( iter = 0; iter < maxIter; iter++ )
2656             {
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);
2662
2663                 if (inVariant == VECTOR)
2664                 {
2665                     dims = 2;
2666
2667                     std::vector<cv::Point2f> data0(N0);
2668                     rng.fill(data0, RNG::UNIFORM, -1, 1);
2669
2670                     std::vector<cv::Point2f> data(N);
2671                     for( i = 0; i < N; i++ )
2672                         data[i] = data0[rng.uniform(0, N0)];
2673
2674                     kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
2675                            5, KMEANS_PP_CENTERS);
2676                 }
2677                 else
2678                 {
2679                     Mat data0(N0, dims, CV_32F);
2680                     rng.fill(data0, RNG::UNIFORM, -1, 1);
2681
2682                     Mat data;
2683
2684                     switch (inVariant)
2685                     {
2686                     case MAT_N_DIM_C1:
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));
2690                         break;
2691
2692                     case MAT_N_1_CDIM:
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));
2696                         break;
2697
2698                     case MAT_1_N_CDIM:
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));
2702                         break;
2703
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));
2709                         break;
2710
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));
2716                         break;
2717                     }
2718
2719                     kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
2720                            5, KMEANS_PP_CENTERS);
2721                 }
2722
2723                 Mat hist(K, 1, CV_32S, Scalar(0));
2724                 for( i = 0; i < N; i++ )
2725                 {
2726                     int l = labels.at<int>(i);
2727                     CV_Assert(0 <= l && l < K);
2728                     hist.at<int>(l)++;
2729                 }
2730                 for( i = 0; i < K; i++ )
2731                     CV_Assert( hist.at<int>(i) != 0 );
2732             }
2733         }
2734         catch(...)
2735         {
2736             ts->printf(cvtest::TS::LOG,
2737                        "context: iteration=%d, N=%d, N0=%d, K=%d\n",
2738                        iter, N, N0, K);
2739             std::cout << labels << std::endl;
2740             ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
2741         }
2742     }
2743 };
2744
2745 TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(MAT_N_DIM_C1); }
2746
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)
2748
2749 typedef testing::TestWithParam<KMeansInputVariant> Core_KMeans_InputVariants;
2750
2751 TEST_P(Core_KMeans_InputVariants, singular)
2752 {
2753     CV_KMeansSingularTest test;
2754     test.safe_run(GetParam());
2755 }
2756
2757 INSTANTIATE_TEST_CASE_P(AllVariants, Core_KMeans_InputVariants, KMeansInputVariant::all());
2758
2759 TEST(CovariationMatrixVectorOfMat, accuracy)
2760 {
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;
2764
2765     cv::Mat gold;
2766     cv::Mat goldMean;
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++)
2771     {
2772         srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size));
2773     }
2774
2775     cv::Mat actual;
2776     cv::Mat actualMean;
2777     cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F);
2778
2779     cv::Mat diff;
2780     cv::absdiff(gold, actual, diff);
2781     cv::Scalar s = cv::sum(diff);
2782     ASSERT_EQ(s.dot(s), 0.0);
2783
2784     cv::Mat meanDiff;
2785     cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff);
2786     cv::Scalar sDiff = cv::sum(meanDiff);
2787     ASSERT_EQ(sDiff.dot(sDiff), 0.0);
2788 }
2789
2790 TEST(CovariationMatrixVectorOfMatWithMean, accuracy)
2791 {
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;
2795
2796     cv::Mat gold;
2797     cv::randu(src,cv::Scalar(-128), cv::Scalar(128));
2798     cv::Mat goldMean;
2799
2800     cv::reduce(src,goldMean,0 ,CV_REDUCE_AVG, CV_32F);
2801
2802     cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F);
2803
2804     std::vector<cv::Mat> srcVec;
2805     for(size_t i = 0; i < vector_size; i++)
2806     {
2807         srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size));
2808     }
2809
2810     cv::Mat actual;
2811     cv::Mat actualMean = goldMean.reshape(0, row_problem_size);
2812     cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F);
2813
2814     cv::Mat diff;
2815     cv::absdiff(gold, actual, diff);
2816     cv::Scalar s = cv::sum(diff);
2817     ASSERT_EQ(s.dot(s), 0.0);
2818
2819     cv::Mat meanDiff;
2820     cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff);
2821     cv::Scalar sDiff = cv::sum(meanDiff);
2822     ASSERT_EQ(sDiff.dot(sDiff), 0.0);
2823 }
2824
2825 /* End of file. */