assert: fixed bugs #9825 and #9963 in assert_computedigits 87/5487/2
Michael BAUDIN [Tue, 22 Nov 2011 09:34:42 +0000 (10:34 +0100)]
Change-Id: Ie1ef672d2bfea9d87902721fd86896785a2a2b57

scilab/CHANGES_5.4.X
scilab/modules/development_tools/macros/assert/assert_computedigits.sci
scilab/modules/development_tools/tests/nonreg_tests/bug_9825.dia.ref [new file with mode: 0644]
scilab/modules/development_tools/tests/nonreg_tests/bug_9825.tst [new file with mode: 0644]
scilab/modules/development_tools/tests/nonreg_tests/bug_9963.dia.ref [new file with mode: 0644]
scilab/modules/development_tools/tests/nonreg_tests/bug_9963.tst [new file with mode: 0644]
scilab/modules/development_tools/tests/unit_tests/assert/computedigits.dia.ref
scilab/modules/development_tools/tests/unit_tests/assert/computedigits.tst

index dff203d..9845d81 100644 (file)
@@ -868,6 +868,11 @@ Bug fixes:
 
 * bug 9957 fixed - msprintf("%d\r", 2) returned '2r'.
 
+* bug 9825 fixed - The assert_computedigits function generously 
+                   gives too large correct digits.
+
+* bug 9963 fixed - The assert_computedigits function was not vectorized.
+
 * bug 9966 fixed - The default value of comptype in assert_checkalmostequal
                    was wrongly chosen.
 
index 0a4eb8b..c95ec30 100644 (file)
@@ -47,12 +47,9 @@ function d = assert_computedigits ( varargin )
   //
   d = zeros(expected)
   //
-  n = size(expected,"*")
-  for i = 1 : n
-    dre = computedigits_data ( real(expected(i)) , real(computed(i)) , basis )
-    dim = computedigits_data ( imag(expected(i)) , imag(computed(i)) , basis )
-    d(i) = min(dre,dim)
-  end
+  dre = computedigits_data ( real(expected) , real(computed) , basis );
+  dim = computedigits_data ( imag(expected) , imag(computed) , basis );
+  d = min(dre,dim)
   //
   // Reshape
   d = matrix(d,nre,nce)
@@ -72,43 +69,40 @@ function argin = argindefault ( rhs , vararglist , ivar , default )
     end
   end
 endfunction
+
 function d = computedigits_data ( expected , computed , basis )
-    dmin = 0
-    dmax = -log(2^(-53))/log(basis)
-    //
-    if ( isnan(expected) & isnan(computed) ) then
-        d = dmax
-    elseif ( isnan(expected) & ~isnan(computed) ) then
-        d = dmin
-    elseif ( ~isnan(expected) & isnan(computed) ) then
-        d = dmin
-        // From now, both expected and computed are non-nan
-    elseif ( expected == 0 & computed == 0 ) then
-        d = dmax
-    elseif ( expected == 0 & computed <> 0 ) then
-        d = dmin
-        // From now, expected is non-zero
-    elseif ( expected == computed ) then
-        d = dmax
-        // From now, expected and computed are different
-    elseif ( expected == %inf & computed <> %inf ) then
-        d = dmin
-    elseif ( expected == -%inf & computed <> -%inf ) then
-        d = dmin
-        // From now, neither of computed, nor expected is infinity
-    else
-        // The max function does not ensure that the sign bit of d is positive.
-        // For example : 
-        // ieee(2); z=max(-0,0); 1/z is -%inf
-        // To force this, consider the special case where the relative error is 
-        // larger than 1.
-        relerr = abs(computed-expected) / abs(expected)
-        if ( relerr >= 1 ) then
-            d = dmin
-        else
-            sigdig = -log ( relerr ) / log(basis)
-            d = max ( sigdig , dmin )
-        end
-    end
+  //
+  dmin = 0
+  dmax = -log(2^(-53))/log(basis)
+  d = ones(expected)*%inf;
+  d( isnan(expected) & isnan(computed) ) = dmax;
+  d( isnan(expected) & ~isnan(computed) ) = dmin;
+  d( ~isnan(expected) & isnan(computed) ) = dmin;
+  // From now, both expected and computed are non-nan
+  k = ~isnan(expected) & ~isnan(computed);
+  d( k & expected == 0 & computed == 0 ) = dmax;
+  d( k & expected == 0 & computed <> 0 ) = dmin;
+  // From now, expected is non-zero
+  k = k & expected <> 0;
+  d( k & expected == computed ) = dmax;
+  // From now, expected and computed are different
+  k = k & expected <> computed;
+  d( k & expected == %inf & computed <> %inf ) = dmin;
+  d( k & expected == -%inf & computed <> -%inf ) = dmin;
+  // From now, neither of computed, nor expected is infinity
+  kdinf=find(d==%inf);
+  if ( kdinf <> [] ) then
+      relerr = ones(expected)*%nan;
+      relerr(kdinf) = abs(computed(kdinf)-expected(kdinf)) ./ abs(expected(kdinf));
+      k = find( relerr >= 1 );
+      if ( k<> [] ) then
+          d(k) = dmin;
+      end
+      k = find( d==%inf & relerr < 1 );
+      if ( k<> [] ) then
+          sigdig(k) = -log ( 2*relerr(k) ) ./ log(basis);
+          d(k) = max ( sigdig(k) , dmin );
+      end
+  end
 endfunction
 
