]> rtime.felk.cvut.cz Git - opencv.git/blobdiff - opencv/tests/cxcore/src/amath.cpp
check the lhs matrix condition number in matrix-solve test, because LU performs poorl...
[opencv.git] / opencv / tests / cxcore / src / amath.cpp
index 1d29d6cdd61f49f1945c3fbdb77be343112c7ab5..f54cc99fc6d29e8913f885b50a95a216af49a4e4 100644 (file)
@@ -142,6 +142,7 @@ protected:
     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
     void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
     double get_success_error_level( int /*test_case_idx*/, int i, int j );
+    int prepare_test_case( int test_case );
     void run_func();
     void prepare_to_validation( int test_case_idx );
     int out_type;
@@ -183,6 +184,33 @@ void CxCore_ExpTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvSc
     *high = cvScalarAll(CV_MAT_DEPTH(out_type)==CV_64F? u : u*0.5);
 }
 
+int CxCore_ExpTest::prepare_test_case( int test_case )
+{
+    int code = CxCore_MathTest::prepare_test_case(test_case);
+    if( code < 0 )
+        return code;
+
+    CvRNG* rng = ts->get_rng();
+
+    int i, j, k, count = cvTsRandInt(rng) % 10;
+    CvMat* src = &test_mat[INPUT][0];
+    int depth = CV_MAT_DEPTH(src->type);
+
+    // add some extremal values
+    for( k = 0; k < count; k++ )
+    {
+        i = cvTsRandInt(rng) % src->rows;
+        j = cvTsRandInt(rng) % (src->cols*CV_MAT_CN(src->type));
+        int sign = cvTsRandInt(rng) % 2 ? 1 : -1;
+        if( depth == CV_32F )
+            ((float*)(src->data.ptr + src->step*i))[j] = FLT_MAX*sign;
+        else
+            ((double*)(src->data.ptr + src->step*i))[j] = DBL_MAX*sign;
+    }
+
+    return code;
+}
+
 
 void CxCore_ExpTest::run_func()
 {
@@ -368,14 +396,14 @@ void CxCore_PowTest::get_test_array_types_and_sizes( int test_case_idx, CvSize**
     int i, j;
     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
     depth += depth == CV_8S;
-    
+
     if( depth < CV_32F || cvTsRandInt(rng)%8 == 0 )
         // integer power
         power = (int)(cvTsRandInt(rng)%21 - 10);
     else
     {
-        i = cvTsRandInt(rng)%16;
-        power = i == 15 ? 0.5 : i == 14 ? -0.5 : cvTsRandReal(rng)*10 - 5;
+        i = cvTsRandInt(rng)%17;
+        power = i == 16 ? 1./3 : i == 15 ? 0.5 : i == 14 ? -0.5 : cvTsRandReal(rng)*10 - 5;
     }
 
     for( i = 0; i < max_arr; i++ )
@@ -463,7 +491,23 @@ void CxCore_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, CvScalar
 void CxCore_PowTest::run_func()
 {
     if(!test_nd)
-        cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
+    {
+        if( fabs(power-1./3) <= DBL_EPSILON && CV_MAT_DEPTH(test_mat[INPUT][0].type) == CV_32F )
+        {
+            cv::Mat a(&test_mat[INPUT][0]), b(&test_mat[OUTPUT][0]);
+            
+            a = a.reshape(1);
+            b = b.reshape(1);
+            for( int i = 0; i < a.rows; i++ )
+            {
+                b.at<float>(i,0) = (float)fabs(cvCbrt(a.at<float>(i,0)));
+                for( int j = 1; j < a.cols; j++ )
+                    b.at<float>(i,j) = (float)fabs(cv::cubeRoot(a.at<float>(i,j)));
+            }
+        }
+        else
+            cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
+    }
     else
     {
         cv::MatND a = cv::cvarrToMatND(test_array[INPUT][0]);
@@ -701,11 +745,11 @@ void CxCore_CartToPolarTest::run_func()
         cv::Mat mag = test_array[OUTPUT][0] ? cv::cvarrToMat(test_array[OUTPUT][0]) : cv::Mat();
         cv::Mat ph = test_array[OUTPUT][1] ? cv::cvarrToMat(test_array[OUTPUT][1]) : cv::Mat();
         if(!mag.data)
-            cv::phase(X, Y, ph, use_degrees);
+            cv::phase(X, Y, ph, use_degrees != 0);
         else if(!ph.data)
             cv::magnitude(X, Y, mag);
         else
-            cv::cartToPolar(X, Y, mag, ph, use_degrees);
+            cv::cartToPolar(X, Y, mag, ph, use_degrees != 0);
     }
 }
 
@@ -846,7 +890,7 @@ void CxCore_PolarToCartTest::run_func()
         cv::Mat Y = test_array[OUTPUT][1] ? cv::cvarrToMat(test_array[OUTPUT][1]) : cv::Mat();
         cv::Mat mag = test_array[INPUT][1] ? cv::cvarrToMat(test_array[INPUT][1]) : cv::Mat();
         cv::Mat ph = test_array[INPUT][0] ? cv::cvarrToMat(test_array[INPUT][0]) : cv::Mat();
-        cv::polarToCart(mag, ph, X, Y, use_degrees);
+        cv::polarToCart(mag, ph, X, Y, use_degrees != 0);
     }
 }
 
