* Bug 8088 fixed: norm() now accepts %nan and %inf terms 74/20774/3
Stéphane Mottelet [Thu, 20 Sep 2018 14:40:36 +0000 (16:40 +0200)]
http://bugzilla.scilab.org/show_bug.cgi?id=8088

Change-Id: I5c30b4dbbc3f643197fd0b4ffb7130adb90c54f8

scilab/modules/elementary_functions/help/en_US/matrixoperations/norm.xml
scilab/modules/elementary_functions/help/fr_FR/matrixoperations/norm.xml
scilab/modules/elementary_functions/help/ja_JP/matrixoperations/norm.xml
scilab/modules/elementary_functions/help/pt_BR/matrixoperations/norm.xml
scilab/modules/elementary_functions/help/ru_RU/matrixoperations/norm.xml
scilab/modules/linear_algebra/sci_gateway/c/sci_norm.c
scilab/modules/linear_algebra/tests/nonreg_tests/bug_8088.tst [new file with mode: 0644]
scilab/modules/linear_algebra/tests/unit_tests/norm.tst

index 196e555..1139d1a 100644 (file)
                 </listitem>
             </varlistentry>
         </variablelist>
-      <para>For [] :</para>
+    </refsection>
+    <refsection>
+        <title>Remark</title>
       <para>
         <literal>norm([])</literal> and <literal>norm([],p)</literal> return 0.
       </para>
+      <para><literal>norm(x)</literal> and <literal>norm(x,p)</literal> return NaN if x contains NaNs.</para>
     </refsection>
     <refsection>
         <title>Examples</title>
index ea75e57..c45325f 100644 (file)
                 </listitem>
             </varlistentry>
         </variablelist>
-
-      <para>Avec [] :</para>
+    </refsection>
+    <refsection>
+        <title>Remarque</title>
       <para>
         <literal>norm([])</literal> et <literal>norm([],p)</literal> valent 0.
       </para>
+      <para><literal>norm(x)</literal> et <literal>norm(x,p)</literal> valent NaN si x contient des NaNs.</para>
     </refsection>
     <refsection>
         <title>Exemples</title>
index 5c13c97..0219f9c 100644 (file)
                 </listitem>
             </varlistentry>
         </variablelist>
-
-      <para>For [] :</para>
+    </refsection>
+    <refsection>
+        <title>リマーク</title>
+      <para>
+       <literal>norm([])</literal>と<literal>norm([],p)</literal>は0を返します。 
+      </para>
       <para>
-        <literal>norm([])</literal> and <literal>norm([],p)</literal> return 0.
+        <literal>norm(x)</literal>と<literal>norm(x,p)</literal>は、xにNaNが含まれる場合、NaNを返します。    
       </para>
     </refsection>
     <refsection>
@@ -173,4 +177,4 @@ norm(A)
             </member>
         </simplelist>
     </refsection>
-</refentry>
\ No newline at end of file
+</refentry>
index c239dd0..a42cee6 100644 (file)
                 </listitem>
             </varlistentry>
         </variablelist>
-
-      <para>For [] :</para>
+    </refsection>
+    <refsection>
+        <title>Observación</title>
+      <para>
+        <literal>norm([])</literal> e <literal>norm([],p)</literal> retornam 0.
+      </para>
       <para>
-        <literal>norm([])</literal> and <literal>norm([],p)</literal> return 0.
+        <literal>norm (x)</literal> e <literal>norm (x,p)</literal> retornam NaN se x contiver NaNs.
       </para>
     </refsection>
     <refsection>
index 5afb302..6713cd1 100644 (file)
                     <para>
                         <itemizedlist>
                             <listitem>
-                                For a matrix <literal>x</literal>: a number among
-                                <literal>1, 2, %inf, -%inf</literal>, or a word among
-                                <literal>"inf"</literal> (or <literal>"i"</literal>) or
-                                <literal>"fro"</literal> (or <literal>"f"</literal>).
+                                Для матрицы <literal>x</literal>: число из
+                                <literal>1, 2, %inf, -%inf</literal>, или слово среди
+                                <literal>"inf"</literal> (или <literal>"i"</literal>) или
+                                <literal>"fro"</literal> (или <literal>"f"</literal>).
                             </listitem>
                             <listitem>