diff --git a/scilab/modules/development_tools/tests/nonreg_tests/bug_9825.dia.ref b/scilab/modules/development_tools/tests/nonreg_tests/bug_9825.dia.ref
new file mode 100644 (file)
index 0000000..dc81f89
--- /dev/null
@@ -0,0 +1,30 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2011 - DIGITEO - Michael Baudin
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- JVM NOT MANDATORY -->
+// <-- Non-regression test for bug 9825 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=9825
+//
+// <-- Short Description -->
+// The assert_computedigits function generously gives too large correct digits.
+function flag = MY_assert_equal ( computed , expected )
+  if computed==expected then
+    flag = 1;
+  else
+    flag = 0;
+  end
+  if flag <> 1 then bugmes();quit;end
+endfunction
+e = 1;
+c = nearfloat("pred",e);
+d = assert_computedigits(e,c,2);
+MY_assert_equal ( d , 52 );
+//
+e = 1;
+d = assert_computedigits(e,e,2);
+MY_assert_equal ( d , 53 );
diff --git a/scilab/modules/development_tools/tests/nonreg_tests/bug_9825.tst b/scilab/modules/development_tools/tests/nonreg_tests/bug_9825.tst
new file mode 100644 (file)
index 0000000..ff7a138
--- /dev/null
@@ -0,0 +1,34 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2011 - DIGITEO - Michael Baudin
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+// <-- JVM NOT MANDATORY -->
+
+// <-- Non-regression test for bug 9825 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=9825
+//
+// <-- Short Description -->
+// The assert_computedigits function generously gives too large correct digits.
+
+function flag = MY_assert_equal ( computed , expected )
+  if computed==expected then
+    flag = 1;
+  else
+    flag = 0;
+  end
+  if flag <> 1 then pause,end
+endfunction
+
+e = 1;
+c = nearfloat("pred",e);
+d = assert_computedigits(e,c,2);
+MY_assert_equal ( d , 52 );
+//
+e = 1;
+d = assert_computedigits(e,e,2);
+MY_assert_equal ( d , 53 );
diff --git a/scilab/modules/development_tools/tests/nonreg_tests/bug_9963.dia.ref b/scilab/modules/development_tools/tests/nonreg_tests/bug_9963.dia.ref
new file mode 100644 (file)
index 0000000..fd7d0c3
--- /dev/null
@@ -0,0 +1,28 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2011 - DIGITEO - Michael Baudin
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- JVM NOT MANDATORY -->
+// <-- Non-regression test for bug 9963 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=9963
+//
+// <-- Short Description -->
+// The assert_computedigits function is not vectorized.
+function flag = MY_assert_equal ( computed , expected )
+  if computed==expected then
+    flag = 1;
+  else
+    flag = 0;
+  end
+  if flag <> 1 then bugmes();quit;end
+endfunction
+// Test performance of computedigits: check that vectorization is used.
+// This test must pass within a second.
+A = rand(100,100);
+B = rand(100,100);
+D = assert_computedigits(A,B);
+MY_assert_equal ( size(D) , [100 100] );
diff --git a/scilab/modules/development_tools/tests/nonreg_tests/bug_9963.tst b/scilab/modules/development_tools/tests/nonreg_tests/bug_9963.tst
new file mode 100644 (file)
index 0000000..1a0f8b4
--- /dev/null
@@ -0,0 +1,32 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2011 - DIGITEO - Michael Baudin
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+// <-- JVM NOT MANDATORY -->
+
+// <-- Non-regression test for bug 9963 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=9963
+//
+// <-- Short Description -->
+// The assert_computedigits function is not vectorized.
+
+function flag = MY_assert_equal ( computed , expected )
+  if computed==expected then
+    flag = 1;
+  else
+    flag = 0;
+  end
+  if flag <> 1 then pause,end
+endfunction
+
+// Test performance of computedigits: check that vectorization is used.
+// This test must pass within a second.
+A = rand(100,100);
+B = rand(100,100);
+D = assert_computedigits(A,B);
+MY_assert_equal ( size(D) , [100 100] );
index 5bfa65b..d10b93a 100644 (file)
@@ -33,10 +33,10 @@ computed = assert_computedigits ( 0 , 1 );
 MY_assert_equal ( computed , 0 );
 //
 computed = assert_computedigits ( 3.1415926 , %pi );