@@ -1227,12 +1271,14 @@ protected:
     void run_func();
     void prepare_to_validation( int test_case_idx );
     CvScalar alpha;
+    bool test_nd;
 };
 
 CxCore_ScaleAddTest::CxCore_ScaleAddTest() :
     CxCore_MatrixTest( "matrix-scaleadd", "cvScaleAdd", 3, 1, false, false, 4 )
 {
     alpha = cvScalarAll(0);
+    test_nd = false;
 }
 
 
@@ -1241,6 +1287,7 @@ void CxCore_ScaleAddTest::get_test_array_types_and_sizes( int test_case_idx, CvS
     CxCore_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
     sizes[INPUT][2] = cvSize(1,1);
     types[INPUT][2] &= CV_MAT_DEPTH_MASK;
+    test_nd = cvTsRandInt(ts->get_rng()) % 2 != 0;
 }
 
 
@@ -1260,13 +1307,22 @@ int CxCore_ScaleAddTest::prepare_test_case( int test_case_idx )
     int code = CxCore_MatrixTest::prepare_test_case( test_case_idx );
     if( code > 0 )
         alpha = cvGet1D( &test_mat[INPUT][2], 0 );
+    if( test_nd )
+        alpha.val[1] = 0;
     return code;
 }
 
 
 void CxCore_ScaleAddTest::run_func()
 {
-    cvScaleAdd( test_array[INPUT][0], alpha, test_array[INPUT][1], test_array[OUTPUT][0] );
+    if(!test_nd)
+        cvScaleAdd( test_array[INPUT][0], alpha, test_array[INPUT][1], test_array[OUTPUT][0] );
+    else
+    {
+        cv::MatND c = cv::cvarrToMatND(test_array[OUTPUT][0]);
+        cv::scaleAdd( cv::cvarrToMatND(test_array[INPUT][0]), alpha.val[0],
+                      cv::cvarrToMatND(test_array[INPUT][1]), c);
+    }
 }
 
 
@@ -1610,7 +1666,7 @@ protected:
     void print_timing_params( int test_case_idx, char* ptr, int params_left );
     void run_func();
     void prepare_to_validation( int test_case_idx );
-    
+
     double scale;
     bool diagMtx;
 };
@@ -1642,7 +1698,7 @@ void CxCore_TransformTest::get_test_array_types_and_sizes( int test_case_idx, Cv
     mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
     types[INPUT][1] = mattype;
     types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
-    
+
     scale = 1./((cvTsRandInt(rng)%4)*50+1);
 
     if( bits & 2 )
@@ -2495,8 +2551,8 @@ int CxCore_InvertTest::prepare_test_case( int test_case_idx )
 
 void CxCore_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
 {
-    *low = cvScalarAll(-2.);
-    *high = cvScalarAll(2.);
+    *low = cvScalarAll(-1.);
+    *high = cvScalarAll(1.);
 }
 
 
@@ -2506,7 +2562,7 @@ void CxCore_InvertTest::run_func()
 }
 
 
