1function gbtest74
2%GBTEST74 test bitwise operators
3
4% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
5% SPDX-License-Identifier: GPL-3.0-or-later
6
7int_types = {
8'int8'
9'int16'
10'int32'
11'int64'
12'uint8'
13'uint16'
14'uint32'
15'uint64' } ;
16
17int_nbits = [ 8, 16, 32, 64, 8, 16, 32, 64 ] ;
18
19rng ('default') ;
20
21for k = 1:8
22
23    type = int_types {k} ;
24    nbits = int_nbits (k) ;
25    fprintf ('\n%s', type) ;
26
27    for trial = 1:40
28        fprintf ('.') ;
29
30        % dense case
31
32        imax = double (intmax (type) / 4) ;
33        A = cast (imax * rand (4), type) ;
34        B = cast ((nbits-1) * rand (4), type) + 1 ;
35        A2 = GrB (A) ;
36        B2 = GrB (B) ;
37        V = rand (4) > 0.5 ;
38
39        C1 = bitget (A, B) ;
40        C2 = bitget (A2, B2) ;
41        assert (isequal (C1, C2)) ;
42
43        C1 = bitset (A, B) ;
44        C2 = bitset (A2, B2) ;
45        assert (isequal (C1, C2)) ;
46
47        C1 = bitset (A, B, 1) ;
48        C2 = bitset (A2, B2, 1) ;
49        assert (isequal (C1, C2)) ;
50
51        C1 = bitset (A, B, 0) ;
52        C2 = bitset (A2, B2, 0) ;
53        assert (isequal (C1, C2)) ;
54
55        C1 = bitset (A, B, V) ;
56        C2 = bitset (A2, B2, V) ;
57        assert (isequal (C1, C2)) ;
58
59        for a = 0:3
60            for b = 1:4
61                C1 = bitset (a, b, 1) ;
62                C2 = bitset (a, b, GrB (1)) ;
63                assert (isequal (C1, C2)) ;
64            end
65        end
66
67        C1 = bitset (a, B, 1) ;
68        C2 = bitset (a, B, GrB (1)) ;
69        assert (isequal (C1, C2)) ;
70
71        C1 = bitand (A, B) ;
72        C2 = bitand (A2, B2) ;
73        assert (isequal (C1, C2)) ;
74
75        C1 = bitor (A, B) ;
76        C2 = bitor (A2, B2) ;
77        assert (isequal (C1, C2)) ;
78
79        C1 = bitxor (A, B) ;
80        C2 = bitxor (A2, B2) ;
81        assert (isequal (C1, C2)) ;
82
83        C1 = bitcmp (A) ;
84        C2 = bitcmp (A2) ;
85        assert (isequal (C1, C2)) ;
86
87        % dense double case, with assumedtype
88        A = double (A) ;
89        B = double (B) ;
90        A2 = GrB (A) ;
91        B2 = GrB (B) ;
92
93        C1 = bitget (A, B, type) ;
94        C2 = bitget (A2, B2, type) ;
95        assert (isequal (C1, C2)) ;
96
97        C1 = bitset (A, B, type) ;
98        C2 = bitset (A2, B2, type) ;
99        assert (isequal (C1, C2)) ;
100
101        C1 = bitset (A, B, 1, type) ;
102        C2 = bitset (A2, B2, 1, type) ;
103        assert (isequal (C1, C2)) ;
104
105        C1 = bitset (A, B, 0, type) ;
106        C2 = bitset (A2, B2, 0, type) ;
107        assert (isequal (C1, C2)) ;
108
109        C1 = bitset (A, B, V, type) ;
110        C2 = bitset (A2, B2, V, type) ;
111        assert (isequal (C1, C2)) ;
112
113        C1 = bitand (A, B, type) ;
114        C2 = bitand (A2, B2, type) ;
115        assert (isequal (C1, C2)) ;
116
117        C1 = bitor (A, B, type) ;
118        C2 = bitor (A2, B2, type) ;
119        assert (isequal (C1, C2)) ;
120
121        C1 = bitxor (A, B, type) ;
122        C2 = bitxor (A2, B2, type) ;
123        assert (isequal (C1, C2)) ;
124
125        if (~ispc)
126            % MATLAB R2019b on Windows has a bug here, so this
127            % test is skipped.  Here is the pure MATLAB test:
128            %
129            %   ver
130            %   A = 1287128410976072704
131            %   fprintf ('A:         %30o\n', A) ;
132            %   C = bitcmp (A, 'uint64')
133            %   fprintf ('bitcmp(A): %30o\n', C) ;
134            %
135            % printing input and output in octal, with spaces
136            % added for readability:
137            %
138            % A:                 0 107 346 307 414 442 532 000
139            %
140            % Linux bitcmp(A):   1 670 431 470 363 335 244 000
141            % Win. bitcmp(A):    1 670 431 470 363 335 250 000
142            %
143            % GraphBLAS obtains the Linux result on all
144            % platforms, including Windows.
145            %
146            % Expanding the last 5 octal digits into binary,
147            % with a space where I think the double mantissa
148            % runs about of bits when converted to uint64.
149            %
150            % A:                 32000 = 011.01 0.000.000.000
151            %
152            % Linux bitcmp(A):   44000 = 100.10 0.000.000.000
153            % Win. bitcmp(A):    50000 = 101.00 0.000.000.000
154            %
155            % Note that A starts out as double, so it only
156            % has about 53 bits of mantissa.  I would expect
157            % the result to have 10 or 11 trailing zeros, as a
158            % result.  On Linux (and also GraphBLAS on Windows),
159            % bitcmp(A) has 10 trailing zero bits, and the
160            % remaining bits are properly complemented.
161            %
162            % On MATLAB in Windows, the result is not comprehensible.
163
164            C1 = bitcmp (A, type) ;
165            C2 = bitcmp (A2, type) ;
166            assert (isequal (C1, C2)) ;
167        end
168
169        C1 = bitshift (A, B, type) ;
170        C2 = bitshift (A2, B2, type) ;
171        assert (isequal (C1, C2)) ;
172
173        % sparse case
174
175        A = sprand (10, 10, 0.5) * imax ;
176        Afull = cast (full (A), type) ;
177        % B ranges in value from 0 to 8
178        B = round (sprand (10, 10, 0.5) * nbits) ;
179        Bfull = cast (full (B), type) ;
180        A2 = GrB.prune (GrB (Afull)) ;
181        B2 = GrB.prune (GrB (Bfull)) ;
182
183        C1 = bitxor (Afull, Bfull) ;
184        C2 = bitxor (A2, B2) ;
185        assert (isequal (C1, full (C2))) ;
186
187        C1 = bitand (Afull, Bfull) ;
188        C2 = bitand (A2, B2) ;
189        assert (isequal (C1, full (C2))) ;
190
191        C1 = bitor (Afull, Bfull) ;
192        C2 = bitor (A2, B2) ;
193        assert (isequal (C1, full (C2))) ;
194
195        C1 = bitshift (Afull, Bfull) ;
196        C2 = bitshift (A2, B2) ;
197        assert (isequal (C1, full (C2))) ;
198
199        C1 = bitcmp (Afull) ;
200        C2 = bitcmp (A2) ;
201        assert (isequal (C1, full (C2))) ;
202
203        % the MATLAB bitget and bitset cannot be used for B == 0,
204        % so find where Bfull is explicitly zero.
205        B_is_nonzero = (B ~= 0) ;
206        A_ok = Afull (B_is_nonzero) ;
207        B_ok = Bfull (B_is_nonzero) ;
208        X1 = bitget (A_ok, B_ok) ;
209
210        % the GraphBLAS bitget and bitset can tolerate B == 0
211        C2 = full (bitget (A2, B2)) ;
212        X2 = C2 (B_is_nonzero) ;
213        assert (isequal (X1, X2))
214
215        X1 = bitset (A_ok, B_ok) ;
216        C2 = full (bitset (A2, B2)) ;
217        X2 = C2 (B_is_nonzero) ;
218        assert (isequal (X1, X2))
219
220        X1 = bitset (A_ok, B_ok, 0) ;
221        C2 = full (bitset (A2, B2, 0)) ;
222        X2 = C2 (B_is_nonzero) ;
223        assert (isequal (X1, X2))
224
225        % dense case with any A and B
226
227        imax = double (intmax (type)) ;
228        imin = double (intmin (type)) ;
229        A1 = GrB ((imax-imin) * rand (4) - imin, type) ;
230        B1 = GrB ((imax-imin) * rand (4) - imin, type) ;
231        A  = cast (A1, type) ;
232        B  = cast (B1, type) ;
233        A2 = GrB.prune (GrB (A1)) ;
234        B2 = GrB.prune (GrB (B1)) ;
235
236        C1 = bitxor (A, B) ;
237        C2 = bitxor (A1, B1) ;
238        assert (isequal (C1, full (C2))) ;
239
240        C1 = bitand (A, B) ;
241        C2 = bitand (A2, B2) ;
242        assert (isequal (C1, full (C2))) ;
243
244        C1 = bitor (A, B) ;
245        C2 = bitor (A2, B2) ;
246        assert (isequal (C1, full (C2))) ;
247
248        if (verLessThan ('matlab', '9.7') && isequal (type, 'int64'))
249            % skip this test (older MATLAB versions have a bug in bitshift)
250        else
251            C1 = bitshift (A, B) ;
252            C2 = bitshift (A2, B2) ;
253            assert (isequal (C1, full (C2))) ;
254        end
255
256        C1 = bitcmp (A) ;
257        C2 = bitcmp (A2) ;
258        assert (isequal (C1, full (C2))) ;
259
260    end
261end
262
263fprintf ('\ngbtest74: all tests passed\n') ;
264
265