-MY_assert_equal ( computed , 7.76806779280040160 );
+MY_assert_equal ( computed , 7.467037797136421240 );
 //
 computed = assert_computedigits ( 3.1415926 , %pi , 2 );
-MY_assert_equal ( computed , 25.80496264389331884 );
+MY_assert_equal ( computed , 24.804962643893318841037 );
 //
 computed = assert_computedigits ( [0 0 1 1] , [0 1 0 1] );
 MY_assert_equal ( computed , [dmax 0 0 dmax] );
@@ -60,7 +60,7 @@ computed = assert_computedigits(1.224646799D-16,8.462643383D-18);
 MY_assert_equal ( computed , 0 );
 //
 computed = assert_computedigits ( 1.2345 + %i*6.7891 , 1.23456789 + %i*6.789123456 );
-MY_assert_equal ( computed , 4.259709168495138698 );
+MY_assert_equal ( computed , 3.9586791728311578886235 );
 //
 // The sign bit of the number of digits may be wrong because
 // ieee(2); z=max(-0,0); 1/z is -%inf
@@ -72,3 +72,91 @@ MY_assert_equal ( 1/computed , %inf );
 computed = assert_computedigits ( 0 , 1.e-305 );
 MY_assert_equal ( 1/computed , %inf );
 ieee(back);
