* Bug 16609 fixed: bitcmp() upgraded for Scilab 6 43/21643/6
Samuel GOUGEON [Sat, 12 Dec 2020 02:58:37 +0000 (03:58 +0100)]
  http://bugzilla.scilab.org/16609
  Help page rewritten (en_US PDF): http://bugzilla.scilab.org/attachment.cgi?id=5197

Change-Id: I9969af87ff46984ed55c390d78b2bdae167b917d

scilab/CHANGES.md
scilab/modules/elementary_functions/help/en_US/bitwise/bitcmp.xml
scilab/modules/elementary_functions/help/ja_JP/bitwise/bitcmp.xml [deleted file]
scilab/modules/elementary_functions/help/ru_RU/bitwise/bitcmp.xml
scilab/modules/elementary_functions/macros/bitcmp.sci
scilab/modules/elementary_functions/tests/unit_tests/bitcmp.dia.ref [deleted file]
scilab/modules/elementary_functions/tests/unit_tests/bitcmp.tst

index 11da378..172764f 100644 (file)
@@ -90,8 +90,8 @@ Packaging & Supported Operating Systems
 [5]: http://java.com/en/download/help/sysreq.xml
 [6]: https://en.wikipedia.org/wiki/SSE2
 
-Feature changes and additions
------------------------------
+Feature changes and additions on 6.1.0
+--------------------------------------
 
 * `airy` has been added: Evaluation of Airy functions of the first and second kind, and their first derivative, possibly scaled.
 * HTTP get, post, put, upload, patch, delete functions added
@@ -193,7 +193,10 @@ Feature changes and additions
 * `atomsGetInstalledPath` is no longer sensitive to the case or completeness of the modules names. Providing the modules versions is now optional.
 * `function` replaces `mc` as the new overloading code for functions in Scilab language.
 
-6.1.1
+
+Feature changes and additions on 6.1.1
+--------------------------------------
+
 * `gsort` is upgraded:
   - It can now sort any sparse 2D matrix, in all `g, r, c, lr, lc` methods, including sparse booleans and in multi-level mode. It was formerly limited to sparse real or complex vectors and only to the `g` mode.
   - Any hypermatrix can be sorted along a dimension > 2.
@@ -204,6 +207,12 @@ Feature changes and additions
   - complex numbers `y` now supported: the real and imaginary parts are interpolated separately.
   - extrapolation option extended: `edgevalue` mode added for all interpolations; `periodic` mode added for linear and spline interpolations. `linear` mode added for the spline interpolations.
 * `xlfont` did not support the documented 4th argument.
+* `bitcmp` is upgraded:
+  - Entended to 64-bit integers.
+  - Extended to all signed integers.
+  - Decimal positive integers > 2^52 up to 2^1024 = number_properties("huge") can now be processed, with bitnum up to 1024 instead of 52.
+  - bitnum can actually be an array. It is now optional as well for input decimal integers.
+
 
 Help pages:
 -----------