-                                For a vector <literal>x</literal>: any number or <literal>%inf</literal>,
-                                <literal>-%inf</literal>; or a word <literal>"inf"</literal>
+                                Для вектора <literal>x</literal>: любое число или <literal>%inf</literal>,
+                                <literal>-%inf</literal>; либо слово <literal>"inf"</literal>
                                 (<literal>"i"</literal>), <literal>"fro"</literal> (<literal>"f"</literal>).
                             </listitem>
                         </itemizedlist>
                     </para>
-                    Default value = 2.
+                    Значение по умолчанию = 2.
             </varlistentry>
             <varlistentry>
                 <term>y</term>
                 <listitem>
                     <para>
-                        norm: single positive real number.
+                        norm: отдельное положительное вещественное число.
                     </para>
                 </listitem>
             </varlistentry>
                 </listitem>
             </varlistentry>
         </variablelist>
-
-        <para>For [] :</para>
+    </refsection>
+    <refsection>
+        <title>Примечание</title>
+        <para>
+            <literal>norm([])</literal> и <literal>norm([],p)</literal> возвращают 0.
+        </para>
         <para>
-            <literal>norm([])</literal> and <literal>norm([],p)</literal> return 0.
+          По соглашению <literal>norm (x)</literal> и <literal>norm (x,p)</literal> возвращают
+          <literal>NaN</literal>, если <literal>x</literal> содержит <literal>NaN</literal>.
         </para>
     </refsection>
     <refsection>
index 91dc21e..f91d1dd 100644 (file)
@@ -47,6 +47,10 @@ int sci_norm(char *fname, void* pvApiCtx)
     int isMat = 0;
     int isComplex = 0;
 
+    // Special cases
+    int _isnan = 0;
+    int _isinf = 0;
+
     CheckInputArgument(pvApiCtx, 1, 2);
     CheckOutputArgument(pvApiCtx, 1, 1);
 
@@ -77,13 +81,11 @@ int sci_norm(char *fname, void* pvApiCtx)
         }
 
         isComplex = 1;
-        for (i = 0; i < iRows * iCols; ++i) // Checking A for %inf, which is not supported by Lapack.
+
+        for (i = 0 ; (i < iRows * iCols) & !_isnan ; i++) // Checking A for %inf or %nan, which is not supported by Lapack.
         {
-            if (la_isinf(pAC[i].r) != 0 || la_isinf(pAC[i].i) != 0 || ISNAN(pAC[i].r) || ISNAN(pAC[i].i))
-            {
-                Scierror(264, _("%s: Wrong value for argument #%d: Must not contain NaN or Inf.\n"), fname, 1);
-                return 0;
-            }
+            _isnan = isnan(pAC[i].r) | isnan(pAC[i].i);
+            _isinf |= isinf(pAC[i].r) | isinf(pAC[i].i);
         }
     }
     else
@@ -95,16 +97,23 @@ int sci_norm(char *fname, void* pvApiCtx)
             Scierror(202, _("%s: Wrong type for argument #%d: Real or complex matrix expected.\n"), fname, 1);
             return 0;
         }
-
-        for (i = 0 ; i < iRows * iCols ; i++) // Checking A for %inf, which is not supported by Lapack.
+        
+        for (i = 0 ; (i < iRows * iCols) & !_isnan ; i++) // Checking A for %inf or %nan, which is not supported by Lapack.
         {
-            if (la_isinf(pA[i]) != 0 || ISNAN(pA[i]))
-            {
-                Scierror(264, _("%s: Wrong value for argument #%d: Must not contain NaN or Inf.\n"), fname, 1);
-                return 0;
-            }
-        }
+            _isnan = isnan(pA[i]);
+            _isinf |= isinf(pA[i]);
+        }        
+    }
+
+    if (_isnan)
+    {
+        createScalarDouble(pvApiCtx, Rhs + 1, NAN);
+        AssignOutputVariable(pvApiCtx, 1) = Rhs + 1;
+        return 0;            
     }
+
+
+
     if (iRows == 0) // A = [] => returning 0.
     {
         createScalarDouble(pvApiCtx, Rhs + 1, 0);
@@ -112,7 +121,7 @@ int sci_norm(char *fname, void* pvApiCtx)
         return 0;
     }
 
-    if (iRows > 1 && iCols > 1) // If A is a matrix, only 1, 2 and %inf are allowed as second argument.
+    if (iRows > 1 && iCols > 1) // If A is a matrix, only 1, 2, %inf and -%inf are allowed as second argument.
     {
         isMat = 1;
     }
