]> rtime.felk.cvut.cz Git - opencv.git/blobdiff - opencv/tests/cxcore/src/aarithm.cpp
round scalars in the case of integer arrays in adds, subrs and absdiffs tests (will...
[opencv.git] / opencv / tests / cxcore / src / aarithm.cpp
index 8af52ee8c71f9354779c45cde04aa7dff61a2b7e..844a46bcb368fdcd7b3b332c24665c2fe05b1dff 100644 (file)
@@ -65,9 +65,11 @@ protected:
     void get_timing_test_array_types_and_sizes( int /*test_case_idx*/,
                         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images );
     void generate_scalars( int depth );
+    void finalize_scalar( CvScalar& s );
     CvScalar alpha, beta, gamma;
     int gen_scalars;
     bool calc_abs;
+    bool test_nd;
 };
 
 
@@ -98,6 +100,7 @@ CxCore_ArithmTestImpl::CxCore_ArithmTestImpl( const char* test_name, const char*
     whole_size_list = arithm_whole_sizes;
     depth_list = arithm_depths;
     cn_list = arithm_channels;
+    test_nd = false;
 }
 
 
@@ -113,7 +116,7 @@ void CxCore_ArithmTestImpl::generate_scalars( int depth )
     {
         CvRNG* rng = ts->get_rng();
         int i;
-        double m = 10.;
+        double m = 3.;
         for( i = 0; i < 4; i++ )
         {
             if( gen_scalars & 1 )
@@ -168,15 +171,23 @@ void CxCore_ArithmTestImpl::generate_scalars( int depth )
     }
 }
 
+void CxCore_ArithmTestImpl::finalize_scalar( CvScalar& s )
+{
+    int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
+    if( depth < CV_32F )
+        s = cvScalar(cvRound(s.val[0]), cvRound(s.val[1]), cvRound(s.val[2]), cvRound(s.val[3]));
+}
+
 void CxCore_ArithmTestImpl::get_test_array_types_and_sizes( int test_case_idx,
                                                             CvSize** sizes, int** types )
 {
     CvRNG* rng = ts->get_rng();
-    int depth = cvTsRandInt(rng)%CV_64F;
+    int depth = cvTsRandInt(rng)%(CV_64F+1);
     int cn = cvTsRandInt(rng) % 4 + 1;
     int i, j;
-    CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
     depth += depth == CV_8S;
+    CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
+    generate_scalars( depth );
 
     for( i = 0; i < max_arr; i++ )
     {
@@ -187,6 +198,7 @@ void CxCore_ArithmTestImpl::get_test_array_types_and_sizes( int test_case_idx,
             types[i][j] = type;
         }
     }
+    test_nd = cvTsRandInt(rng)%3 == 0;
 }
 
 
@@ -196,6 +208,7 @@ void CxCore_ArithmTestImpl::get_timing_test_array_types_and_sizes( int test_case
     CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
                                                       whole_sizes, are_images );
     generate_scalars( types[INPUT][0] );
+    test_nd = false;
 }
 
 