@@ -359,6 +368,7 @@ Bug Fixes
 * [#16557](https://bugzilla.scilab.org/16557): `macr2tree` + `tree2code` translated `e={2}` into `"e=1"` and `e={2,"ab"}` into `"e=[2,"ab"]"`.
 * [#16559](https://bugzilla.scilab.org/16553): `isempty(A)` was true for sparse matrix of dimension 2^16 or larger.
 * [#16596](https://bugzilla.scilab.org/16596): Concatenating encoded integers with sparse numeric data was not possible. 
+* [#16609](https://bugzilla.scilab.org/16609): `bitcmp` needed to be upgraded for Scilab 6.
 * [#16622](https://bugzilla.scilab.org/16622): `inv` could no longer be overloaded for hypermatrices of decimal or complex numbers.
 * [#16623](https://bugzilla.scilab.org/16623): `rand(2,2,2)^2` yielded a wrong result instead of trying to call the `%s_p_s` overload for input hypermatrices.
 * [#16629](https://bugzilla.scilab.org/16629): `interp1`'s documentation did not tell the spline edges conditions ; extrapolation modes were poorly explained. ; the description of the result's size was completely wrong ; x as an option was not documented. A wrong extrapolation value could silently return a wrong result. There was some dead code like `if varargin(5)==%nan`. A bugged error message yielded its own error. When x is implicit, the argument index in error messages could be wrong. `periodic` and `edgevalue` extrapolation modes were not available. `linear` extrapolation was not available for splines. When `xp` is an hypermatrix with `size(xp,1)==1`, the size of the result was irregular/wrong.
index 8cf44d3..b947df7 100644 (file)
@@ -1,10 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- *
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2011 - DIGITEO - Michael Baudin
- *
- * Copyright (C) 2012 - 2016 - Scilab Enterprises
+ * Copyright (C) 2020 - Samuel GOUGEON
  *
  * 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.
  * 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:ns3="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="bitcmp" xml:lang="en">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+      xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns3="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="bitcmp" xml:lang="en">
     <refnamediv>
         <refname>bitcmp</refname>
-        <refpurpose>bitwise complement</refpurpose>
+        <refpurpose>bitwise complement of integers</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Syntax</title>
         </synopsis>
     </refsynopsisdiv>
     <refsection>
-        <title>Parameters</title>
+        <title>Arguments</title>
         <variablelist>
             <varlistentry>
-                <term>x :</term>
-                <listitem>
-                    <para>
-                        a <literal>m</literal>-by-<literal>n</literal> matrix of doubles
-                        or a <literal>m1</literal>-by-<literal>m2</literal>-by-...-by-<literal>mm</literal> hypermatrix of doubles
-                        or a <literal>m</literal>-by-<literal>n</literal> matrix of unsigned integers (<literal>uint8</literal>, <literal>uint16</literal> or <literal>uint32</literal>).
-                        Must contain positive integer values.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>bitnum :</term>
+                <term>x, y</term>
                 <listitem>
-                    <para>
-                        a <literal>m</literal>-by-<literal>n</literal> matrix of doubles
-                        or a <literal>m1</literal>-by-<literal>m2</literal>-by-...-by-<literal>mm</literal> hypermatrix of doubles
-                        or a <literal>m</literal>-by-<literal>n</literal> matrix of unsigned integers (<literal>uint8</literal>, <literal>uint16</literal> or <literal>uint32</literal>).
-                        The input <literal>n</literal> must be in the range 1, 2, ..., <literal>bitmax</literal>
-                        where <literal>bitmax</literal> is the maximum number of bits in <varname>x</varname>.
-                        <varname>bitnum</varname> must contain positive integer values. The default value for <varname>bitnum</varname> is <literal>bitmax</literal>.
-                    </para>
+                    arrays of signed or unsigned integers (int8, .., uint64), or of positive decimal
+                    integers. Hypermatrix supported. <varname>x</varname> and <varname>y</varname>
+                    have the same integer type and the same size.
+                    <para/>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>y :</term>
+                <term>bitnum</term>
                 <listitem>
-                    <para>
-                        a <literal>m</literal>-by-<literal>n</literal> matrix of doubles
-                        or a <literal>m1</literal>-by-<literal>m2</literal>-by-...-by-<literal>mm</literal> hypermatrix of  doubles
-                        or a <literal>m</literal>-by-<literal>n</literal> matrix of unsigned integers.
-                    </para>
+                    positive encoded or decimal integer, or array of positive encoded or decimal
+                    integers of size equal to size(x): bits #1 to #bitnum of <varname>x</varname>
+                    are considered and inversed. According to the integer type of
+                    <varname>x</varname>, <varname>bitnum</varname> must be in the interval
+                    <literal>[1, bitmax]</literal> with bitmax as follows:
+                    <table>
+                        <tr><th>inttype :</th>
+                            <td>int8</td>
+                            <td>uint8</td>
+                            <td>int16</td>
+                            <td>uint16</td>
+                            <td>int32</td>
+                            <td>uint32</td>
+                            <td>int64</td>
+                            <td>uint64</td>
+                            <td>decimal</td>
+                        </tr>
+                        <tr><th>bitmax :</th>
+                            <td>8</td>
+                            <td>8</td>
+                            <td>16</td>
+                            <td>16</td>
+                            <td>32</td>
+                            <td>32</td>
+                            <td>64</td>
+                            <td>64</td>
+                            <td>1024</td>
+                        </tr>
+                    </table>
+                    <para/>
+                    The default <varname>bitnum</varname> value depends on the input integer
+                    type:
+                    <itemizedlist>
+                        <listitem>
+                            <literal>bitnum = bitmax</literal> for encoded integers
+                        </listitem>
+                        <listitem>
+                            <literal>bitnum = 53</literal> for decimal integers
+                            <literal>x ≤ 1/%eps</literal>
+                        </listitem>
+                        <listitem>
+                            <literal>bitnum = int(log2(x))+1</literal> for decimal integers
+                            <literal>x > 1/%eps</literal>.
+                        </listitem>
+                    </itemizedlist>
+                    <para/>
                 </listitem>
             </varlistentry>
         </variablelist>
     <refsection>
         <title>Description</title>
         <para>
-            Given an unsigned integer <varname>x</varname>, this function returns the unsigned integer <varname>y</varname>
-            which is the integer corresponding to the complementary of the binary
-            form of <varname>x</varname>.
+            <literal>bitcmp(x)</literal> computes the binary complement of each element of
+            <varname>x</varname>, and provides it in the corresponding element of <varname>y</varname>.
         </para>
         <para>
-            The integer <varname>bitnum</varname> sets the maximum number of bits.
+            In the following description, 2^0 corresponds to the bit #1. An integer whose highest
+            bit on is #n, is in <literal>[2^(n-1), 2^n-1]</literal>.
         </para>
         <para>
-            If the bits number of the <varname>x</varname> binary representation is less than the
-            <literal>bitmax</literal> number (8,16 or 32) then the bits <literal>'1'</literal> are added to the
-            complementary in order to have <literal>bitmax</literal> number (8, 16 or 32) for the
-            complementary.
+            For <varname>x</varname> such that <literal>abs(x) ≥ 2^bitnum</literal>,
+            its bits <literal>#(bitnum+1)</literal> to <literal>#(int(log2(x))+1)</literal>
+            are ignored. Only its bits <literal>#1</literal> to <literal>#bitnum</literal>
+            are considered and inversed.
         </para>
         <para>
-            If only one input argument is given, <varname>x</varname> must be a matrix of unsigned integers.
+            Example:
+            <screen>
+--> bitget(180, 1:8)
+ ans  =
+   0.   0.   1.   0.   1.   1.   0.   1.
+--> bitcmp(180, 4)
+ ans  =
+   11.
+--> bitget(11, 1:8)
+ ans  =
+   1.   1.   0.   1.   0.   0.   0.   0.
+</screen>
+        </para>
+        <para>
+            For <varname>x</varname> such that <literal>abs(x) &lt; 2^bitnum</literal>,
+            bits <literal>#(int(log2(x))+2)</literal> to <literal>#bitnum</literal> are padded
+            with 0. Then all bits <literal>#1</literal> to <literal>#bitnum</literal> are considered
+            and inversed.
+        </para>
+        <para>
+            Example:
+            <screen>
+--> x = 30; int(log2(30))+2
+ ans  =
+   6.
+--> bitget(30, 1:10)
+ ans  =
+   0.   1.   1.   1.   1.   0.   0.   0.   0.   0.
+--> bitcmp(30, 7)
+ ans  =
+   97.
+--> bitget(97, 1:10)
+ ans  =
+   1.   0.   0.   0.   0.   1.   1.   0.   0.   0.
+</screen>
         </para>
     </refsection>
     <refsection>
         <title>Examples</title>
         <programlisting role="example"><![CDATA[
-// 13 is (1101)_2
-// We insert zeros in the beginning to get a 8-bit number:
-// (00001101)_2
-// The 8-bits complement is then (11110010)_2
-// which is 242
-bitcmp(13,8)
-expected = 242
-
-// The input argument can be an unsigned int
-bitcmp(uint8(99),8)
-expected = 156
+x = uint8(13);
+b = bitget(x, 1:8)
+c = bitcmp(x, 8)
+bitget(c, 1:8)
+1 - b
    ]]></programlisting>
+        <screen><![CDATA[
+--> b = bitget(x, 1:8)
+ b  =
+  1  0  1  1  0  0  0  0
+
+--> c = bitcmp(x, 8)
+ c  =
+  242
+
+--> bitget(c, 1:8)
+ ans  =
+  0  1  0  0  1  1  1  1
+
+--> 1 - b
+ ans  =
+  0  1  0  0  1  1  1  1
+]]></screen>
+        <para/>
+        <para>
+        Negative encoded integers are accepted:
+        </para>
+        <programlisting role="example"><![CDATA[
+bitcmp(int8([-71 -34 -1 0 33 70]))
+bitcmp(int8([-71 -34 -1 0 33 70]), 8)
+bitcmp(int8([-71 -34 -1 0 33 70]), 7)
+bitcmp(int8([-71 -34 -1 0 33 70]), 6)
+bitcmp(int8([-71 -34 -1 0 33 70]), 5)
+bitcmp(int8([-71 -34 -1 0 33 70]), 4)
+     ]]></programlisting>
+        <screen><![CDATA[
+--> bitcmp(int8([-71 -34 -1 0 33 70]))
+ ans  =
+  70  33  0 -1 -34 -71
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 8)
+ ans  =
+  70  33  0 -1 -34 -71
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 7)
+ ans  =
+  70  33  0  127  94  57
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 6)
+ ans  =
+  6  33  0  63  30  57
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 5)
+ ans  =
+  6  1  0  31  30  25
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 4)
+ ans  =
+  6  1  0  15  14  9
+]]></screen>
+        <para/>
+        <para>
+            We can work with 64-bit big integers:
+        </para>
+        <programlisting role="example"><![CDATA[
+b = (rand(1,62)<0.5)*1;
+x = sum(b .* (uint64(2).^(0:61)))
+r = bitcmp(x)
+bg = bitget(r, 1:62);
+[msprintf("%d ",b(:)) ; msprintf("%d ",bg(:))]
+     ]]></programlisting>
+        <screen><![CDATA[
+--> x = sum(b .* (uint64(2).^(0:61)))
+ x  =
+  4154509482123930814
+
+--> r = bitcmp(x)
+ r  =
+  14292234591585620801
+
+--> bg = bitget(r, 1:62);
+--> [msprintf("%d ",b(:)) ; msprintf("%d ",bg(:))]
+ ans  =
+  "0 1 1 1 1 1 0 1 0 0 1 1 0 1 0 0 ... 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 1 0 1 1 0 0 1 1 1 "
+  "1 0 0 0 0 0 1 0 1 1 0 0 1 0 1 1 ... 0 1 1 1 1 0 1 1 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 "
+]]></screen>
+        <para/>
+        <para>
+        bitnum can be an array:
+        </para>
+        <programlisting role="example"><![CDATA[
+bitcmp([0 0 0 0 0], 3:7)
+     ]]></programlisting>
+        <screen><![CDATA[
+--> bitcmp([0 0 0 0 0], 3:7)
+ ans  =
+   7.   15.   31.   63.   127.
+]]></screen>
+        <para/>
+        <para>
+            bitnum can be > 52:
+        </para>
+        <programlisting role="example"><![CDATA[
+format(22)
+bitcmp(2^70, 65)
+sum(2.^(13:64))   // 52 highest bits
+     ]]></programlisting>
+        <screen><![CDATA[
+--> bitcmp(2^70, 65)
+ ans  =
+   36893488147419095040.
+
+--> sum(2.^(13:64))
+ ans  =
+   36893488147419095040.
+]]></screen>
+        <para/>
+        <para>
+            Huge decimal numbers can be processed:
+        </para>
+        <programlisting role="example"><![CDATA[
+format(22)
+log2(1e100)
+r = bitcmp(1e100, 333)
+bitcmp(1e100) // bitnum = int(log2(x)) + 1 is used by default
+bitcmp(r, 333)
+     ]]></programlisting>
+        <screen><![CDATA[
+--> log2(1e100)
+ ans  =
+   332.19280948873625903
+
+--> r = bitcmp(1e100, 333)
+ r  =
+   7.498005798264093D+99
+
+--> bitcmp(1e100)  // bitnum = int(log2(x)) + 1 is used by default
+ ans  =
+   7.498005798264093D+99
+
+--> bitcmp(r, 333)
+ ans  =
+   1.00000000000000D+100
+]]></screen>
+    </refsection>
+    <refsection role="see also">
+        <title>See Also</title>
+        <simplelist type="inline">
+            <member>
+                <link linkend="bitxor">bitxor</link>
+            </member>
+            <member>
+                <link linkend="bitget">bitget</link>
+            </member>
+            <member>
+                <link linkend="minus">minus</link>
+            </member>
+        </simplelist>
+    </refsection>
+    <refsection role="history">
+        <title>History</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.1.1</revnumber>
+                <revdescription>
+                    <itemizedlist>
+                        <listitem>
+                            Extension to 64 bit integers.
+                        </listitem>
+                        <listitem>
+                            Extension to all signed integers.
+                        </listitem>
+                        <listitem>
+                            Decimal positive integers > 2^52 up to 2^1024 = number_properties("huge")
+                            can now be processed, with bitnum up to 1024 instead of 52.
+                        </listitem>
+                        <listitem>
+                            bitnum is now optional as well for input decimal integers.
+                            It can actually be an array.
+                        </listitem>
+                    </itemizedlist>
+                </revdescription>
+            </revision>
+        </revhistory>
     </refsection>
 </refentry>
diff --git a/scilab/modules/elementary_functions/help/ja_JP/bitwise/bitcmp.xml b/scilab/modules/elementary_functions/help/ja_JP/bitwise/bitcmp.xml
deleted file mode 100644 (file)
index 35a9439..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- *
- * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2011 - DIGITEO - Michael Baudin
- *
- * 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.
- *
- -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns3="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="bitcmp" xml:lang="ja">
-    <refnamediv>
-        <refname>bitcmp</refname>
-        <refpurpose>ビット毎の補数</refpurpose>
-    </refnamediv>
-    <refsynopsisdiv>
-        <title>呼び出し手順</title>
-        <synopsis>
-            y = bitcmp(x)
-            y = bitcmp(x, bitnum)
-        </synopsis>
-    </refsynopsisdiv>
-    <refsection>
-        <title>パラメータ</title>
-        <variablelist>
-            <varlistentry>
-                <term>x :</term>
-                <listitem>
-                    <para>
-                        <literal>m</literal>行<literal>n</literal>列の行列(double)または
-                        <literal>m1</literal> x <literal>m2</literal>
-                        x ... x <literal>mm</literal> ハイパー行列(double)
-                        または符合なし整数(
-                        <literal>uint8</literal>, <literal>uint16</literal> または
-                        <literal>uint32</literal>)の
-                        <literal>m</literal>行<literal>n</literal>列行列.
-                        値は正の整数値である必要があります.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>n :</term>
-                <listitem>
-                    <para>
-                        <literal>m</literal>行<literal>n</literal>列の行列(double)または
-                        <literal>m1</literal> x <literal>m2</literal>
-                        x ... x <literal>mm</literal> ハイパー行列(double)
-                        または符合なし整数(
-                        <literal>uint8</literal>, <literal>uint16</literal> または
-                        <literal>uint32</literal>)の
-                        <literal>m</literal>行<literal>n</literal>列行列.
-                        入力<literal>n</literal>は 1,2,...,<literal>bitmax</literal>
-                        の範囲であることが必要です.
-                        ただし,<literal>bitmax</literal> は <varname>x</varname>
-                        の最大ビット数です.
-                        <varname>bitnum</varname>は,正の整数値である必要があります.
-                        <varname>bitnum</varname>のデフォルト値は
-                        <literal>bitmax</literal>です.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>y :</term>
-                <listitem>
-                    <para>
-                        <literal>m</literal>行<literal>n</literal>列の行列(double)または
-                        <literal>m1</literal> x <literal>m2</literal>
-                        x ... x <literal>mm</literal> ハイパー行列(double)
-                        または符合なし整数の
-                        <literal>m</literal>行<literal>n</literal>列行列.
-                    </para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </refsection>
-    <refsection>
-        <title>説明</title>
-        <para>
-            符合なし整数<literal>x</literal>を指定すると, この関数は
-            <literal>x</literal>の2進数形式の補数を値とする
-            符合なし整数<varname>y</varname>を返します.
-        </para>
-        <para>
-            整数 <varname>bitnum</varname> は最大ビット数を指定します.
-        </para>
-        <para>
-            <literal>x</literal>の2進数表現のビット数が<literal>bitmax</literal>
-            の値 (8, 16 または 32)
-            よりも小さい場合, <literal>bitmax</literal>ビット
-            (8, 16 または 32)の補数とするために
-            ビット '1' がこの補数に付加されます.
-        </para>
-        <para>
-            入力引数が1つのみの場合,
-            <varname>x</varname> は符号無し整数の行列とする必要があります.
-        </para>
-    </refsection>
-    <refsection>
-        <title>例</title>
-        <programlisting role="example"><![CDATA[
-// 13 is (1101)_2
-// We insert zeros in the begining to get a 8-bit number:
-// (00001101)_2
-// The 8-bits complement is then (11110010)_2
-// which is 242
-bitcmp(13,8)
-expected = 242
-// The input argument can be an unsigned int
-bitcmp(uint8(99),8)
-expected = 156
-   ]]></programlisting>
-    </refsection>
-</refentry>
index 81a7165..ba9269a 100644 (file)
@@ -1,10 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- *
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2011 - DIGITEO - Michael Baudin
- *
- * Copyright (C) 2012 - 2016 - Scilab Enterprises
+ * Copyright (C) 2020 - Samuel GOUGEON
  *
  * 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.
  * 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:ns3="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="bitcmp" xml:lang="ru">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+      xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns3="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="bitcmp" xml:lang="ru">
     <refnamediv>
         <refname>bitcmp</refname>
-        <refpurpose>побитовое дополнение</refpurpose>
+        <refpurpose>побитовое дополнение целых чисел</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Синтаксис</title>
         <synopsis>
+            y = bitcmp(x)
             y = bitcmp(x, bitnum)
         </synopsis>
     </refsynopsisdiv>
     <refsection>
-        <title>Параметры</title>
+        <title>Аргументы</title>
         <variablelist>
             <varlistentry>
-                <term>x :</term>
-                <listitem>
-                    <para>
-                        матрица чисел двойной точности (<literal>double</literal>) размером <literal>m</literal> на <literal>n</literal>
-                        или гиперматрица чисел двойной точности размером <literal>m1</literal> на <literal>m2</literal> на ... на <literal>mm</literal>
-                        или матрица беззнаковых целых чисел (<literal>uint8</literal>, <literal>uint16</literal> или <literal>uint32</literal>) размером <literal>m</literal> на <literal>n</literal>. Должна содержать положительные целые значения.
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>bitnum :</term>
+                <term>x, y</term>
                 <listitem>
-                    <para>
-                        матрица чисел двойной точности (<literal>double</literal>) размером <literal>m</literal> на <literal>n</literal>
-                        или гиперматрица чисел двойной точности размером <literal>m1</literal> на <literal>m2</literal> на ... на <literal>mm</literal>
-                        или матрица беззнаковых целых чисел (<literal>uint8</literal>, <literal>uint16</literal> или <literal>uint32</literal>) размером <literal>m</literal> на <literal>n</literal>. Должна содержать положительные целые значения.
-                        Входная <varname>bitnum</varname> должна быть в диапазоне 1, 2, ..., <literal>bitmax</literal>
-                        где <literal>bitmax</literal> - максимальное количество битов в <varname>x</varname>.
-                        <varname>bitnum</varname> должна содержать положительные целые значения.
-                    </para>
+                    массивы знаковых и беззнаковых целых чисел (int8, .., uint64)
+                    или положительных десятичных целых чисел. Поддерживаются гиперматрицы.
+                    <varname>x</varname> и <varname>y</varname> одного типа целого
+                    числа и одинакового размера.
+                    <para/>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>y :</term>
+                <term>bitnum</term>
                 <listitem>
-                    <para>
-                        матрица чисел двойной точности размером <literal>m</literal> на <literal>n</literal>
-                        или гиперматрица чисел двойной точности размером <literal>m1</literal> на <literal>m2</literal> на ... на <literal>mm</literal>
-                        или матрица беззнаковых целых чисел (<literal>uint8</literal>, <literal>uint16</literal> или <literal>uint32</literal>) размером <literal>m</literal> на <literal>n</literal>.
-                    </para>
+                    положительное кодированное иди десятичное целое число или массив
+                    положительных кодированных или десятичных целых чисел размером,
+                    равным size(x): учитываются и инвертируются биты от №1 до №bitnum
+                    в <varname>x</varname>. В соответствии с типом целого числа
+                    <varname>x</varname>, <varname>bitnum</varname> должен быть в
+                    интервале <literal>[1, bitmax]</literal>, где <literal>bitmax</literal>:
+                    <table>
+                        <tr><th>inttype :</th>
+                            <td>int8</td>
+                            <td>uint8</td>
+                            <td>int16</td>
+                            <td>uint16</td>
+                            <td>int32</td>
+                            <td>uint32</td>
+                            <td>int64</td>
+                            <td>uint64</td>
+                            <td>decimal</td>
+                        </tr>
+                        <tr><th>bitmax :</th>
+                            <td>8</td>
+                            <td>8</td>
+                            <td>16</td>
+                            <td>16</td>
+                            <td>32</td>
+                            <td>32</td>
+                            <td>64</td>
+                            <td>64</td>
+                            <td>1024</td>
+                        </tr>
+                    </table>
+                    <para/>
+                    Значение по умолчанию <varname>bitnum</varname> зависит от
+                    типа входного целого числа:
+                    <itemizedlist>
+                        <listitem>
+                            <literal>bitnum = bitmax</literal> для кодированных целых чисел
+                        </listitem>
+                        <listitem>
+                            <literal>bitnum = 53</literal> для десятичных целых чисел
+                            <literal>x ≤ 1/%eps</literal>
+                        </listitem>
+                        <listitem>
+                            <literal>bitnum = int(log2(x))+1</literal> для десятичных целых чисел
+                            <literal>x > 1/%eps</literal>.
+                        </listitem>
+                    </itemizedlist>
+                    <para/>
                 </listitem>
             </varlistentry>
         </variablelist>
     <refsection>
         <title>Описание</title>
         <para>
-            Для заданного беззнакового целого числа <varname>x</varname>, эта функция возвращает беззнаковое целое число <varname>y</varname>, которое является целым числом, соответствующим дополнительному коду двоичного представления <varname>x</varname>.
+            <literal>bitcmp(x)</literal> вычисляет двоичный дополнительный код каждого
+            элемента <varname>x</varname> и выдаёт его в соответствующем элементе
+            <varname>y</varname>.
+        </para>
+        <para>
+            В следующем описании 2^0 соответствует биту №1. Целое число, чей наивысший
+            бит №n, находится в интервале <literal>[2^(n-1), 2^n-1]</literal>.
+        </para>
+        <para>
+            Для <varname>x</varname> такого, что <literal>abs(x) ≥ 2^bitnum</literal>,
+            его биты от <literal>#(bitnum+1)</literal> до <literal>№(int(log2(x))+1)</literal>
+            игнорируются. Рассматриваются и инвертируются только его биты от
+            <literal>№1</literal> до <literal>№bitnum</literal>
+        </para>
+        <para>
+            Пример:
+            <screen>
+--> bitget(180, 1:8)
+ ans  =
+   0.   0.   1.   0.   1.   1.   0.   1.
+--> bitcmp(180, 4)
+ ans  =
+   11.
+--> bitget(11, 1:8)
+ ans  =
+   1.   1.   0.   1.   0.   0.   0.   0.
+</screen>
         </para>
         <para>
-            Целое число <varname>bitnum</varname> устанавливает максимальное количество битов.
+            Для <varname>x</varname> такого, что <literal>abs(x) &lt; 2^bitnum</literal>,
+            биты от <literal>№(int(log2(x))+2)</literal> до <literal>№bitnum</literal>
+            дополняются нулями. Затем рассматриваются и инвертируются все биты от <literal>№1</literal> до
+            <literal>№bitnum</literal>.
         </para>
         <para>
-            Если количество битов в двоичном представлении <varname>x</varname> меньше количества
-            <literal>bitmax</literal> (8, 16 или 32), то добавляются биты <literal>'1'</literal> к дополнительному коду для того чтобы у дополнительного кода количество битов было <literal>bitmax</literal> (8, 16 или 32).
+            Пример:
+            <screen>
+--> x = 30; int(log2(30))+2
+ ans  =
+   6.
+--> bitget(30, 1:10)
+ ans  =
+   0.   1.   1.   1.   1.   0.   0.   0.   0.   0.
+--> bitcmp(30, 7)
+ ans  =
+   97.
+--> bitget(97, 1:10)
+ ans  =
+   1.   0.   0.   0.   0.   1.   1.   0.   0.   0.
+</screen>
         </para>
     </refsection>
     <refsection>
         <title>Примеры</title>
         <programlisting role="example"><![CDATA[
-// 13 соответствует (1101)_2
-// Мы вводим нули в начало, чтобы получить 8-битовое число:
-// (00001101)_2
-// 8-битовый дополнительный код тогда (11110010)_2,
-// что соответствует 242
-bitcmp(13,8)
-expected = 242
-
-// Входной аргумент может быть беззнаковым целым числом
-bitcmp(uint8(99),8)
-expected = 156
+x = uint8(13);
+b = bitget(x, 1:8)
+c = bitcmp(x, 8)
+bitget(c, 1:8)
+1 - b
    ]]></programlisting>
+        <screen><![CDATA[
+--> b = bitget(x, 1:8)
+ b  =
+  1  0  1  1  0  0  0  0
+
+--> c = bitcmp(x, 8)
+ c  =
+  242
+
+--> bitget(c, 1:8)
+ ans  =
+  0  1  0  0  1  1  1  1
+
+--> 1 - b
+ ans  =
+  0  1  0  0  1  1  1  1
+]]></screen>
+        <para/>
+        <para>
+        Принимаются отрицательные кодированные целые числа:
+        </para>
+        <programlisting role="example"><![CDATA[
+bitcmp(int8([-71 -34 -1 0 33 70]))
+bitcmp(int8([-71 -34 -1 0 33 70]), 8)
+bitcmp(int8([-71 -34 -1 0 33 70]), 7)
+bitcmp(int8([-71 -34 -1 0 33 70]), 6)
+bitcmp(int8([-71 -34 -1 0 33 70]), 5)
+bitcmp(int8([-71 -34 -1 0 33 70]), 4)
+     ]]></programlisting>
+        <screen><![CDATA[
+--> bitcmp(int8([-71 -34 -1 0 33 70]))
+ ans  =
+  70  33  0 -1 -34 -71
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 8)
+ ans  =
+  70  33  0 -1 -34 -71
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 7)
+ ans  =
+  70  33  0  127  94  57
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 6)
+ ans  =
+  6  33  0  63  30  57
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 5)
+ ans  =
+  6  1  0  31  30  25
+
+--> bitcmp(int8([-71 -34 -1 0 33 70]), 4)
+ ans  =
+  6  1  0  15  14  9
+]]></screen>
+        <para/>
+        <para>
+            Можно работать с 64-битными большими целыми числами:
+        </para>
+        <programlisting role="example"><![CDATA[
+b = (rand(1,62)<0.5)*1;
+x = sum(b .* (uint64(2).^(0:61)))
+r = bitcmp(x)
+bg = bitget(r, 1:62);
+[msprintf("%d ",b(:)) ; msprintf("%d ",bg(:))]
+     ]]></programlisting>
+        <screen><![CDATA[
+--> x = sum(b .* (uint64(2).^(0:61)))
+ x  =
+  4154509482123930814
+
+--> r = bitcmp(x)
+ r  =
+  14292234591585620801
+
+--> bg = bitget(r, 1:62);
+--> [msprintf("%d ",b(:)) ; msprintf("%d ",bg(:))]
+ ans  =
+  "0 1 1 1 1 1 0 1 0 0 1 1 0 1 0 0 ... 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 1 0 1 1 0 0 1 1 1 "
+  "1 0 0 0 0 0 1 0 1 1 0 0 1 0 1 1 ... 0 1 1 1 1 0 1 1 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 0 "
+]]></screen>
+        <para/>
+        <para>
+        bitnum может быть массивом:
+        </para>
+        <programlisting role="example"><![CDATA[
+bitcmp([0 0 0 0 0], 3:7)
+     ]]></programlisting>
+        <screen><![CDATA[
+--> bitcmp([0 0 0 0 0], 3:7)
+ ans  =
+   7.   15.   31.   63.   127.
+]]></screen>
+        <para/>
+        <para>
+            bitnum может быть > 52:
+        </para>
+        <programlisting role="example"><![CDATA[
+format(22)
+bitcmp(2^70, 65)
+sum(2.^(13:64))   // 52 высшие биты
+     ]]></programlisting>
+        <screen><![CDATA[
+--> bitcmp(2^70, 65)
+ ans  =
+   36893488147419095040.
+
+--> sum(2.^(13:64))
+ ans  =
+   36893488147419095040.
+]]></screen>
+        <para/>
+        <para>
+            Могут обрабатываться огромные десятичные числа:
+        </para>
+        <programlisting role="example"><![CDATA[
+format(22)
+log2(1e100)
+r = bitcmp(1e100, 333)
+bitcmp(1e100) // bitnum = int(log2(x)) + 1 is used by default
+bitcmp(r, 333)
+     ]]></programlisting>
+        <screen><![CDATA[
+--> log2(1e100)
+ ans  =
+   332.19280948873625903
+
+--> r = bitcmp(1e100, 333)
+ r  =
+   7.498005798264093D+99
+
+--> bitcmp(1e100)  // bitnum = int(log2(x)) + 1 is used by default
+ ans  =
+   7.498005798264093D+99
+
+--> bitcmp(r, 333)
+ ans  =
+   1.00000000000000D+100
+]]></screen>
+    </refsection>
+    <refsection role="see also">
+        <title>Смотрите также</title>
+        <simplelist type="inline">
+            <member>
+                <link linkend="bitxor">bitxor</link>
+            </member>
+            <member>
+                <link linkend="bitget">bitget</link>
+            </member>
+            <member>
+                <link linkend="minus">минус</link>
+            </member>
+        </simplelist>
+    </refsection>
+    <refsection role="history">
+        <title>История</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.1.1</revnumber>
+                <revdescription>
+                    <itemizedlist>
+                        <listitem>
+                            Расширение до 64-битных целых чисел.
+                        </listitem>
+                        <listitem>
+                            Расширение до всех знаковых целых чисел.
+                        </listitem>
+                        <listitem>
+                            Десятичные положительные целые числа > 2^52 вплоть до
+                            2^1024 = number_properties("huge")
+                            теперь могут быть обработаны с bitnum вплоть до 1024 вместо 52.
+                        </listitem>
+                        <listitem>
+                            bitnum теперь необязательно как и входные десятичные целые числа.
+                            Оно на самом деле может быть массивом.
+                        </listitem>
+                    </itemizedlist>
+                </revdescription>
+            </revision>
+        </revhistory>
     </refsection>
 </refentry>
