Bug #9204: The Frobenius norm of a complex vector returns a real. 80/8780/3
Adeline CARNIS [Thu, 23 Aug 2012 08:33:44 +0000 (10:33 +0200)]
Change-Id: Ifa463084ea66228fb75631b917d7c351d2941a9c

scilab/CHANGES_5.4.X
scilab/modules/linear_algebra/macros/norm.sci
scilab/modules/linear_algebra/tests/nonreg_tests/bug_9204.dia.ref [new file with mode: 0644]
scilab/modules/linear_algebra/tests/nonreg_tests/bug_9204.tst [new file with mode: 0644]

index 5fe6b4c..6ace709 100644 (file)
@@ -66,6 +66,8 @@ Bug Fixes
 * Bug #8488 fixed - NaN values was propagated when we performed the min/max between
                     several matrices.
 
+* Bug #9204 fixed - The Frobenius norm of a complex vector was numerically complex.
+
 * Bug #9616 fixed - In the qp_solve help page, the input arguments in calling
                     sequence did not match those in arguments section.
 
@@ -73,14 +75,14 @@ Bug Fixes
 
 * Bug #9976 fixed - The inverse cdfbet function returned wrong value instead of 0.
 
-* bug #11390 fixed - When the cond function has one input argument, matrices can be
+* Bug #10178 fixed - The norm function returned the message: "division by zero" for
+                     some sparse matrices.
+
+* Bug #11390 fixed - When the cond function has one input argument, matrices can be
                      non square. Moreover, the cond function has been updated to 
                      give the possibility to use another norm than that imposed
                      (by default 2-norm).
 
-* Bug #10178 fixed - The norm function returned the message: "division by zero" for
-                     some sparse matrices.
-
 * Bug #11411 fixed - save function used unsigned char to store length of string.
                      Now it is an integer.
 
index 4829dc8..642a7f7 100644 (file)
@@ -1,7 +1,7 @@
-
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) ????-2008 - INRIA
 // Copyright (C) 2009 - INRIA Michael Baudin
+// Copyright (C) 2012 - Scilab Enterprises - Adeline CARNIS
 //
 // This file must be used under the terms of the CeCILL.
 // This source file is licensed as described in the file COPYING, which
 //   IBM Journal of Research and Development 1983; 27(6):577-581. 
 //
 function y=norm(A,flag)
-//compute various matrix norms
-if argn(2)==1 then flag=2,end
+    //compute various matrix norms
+    if argn(2)==1 then flag=2,end
 