@@ -256,8 +269,21 @@ CxCore_AddTest::CxCore_AddTest()
 
 void CxCore_AddTest::run_func()
 {
-    cvAdd( test_array[INPUT][0], test_array[INPUT][1],
-        test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvAdd( test_array[INPUT][0], test_array[INPUT][1],
+            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
+        cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        if( !test_array[MASK][0] )
+            cv::add(a, b, c);
+        else
+            cv::add(a, b, c, cv::cvarrToMatND(test_array[MASK][0]));
+    }
 }
 
 CxCore_AddTest add_test;
@@ -281,8 +307,21 @@ CxCore_SubTest::CxCore_SubTest()
 
 void CxCore_SubTest::run_func()
 {
-    cvSub( test_array[INPUT][0], test_array[INPUT][1],
-           test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvSub( test_array[INPUT][0], test_array[INPUT][1],
+            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
+        cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        if( !test_array[MASK][0] )
+            cv::subtract(a, b, c);
+        else
+            cv::subtract(a, b, c, cv::cvarrToMatND(test_array[MASK][0]));
+    }
 }
 
 CxCore_SubTest sub_test;
@@ -307,8 +346,27 @@ CxCore_AddSTest::CxCore_AddSTest()
 
 void CxCore_AddSTest::run_func()
 {
-    cvAddS( test_array[INPUT][0], gamma,
-            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    finalize_scalar(gamma);
+    if(!test_nd)
+    {
+        if( test_mat[INPUT][0].cols % 2 == 0 )
+            cvAddS( test_array[INPUT][0], gamma,
+                test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+        else
+        {
+            cv::Mat a = cv::cvarrToMat(test_array[INPUT][0]),
+                c = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]);
+                cv::subtract(a, -cv::Scalar(gamma), c, test_array[MASK][0] ?
+                    cv::cvarrToMat(test_array[MASK][0]) : cv::Mat());
+        }
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::add( cv::cvarrToMatND(test_array[INPUT][0]),
+                 gamma, c, test_array[MASK][0] ?
+                 cv::cvarrToMatND(test_array[MASK][0]) : cv::MatND());
+    }
 }
 
 CxCore_AddSTest adds_test;
@@ -332,8 +390,20 @@ CxCore_SubRSTest::CxCore_SubRSTest()
 
 void CxCore_SubRSTest::run_func()
 {
-    cvSubRS( test_array[INPUT][0], gamma,
-             test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    finalize_scalar(gamma);
+    if(!test_nd)
+    {
+        cvSubRS( test_array[INPUT][0], gamma,
+                test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::subtract( gamma,
+                cv::cvarrToMatND(test_array[INPUT][0]),
+                c, test_array[MASK][0] ?
+                    cv::cvarrToMatND(test_array[MASK][0]) : cv::MatND());
+    }
 }
 
 CxCore_SubRSTest subrs_test;
@@ -368,22 +438,37 @@ void CxCore_AddWeightedTest::get_test_array_types_and_sizes( int test_case_idx,
 
 double CxCore_AddWeightedTest::get_success_error_level( int test_case_idx, int i, int j )
 {
-    if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
+    int type = cvGetElemType(test_array[i][j]), depth = CV_MAT_DEPTH(type);
+    if( depth <= CV_32S )
+        return 2;
+    if( depth == CV_32F )
     {
-        return alpha.val[0] != cvRound(alpha.val[0]) ||
-               beta.val[0] != cvRound(beta.val[0]) ||
-               gamma.val[0] != cvRound(gamma.val[0]);
+        CvScalar low=cvScalarAll(0), high=low;
+        get_minmax_bounds(i,j,type, &low, &high);
+        double a = (fabs(alpha.val[0])+fabs(beta.val[0]))*(fabs(low.val[0])+fabs(high.val[0]));
+        double b = fabs(gamma.val[0]);
+        return (a+b)*500*FLT_EPSILON;
     }
-    else
-        return CvArrTest::get_success_error_level( test_case_idx, i, j );
+    return CvArrTest::get_success_error_level( test_case_idx, i, j );
 }
 
 
 void CxCore_AddWeightedTest::run_func()
 {
-    cvAddWeighted( test_array[INPUT][0], alpha.val[0],
-                   test_array[INPUT][1], beta.val[0],
-                   gamma.val[0], test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvAddWeighted( test_array[INPUT][0], alpha.val[0],
+                    test_array[INPUT][1], beta.val[0],
+                    gamma.val[0], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::addWeighted(cv::cvarrToMatND(test_array[INPUT][0]),
+                alpha.val[0],
+                cv::cvarrToMatND(test_array[INPUT][1]),
+                beta.val[0], gamma.val[0], c);
+    }
 }
 
 CxCore_AddWeightedTest addweighted_test;
@@ -408,7 +493,17 @@ CxCore_AbsDiffTest::CxCore_AbsDiffTest()
 
 void CxCore_AbsDiffTest::run_func()
 {
-    cvAbsDiff( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvAbsDiff( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::absdiff(cv::cvarrToMatND(test_array[INPUT][0]),
+                cv::cvarrToMatND(test_array[INPUT][1]),
+                 c );
+    }
 }
 
 CxCore_AbsDiffTest absdiff_test;
@@ -432,7 +527,17 @@ CxCore_AbsDiffSTest::CxCore_AbsDiffSTest()
 
 void CxCore_AbsDiffSTest::run_func()
 {
-    cvAbsDiffS( test_array[INPUT][0], test_array[OUTPUT][0], gamma );
+    finalize_scalar(gamma);
+    if(!test_nd)
+    {
+        cvAbsDiffS( test_array[INPUT][0], test_array[OUTPUT][0], gamma );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::absdiff(cv::cvarrToMatND(test_array[INPUT][0]),
+                gamma, c);
+    }
 }
 
 CxCore_AbsDiffSTest absdiffs_test;
@@ -529,8 +634,18 @@ double CxCore_MulTest::get_success_error_level( int test_case_idx, int i, int j
 
 void CxCore_MulTest::run_func()
 {
-    cvMul( test_array[INPUT][0], test_array[INPUT][1],
-           test_array[OUTPUT][0], alpha.val[0] );
+    if(!test_nd)
+    {
+        cvMul( test_array[INPUT][0], test_array[INPUT][1],
+              test_array[OUTPUT][0], alpha.val[0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::multiply(cv::cvarrToMatND(test_array[INPUT][0]),
+                     cv::cvarrToMatND(test_array[INPUT][1]),
+                     c, alpha.val[0]);
+    }
 }
 
 void CxCore_MulTest::prepare_to_validation( int /*test_case_idx*/ )
@@ -569,8 +684,18 @@ void CxCore_DivTest::print_timing_params( int test_case_idx, char* ptr, int para
 
 void CxCore_DivTest::run_func()
 {
-    cvDiv( test_array[INPUT][0], test_array[INPUT][1],
-           test_array[OUTPUT][0], alpha.val[0] );
+    if(!test_nd)
+    {
+        cvDiv( test_array[INPUT][0], test_array[INPUT][1],
+              test_array[OUTPUT][0], alpha.val[0] );
+    }
+    else
+    {
+        cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::divide(cv::cvarrToMatND(test_array[INPUT][0]),
+                   b, c, alpha.val[0]);
+    }
 }
 
 void CxCore_DivTest::prepare_to_validation( int /*test_case_idx*/ )
@@ -610,8 +735,17 @@ void CxCore_RecipTest::print_timing_params( int test_case_idx, char* ptr, int pa
 
 void CxCore_RecipTest::run_func()
 {
-    cvDiv( 0, test_array[INPUT][0],
-           test_array[OUTPUT][0], gamma.val[0] );
+    if(!test_nd)
+    {
+        cvDiv( 0, test_array[INPUT][0],
+              test_array[OUTPUT][0], gamma.val[0] );
+    }
+    else
+    {
+        cv::MatND b = cv::cvarrToMatND(test_array[INPUT][0]);
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::divide(gamma.val[0], b, c);
+    }
 }
 
 void CxCore_RecipTest::prepare_to_validation( int /*test_case_idx*/ )
@@ -691,7 +825,13 @@ CxCore_SetIdentityTest::CxCore_SetIdentityTest() :
 
 void CxCore_SetIdentityTest::run_func()
 {
-    cvSetIdentity(test_array[OUTPUT][0], gamma);
+    if(!test_nd)
+        cvSetIdentity(test_array[OUTPUT][0], gamma);
+    else
+    {
+        cv::Mat a = cv::cvarrToMat(test_array[OUTPUT][0]);
+        cv::setIdentity(a, gamma);
+    }
 }
 
 
@@ -724,7 +864,13 @@ CxCore_SetZeroTest::CxCore_SetZeroTest() :
 
 void CxCore_SetZeroTest::run_func()
 {
-    cvSetZero(test_array[OUTPUT][0]);
+    if(!test_nd)
+        cvSetZero(test_array[OUTPUT][0]);
+    else
+    {
+        cv::MatND a = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        a.setTo(cv::Scalar());
+    }
 }
 
 
@@ -757,7 +903,14 @@ CxCore_FillTest::CxCore_FillTest() :
 
 void CxCore_FillTest::run_func()
 {
-    cvSet(test_array[INPUT_OUTPUT][0], gamma, test_array[MASK][0]);
+    const CvArr* mask = test_array[MASK][0];
+    if(!test_nd)
+        cvSet(test_array[INPUT_OUTPUT][0], gamma, mask);
+    else
+    {
+        cv::MatND a = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        a.setTo(gamma, mask ? cv::cvarrToMatND(mask) : cv::MatND());
+    }
 }
 
 
@@ -805,7 +958,18 @@ double CxCore_CopyTest::get_success_error_level( int /*test_case_idx*/, int /*i*
 
 void CxCore_CopyTest::run_func()
 {
-    cvCopy(test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[MASK][0]);
+    const CvArr* mask = test_array[MASK][0];
+    if(!test_nd)
+        cvCopy(test_array[INPUT][0], test_array[INPUT_OUTPUT][0], mask);
+    else
+    {
+        cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        if(!mask)
+            a.copyTo(c);
+        else
+            a.copyTo(c, cv::cvarrToMatND(mask));
+    }
 }
 
 
@@ -1145,7 +1309,7 @@ void CxCore_SplitMergeBaseTest::print_timing_params( int test_case_idx, char* pt
 
     // at once, delete the headers, though is not very good from structural point of view ...
     for( i = 0; i < 4; i++ )
-        cvReleaseMat( (CvMat**)&hdrs[i] );
+        cvRelease&hdrs[i] );
 
     CxCore_MemTest::print_timing_params( test_case_idx, ptr, params_left );
 }
@@ -1169,7 +1333,7 @@ int CxCore_SplitMergeBaseTest::prepare_test_case( int test_case_idx )
             if( coi < 0 || coi == i )
             {
                 if( are_images )
-                    hdrs[i] = cvCreateImageHeader( sz, cvCvToIplDepth(depth), 1 );
+                    hdrs[i] = cvCreateImageHeader( sz, cvIplDepth(depth), 1 );
                 else
                     hdrs[i] = cvCreateMatHeader( sz.height, sz.width, depth );
                 cvSetData( hdrs[i], planes->data.ptr + planes->step*y, planes->step );
@@ -1202,10 +1366,8 @@ void CxCore_SplitMergeBaseTest::prepare_to_validation( int )
                 cvTsExtract( input, h, i );
             else
                 cvTsInsert( h, output, i );
-            if( are_images )
-                cvReleaseImageHeader( (IplImage**)&hdrs[i] );
-            else
-                cvReleaseMat( (CvMat**)&hdrs[i] );
+            cvSetData( hdrs[i], 0, 0 );
+            cvRelease( &hdrs[i] );
             y += sz.height;
         }
     }
@@ -1229,7 +1391,17 @@ CxCore_SplitTest::CxCore_SplitTest() :
 
 void CxCore_SplitTest::run_func()
 {
-    cvSplit( test_array[INPUT][0], hdrs[0], hdrs[1], hdrs[2], hdrs[3] );
+    int i, nz = (hdrs[0] != 0) + (hdrs[1] != 0) + (hdrs[2] != 0) + (hdrs[3] != 0);
+    
+    if(!test_nd || nz != CV_MAT_CN(test_mat[INPUT][0].type))
+        cvSplit( test_array[INPUT][0], hdrs[0], hdrs[1], hdrs[2], hdrs[3] );
+    else
+    {
+        cv::MatND _hdrs[4];
+        for( i = 0; i < nz; i++ )
+            _hdrs[i] = cv::cvarrToMatND(hdrs[i]);
+        cv::split(cv::cvarrToMatND(test_array[INPUT][0]), _hdrs);
+    }
 }
 
 CxCore_SplitTest split_test;
@@ -1251,11 +1423,418 @@ CxCore_MergeTest::CxCore_MergeTest() :
 
 void CxCore_MergeTest::run_func()
 {
-    cvMerge( hdrs[0], hdrs[1], hdrs[2], hdrs[3], test_array[INPUT_OUTPUT][0] );
+    int i, nz = (hdrs[0] != 0) + (hdrs[1] != 0) + (hdrs[2] != 0) + (hdrs[3] != 0);
+    
+    if(!test_nd || nz != CV_MAT_CN(test_mat[INPUT_OUTPUT][0].type))
+        cvMerge( hdrs[0], hdrs[1], hdrs[2], hdrs[3], test_array[INPUT_OUTPUT][0] );
+    else
+    {
+        cv::MatND _hdrs[4], dst = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        for( i = 0; i < nz; i++ )
+            _hdrs[i] = cv::cvarrToMatND(hdrs[i]);
+        cv::merge(_hdrs, nz, dst);
+    }
 }
 
 CxCore_MergeTest merge_test;
 
+///////////////// CompleteSymm /////////////////////
+
+class CxCore_CompleteSymm : public CvArrTest
+{
+public:
+    CxCore_CompleteSymm();
+protected:
+    void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
+    int prepare_test_case( int test_case_idx );
+    void run_func();
+    void prepare_to_validation( int test_case_idx );
+       int LtoR; //flags 
+};
+
+CxCore_CompleteSymm::CxCore_CompleteSymm() :
+    CvArrTest("matrix-symm", "cvCompleteSymm", "Test of cvCompleteSymm function")
+{
+       /*Generates 1 input and 1 outputs (by default we have 2 inputs and 1 output)*/
+       test_array[INPUT].clear();
+       test_array[INPUT].push(NULL);
+       test_array[OUTPUT].clear();
+       test_array[OUTPUT].push(NULL);
+       test_array[REF_OUTPUT].clear();
+       test_array[REF_OUTPUT].push(NULL);
+}
+
+
+void CxCore_CompleteSymm::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
+{
+    CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
+    sizes[INPUT][0] =sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(sizes[INPUT][0].height, sizes[INPUT][0].height );
+
+       /*Making input and output matrixes one-channel*/
+       int type;
+       switch (test_case_idx % 3)
+       {
+               case 0:
+                       type = CV_32FC1;
+                       break;
+               case 1:
+                       type = CV_32SC1;
+                       break;
+               default:
+                       type = CV_64FC1;
+       }
+       types[OUTPUT][0] = types[INPUT][0] = types[REF_OUTPUT][0] = type;
+}
+
+int CxCore_CompleteSymm::prepare_test_case( int test_case_idx )
+{
+    int code = CvArrTest::prepare_test_case( test_case_idx );
+       if (code)
+       {
+               CvRNG* rng = ts->get_rng();
+               unsigned val = cvRandInt(rng);
+               LtoR = val % 2;
+               cvConvert(&test_mat[INPUT][0], &test_mat[OUTPUT][0]);
+       }
+       return code;
+}
+
+void CxCore_CompleteSymm::run_func()
+{
+       cvCompleteSymm(&test_mat[OUTPUT][0],LtoR);
+}
+
+void CxCore_CompleteSymm::prepare_to_validation( int )
+{
+       CvMat* ref_output = cvCreateMat(test_mat[OUTPUT][0].rows, test_mat[OUTPUT][0].cols, CV_64F); 
+       CvMat* input = cvCreateMat(test_mat[INPUT][0].rows, test_mat[INPUT][0].cols, CV_64F);
+       cvConvert(&test_mat[INPUT][0], input);
+       
+       for (int i=0;i<input->rows;i++)
+       {
+               ref_output->data.db[i*input->cols+i]=input->data.db[i*input->cols+i];
+               if (LtoR)
+               {
+                       for (int j=0;j<i;j++)
+                       {
+                               ref_output->data.db[j*input->cols+i] = ref_output->data.db[i*input->cols+j]=input->data.db[i*input->cols+j];
+                       }
+                               
+               }
+               else 
+               {
+                       for (int j=0;j<i;j++)
+                       {
+                               ref_output->data.db[j*input->cols+i] = ref_output->data.db[i*input->cols+j]=input->data.db[j*input->cols+i];
+                       }
+               }
+       }
+
+       cvConvert(ref_output, &test_mat[REF_OUTPUT][0]);
+       cvReleaseMat(&input);
+       cvReleaseMat(&ref_output);
+}
+
+CxCore_CompleteSymm complete_symm;
+
+
+////////////////////////////// Sort /////////////////////////////////
+
+class CxCore_SortTest : public CxCore_MemTest
+{
+public:
+    CxCore_SortTest();
+protected:
+    void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
+    int prepare_test_case( int test_case_idx );
+    void run_func();
+    void prepare_to_validation( int test_case_idx );
+       int flags; //flags for sorting
+private:
+       static int compareIndexes (const void * a, const void * b); // comparing two elements of the matrix with pointers sorting
+       static int compare(const void * a, const void * b); // comparing two elements of the matrix with pointers sorting
+       bool useIndexMatrix;
+       bool useInPlaceSort;
+       CvMat* input;
+
+};
+
+CxCore_SortTest::CxCore_SortTest() :
+    CxCore_MemTest( "matrix-sort", "cvSort", 0, false )
+{
+       /*Generates 1 input and 2 outputs (by default we have 2 inputs and 1 output)*/
+       test_array[INPUT].clear();
+       test_array[INPUT].push(NULL);
+       test_array[OUTPUT].push(NULL);
+       test_array[REF_OUTPUT].push(NULL);
+}
+
+
+void CxCore_SortTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
+{
+    CxCore_MemTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
+    sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(sizes[INPUT][0].height, sizes[INPUT][0].width );
+       types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_32SC1;
+
+       /*Making input and output matrixes one-channel*/
+       types[OUTPUT][0] = types[INPUT][0] = CV_MAKETYPE(CV_MAT_DEPTH(types[INPUT][0]), 1);
+       types[REF_OUTPUT][0] = CV_MAKETYPE(CV_MAT_DEPTH(types[REF_OUTPUT][0]), 1);
+}
+
+int CxCore_SortTest::prepare_test_case( int test_case_idx )
+{
+       if (test_case_idx==0)
+       {
+               useIndexMatrix=true;
+               useInPlaceSort=false;
+       }
+   int code = CxCore_MemTest::prepare_test_case( test_case_idx );
+
+   if( code > 0 )
+       {
+               //Copying input data
+               input = cvCreateMat(test_mat[INPUT][0].rows, test_mat[INPUT][0].cols, CV_64F);
+               cvConvert(&test_mat[INPUT][0], input);
+               CvRNG* rng = ts->get_rng();
+               unsigned val = cvRandInt(rng);
+        // Setting up flags
+               switch (val%4)
+               {
+                       case 0:
+                               flags = CV_SORT_EVERY_ROW + CV_SORT_DESCENDING;
+                               break;
+                       case 1:
+                               flags = CV_SORT_EVERY_ROW + CV_SORT_ASCENDING;
+                               break;
+                       case 2:
+                               flags = CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING;
+                               break;
+                       case 3:
+                               flags = CV_SORT_EVERY_COLUMN + CV_SORT_ASCENDING;
+                               break;
+               }
+               if (val%3) 
+                       useIndexMatrix = !useIndexMatrix;
+
+               if (val%5) 
+                       useInPlaceSort = !useInPlaceSort;
+
+       }
+    return code;
+}
+
+void CxCore_SortTest::run_func()
+{
+       //test_mat[OUTPUT][0] is sorted matrix
+       //test_mat[OUTPUT][1] is index matrix
+       if (useInPlaceSort)
+       {
+               cvConvert(&test_mat[INPUT][0], &test_mat[OUTPUT][0]);
+               if (useIndexMatrix)
+                       cvSort(&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][1]),flags);
+               else
+               {
+                       cvSort(&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][0]),0,flags);
+               }
+
+       }
+       else
+       {
+               if (useIndexMatrix)
+                       cvSort(&(test_mat[INPUT][0]),&(test_mat[OUTPUT][0]),&(test_mat[OUTPUT][1]),flags);
+               else
+               {
+                       cvSort(&(test_mat[INPUT][0]),&(test_mat[OUTPUT][0]),0,flags);
+               }
+       }
+}
+
+int CxCore_SortTest::compareIndexes (const void * a, const void * b)
+{
+       double zero = 1e-30;
+       double res=(**((double**)a)-**((double**)b));
+       return res<-zero?-1:(res>zero?1:0);
+}
+int CxCore_SortTest::compare (const void * a, const void * b)
+{
+       return *((int*)a)-*((int*)b);
+}
+
+void CxCore_SortTest::prepare_to_validation(int)
+{
+       /*Creating matrixes copies to work with*/
+       CvMat* ref_indexes = cvCreateMat(test_mat[REF_OUTPUT][1].rows, test_mat[REF_OUTPUT][1].cols, CV_32SC1); 
+       CvMat* indexes = cvCreateMat(test_mat[OUTPUT][1].rows, test_mat[OUTPUT][1].cols, CV_32SC1); 
+       CvMat* ref_output = cvCreateMat(test_mat[OUTPUT][0].rows, test_mat[OUTPUT][0].cols,CV_64F); 
+       
+       /*Copying data*/
+       cvConvert(&test_mat[REF_OUTPUT][1], ref_indexes);
+       cvConvert(&test_mat[OUTPUT][1], indexes);
+
+       /*Following block generates REF_OUTPUT indexes matrix*/
+       if ((flags == (CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)) ||(flags == (CV_SORT_EVERY_ROW+CV_SORT_DESCENDING)))
+       for (int i=0;i<test_mat[REF_OUTPUT][1].rows;i++)
+               for (int j=0;j<test_mat[REF_OUTPUT][1].cols;j++)
+                       ref_indexes->data.i[ref_indexes->cols*i + j]=j;
+       else 
+       for (int i=0;i<test_mat[REF_OUTPUT][1].rows;i++)
+               for (int j=0;j<test_mat[REF_OUTPUT][1].cols;j++)
+                       ref_indexes->data.i[ref_indexes->cols*i + j]=i;
+       cvConvert(ref_indexes, &test_mat[REF_OUTPUT][1]);
+       /*End of block*/
+
+       /* Matrix User's Sorting Algorithm */
+       int order = -1; // order of sorting (ASCENDING or DESCENDING)
+       //// Following to variables are for sorting rows or cols in one block without any conditions (if statements)
+       short rowsSort=0;
+       short colsSort=0;
+       if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_COLUMN+CV_SORT_ASCENDING)) order=1;
+       if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_ROW+CV_SORT_DESCENDING)) rowsSort=1;
+       else colsSort=1;
+       int i,j;
+       
+       // For accessing [i,j] element using index matrix we can use following formula
+       // input->data.db[(input->cols*i+ref_indexes->cols*i+j)*rowsSort+(cols*(ref_indexes->cols*i+j)+j)*colsSort];
+
+    if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_ROW+CV_SORT_DESCENDING))
+       {
+               double** row = new double*[input->cols];
+               for (i=0;i<input->rows; i++)
+               {
+                       for (int j=0;j<input->cols;j++)
+                               row[j]=&(input->data.db[(input->cols*i+j)]);
+                       qsort(row,input->cols,sizeof(row[0]),&CxCore_SortTest::compareIndexes);
+                       for (int j=0;j<ref_indexes->cols;j++)
+                       {
+                               if (order==1)
+                                       ref_indexes->data.i[ref_indexes->cols*i+j]=(int)(row[j]-&(input->data.db[input->cols*i]));
+                               else
+                                       ref_indexes->data.i[ref_indexes->cols*(i+1)-1-j]=(int)(row[j]-&(input->data.db[input->cols*i]));
+                       }
+               }
+               delete[] row;
+       }
+       else
+       {
+               double** col = new double*[input->rows];
+               for (j=0;j<input->cols; j++)
+               {
+                       for (int i=0;i<input->rows;i++)
+                               col[i]=&(input->data.db[(input->cols*i+j)]);
+                       qsort(col,input->rows,sizeof(col[0]),&CxCore_SortTest::compareIndexes);
+                       for (int i=0;i<ref_indexes->rows;i++)
+                       {
+                               if (order==1)
+                                       ref_indexes->data.i[ref_indexes->cols*i+j]=(int)((col[i]-&(input->data.db[j]))/(ref_output->cols));
+                               else
+                                       ref_indexes->data.i[ref_indexes->cols*(ref_indexes->rows-1-i)+j]=(int)(col[i]-&(input->data.db[j]))/(ref_output->cols);
+                       }
+               }
+               delete[] col;
+       }
+
+       /*End of Sort*/
+
+       int n;
+       for (i=0;i<input->rows;i++)
+               for (j=0;j<input->cols;j++)
+               {
+                       n=(input->cols*i+ref_indexes->data.i[ref_indexes->cols*i+j])*rowsSort+
+                       (input->cols*(ref_indexes->data.i[ref_indexes->cols*i+j])+j)*colsSort;
+                       ref_output->data.db[ref_output->cols*i+j] = input->data.db[n];
+               }
+
+       if (useIndexMatrix)
+       {
+               /* Comparing indexes matrixes */
+               if ((flags == CV_SORT_EVERY_ROW+CV_SORT_ASCENDING)||(flags == CV_SORT_EVERY_ROW+CV_SORT_DESCENDING))
+               {
+                       int begin=0,end=0;
+                       double temp;
+                       for (i=0;i<indexes->rows;i++)
+                       {
+                               for (j=0;j<indexes->cols-1;j++)
+                                       if (ref_output->data.db[ref_output->cols*i+j]==ref_output->data.db[ref_output->cols*i+j+1])
+                                       {
+                                               temp=ref_output->data.db[ref_output->cols*i+j];
+                                               begin=j++;
+                                               while ((j<ref_output->cols)&&(temp==ref_output->data.db[ref_output->cols*i+j])) j++;
+                                               end=--j;
+                                               int* row = new int[end-begin+1];
+                                               int* row1 = new int[end-begin+1];
+
+                                               for (int k=0;k<=end-begin;k++)
+                                               {
+                                                       row[k]=ref_indexes->data.i[ref_indexes->cols*i+k+begin];
+                                                       row1[k]=indexes->data.i[indexes->cols*i+k+begin];
+                                               }
+                                               qsort(row,end-begin+1,sizeof(row[0]),&CxCore_SortTest::compare);
+                                               qsort(row1,end-begin+1,sizeof(row1[0]),&CxCore_SortTest::compare);
+                                               for (int k=0;k<=end-begin;k++)
+                                               {
+                                                       ref_indexes->data.i[ref_indexes->cols*i+k+begin]=row[k];
+                                                       indexes->data.i[indexes->cols*i+k+begin]=row1[k];
+                                               }       
+                                               delete[] row;
+                                               delete[] row1;
+                                       }
+                       }
+               }
+               else
+               {
+                       int begin=0,end=0;
+                       double temp;
+                       for (j=0;j<indexes->cols;j++)
+                       {
+                               for (i=0;i<indexes->rows-1;i++)
+                                       if (ref_output->data.db[ref_output->cols*i+j]==ref_output->data.db[ref_output->cols*(i+1)+j])
+                                       {
+                                               temp=ref_output->data.db[ref_output->cols*i+j];
+                                               begin=i++;
+                                               while ((i<ref_output->rows)&&(temp==ref_output->data.db[ref_output->cols*i+j])) i++;
+                                               end=--i;
+
+                                               int* col = new int[end-begin+1];
+                                               int* col1 = new int[end-begin+1];
+
+                                               for (int k=0;k<=end-begin;k++)
+                                               {
+                                                       col[k]=ref_indexes->data.i[ref_indexes->cols*(k+begin)+j];
+                                                       col1[k]=indexes->data.i[indexes->cols*(k+begin)+j];
+                                               }
+                                               qsort(col,end-begin+1,sizeof(col[0]),&CxCore_SortTest::compare);
+                                               qsort(col1,end-begin+1,sizeof(col1[0]),&CxCore_SortTest::compare);
+                                               for (int k=0;k<=end-begin;k++)
+                                               {
+                                                       ref_indexes->data.i[ref_indexes->cols*(k+begin)+j]=col[k];
+                                                       indexes->data.i[indexes->cols*(k+begin)+j]=col1[k];
+                                               }       
+                                               delete[] col;
+                                               delete[] col1;
+                                       }
+                       }
+               }
+       /* End of compare*/
+       cvConvert(ref_indexes, &test_mat[REF_OUTPUT][1]);
+       cvConvert(indexes, &test_mat[OUTPUT][1]);
+       }
+       else
+       {
+               cvConvert(ref_indexes, &test_mat[REF_OUTPUT][1]);
+               cvConvert(ref_indexes, &test_mat[OUTPUT][1]);
+       }
+
+       cvConvert(ref_output, &test_mat[REF_OUTPUT][0]);
+
+       /*releasing matrixes*/
+       cvReleaseMat(&ref_output); 
+       cvReleaseMat(&input); 
+       cvReleaseMat(&indexes); 
+       cvReleaseMat(&ref_indexes);   
+}
+
+CxCore_SortTest sort_test;
+
 ////////////////////////////// min/max  /////////////////////////////
 
 class CxCore_MinMaxBaseTest : public CxCore_ArithmTest
@@ -1325,7 +1904,16 @@ CxCore_MinTest::CxCore_MinTest()
 
 void CxCore_MinTest::run_func()
 {
-    cvMin( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvMin( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::min(cv::cvarrToMatND(test_array[INPUT][0]),
+                cv::cvarrToMatND(test_array[INPUT][1]), c);
+    }
 }
 
 CxCore_MinTest min_test;
@@ -1348,7 +1936,16 @@ CxCore_MaxTest::CxCore_MaxTest()
 
 void CxCore_MaxTest::run_func()
 {
-    cvMax( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvMax( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::max(cv::cvarrToMatND(test_array[INPUT][0]),
+                cv::cvarrToMatND(test_array[INPUT][1]), c);
+    }
 }
 
 CxCore_MaxTest max_test;
@@ -1371,7 +1968,16 @@ CxCore_MinSTest::CxCore_MinSTest()
 
 void CxCore_MinSTest::run_func()
 {
-    cvMinS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvMinS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::min(cv::cvarrToMatND(test_array[INPUT][0]),
+                gamma.val[0], c);
+    }
 }
 
 CxCore_MinSTest mins_test;
@@ -1393,7 +1999,16 @@ CxCore_MaxSTest::CxCore_MaxSTest()
 
 void CxCore_MaxSTest::run_func()
 {
-    cvMaxS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvMaxS( test_array[INPUT][0], gamma.val[0], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::max(cv::cvarrToMatND(test_array[INPUT][0]),
+                gamma.val[0], c);
+    }
 }
 
 CxCore_MaxSTest maxs_test;
@@ -1508,8 +2123,18 @@ CxCore_AndTest::CxCore_AndTest()
 
 void CxCore_AndTest::run_func()
 {
-    cvAnd( test_array[INPUT][0], test_array[INPUT][1],
-           test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvAnd( test_array[INPUT][0], test_array[INPUT][1],
+              test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::bitwise_and(cv::cvarrToMatND(test_array[INPUT][0]),
+                        cv::cvarrToMatND(test_array[INPUT][1]),
+                        c, cv::cvarrToMatND(test_array[MASK][0]));
+    }
 }
 
 CxCore_AndTest and_test;
@@ -1530,8 +2155,18 @@ CxCore_AndSTest::CxCore_AndSTest()
 
 void CxCore_AndSTest::run_func()
 {
-    cvAndS( test_array[INPUT][0], gamma,
-            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvAndS( test_array[INPUT][0], gamma,
+              test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::bitwise_and(cv::cvarrToMatND(test_array[INPUT][0]),
+                        gamma, c,
+                        cv::cvarrToMatND(test_array[MASK][0]));
+    }
 }
 
 CxCore_AndSTest ands_test;
@@ -1554,8 +2189,19 @@ CxCore_OrTest::CxCore_OrTest()
 
 void CxCore_OrTest::run_func()
 {
-    cvOr( test_array[INPUT][0], test_array[INPUT][1],
-          test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvOr( test_array[INPUT][0], test_array[INPUT][1],
+              test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::bitwise_or(cv::cvarrToMatND(test_array[INPUT][0]),
+                        cv::cvarrToMatND(test_array[INPUT][1]),
+                        c, cv::cvarrToMatND(test_array[MASK][0]));
+    }
+    
 }
 
 CxCore_OrTest or_test;
@@ -1576,8 +2222,18 @@ CxCore_OrSTest::CxCore_OrSTest()
 
 void CxCore_OrSTest::run_func()
 {
-    cvOrS( test_array[INPUT][0], gamma,
-           test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvOrS( test_array[INPUT][0], gamma,
+               test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::bitwise_or(cv::cvarrToMatND(test_array[INPUT][0]),
+                        gamma, c,
+                        cv::cvarrToMatND(test_array[MASK][0]));
+    }
 }
 
 CxCore_OrSTest ors_test;
@@ -1600,8 +2256,19 @@ CxCore_XorTest::CxCore_XorTest()
 
 void CxCore_XorTest::run_func()
 {
-    cvXor( test_array[INPUT][0], test_array[INPUT][1],
-           test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvXor( test_array[INPUT][0], test_array[INPUT][1],
+               test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::bitwise_xor(cv::cvarrToMatND(test_array[INPUT][0]),
+                        cv::cvarrToMatND(test_array[INPUT][1]),
+                        c, cv::cvarrToMatND(test_array[MASK][0]));
+    }
+    
 }
 
 CxCore_XorTest xor_test;
@@ -1622,8 +2289,18 @@ CxCore_XorSTest::CxCore_XorSTest()
 
 void CxCore_XorSTest::run_func()
 {
-    cvXorS( test_array[INPUT][0], gamma,
-            test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    if(!test_nd)
+    {
+        cvXorS( test_array[INPUT][0], gamma,
+               test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[INPUT_OUTPUT][0]);
+        cv::bitwise_xor(cv::cvarrToMatND(test_array[INPUT][0]),
+                        gamma, c,
+                        cv::cvarrToMatND(test_array[MASK][0]));
+    }
 }
 
 CxCore_XorSTest xors_test;
@@ -1646,8 +2323,15 @@ CxCore_NotTest::CxCore_NotTest()
 
 void CxCore_NotTest::run_func()
 {
-    cvNot( test_array[INPUT][0],
-           test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvNot( test_array[INPUT][0], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::bitwise_not(cv::cvarrToMatND(test_array[INPUT][0]), c);
+    }
 }
 
 CxCore_NotTest nots_test;
@@ -1877,8 +2561,18 @@ CxCore_CmpTest::CxCore_CmpTest()
 
 void CxCore_CmpTest::run_func()
 {
-    cvCmp( test_array[INPUT][0], test_array[INPUT][1],
-           test_array[OUTPUT][0], cmp_op );
+    if(!test_nd)
+    {
+        cvCmp( test_array[INPUT][0], test_array[INPUT][1],
+              test_array[OUTPUT][0], cmp_op );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::compare(cv::cvarrToMatND(test_array[INPUT][0]),
+                    cv::cvarrToMatND(test_array[INPUT][1]),
+                    c, cmp_op);
+    }
 }
 
 CxCore_CmpTest cmp_test;
@@ -1899,8 +2593,17 @@ CxCore_CmpSTest::CxCore_CmpSTest()
 
 void CxCore_CmpSTest::run_func()
 {
-    cvCmpS( test_array[INPUT][0], gamma.val[0],
+    if(!test_nd)
+    {
+        cvCmpS( test_array[INPUT][0], gamma.val[0],
             test_array[OUTPUT][0], cmp_op );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::compare(cv::cvarrToMatND(test_array[INPUT][0]),
+                    gamma.val[0], c, cmp_op);
+    }
 }
 
 CxCore_CmpSTest cmps_test;
@@ -1921,8 +2624,19 @@ CxCore_InRangeTest::CxCore_InRangeTest()
 
 void CxCore_InRangeTest::run_func()
 {
-    cvInRange( test_array[INPUT][0], test_array[INPUT][1],
-               test_array[INPUT][2], test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvInRange( test_array[INPUT][0], test_array[INPUT][1],
+                  test_array[INPUT][2], test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::inRange(cv::cvarrToMatND(test_array[INPUT][0]),
+                    cv::cvarrToMatND(test_array[INPUT][1]),
+                    cv::cvarrToMatND(test_array[INPUT][2]),
+                    c);
+    }
 }
 
 CxCore_InRangeTest inrange_test;
@@ -1943,7 +2657,15 @@ CxCore_InRangeSTest::CxCore_InRangeSTest()
 
 void CxCore_InRangeSTest::run_func()
 {
-    cvInRangeS( test_array[INPUT][0], alpha, gamma, test_array[OUTPUT][0] );
+    if(!test_nd)
+    {
+        cvInRangeS( test_array[INPUT][0], alpha, gamma, test_array[OUTPUT][0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::inRange(cv::cvarrToMatND(test_array[INPUT][0]), alpha, gamma, c);
+    }
 }
 
 CxCore_InRangeSTest inranges_test;
@@ -1952,7 +2674,7 @@ CxCore_InRangeSTest inranges_test;
 /////////////////////////// convertscale[abs] ////////////////////////////////////////
 
 static const char* cvt_param_names[] = { "size", "scale", "dst_depth", "depth", 0 };
-static const char* cvt_abs_param_names[] = { "size", "depth" };
+static const char* cvt_abs_param_names[] = { "size", "depth", 0 };
 static const int cvt_scale_flags[] = { 0, 1 };
 
 class CxCore_CvtBaseTestImpl : public CxCore_ArithmTestImpl
@@ -2010,16 +2732,29 @@ void CxCore_CvtBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
 }
 
 
-double CxCore_CvtBaseTestImpl::get_success_error_level( int test_case_idx, int i, int j )
+double CxCore_CvtBaseTestImpl::get_success_error_level( int, int, int )
 {
-    if( CV_MAT_DEPTH(cvGetElemType(test_array[i][j])) <= CV_32S )
-    {
+    if( CV_MAT_DEPTH(test_mat[OUTPUT][0].type) <= CV_32S )
         return alpha.val[0] != cvRound(alpha.val[0]) ||
                beta.val[0] != cvRound(beta.val[0]) ||
                gamma.val[0] != cvRound(gamma.val[0]);
+
+    CvScalar l1, h1, l2, h2;
+    int stype = CV_MAT_TYPE(test_mat[INPUT][0].type);
+    int dtype = CV_MAT_TYPE(test_mat[OUTPUT][0].type);
+    get_minmax_bounds( INPUT, 0, stype, &l1, &h1 );
+    get_minmax_bounds( OUTPUT, 0, dtype, &l2, &h2 );
+    double maxval = 0;
+    for( int i = 0; i < 4; i++ )
+    {
+        maxval = MAX(maxval, fabs(l1.val[i]));
+        maxval = MAX(maxval, fabs(h1.val[i]));
+        maxval = MAX(maxval, fabs(l2.val[i]));
+        maxval = MAX(maxval, fabs(h2.val[i]));
     }
-    else
-        return CvArrTest::get_success_error_level( test_case_idx, i, j );
+    double max_err = (CV_MAT_DEPTH(stype) == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F ?
+        DBL_EPSILON : FLT_EPSILON)*maxval*MAX(fabs(alpha.val[0]), 1.)*100;
+    return max_err;
 }
 
 
@@ -2137,8 +2872,16 @@ CxCore_CvtScaleTest::CxCore_CvtScaleTest()
 
 void CxCore_CvtScaleTest::run_func()
 {
-    cvConvertScale( test_array[INPUT][0], test_array[OUTPUT][0],
-                    alpha.val[0], gamma.val[0] );
+    if(!test_nd)
+    {
+        cvConvertScale( test_array[INPUT][0], test_array[OUTPUT][0],
+                       alpha.val[0], gamma.val[0] );
+    }
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::cvarrToMatND(test_array[INPUT][0]).convertTo(c,c.type(),alpha.val[0], gamma.val[0]);
+    }
 }
 
 CxCore_CvtScaleTest cvtscale_test;
@@ -2160,8 +2903,16 @@ CxCore_CvtScaleAbsTest::CxCore_CvtScaleAbsTest()
 
 void CxCore_CvtScaleAbsTest::run_func()
 {
-    cvConvertScaleAbs( test_array[INPUT][0], test_array[OUTPUT][0],
+    if(!test_nd)
+    {
+        cvConvertScaleAbs( test_array[INPUT][0], test_array[OUTPUT][0],
                        alpha.val[0], gamma.val[0] );
+    }
+    else
+    {
+        cv::Mat c = cv::cvarrToMat(test_array[OUTPUT][0]);
+        cv::convertScaleAbs(cv::cvarrToMat(test_array[INPUT][0]),c,alpha.val[0], gamma.val[0]);
+    }
 }
 
 CxCore_CvtScaleAbsTest cvtscaleabs_test;
@@ -2195,6 +2946,7 @@ protected:
     int output_count;
     bool single_channel;
     bool is_binary;
+    bool test_nd;
 };
 
 
@@ -2218,6 +2970,7 @@ CxCore_StatTestImpl::CxCore_StatTestImpl( const char* test_name,
     whole_size_list = arithm_whole_sizes;
     depth_list = arithm_depths;
     cn_list = arithm_channels;
+    test_nd = false;
 }
 
 
@@ -2246,6 +2999,7 @@ void CxCore_StatTestImpl::get_test_array_types_and_sizes( int test_case_idx,
         coi = cvTsRandInt(rng) % cn + 1;
         cvmat_allowed = false;
     }
+    test_nd = cvTsRandInt(rng) % 3 == 0;
 }
 
 
@@ -2322,7 +3076,7 @@ double CxCore_StatTestImpl::get_success_error_level( int test_case_idx, int i, i
     if( depth == CV_32F )
         return FLT_EPSILON*1000;
     if( depth == CV_64F )
-        return DBL_EPSILON*1000;
+        return DBL_EPSILON*100000;
     else
         return CvArrTest::get_success_error_level( test_case_idx, i, j );
 }
@@ -2377,13 +3131,20 @@ double CxCore_SumTest::get_success_error_level( int /*test_case_idx*/, int /*i*/
     int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
     if( depth == CV_32F )
         return FLT_EPSILON*1000;
-    return DBL_EPSILON*10000;
+    return DBL_EPSILON*100000;
 }
 
 
 void CxCore_SumTest::run_func()
 {
-    *(CvScalar*)(test_mat[OUTPUT][0].data.db) = cvSum(test_array[INPUT][0]);
+    if(!test_nd || coi)
+    {
+        *(CvScalar*)(test_mat[OUTPUT][0].data.db) = cvSum(test_array[INPUT][0]);
+    }
+    else
+    {
+        *(cv::Scalar*)(test_mat[OUTPUT][0].data.db) = cv::sum(cv::cvarrToMatND(test_array[INPUT][0]));
+    }
 }
 
 void CxCore_SumTest::prepare_to_validation( int /*test_case_idx*/ )
@@ -2426,7 +3187,14 @@ CxCore_NonZeroTest::CxCore_NonZeroTest()
 
 void CxCore_NonZeroTest::run_func()
 {
-    test_mat[OUTPUT][0].data.db[0] = cvCountNonZero(test_array[INPUT][0]);
+    if(!test_nd || coi)
+    {
+        test_mat[OUTPUT][0].data.db[0] = cvCountNonZero(test_array[INPUT][0]);
+    }
+    else
+    {
+        test_mat[OUTPUT][0].data.db[0] = cv::countNonZero(cv::cvarrToMatND(test_array[INPUT][0]));
+    }
 }
 
 void CxCore_NonZeroTest::get_test_array_types_and_sizes( int test_case_idx,
@@ -2477,8 +3245,17 @@ CxCore_MeanTest::CxCore_MeanTest()
 
 void CxCore_MeanTest::run_func()
 {
-    *(CvScalar*)(test_mat[OUTPUT][0].data.db) =
-        cvAvg(test_array[INPUT][0], test_array[MASK][0]);
+    if(!test_nd || coi)
+    {
+        *(CvScalar*)(test_mat[OUTPUT][0].data.db) =
+            cvAvg(test_array[INPUT][0], test_array[MASK][0]);
+    }
+    else
+    {
+        *(cv::Scalar*)(test_mat[OUTPUT][0].data.db) = cv::mean(
+                    cv::cvarrToMatND(test_array[INPUT][0]),
+                    cv::cvarrToMatND(test_array[MASK][0]));
+    }
 }
 
 void CxCore_MeanTest::prepare_to_validation( int /*test_case_idx*/ )
@@ -2501,6 +3278,7 @@ public:
 protected:
     void run_func();
     void prepare_to_validation( int test_case_idx );
+    double get_success_error_level( int test_case_idx, int i, int j );
 };
 
 
@@ -2511,20 +3289,48 @@ CxCore_MeanStdDevTest::CxCore_MeanStdDevTest()
 
 void CxCore_MeanStdDevTest::run_func()
 {
-    cvAvgSdv( test_array[INPUT][0],
-              &((CvScalar*)(test_mat[OUTPUT][0].data.db))[0],
-              &((CvScalar*)(test_mat[OUTPUT][0].data.db))[1],
-              test_array[MASK][0] );
+    if(!test_nd || coi)
+    {
+        cvAvgSdv( test_array[INPUT][0],
+                  &((CvScalar*)(test_mat[OUTPUT][0].data.db))[0],
+                  &((CvScalar*)(test_mat[OUTPUT][0].data.db))[1],
+                  test_array[MASK][0] );
+    }
+    else
+    {
+        cv::meanStdDev(cv::cvarrToMatND(test_array[INPUT][0]),
+                       ((cv::Scalar*)(test_mat[OUTPUT][0].data.db))[0],
+                       ((cv::Scalar*)(test_mat[OUTPUT][0].data.db))[1],
+                       cv::cvarrToMatND(test_array[MASK][0]) );
+    }
+}
+
+double CxCore_MeanStdDevTest::get_success_error_level( int test_case_idx, int i, int j )
+{
+    int depth = CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0]));
+    if( depth < CV_64F && depth != CV_32S )
+        return CxCore_StatTest::get_success_error_level( test_case_idx, i, j );
+    return DBL_EPSILON*1e6;
 }
 
 void CxCore_MeanStdDevTest::prepare_to_validation( int /*test_case_idx*/ )
 {
     CvScalar mean, stddev;
+    int i;
+    CvMat* output = &test_mat[OUTPUT][0];
+    CvMat* ref_output = &test_mat[REF_OUTPUT][0];
     cvTsMeanStdDevNonZero( &test_mat[INPUT][0],
         test_array[MASK][0] ? &test_mat[MASK][0] : 0,
         &mean, &stddev, coi );
-    ((CvScalar*)(test_mat[REF_OUTPUT][0].data.db))[0] = mean;
-    ((CvScalar*)(test_mat[REF_OUTPUT][0].data.db))[1] = stddev;
+    ((CvScalar*)(ref_output->data.db))[0] = mean;
+    ((CvScalar*)(ref_output->data.db))[1] = stddev;
+    for( i = 0; i < 4; i++ )
+    {
+        output->data.db[i] *= output->data.db[i];
+        output->data.db[i+4] = output->data.db[i+4]*output->data.db[i+4] + 1000;
+        ref_output->data.db[i] *= ref_output->data.db[i];
+        ref_output->data.db[i+4] = ref_output->data.db[i+4]*ref_output->data.db[i+4] + 1000;
+    }
 }
 
 CxCore_MeanStdDevTest mean_stddev_test;
@@ -2708,8 +3514,20 @@ void CxCore_NormTest::print_timing_params( int test_case_idx, char* ptr, int par
 
 void CxCore_NormTest::run_func()
 {
-    test_mat[OUTPUT][0].data.db[0] = cvNorm( test_array[INPUT][0],
-            test_array[INPUT][1], norm_type, test_array[MASK][0] );
+    if(!test_nd || coi)
+    {
+        test_mat[OUTPUT][0].data.db[0] = cvNorm( test_array[INPUT][0],
+                 test_array[INPUT][1], norm_type, test_array[MASK][0] );
+    }
+    else
+    {
+        cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
+        cv::MatND b = cv::cvarrToMatND(test_array[INPUT][1]);
+        cv::MatND mask = cv::cvarrToMatND(test_array[MASK][0]);
+        test_mat[OUTPUT][0].data.db[0] = b.data ?
+            cv::norm( a, b, norm_type, mask ) :
+            cv::norm( a, norm_type, mask );
+    }
 }
 
 void CxCore_NormTest::prepare_to_validation( int /*test_case_idx*/ )