core(test): regression test for 18473
[platform/upstream/opencv.git] / modules / core / test / test_mat.cpp
1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 #include "test_precomp.hpp"
5
6 #ifdef HAVE_EIGEN
7 #include <Eigen/Core>
8 #include <Eigen/Dense>
9 #include "opencv2/core/eigen.hpp"
10 #endif
11
12 namespace opencv_test { namespace {
13
14 class Core_ReduceTest : public cvtest::BaseTest
15 {
16 public:
17     Core_ReduceTest() {}
18 protected:
19     void run( int);
20     int checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim );
21     int checkCase( int srcType, int dstType, int dim, Size sz );
22     int checkDim( int dim, Size sz );
23     int checkSize( Size sz );
24 };
25
26 template<class Type>
27 void testReduce( const Mat& src, Mat& sum, Mat& avg, Mat& max, Mat& min, int dim )
28 {
29     assert( src.channels() == 1 );
30     if( dim == 0 ) // row
31     {
32         sum.create( 1, src.cols, CV_64FC1 );
33         max.create( 1, src.cols, CV_64FC1 );
34         min.create( 1, src.cols, CV_64FC1 );
35     }
36     else
37     {
38         sum.create( src.rows, 1, CV_64FC1 );
39         max.create( src.rows, 1, CV_64FC1 );
40         min.create( src.rows, 1, CV_64FC1 );
41     }
42     sum.setTo(Scalar(0));
43     max.setTo(Scalar(-DBL_MAX));
44     min.setTo(Scalar(DBL_MAX));
45
46     const Mat_<Type>& src_ = src;
47     Mat_<double>& sum_ = (Mat_<double>&)sum;
48     Mat_<double>& min_ = (Mat_<double>&)min;
49     Mat_<double>& max_ = (Mat_<double>&)max;
50
51     if( dim == 0 )
52     {
53         for( int ri = 0; ri < src.rows; ri++ )
54         {
55             for( int ci = 0; ci < src.cols; ci++ )
56             {
57                 sum_(0, ci) += src_(ri, ci);
58                 max_(0, ci) = std::max( max_(0, ci), (double)src_(ri, ci) );
59                 min_(0, ci) = std::min( min_(0, ci), (double)src_(ri, ci) );
60             }
61         }
62     }
63     else
64     {
65         for( int ci = 0; ci < src.cols; ci++ )
66         {
67             for( int ri = 0; ri < src.rows; ri++ )
68             {
69                 sum_(ri, 0) += src_(ri, ci);
70                 max_(ri, 0) = std::max( max_(ri, 0), (double)src_(ri, ci) );
71                 min_(ri, 0) = std::min( min_(ri, 0), (double)src_(ri, ci) );
72             }
73         }
74     }
75     sum.convertTo( avg, CV_64FC1 );
76     avg = avg * (1.0 / (dim==0 ? (double)src.rows : (double)src.cols));
77 }
78
79 void getMatTypeStr( int type, string& str)
80 {
81     str = type == CV_8UC1 ? "CV_8UC1" :
82     type == CV_8SC1 ? "CV_8SC1" :
83     type == CV_16UC1 ? "CV_16UC1" :
84     type == CV_16SC1 ? "CV_16SC1" :
85     type == CV_32SC1 ? "CV_32SC1" :
86     type == CV_32FC1 ? "CV_32FC1" :
87     type == CV_64FC1 ? "CV_64FC1" : "unsupported matrix type";
88 }
89
90 int Core_ReduceTest::checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim )
91 {
92     int srcType = src.type();
93     bool support = false;
94     if( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
95     {
96         if( srcType == CV_8U && (dstType == CV_32S || dstType == CV_32F || dstType == CV_64F) )
97             support = true;
98         if( srcType == CV_16U && (dstType == CV_32F || dstType == CV_64F) )
99             support = true;
100         if( srcType == CV_16S && (dstType == CV_32F || dstType == CV_64F) )
101             support = true;
102         if( srcType == CV_32F && (dstType == CV_32F || dstType == CV_64F) )
103             support = true;
104         if( srcType == CV_64F && dstType == CV_64F)
105             support = true;
106     }
107     else if( opType == CV_REDUCE_MAX )
108     {
109         if( srcType == CV_8U && dstType == CV_8U )
110             support = true;
111         if( srcType == CV_32F && dstType == CV_32F )
112             support = true;
113         if( srcType == CV_64F && dstType == CV_64F )
114             support = true;
115     }
116     else if( opType == CV_REDUCE_MIN )
117     {
118         if( srcType == CV_8U && dstType == CV_8U)
119             support = true;
120         if( srcType == CV_32F && dstType == CV_32F)
121             support = true;
122         if( srcType == CV_64F && dstType == CV_64F)
123             support = true;
124     }
125     if( !support )
126         return cvtest::TS::OK;
127
128     double eps = 0.0;
129     if ( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
130     {
131         if ( dstType == CV_32F )
132             eps = 1.e-5;
133         else if( dstType == CV_64F )
134             eps = 1.e-8;
135         else if ( dstType == CV_32S )
136             eps = 0.6;
137     }
138
139     assert( opRes.type() == CV_64FC1 );
140     Mat _dst, dst, diff;
141     cv::reduce( src, _dst, dim, opType, dstType );
142     _dst.convertTo( dst, CV_64FC1 );
143
144     absdiff( opRes,dst,diff );
145     bool check = false;
146     if (dstType == CV_32F || dstType == CV_64F)
147         check = countNonZero(diff>eps*dst) > 0;
148     else
149         check = countNonZero(diff>eps) > 0;
150     if( check )
151     {
152         char msg[100];
153         const char* opTypeStr = opType == CV_REDUCE_SUM ? "CV_REDUCE_SUM" :
154         opType == CV_REDUCE_AVG ? "CV_REDUCE_AVG" :
155         opType == CV_REDUCE_MAX ? "CV_REDUCE_MAX" :
156         opType == CV_REDUCE_MIN ? "CV_REDUCE_MIN" : "unknown operation type";
157         string srcTypeStr, dstTypeStr;
158         getMatTypeStr( src.type(), srcTypeStr );
159         getMatTypeStr( dstType, dstTypeStr );
160         const char* dimStr = dim == 0 ? "ROWS" : "COLS";
161
162         sprintf( msg, "bad accuracy with srcType = %s, dstType = %s, opType = %s, dim = %s",
163                 srcTypeStr.c_str(), dstTypeStr.c_str(), opTypeStr, dimStr );
164         ts->printf( cvtest::TS::LOG, msg );
165         return cvtest::TS::FAIL_BAD_ACCURACY;
166     }
167     return cvtest::TS::OK;
168 }
169
170 int Core_ReduceTest::checkCase( int srcType, int dstType, int dim, Size sz )
171 {
172     int code = cvtest::TS::OK, tempCode;
173     Mat src, sum, avg, max, min;
174
175     src.create( sz, srcType );
176     randu( src, Scalar(0), Scalar(100) );
177
178     if( srcType == CV_8UC1 )
179         testReduce<uchar>( src, sum, avg, max, min, dim );
180     else if( srcType == CV_8SC1 )
181         testReduce<char>( src, sum, avg, max, min, dim );
182     else if( srcType == CV_16UC1 )
183         testReduce<unsigned short int>( src, sum, avg, max, min, dim );
184     else if( srcType == CV_16SC1 )
185         testReduce<short int>( src, sum, avg, max, min, dim );
186     else if( srcType == CV_32SC1 )
187         testReduce<int>( src, sum, avg, max, min, dim );
188     else if( srcType == CV_32FC1 )
189         testReduce<float>( src, sum, avg, max, min, dim );
190     else if( srcType == CV_64FC1 )
191         testReduce<double>( src, sum, avg, max, min, dim );
192     else
193         assert( 0 );
194
195     // 1. sum
196     tempCode = checkOp( src, dstType, CV_REDUCE_SUM, sum, dim );
197     code = tempCode != cvtest::TS::OK ? tempCode : code;
198
199     // 2. avg
200     tempCode = checkOp( src, dstType, CV_REDUCE_AVG, avg, dim );
201     code = tempCode != cvtest::TS::OK ? tempCode : code;
202
203     // 3. max
204     tempCode = checkOp( src, dstType, CV_REDUCE_MAX, max, dim );
205     code = tempCode != cvtest::TS::OK ? tempCode : code;
206
207     // 4. min
208     tempCode = checkOp( src, dstType, CV_REDUCE_MIN, min, dim );
209     code = tempCode != cvtest::TS::OK ? tempCode : code;
210
211     return code;
212 }
213
214 int Core_ReduceTest::checkDim( int dim, Size sz )
215 {
216     int code = cvtest::TS::OK, tempCode;
217
218     // CV_8UC1
219     tempCode = checkCase( CV_8UC1, CV_8UC1, dim, sz );
220     code = tempCode != cvtest::TS::OK ? tempCode : code;
221
222     tempCode = checkCase( CV_8UC1, CV_32SC1, dim, sz );
223     code = tempCode != cvtest::TS::OK ? tempCode : code;
224
225     tempCode = checkCase( CV_8UC1, CV_32FC1, dim, sz );
226     code = tempCode != cvtest::TS::OK ? tempCode : code;
227
228     tempCode = checkCase( CV_8UC1, CV_64FC1, dim, sz );
229     code = tempCode != cvtest::TS::OK ? tempCode : code;
230
231     // CV_16UC1
232     tempCode = checkCase( CV_16UC1, CV_32FC1, dim, sz );
233     code = tempCode != cvtest::TS::OK ? tempCode : code;
234
235     tempCode = checkCase( CV_16UC1, CV_64FC1, dim, sz );
236     code = tempCode != cvtest::TS::OK ? tempCode : code;
237
238     // CV_16SC1
239     tempCode = checkCase( CV_16SC1, CV_32FC1, dim, sz );
240     code = tempCode != cvtest::TS::OK ? tempCode : code;
241
242     tempCode = checkCase( CV_16SC1, CV_64FC1, dim, sz );
243     code = tempCode != cvtest::TS::OK ? tempCode : code;
244
245     // CV_32FC1
246     tempCode = checkCase( CV_32FC1, CV_32FC1, dim, sz );
247     code = tempCode != cvtest::TS::OK ? tempCode : code;
248
249     tempCode = checkCase( CV_32FC1, CV_64FC1, dim, sz );
250     code = tempCode != cvtest::TS::OK ? tempCode : code;
251
252     // CV_64FC1
253     tempCode = checkCase( CV_64FC1, CV_64FC1, dim, sz );
254     code = tempCode != cvtest::TS::OK ? tempCode : code;
255
256     return code;
257 }
258
259 int Core_ReduceTest::checkSize( Size sz )
260 {
261     int code = cvtest::TS::OK, tempCode;
262
263     tempCode = checkDim( 0, sz ); // rows
264     code = tempCode != cvtest::TS::OK ? tempCode : code;
265
266     tempCode = checkDim( 1, sz ); // cols
267     code = tempCode != cvtest::TS::OK ? tempCode : code;
268
269     return code;
270 }
271
272 void Core_ReduceTest::run( int )
273 {
274     int code = cvtest::TS::OK, tempCode;
275
276     tempCode = checkSize( Size(1,1) );
277     code = tempCode != cvtest::TS::OK ? tempCode : code;
278
279     tempCode = checkSize( Size(1,100) );
280     code = tempCode != cvtest::TS::OK ? tempCode : code;
281
282     tempCode = checkSize( Size(100,1) );
283     code = tempCode != cvtest::TS::OK ? tempCode : code;
284
285     tempCode = checkSize( Size(1000,500) );
286     code = tempCode != cvtest::TS::OK ? tempCode : code;
287
288     ts->set_failed_test_info( code );
289 }
290
291
292 #define CHECK_C
293
294 TEST(Core_PCA, accuracy)
295 {
296     const Size sz(200, 500);
297
298     double diffPrjEps, diffBackPrjEps,
299     prjEps, backPrjEps,
300     evalEps, evecEps;
301     int maxComponents = 100;
302     double retainedVariance = 0.95;
303     Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1);
304     RNG rng(12345);
305
306     rng.fill( rPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
307     rng.fill( rTestPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
308
309     PCA rPCA( rPoints, Mat(), CV_PCA_DATA_AS_ROW, maxComponents ), cPCA;
310
311     // 1. check C++ PCA & ROW
312     Mat rPrjTestPoints = rPCA.project( rTestPoints );
313     Mat rBackPrjTestPoints = rPCA.backProject( rPrjTestPoints );
314
315     Mat avg(1, sz.width, CV_32FC1 );
316     cv::reduce( rPoints, avg, 0, CV_REDUCE_AVG );
317     Mat Q = rPoints - repeat( avg, rPoints.rows, 1 ), Qt = Q.t(), eval, evec;
318     Q = Qt * Q;
319     Q = Q /(float)rPoints.rows;
320
321     eigen( Q, eval, evec );
322     /*SVD svd(Q);
323      evec = svd.vt;
324      eval = svd.w;*/
325
326     Mat subEval( maxComponents, 1, eval.type(), eval.ptr() ),
327     subEvec( maxComponents, evec.cols, evec.type(), evec.ptr() );
328
329 #ifdef CHECK_C
330     Mat prjTestPoints, backPrjTestPoints, cPoints = rPoints.t(), cTestPoints = rTestPoints.t();
331     CvMat _points, _testPoints, _avg, _eval, _evec, _prjTestPoints, _backPrjTestPoints;
332 #endif
333
334     // check eigen()
335     double eigenEps = 1e-4;
336     double err;
337     for(int i = 0; i < Q.rows; i++ )
338     {
339         Mat v = evec.row(i).t();
340         Mat Qv = Q * v;
341
342         Mat lv = eval.at<float>(i,0) * v;
343         err = cvtest::norm(Qv, lv, NORM_L2 | NORM_RELATIVE);
344         EXPECT_LE(err, eigenEps) << "bad accuracy of eigen(); i = " << i;
345     }
346     // check pca eigenvalues
347     evalEps = 1e-5, evecEps = 5e-3;
348     err = cvtest::norm(rPCA.eigenvalues, subEval, NORM_L2 | NORM_RELATIVE);
349     EXPECT_LE(err , evalEps) << "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW)";
350     // check pca eigenvectors
351     for(int i = 0; i < subEvec.rows; i++)
352     {
353         Mat r0 = rPCA.eigenvectors.row(i);
354         Mat r1 = subEvec.row(i);
355         // eigenvectors have normalized length, but both directions v and -v are valid
356         double err1 = cvtest::norm(r0, r1, NORM_L2 | NORM_RELATIVE);
357         double err2 = cvtest::norm(r0, -r1, NORM_L2 | NORM_RELATIVE);
358         err = std::min(err1, err2);
359         if (err > evecEps)
360         {
361             Mat tmp;
362             absdiff(rPCA.eigenvectors, subEvec, tmp);
363             double mval = 0; Point mloc;
364             minMaxLoc(tmp, 0, &mval, 0, &mloc);
365
366             EXPECT_LE(err, evecEps) << "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW) at " << i << " "
367                 << cv::format("max diff is %g at (i=%d, j=%d) (%g vs %g)\n",
368                         mval, mloc.y, mloc.x, rPCA.eigenvectors.at<float>(mloc.y, mloc.x),
369                         subEvec.at<float>(mloc.y, mloc.x))
370                 << "r0=" << r0 << std::endl
371                 << "r1=" << r1 << std::endl
372                 << "err1=" << err1 << " err2=" << err2
373             ;
374         }
375     }
376
377     prjEps = 1.265, backPrjEps = 1.265;
378     for( int i = 0; i < rTestPoints.rows; i++ )
379     {
380         // check pca project
381         Mat subEvec_t = subEvec.t();
382         Mat prj = rTestPoints.row(i) - avg; prj *= subEvec_t;
383         err = cvtest::norm(rPrjTestPoints.row(i), prj, NORM_L2 | NORM_RELATIVE);
384         if (err < prjEps)
385         {
386             EXPECT_LE(err, prjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_ROW)";
387             continue;
388         }
389         // check pca backProject
390         Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg;
391         err = cvtest::norm(rBackPrjTestPoints.row(i), backPrj, NORM_L2 | NORM_RELATIVE);
392         if (err > backPrjEps)
393         {
394             EXPECT_LE(err, backPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW)";
395             continue;
396         }
397     }
398
399     // 2. check C++ PCA & COL
400     cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents );
401     diffPrjEps = 1, diffBackPrjEps = 1;
402     Mat ocvPrjTestPoints = cPCA.project(rTestPoints.t());
403     err = cvtest::norm(cv::abs(ocvPrjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
404     ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL)";
405     err = cvtest::norm(cPCA.backProject(ocvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
406     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL)";
407
408     // 3. check C++ PCA w/retainedVariance
409     cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, retainedVariance );
410     diffPrjEps = 1, diffBackPrjEps = 1;
411     Mat rvPrjTestPoints = cPCA.project(rTestPoints.t());
412
413     if( cPCA.eigenvectors.rows > maxComponents)
414         err = cvtest::norm(cv::abs(rvPrjTestPoints.rowRange(0,maxComponents)), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
415     else
416         err = cvtest::norm(cv::abs(rvPrjTestPoints), cv::abs(rPrjTestPoints.colRange(0,cPCA.eigenvectors.rows).t()), NORM_L2 | NORM_RELATIVE);
417
418     ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance;
419     err = cvtest::norm(cPCA.backProject(rvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
420     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance;
421
422 #ifdef CHECK_C
423     // 4. check C PCA & ROW
424     _points = cvMat(rPoints);
425     _testPoints = cvMat(rTestPoints);
426     _avg = cvMat(avg);
427     _eval = cvMat(eval);
428     _evec = cvMat(evec);
429     prjTestPoints.create(rTestPoints.rows, maxComponents, rTestPoints.type() );
430     backPrjTestPoints.create(rPoints.size(), rPoints.type() );
431     _prjTestPoints = cvMat(prjTestPoints);
432     _backPrjTestPoints = cvMat(backPrjTestPoints);
433
434     cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_ROW );
435     cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
436     cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
437
438     err = cvtest::norm(prjTestPoints, rPrjTestPoints, NORM_L2 | NORM_RELATIVE);
439     ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW)";
440     err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints, NORM_L2 | NORM_RELATIVE);
441     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW)";
442
443     // 5. check C PCA & COL
444     _points = cvMat(cPoints);
445     _testPoints = cvMat(cTestPoints);
446     avg = avg.t(); _avg = cvMat(avg);
447     eval = eval.t(); _eval = cvMat(eval);
448     evec = evec.t(); _evec = cvMat(evec);
449     prjTestPoints = prjTestPoints.t(); _prjTestPoints = cvMat(prjTestPoints);
450     backPrjTestPoints = backPrjTestPoints.t(); _backPrjTestPoints = cvMat(backPrjTestPoints);
451
452     cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_COL );
453     cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
454     cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
455
456     err = cvtest::norm(cv::abs(prjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
457     ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL)";
458     err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
459     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL)";
460 #endif
461     // Test read and write
462     FileStorage fs( "PCA_store.yml", FileStorage::WRITE );
463     rPCA.write( fs );
464     fs.release();
465
466     PCA lPCA;
467     fs.open( "PCA_store.yml", FileStorage::READ );
468     lPCA.read( fs.root() );
469     err = cvtest::norm(rPCA.eigenvectors, lPCA.eigenvectors, NORM_L2 | NORM_RELATIVE);
470     EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
471     err = cvtest::norm(rPCA.eigenvalues, lPCA.eigenvalues, NORM_L2 | NORM_RELATIVE);
472     EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
473     err = cvtest::norm(rPCA.mean, lPCA.mean, NORM_L2 | NORM_RELATIVE);
474     EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
475 }
476
477 class Core_ArrayOpTest : public cvtest::BaseTest
478 {
479 public:
480     Core_ArrayOpTest();
481     ~Core_ArrayOpTest();
482 protected:
483     void run(int);
484 };
485
486
487 Core_ArrayOpTest::Core_ArrayOpTest()
488 {
489 }
490 Core_ArrayOpTest::~Core_ArrayOpTest() {}
491
492 static string idx2string(const int* idx, int dims)
493 {
494     char buf[256];
495     char* ptr = buf;
496     for( int k = 0; k < dims; k++ )
497     {
498         sprintf(ptr, "%4d ", idx[k]);
499         ptr += strlen(ptr);
500     }
501     ptr[-1] = '\0';
502     return string(buf);
503 }
504
505 static const int* string2idx(const string& s, int* idx, int dims)
506 {
507     const char* ptr = s.c_str();
508     for( int k = 0; k < dims; k++ )
509     {
510         int n = 0;
511         sscanf(ptr, "%d%n", idx + k, &n);
512         ptr += n;
513     }
514     return idx;
515 }
516
517 static double getValue(SparseMat& M, const int* idx, RNG& rng)
518 {
519     int d = M.dims();
520     size_t hv = 0, *phv = 0;
521     if( (unsigned)rng % 2 )
522     {
523         hv = d == 2 ? M.hash(idx[0], idx[1]) :
524         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
525         phv = &hv;
526     }
527
528     const uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], false, phv) :
529     d == 3 ? M.ptr(idx[0], idx[1], idx[2], false, phv) :
530     M.ptr(idx, false, phv);
531     return !ptr ? 0 : M.type() == CV_32F ? *(float*)ptr : M.type() == CV_64F ? *(double*)ptr : 0;
532 }
533
534 static double getValue(const CvSparseMat* M, const int* idx)
535 {
536     int type = 0;
537     const uchar* ptr = cvPtrND(M, idx, &type, 0);
538     return !ptr ? 0 : type == CV_32F ? *(float*)ptr : type == CV_64F ? *(double*)ptr : 0;
539 }
540
541 static void eraseValue(SparseMat& M, const int* idx, RNG& rng)
542 {
543     int d = M.dims();
544     size_t hv = 0, *phv = 0;
545     if( (unsigned)rng % 2 )
546     {
547         hv = d == 2 ? M.hash(idx[0], idx[1]) :
548         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
549         phv = &hv;
550     }
551
552     if( d == 2 )
553         M.erase(idx[0], idx[1], phv);
554     else if( d == 3 )
555         M.erase(idx[0], idx[1], idx[2], phv);
556     else
557         M.erase(idx, phv);
558 }
559
560 static void eraseValue(CvSparseMat* M, const int* idx)
561 {
562     cvClearND(M, idx);
563 }
564
565 static void setValue(SparseMat& M, const int* idx, double value, RNG& rng)
566 {
567     int d = M.dims();
568     size_t hv = 0, *phv = 0;
569     if( (unsigned)rng % 2 )
570     {
571         hv = d == 2 ? M.hash(idx[0], idx[1]) :
572         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
573         phv = &hv;
574     }
575
576     uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], true, phv) :
577     d == 3 ? M.ptr(idx[0], idx[1], idx[2], true, phv) :
578     M.ptr(idx, true, phv);
579     if( M.type() == CV_32F )
580         *(float*)ptr = (float)value;
581     else if( M.type() == CV_64F )
582         *(double*)ptr = value;
583     else
584         CV_Error(CV_StsUnsupportedFormat, "");
585 }
586
587 template<typename Pixel>
588 struct InitializerFunctor{
589     /// Initializer for cv::Mat::forEach test
590     void operator()(Pixel & pixel, const int * idx) const {
591         pixel.x = idx[0];
592         pixel.y = idx[1];
593         pixel.z = idx[2];
594     }
595 };
596
597 template<typename Pixel>
598 struct InitializerFunctor5D{
599     /// Initializer for cv::Mat::forEach test (5 dimensional case)
600     void operator()(Pixel & pixel, const int * idx) const {
601         pixel[0] = idx[0];
602         pixel[1] = idx[1];
603         pixel[2] = idx[2];
604         pixel[3] = idx[3];
605         pixel[4] = idx[4];
606     }
607 };
608
609 template<typename Pixel>
610 struct EmptyFunctor
611 {
612     void operator()(const Pixel &, const int *) const {}
613 };
614
615
616 void Core_ArrayOpTest::run( int /* start_from */)
617 {
618     int errcount = 0;
619
620     // dense matrix operations
621     {
622         int sz3[] = {5, 10, 15};
623         MatND A(3, sz3, CV_32F), B(3, sz3, CV_16SC4);
624         CvMatND matA = cvMatND(A), matB = cvMatND(B);
625         RNG rng;
626         rng.fill(A, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
627         rng.fill(B, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
628
629         int idx0[] = {3,4,5}, idx1[] = {0, 9, 7};
630         float val0 = 130;
631         Scalar val1(-1000, 30, 3, 8);
632         cvSetRealND(&matA, idx0, val0);
633         cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0);
634         cvSetND(&matB, idx0, cvScalar(val1));
635         cvSet3D(&matB, idx1[0], idx1[1], idx1[2], cvScalar(-val1));
636         Ptr<CvMatND> matC(cvCloneMatND(&matB));
637
638         if( A.at<float>(idx0[0], idx0[1], idx0[2]) != val0 ||
639            A.at<float>(idx1[0], idx1[1], idx1[2]) != -val0 ||
640            cvGetReal3D(&matA, idx0[0], idx0[1], idx0[2]) != val0 ||
641            cvGetRealND(&matA, idx1) != -val0 ||
642
643            Scalar(B.at<Vec4s>(idx0[0], idx0[1], idx0[2])) != val1 ||
644            Scalar(B.at<Vec4s>(idx1[0], idx1[1], idx1[2])) != -val1 ||
645            Scalar(cvGet3D(matC, idx0[0], idx0[1], idx0[2])) != val1 ||
646            Scalar(cvGetND(matC, idx1)) != -val1 )
647         {
648             ts->printf(cvtest::TS::LOG, "one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND "
649                        "or the corresponding *Get* functions is not correct\n");
650             errcount++;
651         }
652     }
653     // test cv::Mat::forEach
654     {
655         const int dims[3] = { 101, 107, 7 };
656         typedef cv::Point3i Pixel;
657
658         cv::Mat a = cv::Mat::zeros(3, dims, CV_32SC3);
659         InitializerFunctor<Pixel> initializer;
660
661         a.forEach<Pixel>(initializer);
662
663         uint64 total = 0;
664         bool error_reported = false;
665         for (int i0 = 0; i0 < dims[0]; ++i0) {
666             for (int i1 = 0; i1 < dims[1]; ++i1) {
667                 for (int i2 = 0; i2 < dims[2]; ++i2) {
668                     Pixel& pixel = a.at<Pixel>(i0, i1, i2);
669                     if (pixel.x != i0 || pixel.y != i1 || pixel.z != i2) {
670                         if (!error_reported) {
671                             ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
672                                 "First error detected at (%d, %d, %d).\n", pixel.x, pixel.y, pixel.z);
673                             error_reported = true;
674                         }
675                         errcount++;
676                     }
677                     total += pixel.x;
678                     total += pixel.y;
679                     total += pixel.z;
680                 }
681             }
682         }
683         uint64 total2 = 0;
684         for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
685             total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] / dims[i];
686         }
687         if (total != total2) {
688             ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
689             errcount++;
690         }
691     }
692
693     // test cv::Mat::forEach
694     // with a matrix that has more dimensions than columns
695     // See https://github.com/opencv/opencv/issues/8447
696     {
697         const int dims[5] = { 2, 2, 2, 2, 2 };
698         typedef cv::Vec<int, 5> Pixel;
699
700         cv::Mat a = cv::Mat::zeros(5, dims, CV_32SC(5));
701         InitializerFunctor5D<Pixel> initializer;
702
703         a.forEach<Pixel>(initializer);
704
705         uint64 total = 0;
706         bool error_reported = false;
707         for (int i0 = 0; i0 < dims[0]; ++i0) {
708             for (int i1 = 0; i1 < dims[1]; ++i1) {
709                 for (int i2 = 0; i2 < dims[2]; ++i2) {
710                     for (int i3 = 0; i3 < dims[3]; ++i3) {
711                         for (int i4 = 0; i4 < dims[4]; ++i4) {
712                             const int i[5] = { i0, i1, i2, i3, i4 };
713                             Pixel& pixel = a.at<Pixel>(i);
714                             if (pixel[0] != i0 || pixel[1] != i1 || pixel[2] != i2 || pixel[3] != i3 || pixel[4] != i4) {
715                                 if (!error_reported) {
716                                     ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
717                                         "First error detected at position (%d, %d, %d, %d, %d), got value (%d, %d, %d, %d, %d).\n",
718                                         i0, i1, i2, i3, i4,
719                                         pixel[0], pixel[1], pixel[2], pixel[3], pixel[4]);
720                                     error_reported = true;
721                                 }
722                                 errcount++;
723                             }
724                             total += pixel[0];
725                             total += pixel[1];
726                             total += pixel[2];
727                             total += pixel[3];
728                             total += pixel[4];
729                         }
730                     }
731                 }
732             }
733         }
734         uint64 total2 = 0;
735         for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
736             total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] * dims[3] * dims[4] / dims[i];
737         }
738         if (total != total2) {
739             ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
740             errcount++;
741         }
742     }
743
744     // test const cv::Mat::forEach
745     {
746         const Mat a(10, 10, CV_32SC3);
747         Mat b(10, 10, CV_32SC3);
748         const Mat & c = b;
749         a.forEach<Point3i>(EmptyFunctor<Point3i>());
750         b.forEach<Point3i>(EmptyFunctor<const Point3i>());
751         c.forEach<Point3i>(EmptyFunctor<Point3i>());
752         // tests compilation, no runtime check is needed
753     }
754
755     RNG rng;
756     const int MAX_DIM = 5, MAX_DIM_SZ = 10;
757     // sparse matrix operations
758     for( int si = 0; si < 10; si++ )
759     {
760         int depth = (unsigned)rng % 2 == 0 ? CV_32F : CV_64F;
761         int dims = ((unsigned)rng % MAX_DIM) + 1;
762         int i, k, size[MAX_DIM]={0}, idx[MAX_DIM]={0};
763         vector<string> all_idxs;
764         vector<double> all_vals;
765         vector<double> all_vals2;
766         string sidx, min_sidx, max_sidx;
767         double min_val=0, max_val=0;
768
769         int p = 1;
770         for( k = 0; k < dims; k++ )
771         {
772             size[k] = ((unsigned)rng % MAX_DIM_SZ) + 1;
773             p *= size[k];
774         }
775         SparseMat M( dims, size, depth );
776         map<string, double> M0;
777
778         int nz0 = (unsigned)rng % std::max(p/5,10);
779         nz0 = std::min(std::max(nz0, 1), p);
780         all_vals.resize(nz0);
781         all_vals2.resize(nz0);
782         Mat_<double> _all_vals(all_vals), _all_vals2(all_vals2);
783         rng.fill(_all_vals, CV_RAND_UNI, Scalar(-1000), Scalar(1000));
784         if( depth == CV_32F )
785         {
786             Mat _all_vals_f;
787             _all_vals.convertTo(_all_vals_f, CV_32F);
788             _all_vals_f.convertTo(_all_vals, CV_64F);
789         }
790         _all_vals.convertTo(_all_vals2, _all_vals2.type(), 2);
791         if( depth == CV_32F )
792         {
793             Mat _all_vals2_f;
794             _all_vals2.convertTo(_all_vals2_f, CV_32F);
795             _all_vals2_f.convertTo(_all_vals2, CV_64F);
796         }
797
798         minMaxLoc(_all_vals, &min_val, &max_val);
799         double _norm0 = cv/*test*/::norm(_all_vals, CV_C);
800         double _norm1 = cv/*test*/::norm(_all_vals, CV_L1);
801         double _norm2 = cv/*test*/::norm(_all_vals, CV_L2);
802
803         for( i = 0; i < nz0; i++ )
804         {
805             for(;;)
806             {
807                 for( k = 0; k < dims; k++ )
808                     idx[k] = (unsigned)rng % size[k];
809                 sidx = idx2string(idx, dims);
810                 if( M0.count(sidx) == 0 )
811                     break;
812             }
813             all_idxs.push_back(sidx);
814             M0[sidx] = all_vals[i];
815             if( all_vals[i] == min_val )
816                 min_sidx = sidx;
817             if( all_vals[i] == max_val )
818                 max_sidx = sidx;
819             setValue(M, idx, all_vals[i], rng);
820             double v = getValue(M, idx, rng);
821             if( v != all_vals[i] )
822             {
823                 ts->printf(cvtest::TS::LOG, "%d. immediately after SparseMat[%s]=%.20g the current value is %.20g\n",
824                            i, sidx.c_str(), all_vals[i], v);
825                 errcount++;
826                 break;
827             }
828         }
829
830         Ptr<CvSparseMat> M2(cvCreateSparseMat(M));
831         MatND Md;
832         M.copyTo(Md);
833         SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2);
834
835         int nz1 = (int)M.nzcount(), nz2 = (int)M3.nzcount();
836         double norm0 = cv/*test*/::norm(M, CV_C);
837         double norm1 = cv/*test*/::norm(M, CV_L1);
838         double norm2 = cv/*test*/::norm(M, CV_L2);
839         double eps = depth == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
840
841         if( nz1 != nz0 || nz2 != nz0)
842         {
843             errcount++;
844             ts->printf(cvtest::TS::LOG, "%d: The number of non-zero elements before/after converting to/from dense matrix is not correct: %d/%d (while it should be %d)\n",
845                        si, nz1, nz2, nz0 );
846             break;
847         }
848
849         if( fabs(norm0 - _norm0) > fabs(_norm0)*eps ||
850            fabs(norm1 - _norm1) > fabs(_norm1)*eps ||
851            fabs(norm2 - _norm2) > fabs(_norm2)*eps )
852         {
853             errcount++;
854             ts->printf(cvtest::TS::LOG, "%d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g\n",
855                        si, norm0, norm1, norm2, _norm0, _norm1, _norm2 );
856             break;
857         }
858
859         int n = (unsigned)rng % std::max(p/5,10);
860         n = std::min(std::max(n, 1), p) + nz0;
861
862         for( i = 0; i < n; i++ )
863         {
864             double val1, val2, val3, val0;
865             if(i < nz0)
866             {
867                 sidx = all_idxs[i];
868                 string2idx(sidx, idx, dims);
869                 val0 = all_vals[i];
870             }
871             else
872             {
873                 for( k = 0; k < dims; k++ )
874                     idx[k] = (unsigned)rng % size[k];
875                 sidx = idx2string(idx, dims);
876                 val0 = M0[sidx];
877             }
878             val1 = getValue(M, idx, rng);
879             val2 = getValue(M2, idx);
880             val3 = getValue(M3, idx, rng);
881
882             if( val1 != val0 || val2 != val0 || fabs(val3 - val0*2) > fabs(val0*2)*FLT_EPSILON )
883             {
884                 errcount++;
885                 ts->printf(cvtest::TS::LOG, "SparseMat M[%s] = %g/%g/%g (while it should be %g)\n", sidx.c_str(), val1, val2, val3, val0 );
886                 break;
887             }
888         }
889
890         for( i = 0; i < n; i++ )
891         {
892             double val1, val2;
893             if(i < nz0)
894             {
895                 sidx = all_idxs[i];
896                 string2idx(sidx, idx, dims);
897             }
898             else
899             {
900                 for( k = 0; k < dims; k++ )
901                     idx[k] = (unsigned)rng % size[k];
902                 sidx = idx2string(idx, dims);
903             }
904             eraseValue(M, idx, rng);
905             eraseValue(M2, idx);
906             val1 = getValue(M, idx, rng);
907             val2 = getValue(M2, idx);
908             if( val1 != 0 || val2 != 0 )
909             {
910                 errcount++;
911                 ts->printf(cvtest::TS::LOG, "SparseMat: after deleting M[%s], it is =%g/%g (while it should be 0)\n", sidx.c_str(), val1, val2 );
912                 break;
913             }
914         }
915
916         int nz = (int)M.nzcount();
917         if( nz != 0 )
918         {
919             errcount++;
920             ts->printf(cvtest::TS::LOG, "The number of non-zero elements after removing all the elements = %d (while it should be 0)\n", nz );
921             break;
922         }
923
924         int idx1[MAX_DIM], idx2[MAX_DIM];
925         double val1 = 0, val2 = 0;
926         M3 = SparseMat(Md);
927         cv::minMaxLoc(M3, &val1, &val2, idx1, idx2);
928         string s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
929         if( val1 != min_val || val2 != max_val || s1 != min_sidx || s2 != max_sidx )
930         {
931             errcount++;
932             ts->printf(cvtest::TS::LOG, "%d. Sparse: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t"
933                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
934                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
935             break;
936         }
937
938         cv::minMaxIdx(Md, &val1, &val2, idx1, idx2);
939         s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
940         if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) ||
941            (max_val > 0 && (val2 != max_val || s2 != max_sidx)) )
942         {
943             errcount++;
944             ts->printf(cvtest::TS::LOG, "%d. Dense: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t"
945                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
946                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
947             break;
948         }
949     }
950
951     ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT);
952 }
953
954
955 template <class ElemType>
956 int calcDiffElemCountImpl(const vector<Mat>& mv, const Mat& m)
957 {
958     int diffElemCount = 0;
959     const int mChannels = m.channels();
960     for(int y = 0; y < m.rows; y++)
961     {
962         for(int x = 0; x < m.cols; x++)
963         {
964             const ElemType* mElem = &m.at<ElemType>(y,x*mChannels);
965             size_t loc = 0;
966             for(size_t i = 0; i < mv.size(); i++)
967             {
968                 const size_t mvChannel = mv[i].channels();
969                 const ElemType* mvElem = &mv[i].at<ElemType>(y,x*(int)mvChannel);
970                 for(size_t li = 0; li < mvChannel; li++)
971                     if(mElem[loc + li] != mvElem[li])
972                         diffElemCount++;
973                 loc += mvChannel;
974             }
975             CV_Assert(loc == (size_t)mChannels);
976         }
977     }
978     return diffElemCount;
979 }
980
981 static
982 int calcDiffElemCount(const vector<Mat>& mv, const Mat& m)
983 {
984     int depth = m.depth();
985     switch (depth)
986     {
987     case CV_8U:
988         return calcDiffElemCountImpl<uchar>(mv, m);
989     case CV_8S:
990         return calcDiffElemCountImpl<char>(mv, m);
991     case CV_16U:
992         return calcDiffElemCountImpl<unsigned short>(mv, m);
993     case CV_16S:
994         return calcDiffElemCountImpl<short int>(mv, m);
995     case CV_32S:
996         return calcDiffElemCountImpl<int>(mv, m);
997     case CV_32F:
998         return calcDiffElemCountImpl<float>(mv, m);
999     case CV_64F:
1000         return calcDiffElemCountImpl<double>(mv, m);
1001     }
1002
1003     return INT_MAX;
1004 }
1005
1006 class Core_MergeSplitBaseTest : public cvtest::BaseTest
1007 {
1008 protected:
1009     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng) = 0;
1010
1011     virtual void run(int)
1012     {
1013         // m is Mat
1014         // mv is vector<Mat>
1015         const int minMSize = 1;
1016         const int maxMSize = 100;
1017         const size_t maxMvSize = 10;
1018
1019         RNG& rng = theRNG();
1020         Size mSize(rng.uniform(minMSize, maxMSize), rng.uniform(minMSize, maxMSize));
1021         size_t mvSize = rng.uniform(1, maxMvSize);
1022
1023         int res = cvtest::TS::OK;
1024         int curRes = run_case(CV_8U, mvSize, mSize, rng);
1025         res = curRes != cvtest::TS::OK ? curRes : res;
1026
1027         curRes = run_case(CV_8S, mvSize, mSize, rng);
1028         res = curRes != cvtest::TS::OK ? curRes : res;
1029
1030         curRes = run_case(CV_16U, mvSize, mSize, rng);
1031         res = curRes != cvtest::TS::OK ? curRes : res;
1032
1033         curRes = run_case(CV_16S, mvSize, mSize, rng);
1034         res = curRes != cvtest::TS::OK ? curRes : res;
1035
1036         curRes = run_case(CV_32S, mvSize, mSize, rng);
1037         res = curRes != cvtest::TS::OK ? curRes : res;
1038
1039         curRes = run_case(CV_32F, mvSize, mSize, rng);
1040         res = curRes != cvtest::TS::OK ? curRes : res;
1041
1042         curRes = run_case(CV_64F, mvSize, mSize, rng);
1043         res = curRes != cvtest::TS::OK ? curRes : res;
1044
1045         ts->set_failed_test_info(res);
1046     }
1047 };
1048
1049 class Core_MergeTest : public Core_MergeSplitBaseTest
1050 {
1051 public:
1052     Core_MergeTest() {}
1053     ~Core_MergeTest() {}
1054
1055 protected:
1056     virtual int run_case(int depth, size_t matCount, const Size& size, RNG& rng)
1057     {
1058         const int maxMatChannels = 10;
1059
1060         vector<Mat> src(matCount);
1061         int channels = 0;
1062         for(size_t i = 0; i < src.size(); i++)
1063         {
1064             Mat m(size, CV_MAKETYPE(depth, rng.uniform(1,maxMatChannels)));
1065             rng.fill(m, RNG::UNIFORM, 0, 100, true);
1066             channels += m.channels();
1067             src[i] = m;
1068         }
1069
1070         Mat dst;
1071         merge(src, dst);
1072
1073         // check result
1074         std::stringstream commonLog;
1075         commonLog << "Depth " << depth << " :";
1076         if(dst.depth() != depth)
1077         {
1078             ts->printf(cvtest::TS::LOG, "%s incorrect depth of dst (%d instead of %d)\n",
1079                        commonLog.str().c_str(), dst.depth(), depth);
1080             return cvtest::TS::FAIL_INVALID_OUTPUT;
1081         }
1082         if(dst.size() != size)
1083         {
1084             ts->printf(cvtest::TS::LOG, "%s incorrect size of dst (%d x %d instead of %d x %d)\n",
1085                        commonLog.str().c_str(), dst.rows, dst.cols, size.height, size.width);
1086             return cvtest::TS::FAIL_INVALID_OUTPUT;
1087         }
1088         if(dst.channels() != channels)
1089         {
1090             ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst (%d instead of %d)\n",
1091                        commonLog.str().c_str(), dst.channels(), channels);
1092             return cvtest::TS::FAIL_INVALID_OUTPUT;
1093         }
1094
1095         int diffElemCount = calcDiffElemCount(src, dst);
1096         if(diffElemCount > 0)
1097         {
1098             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1099                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1100             return cvtest::TS::FAIL_INVALID_OUTPUT;
1101         }
1102
1103         return cvtest::TS::OK;
1104     }
1105 };
1106
1107 class Core_SplitTest : public Core_MergeSplitBaseTest
1108 {
1109 public:
1110     Core_SplitTest() {}
1111     ~Core_SplitTest() {}
1112
1113 protected:
1114     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng)
1115     {
1116         Mat src(size, CV_MAKETYPE(depth, (int)channels));
1117         rng.fill(src, RNG::UNIFORM, 0, 100, true);
1118
1119         vector<Mat> dst;
1120         split(src, dst);
1121
1122         // check result
1123         std::stringstream commonLog;
1124         commonLog << "Depth " << depth << " :";
1125         if(dst.size() != channels)
1126         {
1127             ts->printf(cvtest::TS::LOG, "%s incorrect count of matrices in dst (%d instead of %d)\n",
1128                        commonLog.str().c_str(), dst.size(), channels);
1129             return cvtest::TS::FAIL_INVALID_OUTPUT;
1130         }
1131         for(size_t i = 0; i < dst.size(); i++)
1132         {
1133             if(dst[i].size() != size)
1134             {
1135                 ts->printf(cvtest::TS::LOG, "%s incorrect size of dst[%d] (%d x %d instead of %d x %d)\n",
1136                            commonLog.str().c_str(), i, dst[i].rows, dst[i].cols, size.height, size.width);
1137                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1138             }
1139             if(dst[i].depth() != depth)
1140             {
1141                 ts->printf(cvtest::TS::LOG, "%s: incorrect depth of dst[%d] (%d instead of %d)\n",
1142                            commonLog.str().c_str(), i, dst[i].depth(), depth);
1143                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1144             }
1145             if(dst[i].channels() != 1)
1146             {
1147                 ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst[%d] (%d instead of %d)\n",
1148                            commonLog.str().c_str(), i, dst[i].channels(), 1);
1149                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1150             }
1151         }
1152
1153         int diffElemCount = calcDiffElemCount(dst, src);
1154         if(diffElemCount > 0)
1155         {
1156             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1157                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1158             return cvtest::TS::FAIL_INVALID_OUTPUT;
1159         }
1160
1161         return cvtest::TS::OK;
1162     }
1163 };
1164
1165 TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); }
1166 TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); }
1167
1168 TEST(Core_Merge, shape_operations) { Core_MergeTest test; test.safe_run(); }
1169 TEST(Core_Split, shape_operations) { Core_SplitTest test; test.safe_run(); }
1170
1171
1172 TEST(Core_IOArray, submat_assignment)
1173 {
1174     Mat1f A = Mat1f::zeros(2,2);
1175     Mat1f B = Mat1f::ones(1,3);
1176
1177     EXPECT_THROW( B.colRange(0,3).copyTo(A.row(0)), cv::Exception );
1178
1179     EXPECT_NO_THROW( B.colRange(0,2).copyTo(A.row(0)) );
1180
1181     EXPECT_EQ( 1.0f, A(0,0) );
1182     EXPECT_EQ( 1.0f, A(0,1) );
1183 }
1184
1185 void OutputArray_create1(OutputArray m) { m.create(1, 2, CV_32S); }
1186 void OutputArray_create2(OutputArray m) { m.create(1, 3, CV_32F); }
1187
1188 TEST(Core_IOArray, submat_create)
1189 {
1190     Mat1f A = Mat1f::zeros(2,2);
1191
1192     EXPECT_THROW( OutputArray_create1(A.row(0)), cv::Exception );
1193     EXPECT_THROW( OutputArray_create2(A.row(0)), cv::Exception );
1194 }
1195
1196 TEST(Core_Mat, issue4457_pass_null_ptr)
1197 {
1198     ASSERT_ANY_THROW(cv::Mat mask(45, 45, CV_32F, 0));
1199 }
1200
1201 TEST(Core_Mat, reshape_1942)
1202 {
1203     cv::Mat A = (cv::Mat_<float>(2,3) << 3.4884074, 1.4159607, 0.78737736,  2.3456569, -0.88010466, 0.3009364);
1204     int cn = 0;
1205     ASSERT_NO_THROW(
1206         cv::Mat_<float> M = A.reshape(3);
1207         cn = M.channels();
1208     );
1209     ASSERT_EQ(1, cn);
1210 }
1211
1212 static void check_ndim_shape(const cv::Mat &mat, int cn, int ndims, const int *sizes)
1213 {
1214     EXPECT_EQ(mat.channels(), cn);
1215     EXPECT_EQ(mat.dims, ndims);
1216
1217     if (mat.dims != ndims)
1218         return;
1219
1220     for (int i = 0; i < ndims; i++)
1221         EXPECT_EQ(mat.size[i], sizes[i]);
1222 }
1223
1224 TEST(Core_Mat, reshape_ndims_2)
1225 {
1226     const cv::Mat A(8, 16, CV_8UC3);
1227     cv::Mat B;
1228
1229     {
1230         int new_sizes_mask[] = { 0, 3, 4, 4 };
1231         int new_sizes_real[] = { 8, 3, 4, 4 };
1232         ASSERT_NO_THROW(B = A.reshape(1, 4, new_sizes_mask));
1233         check_ndim_shape(B, 1, 4, new_sizes_real);
1234     }
1235     {
1236         int new_sizes[] = { 16, 8 };
1237         ASSERT_NO_THROW(B = A.reshape(0, 2, new_sizes));
1238         check_ndim_shape(B, 3, 2, new_sizes);
1239         EXPECT_EQ(B.rows, new_sizes[0]);
1240         EXPECT_EQ(B.cols, new_sizes[1]);
1241     }
1242     {
1243         int new_sizes[] = { 2, 5, 1, 3 };
1244         cv::Mat A_sliced = A(cv::Range::all(), cv::Range(0, 15));
1245         ASSERT_ANY_THROW(A_sliced.reshape(4, 4, new_sizes));
1246     }
1247 }
1248
1249 TEST(Core_Mat, reshape_ndims_4)
1250 {
1251     const int sizes[] = { 2, 6, 4, 12 };
1252     const cv::Mat A(4, sizes, CV_8UC3);
1253     cv::Mat B;
1254
1255     {
1256         int new_sizes_mask[] = { 0, 864 };
1257         int new_sizes_real[] = { 2, 864 };
1258         ASSERT_NO_THROW(B = A.reshape(1, 2, new_sizes_mask));
1259         check_ndim_shape(B, 1, 2, new_sizes_real);
1260         EXPECT_EQ(B.rows, new_sizes_real[0]);
1261         EXPECT_EQ(B.cols, new_sizes_real[1]);
1262     }
1263     {
1264         int new_sizes_mask[] = { 4, 0, 0, 2, 3 };
1265         int new_sizes_real[] = { 4, 6, 4, 2, 3 };
1266         ASSERT_NO_THROW(B = A.reshape(0, 5, new_sizes_mask));
1267         check_ndim_shape(B, 3, 5, new_sizes_real);
1268     }
1269     {
1270         int new_sizes_mask[] = { 1, 1 };
1271         ASSERT_ANY_THROW(A.reshape(0, 2, new_sizes_mask));
1272     }
1273     {
1274         int new_sizes_mask[] = { 4, 6, 3, 3, 0 };
1275         ASSERT_ANY_THROW(A.reshape(0, 5, new_sizes_mask));
1276     }
1277 }
1278
1279 TEST(Core_Mat, push_back)
1280 {
1281     Mat a = (Mat_<float>(1,2) << 3.4884074f, 1.4159607f);
1282     Mat b = (Mat_<float>(1,2) << 0.78737736f, 2.3456569f);
1283
1284     a.push_back(b);
1285
1286     ASSERT_EQ(2, a.cols);
1287     ASSERT_EQ(2, a.rows);
1288
1289     ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1290     ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1291     ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1292     ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1293
1294     Mat c = (Mat_<float>(2,2) << -0.88010466f, 0.3009364f, 2.22399974f, -5.45933905f);
1295
1296     ASSERT_EQ(c.rows, a.cols);
1297
1298     a.push_back(c.t());
1299
1300     ASSERT_EQ(2, a.cols);
1301     ASSERT_EQ(4, a.rows);
1302
1303     ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1304     ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1305     ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1306     ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1307     ASSERT_FLOAT_EQ(-0.88010466f, a.at<float>(2, 0));
1308     ASSERT_FLOAT_EQ(2.22399974f, a.at<float>(2, 1));
1309     ASSERT_FLOAT_EQ(0.3009364f, a.at<float>(3, 0));
1310     ASSERT_FLOAT_EQ(-5.45933905f, a.at<float>(3, 1));
1311
1312     a.push_back(Mat::ones(2, 2, CV_32FC1));
1313
1314     ASSERT_EQ(6, a.rows);
1315
1316     for(int row=4; row<a.rows; row++) {
1317
1318         for(int col=0; col<a.cols; col++) {
1319
1320             ASSERT_FLOAT_EQ(1.f, a.at<float>(row, col));
1321         }
1322     }
1323 }
1324
1325 TEST(Core_Mat, copyNx1ToVector)
1326 {
1327     cv::Mat_<uchar> src(5, 1);
1328     cv::Mat_<uchar> ref_dst8;
1329     cv::Mat_<ushort> ref_dst16;
1330     std::vector<uchar> dst8;
1331     std::vector<ushort> dst16;
1332
1333     src << 1, 2, 3, 4, 5;
1334
1335     src.copyTo(ref_dst8);
1336     src.copyTo(dst8);
1337
1338     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst8, cv::Mat_<uchar>(dst8));
1339
1340     src.convertTo(ref_dst16, CV_16U);
1341     src.convertTo(dst16, CV_16U);
1342
1343     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst16, cv::Mat_<ushort>(dst16));
1344 }
1345
1346 TEST(Core_Matx, fromMat_)
1347 {
1348     Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1349     Matx22d b(a);
1350     ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1351 }
1352
1353 #ifdef CV_CXX11
1354
1355 TEST(Core_Matx, from_initializer_list)
1356 {
1357     Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1358     Matx22d b = {10, 11, 12, 13};
1359     ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1360 }
1361
1362 TEST(Core_Mat, regression_9507)
1363 {
1364     cv::Mat m = Mat::zeros(5, 5, CV_8UC3);
1365     cv::Mat m2{m};
1366     EXPECT_EQ(25u, m2.total());
1367 }
1368
1369 #endif // CXX11
1370
1371 TEST(Core_InputArray, empty)
1372 {
1373     vector<vector<Point> > data;
1374     ASSERT_TRUE( _InputArray(data).empty() );
1375 }
1376
1377 TEST(Core_CopyMask, bug1918)
1378 {
1379     Mat_<unsigned char> tmpSrc(100,100);
1380     tmpSrc = 124;
1381     Mat_<unsigned char> tmpMask(100,100);
1382     tmpMask = 255;
1383     Mat_<unsigned char> tmpDst(100,100);
1384     tmpDst = 2;
1385     tmpSrc.copyTo(tmpDst,tmpMask);
1386     ASSERT_EQ(sum(tmpDst)[0], 124*100*100);
1387 }
1388
1389 TEST(Core_SVD, orthogonality)
1390 {
1391     for( int i = 0; i < 2; i++ )
1392     {
1393         int type = i == 0 ? CV_32F : CV_64F;
1394         Mat mat_D(2, 2, type);
1395         mat_D.setTo(88.);
1396         Mat mat_U, mat_W;
1397         SVD::compute(mat_D, mat_W, mat_U, noArray(), SVD::FULL_UV);
1398         mat_U *= mat_U.t();
1399         ASSERT_LT(cvtest::norm(mat_U, Mat::eye(2, 2, type), NORM_INF), 1e-5);
1400     }
1401 }
1402
1403
1404 TEST(Core_SparseMat, footprint)
1405 {
1406     int n = 1000000;
1407     int sz[] = { n, n };
1408     SparseMat m(2, sz, CV_64F);
1409
1410     int nodeSize0 = (int)m.hdr->nodeSize;
1411     double dataSize0 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1412     printf("before: node size=%d bytes, data size=%.0f Mbytes\n", nodeSize0, dataSize0);
1413
1414     for (int i = 0; i < n; i++)
1415     {
1416         m.ref<double>(i, i) = 1;
1417     }
1418
1419     double dataSize1 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1420     double threshold = (n*nodeSize0*1.6 + n*2.*sizeof(size_t))*1e-6;
1421     printf("after: data size=%.0f Mbytes, threshold=%.0f MBytes\n", dataSize1, threshold);
1422
1423     ASSERT_LE((int)m.hdr->nodeSize, 32);
1424     ASSERT_LE(dataSize1, threshold);
1425 }
1426
1427
1428 // Can't fix without dirty hacks or broken user code (PR #4159)
1429 TEST(Core_Mat_vector, DISABLED_OutputArray_create_getMat)
1430 {
1431     cv::Mat_<uchar> src_base(5, 1);
1432     std::vector<uchar> dst8;
1433
1434     src_base << 1, 2, 3, 4, 5;
1435
1436     Mat src(src_base);
1437     OutputArray _dst(dst8);
1438     {
1439         _dst.create(src.rows, src.cols, src.type());
1440         Mat dst = _dst.getMat();
1441         EXPECT_EQ(src.dims, dst.dims);
1442         EXPECT_EQ(src.cols, dst.cols);
1443         EXPECT_EQ(src.rows, dst.rows);
1444     }
1445 }
1446
1447 TEST(Core_Mat_vector, copyTo_roi_column)
1448 {
1449     cv::Mat_<uchar> src_base(5, 2);
1450     std::vector<uchar> dst1;
1451
1452     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1453
1454     Mat src_full(src_base);
1455     Mat src(src_full.col(0));
1456 #if 0 // Can't fix without dirty hacks or broken user code (PR #4159)
1457     OutputArray _dst(dst1);
1458     {
1459         _dst.create(src.rows, src.cols, src.type());
1460         Mat dst = _dst.getMat();
1461         EXPECT_EQ(src.dims, dst.dims);
1462         EXPECT_EQ(src.cols, dst.cols);
1463         EXPECT_EQ(src.rows, dst.rows);
1464     }
1465 #endif
1466
1467     std::vector<uchar> dst2;
1468     src.copyTo(dst2);
1469     std::cout << "src = " << src << std::endl;
1470     std::cout << "dst = " << Mat(dst2) << std::endl;
1471     EXPECT_EQ((size_t)5, dst2.size());
1472     EXPECT_EQ(1, (int)dst2[0]);
1473     EXPECT_EQ(3, (int)dst2[1]);
1474     EXPECT_EQ(5, (int)dst2[2]);
1475     EXPECT_EQ(7, (int)dst2[3]);
1476     EXPECT_EQ(9, (int)dst2[4]);
1477 }
1478
1479 TEST(Core_Mat_vector, copyTo_roi_row)
1480 {
1481     cv::Mat_<uchar> src_base(2, 5);
1482     std::vector<uchar> dst1;
1483
1484     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1485
1486     Mat src_full(src_base);
1487     Mat src(src_full.row(0));
1488     OutputArray _dst(dst1);
1489     {
1490         _dst.create(src.rows, src.cols, src.type());
1491         Mat dst = _dst.getMat();
1492         EXPECT_EQ(src.dims, dst.dims);
1493         EXPECT_EQ(src.cols, dst.cols);
1494         EXPECT_EQ(src.rows, dst.rows);
1495     }
1496
1497     std::vector<uchar> dst2;
1498     src.copyTo(dst2);
1499     std::cout << "src = " << src << std::endl;
1500     std::cout << "dst = " << Mat(dst2) << std::endl;
1501     EXPECT_EQ((size_t)5, dst2.size());
1502     EXPECT_EQ(1, (int)dst2[0]);
1503     EXPECT_EQ(2, (int)dst2[1]);
1504     EXPECT_EQ(3, (int)dst2[2]);
1505     EXPECT_EQ(4, (int)dst2[3]);
1506     EXPECT_EQ(5, (int)dst2[4]);
1507 }
1508
1509 TEST(Mat, regression_5991)
1510 {
1511     int sz[] = {2,3,2};
1512     Mat mat(3, sz, CV_32F, Scalar(1));
1513     ASSERT_NO_THROW(mat.convertTo(mat, CV_8U));
1514     EXPECT_EQ(sz[0], mat.size[0]);
1515     EXPECT_EQ(sz[1], mat.size[1]);
1516     EXPECT_EQ(sz[2], mat.size[2]);
1517     EXPECT_EQ(0, cvtest::norm(mat, Mat(3, sz, CV_8U, Scalar(1)), NORM_INF));
1518 }
1519
1520 TEST(Mat, regression_9720)
1521 {
1522     Mat mat(1, 1, CV_32FC1);
1523     mat.at<float>(0) = 1.f;
1524     const float a = 0.1f;
1525     Mat me1 = (Mat)(mat.mul((a / mat)));
1526     Mat me2 = (Mat)(mat.mul((Mat)(a / mat)));
1527     Mat me3 = (Mat)(mat.mul((a * mat)));
1528     Mat me4 = (Mat)(mat.mul((Mat)(a * mat)));
1529     EXPECT_EQ(me1.at<float>(0), me2.at<float>(0));
1530     EXPECT_EQ(me3.at<float>(0), me4.at<float>(0));
1531 }
1532
1533 #ifdef OPENCV_TEST_BIGDATA
1534 TEST(Mat, regression_6696_BigData_8Gb)
1535 {
1536     int width = 60000;
1537     int height = 10000;
1538
1539     Mat destImageBGR = Mat(height, width, CV_8UC3, Scalar(1, 2, 3, 0));
1540     Mat destImageA = Mat(height, width, CV_8UC1, Scalar::all(4));
1541
1542     vector<Mat> planes;
1543     split(destImageBGR, planes);
1544     planes.push_back(destImageA);
1545     merge(planes, destImageBGR);
1546
1547     EXPECT_EQ(1, destImageBGR.at<Vec4b>(0)[0]);
1548     EXPECT_EQ(2, destImageBGR.at<Vec4b>(0)[1]);
1549     EXPECT_EQ(3, destImageBGR.at<Vec4b>(0)[2]);
1550     EXPECT_EQ(4, destImageBGR.at<Vec4b>(0)[3]);
1551
1552     EXPECT_EQ(1, destImageBGR.at<Vec4b>(height-1, width-1)[0]);
1553     EXPECT_EQ(2, destImageBGR.at<Vec4b>(height-1, width-1)[1]);
1554     EXPECT_EQ(3, destImageBGR.at<Vec4b>(height-1, width-1)[2]);
1555     EXPECT_EQ(4, destImageBGR.at<Vec4b>(height-1, width-1)[3]);
1556 }
1557 #endif
1558
1559 TEST(Reduce, regression_should_fail_bug_4594)
1560 {
1561     cv::Mat src = cv::Mat::eye(4, 4, CV_8U);
1562     std::vector<int> dst;
1563
1564     EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MIN, CV_32S), cv::Exception);
1565     EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MAX, CV_32S), cv::Exception);
1566     EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_SUM, CV_32S));
1567     EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_AVG, CV_32S));
1568 }
1569
1570 TEST(Mat, push_back_vector)
1571 {
1572     cv::Mat result(1, 5, CV_32FC1);
1573
1574     std::vector<float> vec1(result.cols + 1);
1575     std::vector<int> vec2(result.cols);
1576
1577     EXPECT_THROW(result.push_back(vec1), cv::Exception);
1578     EXPECT_THROW(result.push_back(vec2), cv::Exception);
1579
1580     vec1.resize(result.cols);
1581
1582     for (int i = 0; i < 5; ++i)
1583         result.push_back(cv::Mat(vec1).reshape(1, 1));
1584
1585     ASSERT_EQ(6, result.rows);
1586 }
1587
1588 TEST(Mat, regression_5917_clone_empty)
1589 {
1590     Mat cloned;
1591     Mat_<Point2f> source(5, 0);
1592
1593     ASSERT_NO_THROW(cloned = source.clone());
1594 }
1595
1596 TEST(Mat, regression_7873_mat_vector_initialize)
1597 {
1598     std::vector<int> dims;
1599     dims.push_back(12);
1600     dims.push_back(3);
1601     dims.push_back(2);
1602     Mat multi_mat(dims, CV_32FC1, cv::Scalar(0));
1603
1604     ASSERT_EQ(3, multi_mat.dims);
1605     ASSERT_EQ(12, multi_mat.size[0]);
1606     ASSERT_EQ(3, multi_mat.size[1]);
1607     ASSERT_EQ(2, multi_mat.size[2]);
1608
1609     std::vector<Range> ranges;
1610     ranges.push_back(Range(1, 2));
1611     ranges.push_back(Range::all());
1612     ranges.push_back(Range::all());
1613     Mat sub_mat = multi_mat(ranges);
1614
1615     ASSERT_EQ(3, sub_mat.dims);
1616     ASSERT_EQ(1, sub_mat.size[0]);
1617     ASSERT_EQ(3, sub_mat.size[1]);
1618     ASSERT_EQ(2, sub_mat.size[2]);
1619 }
1620
1621 TEST(Mat, regression_10507_mat_setTo)
1622 {
1623     Size sz(6, 4);
1624     Mat test_mask(sz, CV_8UC1, cv::Scalar::all(255));
1625     test_mask.at<uchar>(1,0) = 0;
1626     test_mask.at<uchar>(0,1) = 0;
1627     for (int cn = 1; cn <= 4; cn++)
1628     {
1629         cv::Mat A(sz, CV_MAKE_TYPE(CV_32F, cn), cv::Scalar::all(5));
1630         A.setTo(cv::Scalar::all(std::numeric_limits<float>::quiet_NaN()), test_mask);
1631         int nans = 0;
1632         for (int y = 0; y < A.rows; y++)
1633         {
1634             for (int x = 0; x < A.cols; x++)
1635             {
1636                 for (int c = 0; c < cn; c++)
1637                 {
1638                     float v = A.ptr<float>(y, x)[c];
1639                     nans += (v == v) ? 0 : 1;
1640                 }
1641             }
1642         }
1643         EXPECT_EQ(nans, cn * (sz.area() - 2)) << "A=" << A << std::endl << "mask=" << test_mask << std::endl;
1644     }
1645 }
1646
1647 #ifdef CV_CXX_STD_ARRAY
1648 TEST(Core_Mat_array, outputArray_create_getMat)
1649 {
1650     cv::Mat_<uchar> src_base(5, 1);
1651     std::array<uchar, 5> dst8;
1652
1653     src_base << 1, 2, 3, 4, 5;
1654
1655     Mat src(src_base);
1656     OutputArray _dst(dst8);
1657
1658     {
1659         _dst.create(src.rows, src.cols, src.type());
1660         Mat dst = _dst.getMat();
1661         EXPECT_EQ(src.dims, dst.dims);
1662         EXPECT_EQ(src.cols, dst.cols);
1663         EXPECT_EQ(src.rows, dst.rows);
1664     }
1665 }
1666
1667 TEST(Core_Mat_array, copyTo_roi_column)
1668 {
1669     cv::Mat_<uchar> src_base(5, 2);
1670
1671     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1672
1673     Mat src_full(src_base);
1674     Mat src(src_full.col(0));
1675
1676     std::array<uchar, 5> dst1;
1677     src.copyTo(dst1);
1678     std::cout << "src = " << src << std::endl;
1679     std::cout << "dst = " << Mat(dst1) << std::endl;
1680     EXPECT_EQ((size_t)5, dst1.size());
1681     EXPECT_EQ(1, (int)dst1[0]);
1682     EXPECT_EQ(3, (int)dst1[1]);
1683     EXPECT_EQ(5, (int)dst1[2]);
1684     EXPECT_EQ(7, (int)dst1[3]);
1685     EXPECT_EQ(9, (int)dst1[4]);
1686 }
1687
1688 TEST(Core_Mat_array, copyTo_roi_row)
1689 {
1690     cv::Mat_<uchar> src_base(2, 5);
1691     std::array<uchar, 5> dst1;
1692
1693     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1694
1695     Mat src_full(src_base);
1696     Mat src(src_full.row(0));
1697     OutputArray _dst(dst1);
1698     {
1699         _dst.create(5, 1, src.type());
1700         Mat dst = _dst.getMat();
1701         EXPECT_EQ(src.dims, dst.dims);
1702         EXPECT_EQ(1, dst.cols);
1703         EXPECT_EQ(5, dst.rows);
1704     }
1705
1706     std::array<uchar, 5> dst2;
1707     src.copyTo(dst2);
1708     std::cout << "src = " << src << std::endl;
1709     std::cout << "dst = " << Mat(dst2) << std::endl;
1710     EXPECT_EQ(1, (int)dst2[0]);
1711     EXPECT_EQ(2, (int)dst2[1]);
1712     EXPECT_EQ(3, (int)dst2[2]);
1713     EXPECT_EQ(4, (int)dst2[3]);
1714     EXPECT_EQ(5, (int)dst2[4]);
1715 }
1716
1717 TEST(Core_Mat_array, SplitMerge)
1718 {
1719     std::array<cv::Mat, 3> src;
1720     for (size_t i = 0; i < src.size(); ++i)
1721     {
1722         src[i] = Mat(10, 10, CV_8U, Scalar((double)(16 * (i + 1))));
1723     }
1724
1725     Mat merged;
1726     merge(src, merged);
1727
1728     std::array<cv::Mat, 3> dst;
1729     split(merged, dst);
1730
1731     for (size_t i = 0; i < dst.size(); ++i)
1732     {
1733         EXPECT_EQ(0, cvtest::norm(src[i], dst[i], NORM_INF));
1734     }
1735 }
1736 #endif
1737
1738 TEST(Mat, regression_8680)
1739 {
1740    Mat_<Point2i> mat(3,1);
1741    ASSERT_EQ(mat.channels(), 2);
1742    mat.release();
1743    ASSERT_EQ(mat.channels(), 2);
1744 }
1745
1746 #ifdef CV_CXX11
1747
1748 TEST(Mat_, range_based_for)
1749 {
1750     Mat_<uchar> img = Mat_<uchar>::zeros(3, 3);
1751
1752     for(auto& pixel : img)
1753     {
1754         pixel = 1;
1755     }
1756
1757     Mat_<uchar> ref(3, 3);
1758     ref.setTo(Scalar(1));
1759     ASSERT_DOUBLE_EQ(cvtest::norm(img, ref, NORM_INF), 0.);
1760 }
1761
1762 TEST(Mat, from_initializer_list)
1763 {
1764     Mat A({1.f, 2.f, 3.f});
1765     Mat_<float> B(3, 1); B << 1, 2, 3;
1766     Mat_<float> C({3}, {1,2,3});
1767
1768     ASSERT_EQ(A.type(), CV_32F);
1769     ASSERT_DOUBLE_EQ(cvtest::norm(A, B, NORM_INF), 0.);
1770     ASSERT_DOUBLE_EQ(cvtest::norm(A, C, NORM_INF), 0.);
1771     ASSERT_DOUBLE_EQ(cvtest::norm(B, C, NORM_INF), 0.);
1772
1773     auto D = Mat_<double>({2, 3}, {1, 2, 3, 4, 5, 6});
1774     EXPECT_EQ(2, D.rows);
1775     EXPECT_EQ(3, D.cols);
1776 }
1777
1778 TEST(Mat_, from_initializer_list)
1779 {
1780     Mat_<float> A = {1, 2, 3};
1781     Mat_<float> B(3, 1); B << 1, 2, 3;
1782     Mat_<float> C({3}, {1,2,3});
1783
1784     ASSERT_DOUBLE_EQ(cvtest::norm(A, B, NORM_INF), 0.);
1785     ASSERT_DOUBLE_EQ(cvtest::norm(A, C, NORM_INF), 0.);
1786     ASSERT_DOUBLE_EQ(cvtest::norm(B, C, NORM_INF), 0.);
1787 }
1788
1789
1790 TEST(Mat, template_based_ptr)
1791 {
1792     Mat mat = (Mat_<float>(2, 2) << 11.0f, 22.0f, 33.0f, 44.0f);
1793     int idx[2] = {1, 0};
1794     ASSERT_FLOAT_EQ(33.0f, *(mat.ptr<float>(idx)));
1795     idx[0] = 1;
1796     idx[1] = 1;
1797     ASSERT_FLOAT_EQ(44.0f, *(mat.ptr<float>(idx)));
1798 }
1799
1800 TEST(Mat_, template_based_ptr)
1801 {
1802     int dim[4] = {2, 2, 1, 2};
1803     Mat_<float> mat = (Mat_<float>(4, dim) << 11.0f, 22.0f, 33.0f, 44.0f,
1804                                               55.0f, 66.0f, 77.0f, 88.0f);
1805     int idx[4] = {1, 0, 0, 1};
1806     ASSERT_FLOAT_EQ(66.0f, *(mat.ptr<float>(idx)));
1807 }
1808
1809 #endif
1810
1811
1812 BIGDATA_TEST(Mat, push_back_regression_4158)  // memory usage: ~10.6 Gb
1813 {
1814     Mat result;
1815
1816     Mat tail(100, 500000, CV_32FC2, Scalar(1, 2));
1817
1818     tail.copyTo(result);
1819     for (int i = 1; i < 15; i++)
1820     {
1821         result.push_back(tail);
1822         std::cout << "i = " << i << "  result = " << result.size() << "   used = " << (uint64)result.total()*result.elemSize()*(1.0 / (1 << 20)) << " Mb"
1823             << "   allocated=" << (uint64)(result.datalimit - result.datastart)*(1.0 / (1 << 20)) << " Mb" << std::endl;
1824     }
1825     for (int i = 0; i < 15; i++)
1826     {
1827         Rect roi(0, tail.rows * i, tail.cols, tail.rows);
1828         int nz = countNonZero(result(roi).reshape(1) == 2);
1829         EXPECT_EQ(tail.total(), (size_t)nz) << "i=" << i;
1830     }
1831 }
1832
1833
1834 TEST(Core_Merge, hang_12171)
1835 {
1836     Mat src1(4, 24, CV_8UC1, Scalar::all(1));
1837     Mat src2(4, 24, CV_8UC1, Scalar::all(2));
1838     Rect src_roi(0, 0, 23, 4);
1839     Mat src_channels[2] = { src1(src_roi), src2(src_roi) };
1840     Mat dst(4, 24, CV_8UC2, Scalar::all(5));
1841     Rect dst_roi(1, 0, 23, 4);
1842     cv::merge(src_channels, 2, dst(dst_roi));
1843     EXPECT_EQ(5, dst.ptr<uchar>()[0]);
1844     EXPECT_EQ(5, dst.ptr<uchar>()[1]);
1845     EXPECT_EQ(1, dst.ptr<uchar>()[2]);
1846     EXPECT_EQ(2, dst.ptr<uchar>()[3]);
1847     EXPECT_EQ(5, dst.ptr<uchar>(1)[0]);
1848     EXPECT_EQ(5, dst.ptr<uchar>(1)[1]);
1849     EXPECT_EQ(1, dst.ptr<uchar>(1)[2]);
1850     EXPECT_EQ(2, dst.ptr<uchar>(1)[3]);
1851 }
1852
1853 TEST(Core_Split, hang_12171)
1854 {
1855     Mat src(4, 24, CV_8UC2, Scalar(1,2,3,4));
1856     Rect src_roi(0, 0, 23, 4);
1857     Mat dst1(4, 24, CV_8UC1, Scalar::all(5));
1858     Mat dst2(4, 24, CV_8UC1, Scalar::all(10));
1859     Rect dst_roi(0, 0, 23, 4);
1860     Mat dst[2] = { dst1(dst_roi), dst2(dst_roi) };
1861     cv::split(src(src_roi), dst);
1862     EXPECT_EQ(1, dst1.ptr<uchar>()[0]);
1863     EXPECT_EQ(1, dst1.ptr<uchar>()[1]);
1864     EXPECT_EQ(2, dst2.ptr<uchar>()[0]);
1865     EXPECT_EQ(2, dst2.ptr<uchar>()[1]);
1866     EXPECT_EQ(1, dst1.ptr<uchar>(1)[0]);
1867     EXPECT_EQ(1, dst1.ptr<uchar>(1)[1]);
1868     EXPECT_EQ(2, dst2.ptr<uchar>(1)[0]);
1869     EXPECT_EQ(2, dst2.ptr<uchar>(1)[1]);
1870 }
1871
1872 TEST(Core_Split, crash_12171)
1873 {
1874     Mat src(4, 40, CV_8UC2, Scalar(1,2,3,4));
1875     Rect src_roi(0, 0, 39, 4);
1876     Mat dst1(4, 40, CV_8UC1, Scalar::all(5));
1877     Mat dst2(4, 40, CV_8UC1, Scalar::all(10));
1878     Rect dst_roi(0, 0, 39, 4);
1879     Mat dst[2] = { dst1(dst_roi), dst2(dst_roi) };
1880     cv::split(src(src_roi), dst);
1881     EXPECT_EQ(1, dst1.ptr<uchar>()[0]);
1882     EXPECT_EQ(1, dst1.ptr<uchar>()[1]);
1883     EXPECT_EQ(2, dst2.ptr<uchar>()[0]);
1884     EXPECT_EQ(2, dst2.ptr<uchar>()[1]);
1885     EXPECT_EQ(1, dst1.ptr<uchar>(1)[0]);
1886     EXPECT_EQ(1, dst1.ptr<uchar>(1)[1]);
1887     EXPECT_EQ(2, dst2.ptr<uchar>(1)[0]);
1888     EXPECT_EQ(2, dst2.ptr<uchar>(1)[1]);
1889 }
1890
1891 TEST(Core_Merge, bug_13544)
1892 {
1893     Mat src1(2, 2, CV_8UC3, Scalar::all(1));
1894     Mat src2(2, 2, CV_8UC3, Scalar::all(2));
1895     Mat src3(2, 2, CV_8UC3, Scalar::all(3));
1896     Mat src_arr[] = { src1, src2, src3 };
1897     Mat dst;
1898     merge(src_arr, 3, dst);
1899     ASSERT_EQ(9, dst.channels());  // Avoid memory access out of buffer
1900     EXPECT_EQ(3, (int)dst.ptr<uchar>(0)[6]);
1901     EXPECT_EQ(3, (int)dst.ptr<uchar>(0)[7]);
1902     EXPECT_EQ(3, (int)dst.ptr<uchar>(0)[8]);
1903     EXPECT_EQ(1, (int)dst.ptr<uchar>(1)[0]);
1904     EXPECT_EQ(1, (int)dst.ptr<uchar>(1)[1]);
1905     EXPECT_EQ(1, (int)dst.ptr<uchar>(1)[2]);
1906     EXPECT_EQ(2, (int)dst.ptr<uchar>(1)[3]);
1907     EXPECT_EQ(2, (int)dst.ptr<uchar>(1)[4]);
1908     EXPECT_EQ(2, (int)dst.ptr<uchar>(1)[5]);
1909     EXPECT_EQ(3, (int)dst.ptr<uchar>(1)[6]);
1910     EXPECT_EQ(3, (int)dst.ptr<uchar>(1)[7]);
1911     EXPECT_EQ(3, (int)dst.ptr<uchar>(1)[8]);
1912 }
1913
1914 struct CustomType  // like cv::Keypoint
1915 {
1916     Point2f pt;
1917     float size;
1918     float angle;
1919     float response;
1920     int octave;
1921     int class_id;
1922 };
1923
1924 static void test_CustomType(InputArray src_, OutputArray dst_)
1925 {
1926     Mat src = src_.getMat();
1927     ASSERT_EQ(sizeof(CustomType), src.elemSize());
1928     CV_CheckTypeEQ(src.type(), CV_MAKETYPE(CV_8U, sizeof(CustomType)), "");
1929
1930     CustomType* kpt = NULL;
1931     {
1932         Mat dst = dst_.getMat();
1933         for (size_t i = 0; i < dst.total(); i++)
1934         {
1935             kpt = dst.ptr<CustomType>(0) + i;
1936             kpt->octave = (int)i;
1937         }
1938     }
1939     const int N = (int)src.total();
1940     dst_.create(1, N * 2, rawType<CustomType>());
1941     Mat dst = dst_.getMat();
1942     for (size_t i = N; i < dst.total(); i++)
1943     {
1944         kpt = dst.ptr<CustomType>(0) + i;
1945         kpt->octave = -(int)i;
1946     }
1947 #if 0 // Compilation error
1948     CustomType& kpt = dst.at<CustomType>(0, 5);
1949 #endif
1950 }
1951
1952 TEST(Core_InputArray, support_CustomType)
1953 {
1954     std::vector<CustomType> kp1(5);
1955     std::vector<CustomType> kp2(3);
1956     test_CustomType(rawIn(kp1), rawOut(kp2));
1957     ASSERT_EQ((size_t)10, kp2.size());
1958     for (int i = 0; i < 3; i++)
1959     {
1960         EXPECT_EQ(i, kp2[i].octave);
1961     }
1962     for (int i = 3; i < 5; i++)
1963     {
1964         EXPECT_EQ(0, kp2[i].octave);
1965     }
1966     for (int i = 5; i < 10; i++)
1967     {
1968         EXPECT_EQ(-i, kp2[i].octave);
1969     }
1970 }
1971
1972
1973 TEST(Core_InputArray, fetch_MatExpr)
1974 {
1975     Mat a(Size(10, 5), CV_32FC1, 5);
1976     Mat b(Size(10, 5), CV_32FC1, 2);
1977     MatExpr expr = a * b.t();                    // gemm expression
1978     Mat dst;
1979     cv::add(expr, Scalar(1), dst);               // invoke gemm() here
1980     void* expr_data = expr.a.data;
1981     Mat result = expr;                           // should not call gemm() here again
1982     EXPECT_EQ(expr_data, result.data);           // expr data is reused
1983     EXPECT_EQ(dst.size(), result.size());
1984 }
1985
1986
1987 TEST(Core_Vectors, issue_13078)
1988 {
1989     float floats_[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
1990     std::vector<float> floats(floats_, floats_ + 8);
1991     std::vector<int> ints(4);
1992
1993     Mat m(4, 1, CV_32FC1, floats.data(), sizeof(floats[0]) * 2);
1994
1995     m.convertTo(ints, CV_32S);
1996
1997     ASSERT_EQ(1, ints[0]);
1998     ASSERT_EQ(3, ints[1]);
1999     ASSERT_EQ(5, ints[2]);
2000     ASSERT_EQ(7, ints[3]);
2001 }
2002
2003 TEST(Core_Vectors, issue_13078_workaround)
2004 {
2005     float floats_[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2006     std::vector<float> floats(floats_, floats_ + 8);
2007     std::vector<int> ints(4);
2008
2009     Mat m(4, 1, CV_32FC1, floats.data(), sizeof(floats[0]) * 2);
2010
2011     m.convertTo(Mat(ints), CV_32S);
2012
2013     ASSERT_EQ(1, ints[0]);
2014     ASSERT_EQ(3, ints[1]);
2015     ASSERT_EQ(5, ints[2]);
2016     ASSERT_EQ(7, ints[3]);
2017 }
2018
2019 TEST(Core_MatExpr, issue_13926)
2020 {
2021     Mat M1 = (Mat_<double>(4,4,CV_64FC1) << 1, 2, 3, 4,
2022                                            5, 6, 7, 8,
2023                                            9, 10, 11, 12,
2024                                            13, 14, 15, 16);
2025
2026     Matx44d M2(1, 2, 3, 4,
2027                5, 6, 7, 8,
2028                9, 10, 11, 12,
2029                13, 14, 15, 16);
2030
2031     EXPECT_GE(1e-6, cvtest::norm(M1*M2, M1*M1, NORM_INF)) << Mat(M1*M2) << std::endl << Mat(M1*M1);
2032     EXPECT_GE(1e-6, cvtest::norm(M2*M1, M2*M2, NORM_INF)) << Mat(M2*M1) << std::endl << Mat(M2*M2);
2033 }
2034
2035 TEST(Core_MatExpr, issue_16655)
2036 {
2037     Mat a(Size(5, 5), CV_32FC3, Scalar::all(1));
2038     Mat b(Size(5, 5), CV_32FC3, Scalar::all(2));
2039     MatExpr ab_expr = a != b;
2040     Mat ab_mat = ab_expr;
2041     EXPECT_EQ(CV_8UC3, ab_expr.type())
2042         << "MatExpr: CV_8UC3 != " << typeToString(ab_expr.type());
2043     EXPECT_EQ(CV_8UC3, ab_mat.type())
2044         << "Mat: CV_8UC3 != " << typeToString(ab_mat.type());
2045 }
2046
2047 TEST(Core_MatExpr, issue_16689)
2048 {
2049     Mat a(Size(10, 5), CV_32FC1, 5);
2050     Mat b(Size(10, 5), CV_32FC1, 2);
2051     Mat bt(Size(5, 10), CV_32FC1, 3);
2052     {
2053         MatExpr r = a * bt;  // gemm
2054         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5] x [5x10] => [5x5]";
2055     }
2056     {
2057         MatExpr r = a * b.t();  // gemm
2058         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5] x [10x5].t() => [5x5]";
2059     }
2060     {
2061         MatExpr r = a.t() * b;  // gemm
2062         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5].t() x [10x5] => [10x10]";
2063     }
2064     {
2065         MatExpr r = a.t() * bt.t();  // gemm
2066         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5].t() x [5x10].t() => [10x10]";
2067     }
2068 }
2069
2070 #ifdef HAVE_EIGEN
2071 TEST(Core_Eigen, eigen2cv_check_Mat_type)
2072 {
2073     Mat A(4, 4, CV_32FC1, Scalar::all(0));
2074     Eigen::MatrixXf eigen_A;
2075     cv2eigen(A, eigen_A);
2076
2077     Mat_<float> f_mat;
2078     EXPECT_NO_THROW(eigen2cv(eigen_A, f_mat));
2079     EXPECT_EQ(CV_32FC1, f_mat.type());
2080
2081     Mat_<double> d_mat;
2082     EXPECT_ANY_THROW(eigen2cv(eigen_A, d_mat));
2083     //EXPECT_EQ(CV_64FC1, d_mat.type());
2084 }
2085 #endif // HAVE_EIGEN
2086
2087 #ifdef OPENCV_EIGEN_TENSOR_SUPPORT
2088 TEST(Core_Eigen, cv2eigen_check_tensor_conversion)
2089 {
2090     Mat A(2, 3, CV_32FC3);
2091     float value = 0;
2092     for(int row=0; row<A.rows; row++)
2093         for(int col=0; col<A.cols; col++)
2094             for(int ch=0; ch<A.channels(); ch++)
2095                 A.at<Vec3f>(row,col)[ch] = value++;
2096
2097     Eigen::Tensor<float, 3, Eigen::RowMajor> row_tensor;
2098     cv2eigen(A, row_tensor);
2099
2100     float* mat_ptr = (float*)A.data;
2101     float* tensor_ptr = row_tensor.data();
2102     for (int i=0; i< row_tensor.size(); i++)
2103         ASSERT_FLOAT_EQ(mat_ptr[i], tensor_ptr[i]);
2104
2105     Eigen::Tensor<float, 3, Eigen::ColMajor> col_tensor;
2106     cv2eigen(A, col_tensor);
2107     value = 0;
2108     for(int row=0; row<A.rows; row++)
2109         for(int col=0; col<A.cols; col++)
2110             for(int ch=0; ch<A.channels(); ch++)
2111                 ASSERT_FLOAT_EQ(value++, col_tensor(row,col,ch));
2112 }
2113 #endif // OPENCV_EIGEN_TENSOR_SUPPORT
2114
2115 #ifdef OPENCV_EIGEN_TENSOR_SUPPORT
2116 TEST(Core_Eigen, eigen2cv_check_tensor_conversion)
2117 {
2118     Eigen::Tensor<float, 3, Eigen::RowMajor> row_tensor(2,3,3);
2119     Eigen::Tensor<float, 3, Eigen::ColMajor> col_tensor(2,3,3);
2120     float value = 0;
2121     for(int row=0; row<row_tensor.dimension(0); row++)
2122         for(int col=0; col<row_tensor.dimension(1); col++)
2123             for(int ch=0; ch<row_tensor.dimension(2); ch++)
2124             {
2125                 row_tensor(row,col,ch) = value;
2126                 col_tensor(row,col,ch) = value;
2127                 value++;
2128             }
2129
2130     Mat A;
2131     eigen2cv(row_tensor, A);
2132
2133     float* tensor_ptr = row_tensor.data();
2134     float* mat_ptr = (float*)A.data;
2135     for (int i=0; i< row_tensor.size(); i++)
2136         ASSERT_FLOAT_EQ(tensor_ptr[i], mat_ptr[i]);
2137
2138     Mat B;
2139     eigen2cv(col_tensor, B);
2140
2141     value = 0;
2142     for(int row=0; row<B.rows; row++)
2143         for(int col=0; col<B.cols; col++)
2144             for(int ch=0; ch<B.channels(); ch++)
2145                 ASSERT_FLOAT_EQ(value++, B.at<Vec3f>(row,col)[ch]);
2146 }
2147 #endif // OPENCV_EIGEN_TENSOR_SUPPORT
2148
2149 #ifdef OPENCV_EIGEN_TENSOR_SUPPORT
2150 TEST(Core_Eigen, cv2eigen_tensormap_check_tensormap_access)
2151 {
2152     float arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
2153     Mat a_mat(2, 2, CV_32FC3, arr);
2154     Eigen::TensorMap<Eigen::Tensor<float, 3, Eigen::RowMajor>> a_tensor = cv2eigen_tensormap<float>(a_mat);
2155
2156     for(int i=0; i<a_mat.rows; i++) {
2157         for (int j=0; j<a_mat.cols; j++) {
2158             for (int ch=0; ch<a_mat.channels(); ch++) {
2159                 ASSERT_FLOAT_EQ(a_mat.at<Vec3f>(i,j)[ch], a_tensor(i,j,ch));
2160                 ASSERT_EQ(&a_mat.at<Vec3f>(i,j)[ch], &a_tensor(i,j,ch));
2161             }
2162         }
2163     }
2164 }
2165 #endif // OPENCV_EIGEN_TENSOR_SUPPORT
2166
2167 TEST(Mat, regression_12943)  // memory usage: ~4.5 Gb
2168 {
2169     applyTestTag(CV_TEST_TAG_MEMORY_6GB);
2170
2171     const int width = 0x8000;
2172     const int height = 0x10001;
2173
2174     cv::Mat src(height, width, CV_8UC1, Scalar::all(128));
2175
2176     cv::Mat dst;
2177     cv::flip(src, dst, 0);
2178 }
2179
2180 TEST(Mat, empty_iterator_16855)
2181 {
2182     cv::Mat m;
2183     EXPECT_NO_THROW(m.begin<uchar>());
2184     EXPECT_NO_THROW(m.end<uchar>());
2185     EXPECT_TRUE(m.begin<uchar>() == m.end<uchar>());
2186 }
2187
2188
2189 TEST(Mat, regression_18473)
2190 {
2191     std::vector<int> sizes(3);
2192     sizes[0] = 20;
2193     sizes[1] = 50;
2194     sizes[2] = 100;
2195 #if 1  // with the fix
2196     std::vector<size_t> steps(2);
2197     steps[0] = 50*100*2;
2198     steps[1] = 100*2;
2199 #else  // without the fix
2200     std::vector<size_t> steps(3);
2201     steps[0] = 50*100*2;
2202     steps[1] = 100*2;
2203     steps[2] = 2;
2204 #endif
2205     std::vector<short> data(20*50*100, 0);  // 1Mb
2206     data[data.size() - 1] = 5;
2207
2208     // param steps Array of ndims-1 steps
2209     Mat m(sizes, CV_16SC1, (void*)data.data(), (const size_t*)steps.data());
2210
2211     ASSERT_FALSE(m.empty());
2212     EXPECT_EQ((int)5, (int)m.at<short>(19, 49, 99));
2213 }
2214
2215
2216 }} // namespace