* Bug 15058 fixed: gcd and lcm result could be puzzingly <0 20/19520/5
Samuel GOUGEON [Sun, 29 Oct 2017 21:32:00 +0000 (22:32 +0100)]
  http://bugzilla.scilab.org/15058

Change-Id: I7c72b4bdeb89c6bc80b6789eaf814f147307edec

14 files changed:
scilab/CHANGES.md
scilab/modules/elementary_functions/help/en_US/discrete/gcd.xml
scilab/modules/elementary_functions/help/en_US/discrete/lcm.xml
scilab/modules/elementary_functions/help/fr_FR/discrete/lcm.xml
scilab/modules/elementary_functions/help/ja_JP/discrete/lcm.xml
scilab/modules/elementary_functions/help/pt_BR/discrete/lcm.xml
scilab/modules/elementary_functions/help/ru_RU/discrete/lcm.xml
scilab/modules/helptools/data/configuration/scilab_macros.txt
scilab/modules/overloading/macros/%i_lcm.sci [deleted file]
scilab/modules/polynomials/macros/gcd.sci
scilab/modules/polynomials/macros/lcm.sci
scilab/modules/polynomials/tests/unit_tests/gcd.tst
scilab/modules/polynomials/tests/unit_tests/lcm.dia.ref [deleted file]
scilab/modules/polynomials/tests/unit_tests/lcm.tst

index 20fa64f..d4a3fa3 100644 (file)
@@ -218,6 +218,7 @@ bounds selected out of the axes areas is now restored, after the Scilab 5.4 regr
    All files were formerly opened in Scinotes and could make it frozen.
 * `size` can now be overloadable for tlist lists, as it already could for mlist lists.
 * `gcd` now accepts `int64` and `uint64` integers. The input can now be any array instead of a row.
+* `gcd` and `lcm` of integers now return always a positive result.
 * `cat` has been rewritten. It is now fast and can process heavy arrays at high dimensions.
 * `fplot3d1` remove warning messages when it was called without option.
 * `whereis` has been upgraded:
@@ -434,6 +435,7 @@ the [development mailing list](dev@lists.scilab.org) for a particular toolbox.
 * [#15053](http://bugzilla.scilab.org/show_bug.cgi?id=15053): `_str2code` was removed with no proper equivalence and made `mfile2sci` failing.
 * [#15054](http://bugzilla.scilab.org/show_bug.cgi?id=15054): The callbacks of `wfir_gui()` were not prioritary.
 * [#15057](http://bugzilla.scilab.org/show_bug.cgi?id=15057): `Matplot` `.data` assignation did not take care of >2 dimension
+* [#15058](http://bugzilla.scilab.org/show_bug.cgi?id=15058): With integers, `gcd` and `lcm` could return a negative result, depending on the order of negative components.
 * [#15060](http://bugzilla.scilab.org/show_bug.cgi?id=15060): `fplot3d` did not draw because of an addition with an empty matrix which now returns an empty matrix.
 * [#15063](http://bugzilla.scilab.org/show_bug.cgi?id=15063): `fort` wasn't properly removed.
 * [#15070](http://bugzilla.scilab.org/show_bug.cgi?id=15070): `bitset` failed when the bit position is specified as encoded integer.
index 613bec3..3c0a268 100644 (file)
@@ -19,7 +19,7 @@
         xml:lang="en" xml:id="gcd">
     <refnamediv>
         <refname>gcd</refname>
-        <refpurpose>Greatest Common Divisor</refpurpose>
+        <refpurpose>Greatest (positive) Common Divisor</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Syntax</title>
@@ -78,6 +78,9 @@
             <varname>U</varname> gets the corresponding signed inttype.
         </para>
         <para>
+            When <literal>P</literal> are integers, the returned GCD is always positive.
+        </para>
+        <para>
             When a second output is expected, an unimodular matrix <literal>U</literal> of the
             <literal>P</literal> type is returned, such that
             <itemizedlist>
@@ -167,6 +170,10 @@ gcd([0 0])
                         <listitem>
                             The input <literal>P</literal> may be any array instead of a row vector.
                         </listitem>
+                        <listitem>
+                            For input integers possibly negative, the returned GCD is now always
+                            positive.
+                        </listitem>
                     </itemizedlist>
                 </revdescription>
             </revision>
index 4dfe172..398e737 100644 (file)
  * along with this program.
  *
  -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:lang="en" xml:id="lcm">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+          xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML"
+          xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org"
+          xml:lang="en" xml:id="lcm">
     <refnamediv>
         <refname>lcm</refname>
-        <refpurpose>least common multiple</refpurpose>
+        <refpurpose>least common (positive) multiple of integers or of polynomials</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Syntax</title>
-        <synopsis>[pp, fact] = lcm(p)</synopsis>
+        <synopsis>
+           pp = lcm(p)
+          [pp, fact] = lcm(p)
+        </synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Arguments</title>
             <code>pp = lcm(p)</code> computes the lcm <varname>pp</varname> of polynomial vector <varname>p</varname>.
         </para>
         <para>
-            <code>[pp, fact] = lcm(p)</code> computes in addition the vector <varname>fact</varname> such that:
+            <code>[pp, fact] = lcm(p)</code> computes in addition the vector <varname>fact</varname>
+            such that <literal>p.*fact = pp*ones(p)</literal>.
         </para>
         <para>
-            <code>p.*fact = pp*ones(p)</code>.
+          If <literal>p</literal> is a set of integers with some negative ones, the returned value
+          <literal>pp</literal> of their LCM is always positive.
         </para>
         <para>
-            The least common multiple of an array <literal>p</literal> of real numbers can be obtained by
-            converting it to a polynomial before calling <literal>lcm</literal>, through <code>p = inv_coeff(p, 0)</code>.
+            If <literal>p</literal> is an array of decimal integers, they are priorly converted
+            into <literal>int32</literal> before processing.
         </para>
         <para>
-            If <literal>p</literal> is given as an integer double (type 1), then it is treated as an <literal>int32</literal>.
+            The least common multiple of an array <literal>p</literal> of real numbers can be
+            obtained by converting it to a polynomial before calling <literal>lcm</literal>,
+            through <code>p = inv_coeff(p, 0)</code>.
         </para>
     </refsection>
     <refsection>
@@ -96,4 +106,15 @@ lcm(V)
             </member>
         </simplelist>
     </refsection>
+    <refsection role="history">
+        <title>History</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.0.1</revnumber>
+                <revdescription>
+                   For input integers possibly negative, the returned LCM is now always positive.
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
 </refentry>
index 6c3e019..67340e9 100644 (file)
@@ -2,13 +2,15 @@
 <refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:lang="fr" xml:id="lcm">
     <refnamediv>
         <refname>lcm</refname>
-        <refpurpose>Plus petit commun multiple (PPCM) de polynômes
-            ou d'entiers
+        <refpurpose>Plus petit multiple commun (PPCM) de polynômes ou d'entiers
         </refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Séquence d'appel</title>
-        <synopsis>[pp, fact] = lcm(p)</synopsis>
+        <synopsis>
+           pp = lcm(p)
+          [pp, fact] = lcm(p)
+        </synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Paramètres</title>
@@ -16,7 +18,8 @@
             <varlistentry>
                 <term>p</term>
                 <listitem>
-                    <para>vecteur de polynômes (type égal à 2) ou d'entiers (type égal à 1 ou 8)
+                    <para>vecteur de polynômes (type égal à 2) ou d'entiers décimaux ou encodés
+                      (type 1 ou 8).
                     </para>
                 </listitem>
             </varlistentry>
             <literal>p</literal> au sens des polynômes ou des entiers.
         </para>
         <para>
-            <literal>[pp, fact] = lcm(p)</literal> calcule de plus le vecteur <literal>fact</literal> tel que :
+            <literal>[pp, fact] = lcm(p)</literal> calcule de plus le vecteur <literal>fact</literal>
+            tel que <literal>p .* fact = pp * ones(p)</literal>
         </para>
         <para>
-            <literal>p.*fact = pp*ones(p)</literal>
+          Si <literal>p</literal> est une matrice d'entiers dont certains sont négatifs,
+          le PPCM <literal>pp</literal> retourné est toujours positif.
         </para>
         <para>
-            Le plus petit commun multiple d'une matrice <literal>p</literal> de réels peut s'obtenir en la convertissant
-            en polynôme avant d'appeler <literal>lcm</literal>, grâce à la commande <literal>p = inv_coeff(p, 0)</literal>.
+            Si <literal>p</literal> est une matrice d'entiers décimaux, elle est préalablement
+            convertie en entiers <literal>int32</literal> avant les calculs.
         </para>
         <para>
-            Si <literal>p</literal> est donné comme un flottant entier (type 1), alors il est traité comme un <literal>int32</literal>.
+            Le plus petit commun multiple d'une matrice <literal>p</literal> de réels peut
+            s'obtenir en la convertissant en polynôme avant d'appeler <literal>lcm</literal>,
+            grâce à la commande <literal>p = inv_coeff(p, 0)</literal>.
         </para>
     </refsection>
     <refsection>
@@ -85,4 +92,16 @@ lcm(V)
             </member>
         </simplelist>
     </refsection>
+    <refsection role="history">
+        <title>Historique</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.0.1</revnumber>
+                <revdescription>
+                   Pour un ensemble d'entiers dont certains sont négatifs, lcm() en retourne désormais
+                   toujours la valeur absolue du PPCM.
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
 </refentry>
index 0b4e3d3..3637437 100644 (file)
  *
  -->
 
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:lang="ja" xml:id="lcm">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+          xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML"
+          xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org"
+          xml:lang="ja" xml:id="lcm">
 
     <refnamediv>
 
 
         <title>呼び出し手順</title>
 
-        <synopsis>[pp, fact] = lcm(p)</synopsis>
+        <synopsis>
+           pp = lcm(p)
+          [pp, fact] = lcm(p)
+        </synopsis>
 
     </refsynopsisdiv>
 
 
             <code>[pp, fact] = lcm(p)</code> は,これに加えて以下のような
 
-            ベクトル<varname>fact</varname>を計算します:
-
+            ベクトル<varname>fact</varname>を計算します <literal>p .* fact = pp * ones(p)</literal>
         </para>
-
         <para>
-
-            <code>p.*fact = pp*ones(p)</code>
-
+          If <literal>p</literal> is a set of integers with some negative ones, the returned value
+          <literal>pp</literal> of their LCM is always positive.
+        </para>
+        <para>
+            If <literal>p</literal> is an array of decimal integers, they are priorly converted
+            into <literal>int32</literal> before processing.
         </para>
-
         <para>
-
             実数の配列<literal>p</literal>の最小公倍数は,
-
             <literal>lcm</literal>をコールする前に<code>p = inv_coeff(p, 0)</code>により
-
             多項式に変換することにより得られます.
-
         </para>
 
     </refsection>
@@ -161,6 +163,17 @@ lcm(V)
         </simplelist>
 
     </refsection>
+    <refsection role="history">
+        <title>履歴</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.0.1</revnumber>
+                <revdescription>
+                   For input integers possibly negative, the returned LCM is now always positive.
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
 
 </refentry>
 
index 034188e..afb59e2 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2006-2008 - INRIA
  * along with this program.
  *
  -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns4="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="lcm" xml:lang="pt">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns4="http://www.w3.org/1999/xhtml"
+        xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook"
+        xmlns:scilab="http://www.scilab.org" xml:id="lcm" xml:lang="pt">
     <refnamediv>
         <refname>lcm</refname>
-        <refpurpose>mínimo múltiplo comum</refpurpose>
+        <refpurpose>mínimo múltiplo comum</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
-        <title> Seqüência de Chamamento </title>
-        <synopsis>[pp,fact]=lcm(p)</synopsis>
+        <title> Seqüência de Chamamento </title>
+        <synopsis>
+             pp = lcm(p)
+            [pp, fact] = lcm(p)
+        </synopsis>
     </refsynopsisdiv>
     <refsection>
-        <title>Parâmetros</title>
+        <title>Parâmetros</title>
         <variablelist>
             <varlistentry>
                 <term>p</term>
                 <listitem>
-                    <para>vetor de polinômios </para>
+                    <para>vetor de polinômios </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>fact</term>
                 <listitem>
-                    <para>vetor de polinômios ou inteiros (tipo igual a 8)</para>
+                    <para>vetor de polinômios ou inteiros (tipo igual a 8)</para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>pp</term>
                 <listitem>
-                    <para>polinômio ou inteiro</para>
+                    <para>polinômio ou inteiro</para>
                 </listitem>
             </varlistentry>
         </variablelist>
     </refsection>
     <refsection>
-        <title>Descrição</title>
+        <title>Descrição</title>
         <para>
             <literal>pp=lcm(p)</literal> computa o MMC <literal>pp</literal> do
-            vetor de polinômios <literal>p</literal>.
+            vetor de polinômios <literal>p</literal>.
         </para>
         <para>
             <literal>[pp,fact]=lcm(p)</literal> computa, ainda, o vetor
-            <literal>fact</literal> tal que:
+            <literal>fact</literal> tal que <literal>p.*fact=pp*ones(p)</literal>
         </para>
         <para>
-            <literal>p.*fact=pp*ones(p)</literal>
+          If <literal>p</literal> is a set of integers with some negative ones, the returned value
+          <literal>pp</literal> of their LCM is always positive.
+        </para>
+        <para>
+            If <literal>p</literal> is an array of decimal integers, they are priorly converted
+            into <literal>int32</literal> before processing.
         </para>
     </refsection>
     <refsection>
@@ -74,7 +85,7 @@ lcm(V)
  ]]></programlisting>
     </refsection>
     <refsection>
-        <title> Ver Também </title>
+        <title> Ver Também </title>
         <simplelist type="inline">
             <member>
                 <link linkend="gcd">gcd</link>
@@ -84,4 +95,15 @@ lcm(V)
             </member>
         </simplelist>
     </refsection>
+    <refsection role="history">
+        <title>Histórico</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.0.1</revnumber>
+                <revdescription>
+                    For input integers possibly negative, the returned LCM is now always positive.
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
 </refentry>
index 5a44b38..c9649ff 100644 (file)
  * along with this program.
  *
  -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:lang="ru" xml:id="lcm">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+          xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML"
+          xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org"
+          xml:lang="ru" xml:id="lcm">
     <refnamediv>
         <refname>lcm</refname>
         <refpurpose>наименьшее общее кратное (НОК)</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Синтаксис</title>
-        <synopsis>[pp, fact] = lcm(p)</synopsis>
+        <synopsis>
+           pp = lcm(p)
+          [pp, fact] = lcm(p)
+        </synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Аргументы</title>
     <refsection>
         <title>Описание</title>
         <para>
-            <code>pp=lcm(p)</code> вычисляет наименьшее общее кратное <varname>pp</varname> вектора полиномиальных значений <varname>p</varname>.
+            <code>pp=lcm(p)</code> вычисляет наименьшее общее кратное <varname>pp</varname> вектора
+            полиномиальных значений <varname>p</varname>.
         </para>
         <para>
-            <code>[pp, fact]=lcm(p)</code> вычисляет дополнительно вектор <varname>fact</varname> такой, что:
+            <code>[pp, fact]=lcm(p)</code> вычисляет дополнительно вектор <varname>fact</varname>
+            такой, что <literal>p .* fact = pp * ones(p)</literal>.
         </para>
         <para>
-            <code>p.*fact=pp*ones(p)</code>.
+          If <literal>p</literal> is a set of integers with some negative ones, the returned value
+          <literal>pp</literal> of their LCM is always positive.
+        </para>
+        <para>
+            If <literal>p</literal> is an array of decimal integers, they are priorly converted
+            into <literal>int32</literal> before processing.
         </para>
     </refsection>
     <refsection>
@@ -87,4 +100,15 @@ lcm(V)
             </member>
         </simplelist>
     </refsection>
+    <refsection role="history">
+        <title>История</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.0.1</revnumber>
+                <revdescription>
+                   For input integers possibly negative, the returned LCM is now always positive.
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
 </refentry>
index 9819ec3..41b7c1c 100644 (file)
@@ -687,14 +687,12 @@ systmat
 %i_d_i
 %i_dsearch
 %i_e
-%i_gcd
 %i_i_ce
 %i_i_h
 %i_i_hm
 %i_i_i
 %i_i_s
 %i_i_st
-%i_lcm
 %i_length
 %i_m_i
 %i_or
diff --git a/scilab/modules/overloading/macros/%i_lcm.sci b/scilab/modules/overloading/macros/%i_lcm.sci
deleted file mode 100644 (file)
index 2248eca..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) INRIA - Serge Steer
-//
-// Copyright (C) 2012 - 2016 - Scilab Enterprises
-//
-// This file is hereby licensed under the terms of the GNU GPL v2.0,
-// pursuant to article 5.3.4 of the CeCILL v.2.1.
-// This file was originally licensed under the terms of the CeCILL v2.1,
-// and continues to be available under such terms.
-// For more information, see the COPYING file which you should have received
-// along with this program.
-
-function [q,fact]=%i_lcm(p)
-    //p=lcm(p) computes the lcm of polynomial vector p
-    //[pp,fact]=lcm(p) computes besides the vector fact of factors
-    //such that  p.*fact=pp*ones(p)
-    //!
-
-    k=find(p==0)
-    if k<>[] then q=p(k(1)),fact=0*ones(p),fact(k)=1,return,end
-
-    q=p(1);
-    for k=2:size(p,"*")
-        q=q/gcd([q,p(k)])*p(k);
-    end
-    fact=q./p
-endfunction
index cc3d63d..d897b7f 100644 (file)
@@ -2,6 +2,7 @@
 // Copyright (C) ????-2008 - INRIA
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
 // Copyright (C) 2017 - Samuel GOUGEON : http://bugzilla.scilab.org/15017
+//                                       http://bugzilla.scilab.org/15058
 //
 // This file is hereby licensed under the terms of the GNU GPL v2.0,
 // pursuant to article 5.3.4 of the CeCILL v.2.1.
@@ -80,6 +81,10 @@ function [x, uu] = gcd(p)
             end
         end
     end
+    if type(p)~=2 & x~=[] & x<0 then
+        x = -x;
+        uu(:,$) = -uu(:,$);
+    end
     if type(p)==8
         x  = iconvert(x, intype)
         uu = iconvert(uu, modulo(intype,10))    // may have negative terms
index a2d4a9b..3ee7e52 100644 (file)
@@ -1,5 +1,7 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) ????-2008 - INRIA
+// Copyright (C) INRIA - Serge Steer
+// Copyright (C) 2017 - Samuel GOUGEON : http://bugzilla.scilab.org/15058
 //
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
 //
@@ -10,7 +12,6 @@
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-
 function [p, fact] = lcm(p)
     //p=lcm(p) computes the lcm of polynomial vector p
     //[pp,fact]=lcm(p) computes besides the vector fact of factors
@@ -18,25 +19,38 @@ function [p, fact] = lcm(p)
     //!
 
     if type(p)<>1 & type(p)<>2 & type(p)<>8 then
-        error(msprintf(_("%s: Wrong type for argument #%d: Integer array or Polynomial expected.\n"), "lcm", 1));
+        msg = _("%s: Wrong type for argument #%d: Integer array or Polynomial expected.\n");
+        error(msprintf(msg, "lcm", 1));
     end
 
     if type(p)==1 then
-        if floor(p)<>p then
-            error(msprintf(_("%s: Wrong type for argument #%d: Integer array or Polynomial expected.\n"), "lcm", 1));
+        if floor(p) <> p then
+            msg = _("%s: Wrong type for argument #%d: Integer array or Polynomial expected.\n");
+            error(msprintf(msg, "lcm", 1));
         else
-            p = iconvert(p,4);
+            p = iconvert(p, 4);
         end
     end
 
+    // Integers:
     if type(p)==8 then
-        if argn(1)==2 then [p, fact] = %i_lcm(p), else p = %i_lcm(p), end
+        if argn(1)==2 then
+            [p, fact] = %i_lcm(p);
+        else
+            p = %i_lcm(p);
+        end
+        if p~=[] & p<0 then
+            p = -p
+            fact = -fact;
+        end
         return
     end
 
+    // Polynomials:
     [m, n] = size(p),
     p = matrix(p, m*n, 1),
-    p0 = p(1); fact = 1;
+    p0 = p(1);
+    fact = 1;
     for l = 2:m*n,
         [u, v] = simp(p0, p(l)),
         p0 = p0*v,
@@ -44,5 +58,26 @@ function [p, fact] = lcm(p)
     end,
     fact = matrix(fact, m, n),
     p = p0;
+endfunction
+
+// ----------------------------------------------------------------------------
 
+function [q, fact] = %i_lcm(p)
+    // p = lcm(p) computes the lcm of polynomial vector p
+    // [pp,fact]=lcm(p) computes besides the vector fact of factors
+    // such that  p.*fact=pp*ones(p)
+
+    k = find(p==0);
+    if k <> [] then
+        q = p(k(1));
+        fact = 0*ones(p);
+        fact(k) = 1;
+        return
+    end
+
+    q = p(1);
+    for k = 2:size(p,"*")
+        q = q / %i_gcd([q,p(k)]) * p(k);
+    end
+    fact = q ./ p;
 endfunction
index 7668ba0..a262436 100644 (file)
@@ -74,6 +74,28 @@ v = [d*2*25*31 ; d*29*37];  //    1.031D+13 ; 7.135D+12
 assert_checkequal(g, d);
 assert_checkequal(v'*f, [0 g]);
 
+
+// With negative numbers
+// ---------------------
+// http://bugzilla.scilab.org/15058
+v = v(:)';
+v(1) = -v(1);
+[g, f] = gcd(v);
+assert_checktrue(g>0);
+assert_checkequal(g, d);
+assert_checkequal(v*f, [0 g]);
+v = -v;
+[g, f] = gcd(v);
+assert_checktrue(g>0);
+assert_checkequal(g, d);
+assert_checkequal(v*f, [0 g]);
+v = -abs(v);
+[g, f] = gcd(v);
+assert_checktrue(g>0);
+assert_checkequal(g, d);
+assert_checkequal(v*f, [0 g]);
+
+
 // With polynomials
 // ----------------
 d = (1-%z)*(2+%z)*(5*%z -4);
diff --git a/scilab/modules/polynomials/tests/unit_tests/lcm.dia.ref b/scilab/modules/polynomials/tests/unit_tests/lcm.dia.ref
deleted file mode 100644 (file)
index 6a7b4bc..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2013 - Scilab Enterprises - Bruno JOFRET
-//
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
-// <-- CLI SHELL MODE -->
-s=poly(0,'s');
-p=[s,s*(s+1)^2,s^2*(s+2)];
-[pp,fact]=lcm(p);
-assert_checkequal(pp, s^5+4*s^4+5*s^3+2*s^2);
-assert_checkequal(fact, [2*s+5*s^2+4*s^3+s^4, 2*s+s^2, 1+2*s+s^2]);
-V=int32([2^2*3^5, 2^3*3^2,2^2*3^4*5]);
-assert_checkequal(lcm(V), int32(9720));
-// Interger Overflow
-V = int32([59356 44517]);
-assert_checkequal(lcm(V), int32(178068));
-V = int32([50000 50000]);
-assert_checkequal(lcm(V), int32(50000));
index 9c696ae..8c4537d 100644 (file)
@@ -1,16 +1,17 @@
 // =============================================================================
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) 2013 - Scilab Enterprises - Bruno JOFRET
+// Copyright (C) 2017 - Samuel GOUGEON
 //
 //  This file is distributed under the same license as the Scilab package.
 // =============================================================================
 
 // <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
 
-
-s=poly(0,'s');
-p=[s,s*(s+1)^2,s^2*(s+2)];
-[pp,fact]=lcm(p);
+s = poly(0,'s');
+p = [s,s*(s+1)^2,s^2*(s+2)];
+[pp, fact] = lcm(p);
 
 assert_checkequal(pp, s^5+4*s^4+5*s^3+2*s^2);
 assert_checkequal(fact, [2*s+5*s^2+4*s^3+s^4, 2*s+s^2, 1+2*s+s^2]);
@@ -18,9 +19,22 @@ assert_checkequal(fact, [2*s+5*s^2+4*s^3+s^4, 2*s+s^2, 1+2*s+s^2]);
 V=int32([2^2*3^5, 2^3*3^2,2^2*3^4*5]);
 assert_checkequal(lcm(V), int32(9720));
 
-// Interger Overflow
+// Integer Overflow
 V = int32([59356 44517]);
 assert_checkequal(lcm(V), int32(178068));
 
 V = int32([50000 50000]);
-assert_checkequal(lcm(V), int32(50000));
\ No newline at end of file
+assert_checkequal(lcm(V), int32(50000));
+
+// With negative integers
+// ----------------------
+// http://bugzilla.scilab.org/15058
+v = [-2*3*5*7  7*11  -13*17];
+LCMref = int32(2*3*5*7*11*13*17);
+factRef = int32([-11*13*17, 2*3*5*13*17, -2*3*5*7*11]);
+[LCM, fact] = lcm(v);
+assert_checkequal(LCM, LCMref);
+assert_checkequal(fact, factRef);
+[LCM, fact] = lcm(-v);
+assert_checkequal(LCM, LCMref);
+assert_checkequal(fact, -factRef);