index b09731c..c482ee7 100644 (file)
@@ -1,8 +1,8 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) ???? - INRIA - Farid BELAHCENE
 // Copyright (C) 2008 - INRIA - Pierre MARECHAL
-//
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2020 - Samuel GOUGEON
 //
 // 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.
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-function y = bitcmp(x,n)
+function y = bitcmp(x, n)
 
-    // BITCMP function
-    //
-    // Given an unsigned integer x, this function returns the unsigned integer
-    // which is the integer corresponding to the complementary of the binary
-    // form of x
-    //
-    // If the bits number of the x binary representation is less than the
-    // bitmax number (8,16 or 32) then the bits '1' are added to the
-    // complementary in order to have bitmax number (8, 16 or 32) for the
-    // complementary
-    //
-    // for example for the type uint8 (bitmax=8), the complementary of '1101' is not '0010' but '11110010'
-    // The integer n sets the bits max number
-    // -Inputs :
-    //  x : an unsigned integer
-    //  n : a positive integer between 1 and the bitmax of the x type
-    //
-    // -Output :
-    //  y : an unsigned integer
+    // BITCMP function: bitwise complement of integers
     //
-    // P. Marechal, 5 Feb 2008
-    //   - Add argument check
+    // P. Marechal, 2008 : Add argument check
+    // S. Gougeon, 2020 :
+    //   * Entension to 64 bit integers.
+    //   * Extension to all signed integers.
+    //   * Decimal positive integers > 2^52 up to 2^1024 = number_properties("huge")
+    //      can now be processed, with bitnum up to 1024 instead of 52.
+    //   * bitnum is now optional as well for input decimal integers.
+    //     It can actually be an array.
 
