50c6e9f84e7450032027993e75689ab08d90c79a
[scilab.git] / scilab / modules / elementary_functions / macros / bitset.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2008 - INRIA - Pierre MARECHAL
3 //
4 // Copyright (C) 2012 - 2016 - Scilab Enterprises
5 //
6 // This file is hereby licensed under the terms of the GNU GPL v2.0,
7 // pursuant to article 5.3.4 of the CeCILL v.2.1.
8 // This file was originally licensed under the terms of the CeCILL v2.1,
9 // and continues to be available under such terms.
10 // For more information, see the COPYING file which you should have received
11 // along with this program.
12
13 function y = bitset(x,pos,v)
14
15     // INRIA 2008 - Pierre MARECHAL
16     //
17     // BITSET function
18     // Set bit at specified position
19
20     // Check input arguments
21     // =========================================================================
22
23     // check number input argument
24
25     rhs = argn(2);
26
27     if rhs < 2 then
28         error(msprintf(gettext("%s: Wrong number of input argument(s): At least %d expected.\n"),"bitset",2));
29     end
30
31     // case empty matrix
32     if isempty(x)
33         if ~isempty(pos) & prod(size(pos))<>1
34             error(msprintf(gettext("%s: Wrong size for input arguments: Same sizes expected.\n"),"bitset"));
35         else
36             y=[]
37             return
38         end
39     end
40
41     // check v value
42     if rhs == 3 & or(v <> 0 & v <> 1) then
43         error(msprintf(gettext("%s: Wrong value for input argument #%d: 0 or 1 expected.\n"),"bitset",3));
44     elseif rhs == 2 then
45         v = ones(x);
46     end
47
48     // check size
49     if or(size(x) <> size(pos)) | or(size(v) <> size(x)) then
50         error(msprintf(gettext("%s: Wrong size for input arguments: Same sizes expected.\n"),"bitset"));
51     end
52
53     // check type
54     if (type(x) == 1  & (or(x-floor(x) <> 0) | or(x < 0))) ..
55         | (type(x) == 8  & (inttype(x) < 10)) ..
56         | (typeof(x) == "hypermat" & (or(x-floor(x) <> 0) | or(x < 0))) ..
57         | (type(x) <> 1 & type(x) <> 8 & typeof(x) <> "hypermat") then
58         error(msprintf(gettext("%s: Wrong type for input argument #%d: Scalar/matrix/hypermatrix of unsigned integers expected.\n"),"bitset",1));
59     end
60
61     if (type(pos) == 1  & (or(pos-floor(pos) <> 0) | or(pos < 0))) ..
62         | (type(pos) == 8  & (inttype(pos) < 10)) ..
63         | (typeof(pos) == "hypermat" & (or(pos-floor(pos) <> 0) | or(pos < 0))) ..
64         | (type(pos) <> 1 & type(pos) <> 8 & typeof(pos) <> "hypermat") then
65         error(msprintf(gettext("%s: Wrong type for input argument #%d: Scalar/matrix/hypermatrix of unsigned integers expected.\n"),"bitset",2));
66     end
67
68     // check pos value
69     select inttype(x(1))
70     case 0  then posmax = 52;
71     case 11 then posmax = 8;
72     case 12 then posmax = 16;
73     case 14 then posmax = 32;
74     end
75
76     if or(pos > posmax) | or(pos < 1) then
77         error(msprintf(gettext("%s: Wrong value for input argument #%d: Must be between %d and %d.\n"),"bitset",2,1,posmax));
78     end
79
80     // Algorithm
81     // =========================================================================
82
83     if size(pos,"*") == 1;
84         pos  = ones(x)*pos;
85     end
86
87     if size(x,"*") == 1;
88         x    = ones(pos)*x;
89     end
90
91     vZero = find(v == 0);
92     vOne = find(v == 1);
93     sz = size(x);
94
95     if type(x(1)) == 8 then
96
97         select inttype(x(1))
98         case 11 then mask = uint8(2^(pos(:)-1));
99         case 12 then mask = uint16(2^(pos(:)-1));
100         case 14 then mask = uint32(2^(pos(:)-1));
101         end
102
103         mask = matrix(mask, sz);
104         y(vZero) = x(vZero) & (~mask(vZero));
105         y(vOne) = x(vOne) | mask(vOne);
106         y = matrix(y, sz);
107
108         return;
109
110     else
111         // type == 1
112         a     = 2^32;
113         mask  = uint32(zeros(pos));
114
115         y_MSB  = uint32(zeros(pos));
116         y_LSB  = uint32(zeros(pos));
117
118         y_LSB = uint32( x - double(uint32(x/a)) * a ); // LSB Less Significant Bits
119         y_MSB = uint32( x/a );                         // MSB Most Significant Bits
120         yMSB  = y_MSB;
121         yLSB  = y_LSB;
122
123         if or(pos<=32) then
124             mask(pos<=32) = uint32(2^(pos(pos<=32) -1));
125             yLSB = y_LSB(pos<=32);
126             ymask = mask(pos<=32);
127             // v == 0
128             yLSB(vZero) = yLSB(vZero) & (~ymask(vZero));
129             // v == 1
130             yLSB(vOne) = yLSB(vOne) | ymask(vOne);
131             yLSB = matrix(yLSB, sz);
132         end
133
134         if or(pos>32) then
135             mask(pos>32) = uint32(2^(pos(pos>32) -32 -1));
136             yMSB = y_MSB(pos>32);
137             ymask = mask(pos>32);
138             yMSB(vZero) = yMSB(vZero) & (~ymask(vZero));
139             yMSB(vOne) = yMSB(vOne) | ymask(vOne);
140             // v == 0
141             yMSB(vZero) = yMSB(vZero) & (~ymask(vZero));
142             // v == 1
143             yMSB(vOne) = yMSB(vOne) | ymask(vOne);
144             yMSB = matrix(yMSB, sz);
145         end
146         y = double(a * yMSB + yLSB);
147     end
148
149 endfunction