1function test20(fulltest) 2%TEST20 test GrB_mxm, mxv, and vxm 3 4% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. 5% SPDX-License-Identifier: Apache-2.0 6 7[binops, ~, add_ops, types, ~, ~] = GB_spec_opsall ; 8mult_ops = binops.all ; 9types = types.all ; 10 11tic 12 13if (nargin < 1) 14 fulltest = 0 ; 15end 16 17if (fulltest == 2) 18 fprintf ('test20: lengthy tests of GrB_mxm, mxv, and vxm\n') ; 19 n_semirings_max = inf ; 20else 21 fprintf ('test20: quick test of GrB_mxm, mxv, and vxm\n') ; 22 n_semirings_max = 1 ; 23end 24 25% types to test: 26kk = 1 ; 27% ops to test 28aa = 1 ; 29 30if (fulltest > 0) 31 k1_list = 1:length(mult_ops) ; 32 k2_list = 1:length(add_ops) ; 33 k3_list = 1:length(types) ; 34else 35 k1_list = [ 9 ] ; % times 36 k2_list = [ 3 ] ; % plus 37 k3_list = [ 11 ] ; % double 38end 39 40kk = min (kk, length (types)) ; 41 42dnn = struct ; 43dtn = struct ( 'inp0', 'tran' ) ; 44dnt = struct ( 'inp1', 'tran' ) ; 45dtt = struct ( 'inp0', 'tran', 'inp1', 'tran' ) ; 46 47n_semirings = 0 ; 48ntrials = 0 ; 49 50for k1 = k1_list % 1:length(mult_ops) 51 mulop = mult_ops {k1} ; 52 % if (~GB_spec_is_positional (mulop)) 53 % continue ; 54 % end 55 56 for k2 = k2_list % 1:length(add_ops) 57 58 addop = add_ops {k2} ; 59 fprintf ('\nsemiring %s:%s ', addop, mulop) ; 60 61 for k3 = k3_list % 1:length (types) 62 63 rng ('default') ; 64 type = types {k3} ; 65 66 semiring.multiply = mulop ; 67 semiring.add = addop ; 68 semiring.class = type ; 69 if (n_semirings_max == 1) 70 semiring 71 end 72 73 % create the semiring. some are not valid because the or,and,xor 74 % monoids can only be used when z is boolean for z=mult(x,y). 75 try 76 [mult_op add_op id] = GB_spec_semiring (semiring) ; 77 [mult_opname mult_optype ztype] = GB_spec_operator (mult_op); 78 [ add_opname add_optype] = GB_spec_operator (add_op) ; 79 identity = GB_spec_identity (semiring.add, add_optype) ; 80 catch 81 continue 82 end 83 84 if (n_semirings+1 > n_semirings_max) 85 fprintf ('\ntest20: all quick tests passed\n') ; 86 return ; 87 end 88 89 % fprintf ('\n%4d ', n_semirings) ; 90 % fprintf ('%12.2f mxm semiring %s:%s:%s ', toc,addop,mulop,type) ; 91 % fprintf (' id: %g ', double (identity)) ; 92 n_semirings = n_semirings + 1 ; 93 94 % for k4 = [0 5 11 15] % 0:length(mult_ops) 95 for k4 = [ 0 randperm(length(mult_ops), aa)] 96 97 if (k4 == 0) 98 accum_op = '' ; 99 ntypes = 1 ; 100 else 101 accum_op = mult_ops {k4} ; 102 % ntypes = [1 2 8 ] ; % length (types) ; 103 % ntypes = 1:length (types) ; 104 ntypes = randperm (length (types),kk) ; 105 end 106 107 for k5 = ntypes 108 109 clear accum 110 if (~isempty (accum_op)) 111 accum_type = types {k5} ; 112 accum.opname = accum_op ; 113 accum.optype = accum_type ; 114 else 115 accum = '' ; 116 accum_type = '' ; 117 end 118 119 if (GB_spec_is_positional (accum)) 120 continue ; 121 end 122 123 try 124 GB_spec_operator (accum) ; 125 catch 126 continue 127 end 128 129 for Mask_complement = [false true] 130 131 if (Mask_complement) 132 dnn.mask = 'complement' ; 133 dtn.mask = 'complement' ; 134 dnt.mask = 'complement' ; 135 dtt.mask = 'complement' ; 136 else 137 dnn.mask = 'default' ; 138 dtn.mask = 'default' ; 139 dnt.mask = 'default' ; 140 dtt.mask = 'default' ; 141 end 142 143 for C_replace = [false true] 144 145 if (C_replace) 146 dnn.outp = 'replace' ; 147 dtn.outp = 'replace' ; 148 dnt.outp = 'replace' ; 149 dtt.outp = 'replace' ; 150 else 151 dnn.outp = 'default' ; 152 dtn.outp = 'default' ; 153 dnt.outp = 'default' ; 154 dtt.outp = 'default' ; 155 end 156 157 % pick a random class, and int32 158 atypes = randperm(length(types),kk) ; 159 % 1:length (types) 160 atypes = unique ([atypes 6]) ; 161 162 % try all matrix types, to test casting 163 for k6 = atypes 164 165 aclas = types {k6} ; 166 167 if (isequal (aclas, 'int32') && ... 168 mod (n_semirings, 100) == 1) 169 % single or double would lead to 170 % different roundoff errors 171 hyper_range = 0:1 ; 172 csc_range = 0:1 ; 173 else 174 hyper_range = 0 ; 175 csc_range = 1 ; 176 end 177 178 % try some matrices 179 for m = 8 % [1 5 10 ] 180 181 for n = 5 % [ 1 5 10 ] 182 183 for s = 4 % [ 1 5 10 ] 184 for density = [0.1 0.2 0.3 0.5] 185 186 % try all combinations of hyper/ 187 % non-hyper and CSR/CSC 188 for A_is_hyper = hyper_range 189 for A_is_csc = csc_range 190 for B_is_hyper = hyper_range 191 for B_is_csc = csc_range 192 for C_is_hyper = hyper_range 193 for C_is_csc = csc_range 194 for M_is_hyper = hyper_range 195 for M_is_csc = csc_range 196 197 if (mod (ntrials, 23) == 0) 198 fprintf ('.') ; 199 end 200 201 %----------------------------------- 202 % A*B 203 %----------------------------------- 204 205 A = GB_spec_random (m,s,density,100,aclas, A_is_csc, A_is_hyper) ; 206 B = GB_spec_random (s,n,density,100,aclas, B_is_csc, B_is_hyper) ; 207 C = GB_spec_random (m,n,density,100,aclas, C_is_csc, C_is_hyper) ; 208 209 % C = A*B, no mask 210 Mask = [ ] ; 211 C0 = GB_spec_mxm (C, [ ], accum, semiring, A, B, dnn); 212 C1 = GB_mex_mxm (C, [ ], accum, semiring, A, B, dnn); 213 GB_spec_compare (C0, C1, identity) ; 214 215 % w = A*u, no mask 216 w = GB_spec_random (m,1,density,100,type) ; 217 u = GB_spec_random (s,1,density,100,type) ; 218 219 w0 = GB_spec_mxv (w, [ ], accum, semiring, A, u, dnn); 220 w1 = GB_mex_mxv (w, [ ], accum, semiring, A, u, dnn); 221 GB_spec_compare (w0, w1, identity) ; 222 223 % w' = u'*A' no mask 224 w0 = GB_spec_vxm (w, [ ], accum, semiring, u, A, dnt); 225 w1 = GB_mex_vxm (w, [ ], accum, semiring, u, A, dnt); 226 GB_spec_compare (w0, w1, identity) ; 227 228 % C = A*B with mask 229 % Mask = sprandn (m,n,0.2) ~= 0 ; 230 Mask = GB_random_mask(m,n,0.2, M_is_csc, M_is_hyper) ; 231 C0 = GB_spec_mxm (C, Mask, accum, semiring, A, B, dnn); 232 C1 = GB_mex_mxm (C, Mask, accum, semiring, A, B, dnn); 233 GB_spec_compare (C0, C1, identity) ; 234 235 % C = A*B with mask (with explicit zero entries) 236 Mask1 = sprandn (m,n,0.2) ~= 0 ; 237 Mask2 = Mask1 .* spones (sprandn (m,n,0.5)) ; 238 S = sparse (m,n) ; 239 Mask3 = GB_mex_Matrix_eWiseAdd (S,[ ],[ ],'minus',Mask1,Mask2) ; 240 clear Mask 241 Mask.matrix = Mask3.matrix ; 242 Mask.is_csc = M_is_csc ; 243 Mask.is_hyper = M_is_hyper ; 244 clear Mask1 Mask2 Mask3 245 % the Mask matrix will not pass GB_spok(Mask) test since 246 % it will have explicit zeros 247 248 C0 = GB_spec_mxm (C, Mask, accum, semiring, A, B, dnn); 249 C1 = GB_mex_mxm (C, Mask, accum, semiring, A, B, dnn); 250 GB_spec_compare (C0, C1, identity) ; 251 252 % w = A*u with mask 253 % mask = sprandn (m,1,0.2) ~= 0 ; 254 mask = GB_random_mask (m,1,0.2) ; 255 w0 = GB_spec_mxv (w, mask, accum, semiring, A, u, dnn); 256 w1 = GB_mex_mxv (w, mask, accum, semiring, A, u, dnn); 257 GB_spec_compare (w0, w1, identity) ; 258 259 % w' = u'*A' with mask 260 w0 = GB_spec_vxm (w, mask, accum, semiring, u, A, dnt) ; 261 w1 = GB_mex_vxm (w, mask, accum, semiring, u, A, dnt) ; 262 GB_spec_compare (w0, w1, identity) ; 263 264 %----------------------------------- 265 % A'*B 266 %----------------------------------- 267 268 A = GB_spec_random (s,m,density,100,aclas, A_is_csc, A_is_hyper) ; 269 B = GB_spec_random (s,n,density,100,aclas, B_is_csc, B_is_hyper) ; 270 C = GB_spec_random (m,n,density,100,aclas, C_is_csc, C_is_hyper) ; 271 272 % C = A'*B, no Mask 273 C0 = GB_spec_mxm (C, [ ], accum, semiring, A, B, dtn); 274 C1 = GB_mex_mxm (C, [ ], accum, semiring, A, B, dtn); 275 GB_spec_compare (C0, C1, identity) ; 276 277 % w = A'*u, no mask 278 279 w0 = GB_spec_mxv (w, [ ], accum, semiring, A, u, dtn); 280 w1 = GB_mex_mxv (w, [ ], accum, semiring, A, u, dtn); 281 GB_spec_compare (w0, w1, identity) ; 282 283 % w' = u'*A, no mask 284 w0 = GB_spec_vxm (w, [ ], accum, semiring, u, A, dnn); 285 w1 = GB_mex_vxm (w, [ ], accum, semiring, u, A, dnn); 286 GB_spec_compare (w0, w1, identity) ; 287 288 % C = A'*B with mask 289 % Mask = sprandn (m,n,0.2) ~= 0 ; 290 Mask = GB_random_mask (m,n,0.2, M_is_csc, M_is_hyper) ; 291 C0 = GB_spec_mxm (C, Mask, accum, semiring, A, B, dtn); 292 C1 = GB_mex_mxm (C, Mask, accum, semiring, A, B, dtn); 293 GB_spec_compare (C0, C1, identity) ; 294 295 % C = A'*B with mask 296 Mask1 = sprandn (m,n,0.2) ~= 0 ; 297 Mask2 = Mask1 .* spones (sprandn (m,n,0.5)) ; 298 S = sparse (m,n) ; 299 Mask3 = GB_mex_Matrix_eWiseAdd (S,[ ],[ ],'minus',Mask1,Mask2) ; 300 clear Mask 301 Mask.matrix = Mask3.matrix ; 302 Mask.is_csc = M_is_csc ; 303 Mask.is_hyper = M_is_hyper ; 304 clear Mask1 Mask2 Mask3 305 % the Mask matrix will not pass GB_spok(Mask) test since 306 % it will have explicit zeros 307 C0 = GB_spec_mxm (C, Mask, accum, semiring, A, B, dtn); 308 C1 = GB_mex_mxm (C, Mask, accum, semiring, A, B, dtn); 309 GB_spec_compare (C0, C1, identity) ; 310 311 % w = A'*u, with mask 312 % mask = sprandn (m,1,0.2) ~= 0 ; 313 mask = GB_random_mask (m,1,0.2) ; 314 w0 = GB_spec_mxv (w, mask, accum, semiring, A, u, dtn); 315 w1 = GB_mex_mxv (w, mask, accum, semiring, A, u, dtn); 316 GB_spec_compare (w0, w1, identity) ; 317 318 % w' = u'*A, with mask 319 w0 = GB_spec_vxm (w, mask, accum, semiring, u, A, dnn); 320 w1 = GB_mex_vxm (w, mask, accum, semiring, u, A, dnn); 321 GB_spec_compare (w0, w1, identity) ; 322 323 %----------------------------------- 324 % A*B' 325 %----------------------------------- 326 327 % no mask 328 329 A = GB_spec_random (m,s,density,100,aclas, A_is_csc, A_is_hyper) ; 330 B = GB_spec_random (n,s,density,100,aclas, B_is_csc, B_is_hyper) ; 331 C = GB_spec_random (m,n,density,100,aclas, C_is_csc, C_is_hyper) ; 332 333 C0 = GB_spec_mxm (C, [ ], accum, semiring, A, B, dnt); 334 C1 = GB_mex_mxm (C, [ ], accum, semiring, A, B, dnt); 335 GB_spec_compare (C0, C1, identity) ; 336 337 % with mask 338 % Mask = sprandn (m,n,0.2) ~= 0 ; 339 Mask = GB_random_mask (m,n,0.2, M_is_csc, M_is_hyper) ; 340 C0 = GB_spec_mxm (C, Mask, accum, semiring, A, B, dnt); 341 C1 = GB_mex_mxm (C, Mask, accum, semiring, A, B, dnt); 342 GB_spec_compare (C0, C1, identity) ; 343 344 %----------------------------------- 345 % A'*B' 346 %----------------------------------- 347 348 % no Mask 349 350 A = GB_spec_random (s,m,density,100,aclas, A_is_csc, A_is_hyper) ; 351 B = GB_spec_random (n,s,density,100,aclas, B_is_csc, B_is_hyper) ; 352 C = GB_spec_random (m,n,density,100,aclas, C_is_csc, C_is_hyper) ; 353 354 C0 = GB_spec_mxm (C, [ ], accum, semiring, A, B, dtt); 355 C1 = GB_mex_mxm (C, [ ], accum, semiring, A, B, dtt); 356 GB_spec_compare (C0, C1, identity) ; 357 358 359 % A'*B', with mask 360 % Mask = sprandn (m,n,0.2) ~= 0 ; 361 Mask = GB_random_mask (m,n,0.2, M_is_csc, M_is_hyper) ; 362 363 C0 = GB_spec_mxm (C, Mask, accum, semiring, A, B, dtt); 364 C1 = GB_mex_mxm (C, Mask, accum, semiring, A, B, dtt); 365 GB_spec_compare (C0, C1, identity) ; 366 367 ntrials = ntrials + 1 ; 368 369 370end 371end 372end 373end 374end 375end 376end 377end 378end 379end 380end 381end 382end 383end 384end 385end 386end 387end 388end 389end 390 391fprintf ('semirings tested: %d\n', n_semirings) ; 392fprintf ('\ntest20: all tests passed\n') ; 393 394