* Bug 16609 fixed: bitcmp() upgraded for Scilab 6
[scilab.git] / scilab / modules / elementary_functions / macros / bitcmp.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) ???? - INRIA - Farid BELAHCENE
3 // Copyright (C) 2008 - INRIA - Pierre MARECHAL
4 // Copyright (C) 2012 - 2016 - Scilab Enterprises
5 // Copyright (C) 2020 - Samuel GOUGEON
6 //
7 // This file is hereby licensed under the terms of the GNU GPL v2.0,
8 // pursuant to article 5.3.4 of the CeCILL v.2.1.
9 // This file was originally licensed under the terms of the CeCILL v2.1,
10 // and continues to be available under such terms.
11 // For more information, see the COPYING file which you should have received
12 // along with this program.
13
14 function y = bitcmp(x, n)
15
16     // BITCMP function: bitwise complement of integers
17     //
18     // P. Marechal, 2008 : Add argument check
19     // S. Gougeon, 2020 :
20     //   * Entension to 64 bit integers.
21     //   * Extension to all signed integers.
22     //   * Decimal positive integers > 2^52 up to 2^1024 = number_properties("huge")
23     //      can now be processed, with bitnum up to 1024 instead of 52.
24     //   * bitnum is now optional as well for input decimal integers.
25     //     It can actually be an array.
26
27     rhs = argn(2);
28
29     // CHECK INPUT ARGUMENTS
30     // =========================================================================
31     if rhs < 1 | rhs > 2 then
32         msg = gettext("%s: Wrong number of input arguments: %d or %d expected.\n")
33         error(msprintf(msg, "bitcmp", 1, 2));
34     end
35
36
37     // Check types
38     if and(type(x)<>[1 8]) | (type(x)==1 & ~isreal(x))
39         msg = gettext("%s: Argument #%d: Decimal or encoded integers expected.\n");
40         error(msprintf(msg, "bitcmp",1))
41     end
42     if x==[] then
43         y = []
44         return
45     end
46     if type(x)==1 & (or(x-floor(x)<>0) | or(x<0)) then
47         msg = gettext("%s: Argument #%d: Positive decimal integers expected.\n");
48         error(msprintf(msg, "bitcmp",1))
49     end
50     select inttype(x)
51     case 0  then
52         nmax = 1024
53         p = int(log2(x)) + 1
54     case 1 then nmax = 8
55     case 2 then nmax = 16
56     case 4 then nmax = 32
57     case 8 then nmax = 64
58     case 11 then nmax = 8
59     case 12 then nmax = 16
60     case 14 then nmax = 32
61     case 18 then nmax = 64
62     end
63
64     if rhs == 2
65         if size(n,"*")<>1 & or(size(n)<>size(x))
66             msg = gettext("%s: Argument #%d: Wrong size.\n")
67             error(msprintf(msg, "bitcmp", 2))
68         end
69         if and(type(n)<>[1 8]) | n<>int(n) | (type(n)==1 & ~isreal(n))
70             msg = gettext("%s: Argument #%d: Real or encoded integer expected.\n")
71             error(msprintf(msg, "bitcmp", 2))
72         end
73         if n > nmax | n<1 then
74             msg = gettext("%s: Argument #%d: Must be in the interval [%d, %d].\n")
75             error(msprintf(msg, "bitcmp", 2, 1, nmax));
76         end
77     else
78         if type(x)==8
79             n = nmax
80         else
81             n = ones(x)*53
82             k = abs(x) > 1/%eps
83             n(k) = p(k)
84         end
85     end
86
87     // PROCESSING
88     // =========================================================================
89     // Encoded integers
90     if type(x)==8 then
91         y = ~x
92         // Canceling bits > n:
93         if rhs > 1 then
94             it = inttype(x)
95             y = y & (iconvert(2,it)^n - 1)
96         end
97
98     else
99     // Decimal integers
100         y = x
101         mask = 2.^n - (2.^max(0,n-52))
102         k = n < p
103         y(k) = bitand(y(k), mask)
104         y = bitxor(y, mask)
105     end
106
107 endfunction