1function test22(fulltest)
2%TEST22 test GrB_transpose
3
4% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
5% SPDX-License-Identifier: Apache-2.0
6
7if (nargin < 1)
8    % do a short test, by default
9    fulltest = 0 ;
10end
11
12[binops, ~, ~, types, ~, ~] = GB_spec_opsall ;
13binops = binops.all ;
14types = types.all ;
15
16if (fulltest)
17    fprintf ('\n==== exhaustive test for GB_mex_transpose:\n') ;
18    problems = [
19        10,    8,   40,  -5, 100
20        10,  20,  100,  -99, 200
21        100, 200, 1000, -99, 200
22         50,  50,  500,  -2, 3
23        ] ;
24else
25    fprintf ('\n==== test GB_mex_transpose:\n') ;
26    problems = [
27        10,    8,   40,  -5, 100
28        ] ;
29end
30
31% try several problems
32for k0 = 1:size (problems,1) ;
33
34    % create nnz triplets for a matrix of size nrows-by-nrows
35    nrows = problems (k0,1) ;
36    ncols = problems (k0,2) ;
37    nnz = problems (k0,3) ;
38    y1 = problems (k0,4) ;
39    y2 = problems (k0,5) ;
40
41    % create A
42    rng ('default') ;
43    I = irand (0, nrows-1, nnz, 1) ;
44    J = irand (0, ncols-1, nnz, 1) ;
45    Y = y2 * rand (nnz, 1) + y1 ;
46    clear A
47    A.matrix = sparse (double (I)+1, double (J)+1, Y, nrows, ncols) ;
48
49    % create Cin; note that it has the same dimensions as A, so if A
50    % gets transpose, Cin must also be transposed (so use Cin2 instead)
51    I = irand (0, nrows-1, nnz, 1) ;
52    J = irand (0, ncols-1, nnz, 1) ;
53    Y = y2 * rand (nnz, 1) + y1 ;
54    clear Cin
55    Cin.matrix = sparse (double (I)+1, double (J)+1, Y, nrows, ncols) ;
56
57    clear Cin2
58    Cin2.matrix = Cin.matrix' ;
59
60    clear Cempty
61    Cempty.matrix = sparse (nrows, ncols) ;
62    Cempty2.matrix = Cempty.matrix' ;
63
64    % create a boolean Mask with roughly the same density as A and Cin
65    Mask = cast (sprandn (nrows, ncols, nnz/(nrows*ncols)), 'logical') ;
66
67    fprintf ('\nnrows: %d ncols %d nnz %d ymin %g ymax %g\n', ...
68        nrows, ncols, nnz, min (Y), max (Y)) ;
69
70    % try every type for A
71    for k1 = 1:length (types)
72        atype = types {k1} ;
73        A.class = atype ;
74        Cempty.class = atype ;
75        Cempty2.class = atype ;
76        fprintf ('%s', atype) ;
77
78        % C = A'
79        C = GB_mex_transpose  (Cempty2, [ ], [ ], A, [ ]) ;
80        assert (GB_spok (C.matrix*1) == 1) ;
81        S = GB_spec_transpose (Cempty2, [ ], [ ], A, [ ]) ;
82        assert (isequal (C.class, A.class)) ;
83        assert (isequal (C.class, S.class)) ;
84        assert (isequal (full (double (C.matrix)), double (S.matrix))) ;
85        if (isequal (C.class, 'double'))
86            assert (isequal (C.matrix, A.matrix')) ;
87        end
88
89        % C = A
90        clear desc
91        desc = struct ('inp0', 'tran') ;
92        C = GB_mex_transpose  (Cempty, [ ], [ ], A, desc) ;
93        assert (GB_spok (C.matrix*1) == 1) ;
94        S = GB_spec_transpose (Cempty, [ ], [ ], A, desc) ;
95        assert (isequal (C.class, A.class)) ;
96        assert (isequal (C.class, S.class)) ;
97        assert (isequal (full (double (C.matrix)), double (S.matrix))) ;
98        if (isequal (C.class, 'double'))
99            assert (isequal (C.matrix, A.matrix)) ;
100        end
101
102        % C<Mask> = A'
103        Cempty2.class = A.class ;
104        C = GB_mex_transpose  (Cempty2, Mask', [ ], A, [ ]) ;
105        assert (GB_spok (C.matrix*1) == 1) ;
106        S = GB_spec_transpose (Cempty2, Mask', [ ], A, [ ]) ;
107        assert (isequal (C.class, A.class)) ;
108        assert (isequal (C.class, S.class)) ;
109        assert (isequal (full (double (C.matrix)), double (S.matrix))) ;
110        if (isequal (C.class, 'double'))
111            assert (isequal (C.matrix .* Mask', (A.matrix').*Mask')) ;
112        end
113
114        % C<Mask> = A
115        clear desc
116        desc = struct ('inp0', 'tran') ;
117        Cempty.class = A.class ;
118        C = GB_mex_transpose  (Cempty, Mask, [ ], A, desc) ;
119        assert (GB_spok (C.matrix*1) == 1) ;
120        S = GB_spec_transpose (Cempty, Mask, [ ], A, desc) ;
121        assert (isequal (C.class, A.class)) ;
122        assert (isequal (C.class, S.class)) ;
123        assert (isequal (full (double (C.matrix)), double (S.matrix))) ;
124        if (isequal (C.class, 'double'))
125            assert (isequal (C.matrix .* Mask, A.matrix .* Mask)) ;
126        end
127
128        % try every class for Cin
129        for k2 = 1:length (types)
130            cinclass = types {k2} ;
131            fprintf ('.') ;
132            Cin2.class = cinclass ;
133            Cin.class = cinclass ;
134
135            % try every operator
136            for k3 = 0:length (binops)
137                if (k3 == 0)
138                    op = '' ;
139                    ntypes = 1 ;
140                else
141                    op = binops {k3} ;
142                    ntypes = length (types) ;
143                end
144
145                % try every operator class
146                for k4 = 1:ntypes
147                    if (isempty (op))
148                        optype = '' ;
149                    else
150                        optype = types {k4} ;
151                    end
152
153                    clear accum
154                    accum.opname = op ;
155                    accum.optype = optype ;
156
157                    if (GB_spec_is_positional (accum))
158                        continue ;
159                    end
160
161                    try
162                        GB_spec_operator (accum) ;
163                    catch
164                        continue
165                    end
166
167                    % C = op (Cin2,A')
168                    C = GB_mex_transpose  (Cin2, [ ], accum, A, [ ]) ;
169                    assert (GB_spok (C.matrix*1) == 1) ;
170                    S = GB_spec_transpose (Cin2, [ ], accum, A, [ ]) ;
171                    assert (isequal (C.class, cinclass)) ;
172                    assert (isequal (C.class, S.class)) ;
173                    if (~(isequalwithequalnans (full (double (C.matrix)), ...
174                        double (S.matrix))))
175                        assert (false)
176                    end
177
178                    % C = op (Cin,A)
179                    clear desc
180                    desc = struct ('inp0', 'tran') ;
181                    C = GB_mex_transpose  (Cin, [ ], accum, A, desc) ;
182                    assert (GB_spok (C.matrix*1) == 1) ;
183                    S = GB_spec_transpose (Cin, [ ], accum, A, desc) ;
184                    assert (isequal (C.class, cinclass)) ;
185                    assert (isequal (C.class, S.class)) ;
186                    assert (isequalwithequalnans (full (double (C.matrix)), ...
187                        double (S.matrix))) ;
188
189                    % try with a Mask (Mask must be sparse; logical and double)
190                    for k5 = [1 11]
191                        mask_class = types {k5} ;
192                        M = cast (Mask, mask_class) ;
193
194                        % C = op (Cin2,A')
195                        C = GB_mex_transpose  (Cin2, M', accum, A, [ ]) ;
196                        assert (GB_spok (C.matrix*1) == 1) ;
197                        S = GB_spec_transpose (Cin2, M', accum, A, [ ]) ;
198                        assert (isequal (C.class, cinclass)) ;
199                        assert (isequal (C.class, S.class)) ;
200                        assert (isequalwithequalnans (...
201                            full (double (C.matrix)), ...
202                            double (S.matrix))) ;
203
204                        % C = op (Cin,A)
205                        clear desc
206                        desc = struct ('inp0', 'tran') ;
207                        C = GB_mex_transpose  (Cin, M, accum, A, desc) ;
208                        assert (GB_spok (C.matrix*1) == 1) ;
209                        S = GB_spec_transpose (Cin, M, accum, A, desc) ;
210                        assert (isequal (C.class, cinclass)) ;
211                        assert (isequal (C.class, S.class)) ;
212                        assert (isequalwithequalnans (...
213                            full (double (C.matrix)), ...
214                            double (S.matrix))) ;
215
216                    end
217                end
218            end
219        end
220    end
221end
222
223fprintf ('\ntest22: all tests passed\n') ;
224
225