@@ -127,7 +136,11 @@ int sci_norm(char *fname, void* pvApiCtx)
     if (Rhs == 1) // One argument => returning norm 2.
     {
         // Call normP() or normPC().
-        if (isComplex)
+        if (_isinf)
+        {
+            ret = INFINITY;
+        }
+        else if (isComplex)
         {
             ret = normPC(pAC, iRows, iCols, 2); // if A is a complex matrix, call the complex function.
         }
@@ -180,7 +193,11 @@ int sci_norm(char *fname, void* pvApiCtx)
             return 0;
         }
 
-        if (isComplex)
+        if (_isinf)
+        {
+            ret = INFINITY;
+        }
+        else if (isComplex)
         {
             ret = normStringC(pAC, iRows, iCols, pflagChar); // if A is a complex matrix, call the complex function.
         }
@@ -232,7 +249,11 @@ int sci_norm(char *fname, void* pvApiCtx)
                 return 0;
             }
 
-            if (isComplex)
+            if (_isinf && la_isinf(flagVal) == 0) // Infs in A and flag != -%inf
+            {
+                ret = INFINITY;
+            }
+            else if (isComplex)
             {
                 ret = normPC(pAC, iRows, iCols, flagVal); // if A is a complex matrix, call the complex function.
             }
diff --git a/scilab/modules/linear_algebra/tests/nonreg_tests/bug_8088.tst b/scilab/modules/linear_algebra/tests/nonreg_tests/bug_8088.tst
new file mode 100644 (file)
index 0000000..7911bc6
--- /dev/null
@@ -0,0 +1,51 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2018 - Stéphane MOTTELET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 8088 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/8088
+//
+// <-- Short Description -->
+// norm() doesn't handle matrices containing %inf or %nan.
+
+//
+// Inf and NaN Exceptions
+// By convention, norm(X,p) == Inf if X contains Infs and no NaNs and p != -%inf
+// and norm(X,p) == NaN  if X contains NaNs.
+//
+// vector
+//
+for p=list(-1,0,1,2,3,%inf,"inf","fro")
+  assert_checkequal(norm([1 %nan],p), %nan);
+  assert_checkequal(norm([%inf %nan],p), %nan);
+  assert_checkequal(norm([%i %nan],p), %nan);
+  assert_checkequal(norm([1 %inf],p), %inf);
+  assert_checkequal(norm([%i %inf],p), %inf);
+end
+assert_checkequal(norm([1 %inf],-%inf), 1);
+assert_checkequal(norm([%i %inf],-%inf), 1);
+assert_checkequal(norm([%nan %inf],-%inf), %nan);
+assert_checkequal(norm([%i %inf %nan],-%inf), %nan);
+//
+// matrix
+//
+for p=list(1,2,%inf,"inf","fro")
+  assert_checkequal(norm([1 0; %nan 0],p), %nan);
+  assert_checkequal(norm([1 0; %inf 0],p), %inf);
+  assert_checkequal(norm([%i 0; %nan 0],p), %nan);
+  assert_checkequal(norm([%i 0; %inf 0],p), %inf);
+  assert_checkequal(norm([%inf 0; %nan 0],p), %nan);
+end
+assert_checkequal(norm([1 0; %nan 0],-%inf), %nan);
+assert_checkequal(norm([1 0; %inf 0],-%inf), 1);
+assert_checkequal(norm([%i 0; %nan 0],-%inf), %nan);
+assert_checkequal(norm([%i 0; %inf 0],-%inf), 1);
+assert_checkequal(norm([%inf 0; %nan 0],-%inf), %nan);
\ No newline at end of file
index 2685065..da09250 100644 (file)
@@ -133,16 +133,3 @@ for i = 1:1000
 end
 t = toc();
 assert_checktrue( t < 4 );
-
-//
-// IEEE compliance
-//
-refMsg = msprintf(_("%s: Wrong value for argument #%d: Must not contain NaN or Inf.\n"), "norm", 1);
-assert_checkerror("norm(%nan)", refMsg);
-assert_checkerror("norm([%i %nan])", refMsg);
-assert_checkerror("norm([%i %inf])", refMsg);
-assert_checkerror("norm([%i; %nan])", refMsg);
-assert_checkerror("norm([%i; %inf])", refMsg);
-assert_checkerror("norm([1 0; %nan 0])", refMsg);
-assert_checkerror("norm([1 0; %inf 0]);", refMsg);
-assert_checkerror("norm([%inf 0; %nan 0]);", refMsg);