-    // check number input argument
     rhs = argn(2);
 
-    if rhs == 0 then
-        error(msprintf(gettext("%s: Wrong number of input argument(s): At least %d expected.\n"),"bitcmp",1));
-    elseif (type(x) == 1) & (rhs == 1) then
-        error(msprintf(gettext("%s: Wrong number of input argument(s): %d expected.\n"),"bitcmp",2));
+    // CHECK INPUT ARGUMENTS
+    // =========================================================================
+    if rhs < 1 | rhs > 2 then
+        msg = gettext("%s: Wrong number of input arguments: %d or %d expected.\n")
+        error(msprintf(msg, "bitcmp", 1, 2));
     end
 
-    // check type
-
-    if    (type(x)==1  & (x-floor(x)<>0 | x<0)) ..
-        | (type(x)==8  & (inttype(x)<10)) ..
-        | (type(x)<>1  & type(x)<>8) then
 
-        error(msprintf(gettext("%s: Wrong input argument #%d: Scalar/matrix of unsigned integers expected.\n"),"bitcmp",1));
+    // Check types
+    if and(type(x)<>[1 8]) | (type(x)==1 & ~isreal(x))
+        msg = gettext("%s: Argument #%d: Decimal or encoded integers expected.\n");
+        error(msprintf(msg, "bitcmp",1))
     end