-if type(A)==1 then
-  if A==[] then y=0,return,end
-  if or(size(A)==1) then // vector norm
-    if type(flag)==10 then //'inf' or 'fro'
-      select convstr(part(flag,1))
-      case 'i' then //'inf'
-       y=max(abs(A))
-      case 'f' then //'fro'
-       A=A(:)
-        //
-        // Scaling for better floating point accuracy.
-        //
-       //
-        s = max(abs(A));
-        if s==0.0 then
-          y=sqrt(A'*A);
-        else
-          sA = A/s;
-          y = s * sqrt(sA'*sA);
+    if type(A)==1 then
+        if A==[] then y=0,return,end
+        if or(size(A)==1) then // vector norm
+            if type(flag)==10 then //'inf' or 'fro'
+                select convstr(part(flag,1))
+                case 'i' then //'inf'
+                    y=max(abs(A))
+                case 'f' then //'fro'
+                    A=A(:)
+                    //
+                    // Scaling for better floating point accuracy.
+                    //
+                    //
+                    s = max(abs(A));
+                    if s==0.0 then
+                        y=sqrt(A'*A);
+                    else
+                        sA = A/s;
+                        // return real result
+                        y = s * sqrt(abs(sA'*sA));
+                    end
+                else
+                    error("invalid value for flag")
+                end
+            elseif type(flag)==1 then //p_norm
+                p=flag;
+                if ~isreal(p) then
+                    error('flag must be real')
+                end
+                if p==%inf then
+                    y=max(abs(A))
+                elseif p==1 then
+                    y=sum(abs(A))
+                elseif p==-%inf then
+                    y=min(abs(A))
+                elseif isnan(p) then
+                    y=%nan
+                elseif p==0 then
+                    y=%inf
+                else
+                    //
+                    // Scaling for better floating point accuracy.
+                    //
+                    s = max(abs(A));
+                    if s==0.0 then
+                        y=sum(abs(A).^p)^(1/p);
+                    else
+                        sA = A/s;
+                        y = s * sum(abs(sA).^p)^(1/p);
+                    end
+                end
+            else
+                error("invalid value for flag")
+            end
+        else //matrix norm
+            if type(flag)==10 then //'inf' or 'fro'
+                select convstr(part(flag,1))
+                case 'i' then //'inf'
+                    y=max(sum(abs(A),2))  
+                case 'f' then //'fro'
+                    //
+                    // Scaling for better floating point accuracy.
+                    //
+                    s = max(abs(A));
+                    if s==0.0 then
+                        if size(A,1)>size(A,2) then
+                            y=sqrt(sum(diag(A'*A))) 
+                        else
+                            y=sqrt(sum(diag(A*A'))) 
+                        end
+                    else
+                        sA = A/s;
+                        if size(A,1)>size(A,2) then
+                            // return real result
+                            y = s * sqrt(sum(abs(diag(sA'*sA))))
+                        else
+                            y = s * sqrt(sum(abs(diag(sA*sA'))))
+                        end
+                    end
+                else
+                    error("invalid value for flag")
+                end
+            elseif type(flag)==1 then //p_norm
+                p=flag;
+                select p
+                case 1 then 
+                    y=max(sum(abs(A),1))
+                case 2 then
+                    y=max(svd(A))
+                case %inf then
+                    y=max(sum(abs(A),2))  
+                else
+                    error('flag must be 1 2 or inf')
+                end
+            else
+                error("invalid value for flag")
+            end    
         end
-      else
-       error("invalid value for flag")
-      end
-    elseif type(flag)==1 then //p_norm
-      p=flag;
-      if ~isreal(p) then
-       error('flag must be real')
-      end
-      if p==%inf then
-       y=max(abs(A))
-      elseif p==1 then
-       y=sum(abs(A))
-      elseif p==-%inf then
-       y=min(abs(A))
-      elseif isnan(p) then
-       y=%nan
-      elseif p==0 then
-       y=%inf
-      else
-        //
-        // Scaling for better floating point accuracy.
-        //
-        s = max(abs(A));
-        if s==0.0 then
-          y=sum(abs(A).^p)^(1/p);
+    else
+        if type(A)==16|type(A)==17 then
+            n=getfield(1,A);n=n(1)
         else
-          sA = A/s;
-          y = s * sum(abs(sA).^p)^(1/p);
+            [t,n]=typename()
+            n=stripblanks(n(find(t==type(A))))
         end
-      end
-    else
-      error("invalid value for flag")
-    end
-  else //matrix norm
-    if type(flag)==10 then //'inf' or 'fro'
-      select convstr(part(flag,1))
-      case 'i' then //'inf'
-       y=max(sum(abs(A),2))  
-       case 'f' then //'fro'
-        //
-        // Scaling for better floating point accuracy.
-        //
-        s = max(abs(A));
-        if s==0.0 then
-         if size(A,1)>size(A,2) then
-           y=sqrt(sum(diag(A'*A))) 
-         else
-           y=sqrt(sum(diag(A*A'))) 
-         end
+        fun='%'+n+'_norm'
+        if exists(fun)==1 then
+            execstr('y='+fun+'(A,flag)')
         else
-          sA = A/s;
-         if size(A,1)>size(A,2) then
-            y = s * sqrt(sum(diag(sA'*sA)))
-         else
-            y = s * sqrt(sum(diag(sA*sA')))
-          end
+            error('norm not defined for type ""'+n+'"" .'+..
+            'Check argument or define function '+fun)
         end
-      else
-       error("invalid value for flag")
-      end
-    elseif type(flag)==1 then //p_norm
-      p=flag;
-      select p
-       case 1 then 
-       y=max(sum(abs(A),1))
-       case 2 then
-       y=max(svd(A))
-       case %inf then
-       y=max(sum(abs(A),2))  
-      else
-       error('flag must be 1 2 or inf')
-      end
-    else
-      error("invalid value for flag")
-    end    
-  end
-else
-  if type(A)==16|type(A)==17 then
-    n=getfield(1,A);n=n(1)
-  else
-    [t,n]=typename()
-    n=stripblanks(n(find(t==type(A))))
-  end
-  fun='%'+n+'_norm'
-  if exists(fun)==1 then
-    execstr('y='+fun+'(A,flag)')
-  else
-    error('norm not defined for type ""'+n+'"" .'+..
-         'Check argument or define function '+fun)
-  end
-end
+    end
 endfunction
 
diff --git a/scilab/modules/linear_algebra/tests/nonreg_tests/bug_9204.dia.ref b/scilab/modules/linear_algebra/tests/nonreg_tests/bug_9204.dia.ref
new file mode 100644 (file)
index 0000000..e308dd4
--- /dev/null
@@ -0,0 +1,20 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2012 - Scilab Enterprises - Adeline CARNIS
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- CLI SHELL MODE -->
+// <-- Non-regression test for bug 9204 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=9204
+//
+// <-- Short Description -->
+//    The Frobenius norm of a complex vector was numerically complex.
+x = [1 2 3 -4];
+x = x + %i * x;
+assert_checkalmostequal(norm(x, 'fro'), 7.7459667);
+x = [1 2;3 4];
+x = x + %i * x;
+assert_checkalmostequal(norm(x, 'fro'), 7.7459667);
diff --git a/scilab/modules/linear_algebra/tests/nonreg_tests/bug_9204.tst b/scilab/modules/linear_algebra/tests/nonreg_tests/bug_9204.tst
new file mode 100644 (file)
index 0000000..674d3ec
--- /dev/null
@@ -0,0 +1,25 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2012 - Scilab Enterprises - Adeline CARNIS
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+// <-- CLI SHELL MODE -->
+
+// <-- Non-regression test for bug 9204 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=9204
+//
+// <-- Short Description -->
+//    The Frobenius norm of a complex vector was numerically complex.
+
+
+x = [1 2 3 -4];
+x = x + %i * x;
+assert_checkalmostequal(norm(x, 'fro'), 7.7459667);
+
+x = [1 2;3 4];
+x = x + %i * x;
+assert_checkalmostequal(norm(x, 'fro'), 7.7459667);