-static double cvTsSVDet( CvMat* mat )
+static double cvTsSVDet( CvMat* mat, double* ratio )
 {
     int type = CV_MAT_TYPE(mat->type);
     int i, nm = MIN( mat->rows, mat->cols );
@@ -2519,11 +2575,13 @@ static double cvTsSVDet( CvMat* mat )
     {
         for( i = 0; i < nm; i++ )
             det *= w->data.fl[i];
+        *ratio = w->data.fl[nm-1] < FLT_EPSILON ? FLT_MAX : w->data.fl[0]/w->data.fl[nm-1];
     }
     else
     {
         for( i = 0; i < nm; i++ )
             det *= w->data.db[i];
+        *ratio = w->data.db[nm-1] < FLT_EPSILON ? DBL_MAX : w->data.db[0]/w->data.db[nm-1];
     }
 
     cvReleaseMat( &w );
@@ -2533,8 +2591,9 @@ static double cvTsSVDet( CvMat* mat )
 void CxCore_InvertTest::prepare_to_validation( int )
 {
     CvMat* input = &test_mat[INPUT][0];
-    double det = cvTsSVDet( input );
+    double ratio = 0, det = cvTsSVDet( input, &ratio );
     double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*500;
+    double rthreshold = CV_MAT_DEPTH(input->type) == CV_32F ? 1e6 : 1e12;
 
     if( CV_MAT_TYPE(input->type) == CV_32FC1 )
         cvTsConvert( input, &test_mat[TEMP][1] );
@@ -2542,7 +2601,9 @@ void CxCore_InvertTest::prepare_to_validation( int )
         cvTsCopy( input, &test_mat[TEMP][1], 0 );
 
     if( (method == CV_LU && result == 0) ||
-        (det < threshold || result < threshold) )
+        det < threshold ||
+        (method == CV_LU && ratio > rthreshold) ||
+        (method == CV_SVD && result < threshold) )
     {
         cvTsZero( &test_mat[OUTPUT][0] );
         cvTsZero( &test_mat[REF_OUTPUT][0] );
@@ -2680,14 +2741,14 @@ int CxCore_SolveTest::prepare_test_case( int test_case_idx )
 
 void CxCore_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, CvScalar* low, CvScalar* high )
 {
-    *low = cvScalarAll(-2.);
-    *high = cvScalarAll(2.);
+    *low = cvScalarAll(-1.);
+    *high = cvScalarAll(1.);
 }
 
 
 double CxCore_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
 {
-    return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 3e-2 : 1e-8;
+    return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-8;
 }
 
 
@@ -2700,26 +2761,41 @@ void CxCore_SolveTest::prepare_to_validation( int )
 {
     //int rank = test_mat[REF_OUTPUT][0].rows;
     CvMat* dst;
+    CvMat* input = &test_mat[INPUT][0];
 
-    if( method == CV_LU && result == 0 )
+    if( method == CV_LU )
     {
-        if( CV_MAT_TYPE(test_mat[INPUT][0].type) == CV_32FC1 )
-            cvTsConvert( &test_mat[INPUT][0], &test_mat[TEMP][1] );
-        else
-            cvTsCopy( &test_mat[INPUT][0], &test_mat[TEMP][1], 0 );
+        if( result == 0 )
+        {
+            if( CV_MAT_TYPE(input->type) == CV_32FC1 )
+                cvTsConvert( input, &test_mat[TEMP][1] );
+            else
+                cvTsCopy( input, &test_mat[TEMP][1], 0 );
 
-        cvTsZero( &test_mat[OUTPUT][0] );
-        double det = cvTsLU( &test_mat[TEMP][1], 0, 0 );
-        cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(det != 0),
-                 &test_mat[REF_OUTPUT][0], 0 );
-        return;
+            cvTsZero( &test_mat[OUTPUT][0] );
+            double det = cvTsLU( &test_mat[TEMP][1], 0, 0 );
+            cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.), cvScalarAll(det != 0),
+                     &test_mat[REF_OUTPUT][0], 0 );
+            return;
+        }
+     
+        double threshold = (CV_MAT_DEPTH(input->type) == CV_32F ? FLT_EPSILON : DBL_EPSILON)*500;
+        double rthreshold = CV_MAT_DEPTH(input->type) == CV_32F ? 1e6 : 1e12;   
+        double ratio = 0, det = cvTsSVDet( input, &ratio );
+        if( det < threshold || ratio > rthreshold )
+        {
+            cvTsZero( &test_mat[OUTPUT][0] );
+            cvTsZero( &test_mat[REF_OUTPUT][0] );
+            return;
+        }
     }
+        
 
-    dst = test_mat[INPUT][0].rows <= test_mat[INPUT][0].cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
+    dst = input->rows <= input->cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
 
-    cvTsGEMM( &test_mat[INPUT][0], &test_mat[TEMP][0], 1., &test_mat[INPUT][1], -1., dst, 0 );
+    cvTsGEMM( input, &test_mat[TEMP][0], 1., &test_mat[INPUT][1], -1., dst, 0 );
     if( dst != &test_mat[OUTPUT][0] )
-        cvTsGEMM( &test_mat[INPUT][0], dst, 1., 0, 0., &test_mat[OUTPUT][0], CV_GEMM_A_T );
+        cvTsGEMM( input, dst, 1., 0, 0., &test_mat[OUTPUT][0], CV_GEMM_A_T );
     cvTsZero( &test_mat[REF_OUTPUT][0] );
 }