-
-    if  (rhs == 2) & ( ..
-        (type(n)==1  & (n-floor(n)<>0 | x<0)) ..
-        | (type(n)==8  & (inttype(n)<10)) ..
-        | (type(n)<>1  & type(n)<>8) ..
-        | (size(n,"*")<>1) ) then
-
-        error(msprintf(gettext("%s: Wrong input argument #%d: An unsigned integer expected.\n"),"bitcmp",2));
+    if x==[] then
+        y = []
+        return
+    end
+    if type(x)==1 & (or(x-floor(x)<>0) | or(x<0)) then
+        msg = gettext("%s: Argument #%d: Positive decimal integers expected.\n");
+        error(msprintf(msg, "bitcmp",1))
     end
-
-    // check n value
-
     select inttype(x)
-    case 0  then nmax = 52;
-    case 11 then nmax = 8;
-    case 12 then nmax = 16;
-    case 14 then nmax = 32;
+    case 0  then
+        nmax = 1024
+        p = int(log2(x)) + 1
+    case 1 then nmax = 8
+    case 2 then nmax = 16
+    case 4 then nmax = 32
+    case 8 then nmax = 64
+    case 11 then nmax = 8
+    case 12 then nmax = 16
+    case 14 then nmax = 32
+    case 18 then nmax = 64
     end
 