+//
+// An empirically found test case
+a = [
+3.982729777831130693D-59
+2.584939414228211484D-26
+4.391531370352049090D+43 
+1.725436586898508346D+68
+];
+b = [
+3.982729777831130693D-59
+2.584939414228211484D-26
+4.391531370352048595D+43
+1.725436586898508107D+68
+];
+c = assert_computedigits ( a , b , 2 );
+e = [
+    53.        
+    53.        
+    51.977632  
+    51.678072  
+];
+assert_checkalmostequal ( c , e , 1.e-7 );
+//
+// Check that the vectorization was correct, i.e. no specific  
+// case in the processing of the data is forgotten.
+//
+function pI = permInverse(p)
+    // Given the permutation p, compute the 
+    // inverse permutation pI.
+    N = size(p,"*")
+    pI(p) = (1:N)'
+endfunction
+a = [
+1.234567891234567891
+1.2345678912345678
+1.23456789123456
+1.234567891234
+1.2345678912
+1.23456789
+1.234567
+1.2345
+1.23
+1.2
+1.
+0.
+%nan
+%nan
+%nan
+%inf
+%inf
+%inf
+-%inf
+-%inf
+-%inf
+0.
+0.
+-0.
+-0.
+];
+N = size(a,"*");
+for k = 1 : 10
+    mprintf("Test #%d\n",k);
+    p1 = grand(1,"prm",(1:N)');
+    p2 = grand(1,"prm",(1:N)');
+    computed = a(p1);
+    expected = a(p2);
+    d1 = assert_computedigits(computed,expected);
+    // Permute both computed and expected with the same permutation p3:
+    // d must not change.
+    p3 = grand(1,"prm",(1:N)');
+    computedP = computed(p3);
+    expectedP = expected(p3);
+    d2 = assert_computedigits(computedP,expectedP);
+    // Apply inverse permutation on d2.
+    pI = permInverse(p3);
+    d2 = d2(pI);
+    assert_checkequal(d1,d2);
+end
+Test #1
+Test #2
+Test #3
+Test #4
+Test #5
+Test #6
+Test #7
+Test #8
+Test #9
+Test #10
index 81eebe8..16503b5 100644 (file)
@@ -37,10 +37,10 @@ computed = assert_computedigits ( 0 , 1 );
 MY_assert_equal ( computed , 0 );
 //
 computed = assert_computedigits ( 3.1415926 , %pi );
-MY_assert_equal ( computed , 7.76806779280040160 );
+MY_assert_equal ( computed , 7.467037797136421240 );
 //
 computed = assert_computedigits ( 3.1415926 , %pi , 2 );
-MY_assert_equal ( computed , 25.80496264389331884 );
+MY_assert_equal ( computed , 24.804962643893318841037 );
 //
 computed = assert_computedigits ( [0 0 1 1] , [0 1 0 1] );
 MY_assert_equal ( computed , [dmax 0 0 dmax] );
@@ -64,7 +64,7 @@ computed = assert_computedigits(1.224646799D-16,8.462643383D-18);
 MY_assert_equal ( computed , 0 );
 //
 computed = assert_computedigits ( 1.2345 + %i*6.7891 , 1.23456789 + %i*6.789123456 );
-MY_assert_equal ( computed , 4.259709168495138698 );
+MY_assert_equal ( computed , 3.9586791728311578886235 );
 //
 // The sign bit of the number of digits may be wrong because
 // ieee(2); z=max(-0,0); 1/z is -%inf
@@ -77,3 +77,85 @@ computed = assert_computedigits ( 0 , 1.e-305 );
 MY_assert_equal ( 1/computed , %inf );
 ieee(back);
 
+//
+// An empirically found test case
+a = [
+3.982729777831130693D-59
+2.584939414228211484D-26
+4.391531370352049090D+43 
+1.725436586898508346D+68
+];
+b = [
+3.982729777831130693D-59
+2.584939414228211484D-26
+4.391531370352048595D+43
+1.725436586898508107D+68
+];
+c = assert_computedigits ( a , b , 2 );
+e = [
+    53.        
+    53.        
+    51.977632  
+    51.678072  
+];
+assert_checkalmostequal ( c , e , 1.e-7 );
+//
+// Check that the vectorization was correct, i.e. no specific  
+// case in the processing of the data is forgotten.
+//
+function pI = permInverse(p)
+    // Given the permutation p, compute the 
+    // inverse permutation pI.
+    N = size(p,"*")
+    pI(p) = (1:N)'
+endfunction
+
+a = [
+1.234567891234567891
+1.2345678912345678
+1.23456789123456
+1.234567891234
+1.2345678912
+1.23456789
+1.234567
+1.2345
+1.23
+1.2
+1.
+0.
+%nan
+%nan
+%nan
+%inf
+%inf
+%inf
+-%inf
+-%inf
+-%inf
+0.
+0.
+-0.
+-0.
+];
+
+N = size(a,"*");
+for k = 1 : 10
+    mprintf("Test #%d\n",k);
+    p1 = grand(1,"prm",(1:N)');
+    p2 = grand(1,"prm",(1:N)');
+    computed = a(p1);
+    expected = a(p2);
+    d1 = assert_computedigits(computed,expected);
+    // Permute both computed and expected with the same permutation p3:
+    // d must not change.
+    p3 = grand(1,"prm",(1:N)');
+    computedP = computed(p3);
+    expectedP = expected(p3);
+    d2 = assert_computedigits(computedP,expectedP);
+    // Apply inverse permutation on d2.
+    pI = permInverse(p3);
+    d2 = d2(pI);
+    assert_checkequal(d1,d2);
+end
+
+