74804822c194a9dfef272a90f08b96d5829fdfc2
[scilab.git] / scilab / modules / elementary_functions / macros / bitget.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) 2017 - Samuel GOUGEON
5 // Copyright (C) 2012 - 2016 - Scilab Enterprises
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 z = bitget(x, pos)
15 /*
16    P. Marechal, 5 Feb 2008
17    - Add argument check
18    S. Gougeon - 2017:
19     - Bug 2694: Positive signed encoded integers were not supported
20     - new uint64 and int64 integers were not supported
21     - decimal numbers: pos was limited to 52 instead of log2(number_properties("huge")) == 1024
22     - decimal numbers x > 2^52 with pos < log2(x)-52 returned 0 instead of %nan
23     - Several bits from each component of an array
24 */
25     fname = "bitget"
26
27     // CHECKING ARGUMENTS
28     // ==================
29     rhs = argn(2)
30     if rhs~=2 then
31         msg = _("%s: Wrong number of input argument(s): %d expected.\n");
32         error(msprintf(msg, fname, 2));
33     end
34
35     // case empty matrix
36     if x==[] | pos==[]
37         z = [];
38         return
39     end
40
41     // check for positive integers
42     msg = gettext("%s: Argument #%d: Non-negative integers expected.\n")
43     if  (type(x)<>1  & type(x)<>8) || or(x<0) || ..
44         (type(x)==1  & (or((x-floor(x))<>0) | or(imag(x)~=0)))
45         error(msprintf(msg, fname, 1));
46     elseif type(x)==1
47         x = real(x);
48     end
49     if  (type(pos)<>1  & type(pos)<>8) || or(pos<0) || ..
50         (type(pos)==1  & (or((pos - floor(pos))<>0) | or(imag(pos)~=0)))
51         error(msprintf(msg, fname, 2));
52     elseif type(pos)==1
53         pos = real(pos);
54     end
55
56     // check sizes
57     fromEach = length(x)>1 & length(pos)>1 & (or(size(x)<>size(pos)));
58     if size(x,"*") == 1
59         x = ones(pos) * x;
60     end
61     if size(pos,"*") == 1
62         pos = ones(x) * pos;
63     end
64
65     // check pos value
66     icode = inttype(x)
67     select modulo(icode, 10)
68     case 0  then posmax = 1024  // log2(number_properties("huge"))
69     case 1 then posmax = 8
70     case 2 then posmax = 16
71     case 4 then posmax = 32
72     case 8 then posmax = 64
73     end
74     if icode>0 & icode<10 then  // Signed integers
75         posmax = posmax - 1     // => sign bit reserved
76     end
77     if or(pos>posmax) | or(pos<1) then
78         msg = _("%s: Wrong value for input argument #%d: Must be between %d and %d.\n")
79         error(msprintf(msg, fname, 2, 1, posmax));
80     end
81
82     // PROCESSING
83     // ==========
84     if fromEach then
85         masks = 2.^(pos-1);
86         [X,B] = ndgrid(x(:), masks);
87         z = bool2s(bitand(X,B)==B);
88         if type(x)==1
89             [X,B] = ndgrid(x(:), pos);
90             below_eps = B<=(log2(X)-52);
91             z(below_eps) = %nan;
92         else
93             z = iconvert(z, inttype(x));
94         end
95     else
96         if  type(x)==8
97             mask = iconvert(2 .^(pos-1), inttype(x));
98             z = iconvert(1 * ((x & mask) > 0),inttype(x));
99         else
100             tmp = x ./ (2 .^pos);
101             z = bool2s((tmp - fix(tmp))>=0.5);
102             below_eps = pos<=(log2(x)-52);
103             z(below_eps) = %nan;
104         end
105     end
106 endfunction
107