-    if rhs>1 then
-
-        if (n>nmax) | (n<1) then
-            error(msprintf(gettext("%s: Wrong value for input argument #%d: Must be between %d and %d.\n"),"bitcmp",2,1,nmax));
+    if rhs == 2
+        if size(n,"*")<>1 & or(size(n)<>size(x))
+            msg = gettext("%s: Argument #%d: Wrong size.\n")
+            error(msprintf(msg, "bitcmp", 2))
+        end
+        if and(type(n)<>[1 8]) | n<>int(n) | (type(n)==1 & ~isreal(n))
+            msg = gettext("%s: Argument #%d: Real or encoded integer expected.\n")
+            error(msprintf(msg, "bitcmp", 2))
+        end
+        if n > nmax | n<1 then
+            msg = gettext("%s: Argument #%d: Must be in the interval [%d, %d].\n")
+            error(msprintf(msg, "bitcmp", 2, 1, nmax));
         end
-
     else
-        n = nmax;
+        if type(x)==8
+            n = nmax
+        else
+            n = ones(x)*53
+            k = abs(x) > 1/%eps
+            n(k) = p(k)
+        end
     end
 
-    // Algorithm
+    // PROCESSING
     // =========================================================================
-
-    // empty matrix shortcut
-
-    if isempty(x) then
-        y = [];
-        return;
-    end
-
-    // unit8, uint16 and uint32 shortcut
-
+    // Encoded integers
     if type(x)==8 then
-        y = ~x;
+        y = ~x
+        // Canceling bits > n:
         if rhs > 1 then
-            select inttype(x)
-            case 11 then y = y & uint8(  2^n - 1);
-            case 12 then y = y & uint16( 2^n - 1);
-            case 14 then y = y & uint32( 2^n - 1);
-            end
-        end
-        return;
-    end
-
-    n = ones(x)*n;
-
-    if type(x) == 1 then
-
-        a     = 2^32;
-
-        y_LSB = uint32( x - double(uint32(x/a)) * a ); // LSB Less Significant Bits
-        y_MSB = uint32( x/a );                         // MSB Most Significant Bits
-
-        y_LSB = ~y_LSB;
-        y_MSB = ~y_MSB;
-
-        if n <= 32 then
-            y_LSB = y_LSB & uint32( 2^n - 1);
-            y_MSB = uint32(0);
-        else
-            y_MSB = y_MSB & uint32( 2^(n-32) - 1);
+            it = inttype(x)
+            y = y & (iconvert(2,it)^n - 1)
         end
 
-        y = double( a * y_MSB + y_LSB );
+    else
+    // Decimal integers
+        y = x
+        mask = 2.^n - (2.^max(0,n-52))
+        k = n < p
+        y(k) = bitand(y(k), mask)
+        y = bitxor(y, mask)
     end
 
 endfunction
diff --git a/scilab/modules/elementary_functions/tests/unit_tests/bitcmp.dia.ref b/scilab/modules/elementary_functions/tests/unit_tests/bitcmp.dia.ref
deleted file mode 100644 (file)
index 6dab544..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2013 - Scilab Enterprises - Charlotte HECQUET
-//
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
-// <-- CLI SHELL MODE -->
-// unit test for bitcmp function
-// =============================================================================
-// Tests for one input argument
-assert_checkequal(bitcmp(uint8(99)),uint8(156));
-assert_checkequal(bitcmp(uint16(99)),uint16(65436));
-assert_checkequal(bitcmp(uint32(99)),uint32(4294967196));
-assert_checkequal(bitcmp(uint8([13,99])),uint8([242,156]));
-assert_checkequal(bitcmp(uint16([13,99])),uint16([65522,65436]));
-assert_checkequal(bitcmp(uint32([13,99])),uint32([4294967282,4294967196]));
-// Tests for two input arguments
-assert_checktrue(bitcmp(99,8)==uint8(156));
-assert_checktrue(bitcmp(99,16)==uint16(65436));
-assert_checktrue(bitcmp(99,32)==uint32(4294967196));
-assert_checktrue(bitcmp([13,99],8)==uint8([242,156]));
-assert_checktrue(bitcmp([13,99],16)==uint16([65522,65436]));
-assert_checktrue(bitcmp([13,99],32)==uint32([4294967282,4294967196]));
-// Error messages
-errmsg = msprintf(_("%s: Wrong number of input argument(s): At least %d expected.\n"),"bitcmp",1);
-assert_checkerror("bitcmp()",errmsg); //no input argument
-errmsg3 = msprintf(_("%s: Wrong number of input argument(s): %d expected.\n"),"bitcmp",2);
-assert_checkerror("bitcmp(99)",errmsg3); //First (and only) argument is not an unsigned integer
-errmsg4 = msprintf(_("%s: Wrong input argument #%d: Scalar/matrix of unsigned integers expected.\n"),"bitcmp",1);
-assert_checkerror("bitcmp(""s"")",errmsg4); //input argument is a char
-errmsg5 = msprintf(_("%s: Wrong value for input argument #%d: Must be between %d and %d.\n"),"bitcmp",2,1,8);
-assert_checkerror("bitcmp(uint8(99),16)",errmsg5); //wrong value for second input argument
-errmsg6 = msprintf(_("%s: Wrong input argument #%d: An unsigned integer expected.\n"),"bitcmp",2);
-assert_checkerror("bitcmp(uint8(99),5.5)",errmsg6); //second argument is a double
index 2d33ac8..0b4ed76 100644 (file)
 // =============================================================================
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) 2013 - Scilab Enterprises - Charlotte HECQUET
+// Copyright (C) 2020 - Samuel GOUGEON
 //
 //  This file is distributed under the same license as the Scilab package.
 // =============================================================================
 
 // <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
 
 // unit test for bitcmp function
 // =============================================================================
 
+function r = cint64(valstr)
+    // Returns the uint64 or int64 value matching its given literal representation
+    s = strsplit(valstr)($:-1:1);
+    neg = s($)=="-"
+    if neg, s($) = [], end
+    s = evstr(s);
+    r = 0
+    for i = 1:size(s,"*")
+        r = r + uint64(10).^(i-1)*s(i)
+    end
+    if neg, r = -int64(r), end
+endfunction
+
+// =====================
+// With encoded integers
+// =====================
 // Tests for one input argument
-assert_checkequal(bitcmp(uint8(99)),uint8(156));
-assert_checkequal(bitcmp(uint16(99)),uint16(65436));
-assert_checkequal(bitcmp(uint32(99)),uint32(4294967196));
+// ----------------------------
+assert_checkequal(bitcmp(int8(99)),  int8(-100));
+assert_checkequal(bitcmp(int16(99)), int16(-100));
+assert_checkequal(bitcmp(int32(99)), int32(-100));
+assert_checkequal(bitcmp(int64(99)), int64(-100));
+
+assert_checkequal(bitcmp(uint8(99)),  uint8(156));
+assert_checkequal(bitcmp(uint16(99)), uint16(65436));
+assert_checkequal(bitcmp(uint32(99)), uint32(4294967196));
+assert_checkequal(bitcmp(uint64(99)), cint64("18446744073709551516"));
+assert_checkequal(bitcmp(cint64("18446744073709551516")), uint64(99));
+
+assert_checkequal(bitcmp(int8([13,99])),  int8([-14 -100]));
+assert_checkequal(bitcmp(int16([13,99])), int16([-14 -100]));
+assert_checkequal(bitcmp(int32([13,99])), int32([-14 -100]));
+assert_checkequal(bitcmp(int64([13,99])), int64([-14 -100]));
 
-assert_checkequal(bitcmp(uint8([13,99])),uint8([242,156]));
-assert_checkequal(bitcmp(uint16([13,99])),uint16([65522,65436]));
-assert_checkequal(bitcmp(uint32([13,99])),uint32([4294967282,4294967196]));
+assert_checkequal(bitcmp(uint8([13,99])),  uint8([242,156]));
+assert_checkequal(bitcmp(uint16([13,99])), uint16([65522,65436]));
+assert_checkequal(bitcmp(uint32([13,99])), uint32([4294967282,4294967196]));
+assert_checkequal(bitcmp(uint64([13,99])), [cint64("18446744073709551602") cint64("18446744073709551516")]);
+assert_checkequal(bitcmp([cint64("18446744073709551602") cint64("18446744073709551516")]), uint64([13,99]));
+m = uint64(%inf);
+r = bitcmp([uint64(0:2), m-2, m-1, m]);
+assert_checkequal(r, [cint64("18446744073709551613")+[2 1 0] uint64([2 1 0])]);
 
 // Tests for two input arguments
-assert_checktrue(bitcmp(99,8)==uint8(156));
-assert_checktrue(bitcmp(99,16)==uint16(65436));
-assert_checktrue(bitcmp(99,32)==uint32(4294967196));
+// -----------------------------
+// scalar bitnum
+assert_checkequal(bitcmp(int8([-71 -34 -1 0 33 70]), 8), int8([70 33 0 -1 -34 -71]));
+assert_checkequal(bitcmp(int8([-71 -34 -1 0 33 70]), 7), int8([70 33 0 127 94 57]));
+assert_checkequal(bitcmp(int8([-71 -34 -1 0 33 70]), 6), int8([6 33 0 63 30 57]));
+assert_checkequal(bitcmp(int8([-71 -34 -1 0 33 70]), 5), int8([6 1 0 31 30 25]));
+assert_checkequal(bitcmp(int8([-71 -34 -1 0 33 70]), 4), int8([6 1 0 15 14 9]));
+assert_checkequal(bitcmp(int8([-71 -34 -1 0 33 70]), 3), int8([6 1 0 7 6 1]));
+assert_checkequal(bitcmp(int8([-71 -34 -1 0 33 70]), 2), int8([2 1 0 3 2 1]));
+
+assert_checkequal(bitcmp(uint8(99),8), uint8(156));
+assert_checkequal(bitcmp(uint16(99),16), uint16(65436));
+assert_checkequal(bitcmp(uint32(99),32), uint32(4294967196));
+
+assert_checkequal(bitcmp(uint8([13,99]),8),  uint8([242,156]));
+assert_checkequal(bitcmp(uint16([13,99]),16), uint16([65522,65436]));
+assert_checkequal(bitcmp(uint32([13,99]),32), uint32([4294967282,4294967196]));
+ui64 = cint64("1844674407370955161");
+b = bitget(ui64,1:64);
+for i = 2:63
+    assert_checkequal(bitcmp(ui64, i), bitset(uint64(0), 1:i, 1-b(1:i)));
+end
+// bitnum array
+[in, out] = ([0 0 0 0 0], [7 15 31 63 127]);
+assert_checkequal(bitcmp(uint8(in), 3:7), uint8(out));
+assert_checkequal(bitcmp(uint16(in), 3:7), uint16(out));
+assert_checkequal(bitcmp(uint32(in), 3:7), uint32(out));
+assert_checkequal(bitcmp(uint64(in), 3:7), uint64(out));
+assert_checkequal(bitcmp(in, 3:7), out);
+
+// =====================
+// With decimal integers
+// =====================
+assert_checkequal(bitcmp(99,8), 156);
+assert_checkequal(bitcmp(99,16), 65436);
+assert_checkequal(bitcmp(99,32), 4294967196);
 
-assert_checktrue(bitcmp([13,99],8)==uint8([242,156]));
-assert_checktrue(bitcmp([13,99],16)==uint16([65522,65436]));
-assert_checktrue(bitcmp([13,99],32)==uint32([4294967282,4294967196]));
+assert_checkequal(bitcmp([13,99],8),  [242,156]);
+assert_checkequal(bitcmp([13,99],16), [65522,65436]);
+assert_checkequal(bitcmp([13,99],32), [4294967282,4294967196]);
 
+assert_checkequal(bitcmp(0:10, 8), double(bitcmp(uint8(0:10))));
+assert_checkequal(bitcmp(0:10, 16), double(bitcmp(uint16(0:10))));
+assert_checkequal(bitcmp(0:10, 32), double(bitcmp(uint32(0:10))));
+assert_checkequal(bitcmp(0:10, 40)-2^40, -1:-1:-11);
+assert_checkequal(bitcmp(0:10, 52)-2^52, -1:-1:-11);
+assert_checkequal(bitcmp(2^52 + (-11:-1),52), 10:-1:0);
+assert_checkequal(bitcmp(2^40 + (-11:-1), 40), 10:-1:0);
+
+// with bitnum > 53
+// ----------------
+b = bitget(1e100,281:333); // log2(1e100) == 332.ddd
+bcmp332 = bitset(0,281:333,1-b); // 7.4980057982640933D+99
+assert_checkalmostequal(bitcmp(1e100,333), bcmp332, %eps);
+assert_checkalmostequal(bitcmp(1e100), bcmp332, %eps);
+assert_checkalmostequal(bitcmp(bcmp332,333), 1e100, %eps);
+r = bitcmp(0,333);
+assert_checkalmostequal(bitcmp(r,333)/2^333, 0, 0, %eps);
+
+V = [1e100 2e150 1e200 3e250 1e300];
+// one by one:
+for v = V
+    n = int(log2(v)) + 1;
+    bits = bitget(v, n:-1:n-51);
+    cbits = bitget(bitcmp(v,n), n:-1:n-51);
+    assert_checktrue(and((bits+cbits)==1));
+end
+// in a vector:
+n = int(log2(V)) + 1;
+    // with distinct implicit bitnums
+r = bitcmp(V);
+r = bitcmp(r, n);
+assert_checkalmostequal(r, V, %eps);
+
+
+// ==============
 // Error messages
-errmsg = msprintf(_("%s: Wrong number of input argument(s): At least %d expected.\n"),"bitcmp",1);
-assert_checkerror("bitcmp()",errmsg); //no input argument
-errmsg3 = msprintf(_("%s: Wrong number of input argument(s): %d expected.\n"),"bitcmp",2);
-assert_checkerror("bitcmp(99)",errmsg3); //First (and only) argument is not an unsigned integer
-errmsg4 = msprintf(_("%s: Wrong input argument #%d: Scalar/matrix of unsigned integers expected.\n"),"bitcmp",1);
-assert_checkerror("bitcmp(""s"")",errmsg4); //input argument is a char
-errmsg5 = msprintf(_("%s: Wrong value for input argument #%d: Must be between %d and %d.\n"),"bitcmp",2,1,8);
-assert_checkerror("bitcmp(uint8(99),16)",errmsg5); //wrong value for second input argument
-errmsg6 = msprintf(_("%s: Wrong input argument #%d: An unsigned integer expected.\n"),"bitcmp",2);
-assert_checkerror("bitcmp(uint8(99),5.5)",errmsg6); //second argument is a double
+// ==============
+errmsg = msprintf(_("%s: Wrong number of input arguments: %d or %d expected.\n"), "bitcmp", 1, 2);
+assert_checkerror("bitcmp()", errmsg);       // no input argument
+errmsg = _("Wrong number of input arguments.")
+assert_checkerror("bitcmp(1,2,3)", errmsg);  // too many argins
+
+// argin#1
+errmsg = msprintf(_("%s: Argument #%d: Decimal or encoded integers expected.\n"), "bitcmp", 1);
+assert_checkerror("bitcmp(""s"")", errmsg);
+assert_checkerror("bitcmp(%i)", errmsg);
+errmsg = msprintf(_("%s: Argument #%d: Positive decimal integers expected.\n"), "bitcmp", 1);
+assert_checkerror("bitcmp(1.2)", errmsg);
+assert_checkerror("bitcmp(-2)", errmsg);
+
+// argin#2
+errmsg = msprintf(_("%s: Argument #%d: Wrong size.\n"), "bitcmp", 2);
+assert_checkerror("bitcmp(2, [1 2])", errmsg);
+errmsg = msprintf(_("%s: Argument #%d: Real or encoded integer expected.\n"), "bitcmp", 2);
+assert_checkerror("bitcmp(2, 4.5)", errmsg);
+assert_checkerror("bitcmp(2, 3+%i)", errmsg);
+errmsg = msprintf(_("%s: Argument #%d: Must be in the interval [%d, %d].\n"),"bitcmp", 2, 1, 8);
+assert_checkerror("bitcmp(uint8(99), 9)", errmsg);
+assert_checkerror("bitcmp(uint8(99), 16)", errmsg);