1function C = GB_spec_mxm (C, Mask, accum, semiring, A, B, descriptor) 2%GB_SPEC_MXM a MATLAB mimic of GrB_mxm 3% 4% Usage: 5% C = GB_spec_mxm (C, Mask, accum, semiring, A, B, descriptor) 6% 7% Computes C<Mask> = accum(C,T), in GraphBLAS notation, where T =A*B, A'*B, 8% A*B' or A'*B'. The matrix C is returned as a struct with C.matrix being the 9% values of the matrix, C.pattern the 'nonzero' pattern, and C.class the type 10% of the matrix. A and B can be plain matrices on input, or they can be 11% structs like C. See GB_spec_matrix.m for more details. See 12% GB_spec_transpose.m for a description of the input parameters, except for 13% semiring; see GB_spec_semiring for a description of the semiring. 14% 15% The semiring defines the multiply and add operators and the additive 16% identity. The matrix multiplication T = A*B is then defined as: 17% 18% [m s] = size (A) ; 19% [s n] = size (B) ; 20% ztype, xtype, ytype: the types of the multiply operator 21% T = identity (m,n,ztype) ; where identity is defined by semiring.add 22% for j = 1:n 23% for i = 1:m 24% for k = 1:s 25% if (A (i,k) and B (k,j) are 'nonzero' 26% aik = cast (A(i,k), xtype) 27% bkj = cast (B(k,j), ytype) 28% T (i,j) = add (T (i,j), multiply (aik, bkj)) 29% end 30% end 31% end 32% end 33% 34% Where A(i,j) 'nonzero' means that the entry is in the data structure for the 35% sparse matrix A. If it is not there, it is implied to be equal to the 36% addititive identity. The identity value does not appear in the sparse 37% GraphBLAS matrix; it is the value of entries not present in the data 38% structure. The MATLAB GB_spec_*.m functions operate on dense matrices, 39% however, so these entries must be explicitly set to the additive identity. 40% 41% This gives a matrix T which is then accumulated into the result via 42% C<Mask> = accum (C,T). See GrB_accum_mask for a description of this 43% last step. 44 45% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. 46% SPDX-License-Identifier: Apache-2.0 47 48%------------------------------------------------------------------------------- 49% get inputs 50%------------------------------------------------------------------------------- 51 52if (nargout > 1 || nargin ~= 7) 53 error ('usage: C = GB_spec_mxm (C, Mask, accum, semiring, A, B, descriptor)') ; 54end 55 56% Convert inputs to dense matrices with explicit patterns and types, 57% and with where X(~X.pattern)==identity for all matrices A, B, and C. 58[multiply add identity ztype xtype ytype] = GB_spec_semiring (semiring) ; 59if (isempty (identity)) 60 identity = 0 ; 61end 62C = GB_spec_matrix (C, identity) ; 63A = GB_spec_matrix (A, identity) ; 64B = GB_spec_matrix (B, identity) ; 65[C_replace Mask_comp Atrans Btrans Mask_struct] = ... 66 GB_spec_descriptor (descriptor) ; 67Mask = GB_spec_getmask (Mask, Mask_struct) ; 68 69%------------------------------------------------------------------------------- 70% do the work via a clean MATLAB interpretation of the entire GraphBLAS spec 71%------------------------------------------------------------------------------- 72 73% apply the descriptor to A 74if (Atrans) 75 A.matrix = A.matrix.' ; 76 A.pattern = A.pattern' ; 77end 78 79% apply the descriptor to B 80if (Btrans) 81 B.matrix = B.matrix.' ; 82 B.pattern = B.pattern' ; 83end 84 85% T = A*B 86[m s] = size (A.matrix) ; 87[s n] = size (B.matrix) ; 88T.matrix = GB_spec_zeros ([m n], ztype) ; 89T.pattern = zeros (m, n, 'logical') ; 90T.matrix (:,:) = identity ; 91T.class = ztype ; 92 93A_matrix = GB_mex_cast (A.matrix, xtype) ; 94B_matrix = GB_mex_cast (B.matrix, ytype) ; 95 96op_is_positional = GB_spec_is_positional (multiply) ; 97multop = multiply.opname ; 98 99for j = 1:n 100 for i = 1:m 101 for k = 1:s 102 % T (i,j) += A (i,k) * B (k,j), using the semiring 103 if (A.pattern (i,k) && B.pattern (k,j)) 104 if (op_is_positional) 105 z = GB_spec_binop_positional (multop, i, k, k, j) ; 106 else 107 z = GB_spec_op (multiply, A_matrix (i,k), B_matrix (k,j)) ; 108 end 109 T.matrix (i,j) = GB_spec_op (add, T.matrix (i,j), z) ; 110 T.pattern (i,j) = true ; 111 end 112 end 113 end 114end 115 116% C<Mask> = accum (C,T): apply the accum, then Mask, and return the result 117C = GB_spec_accum_mask (C, Mask, accum, T, C_replace, Mask_comp, identity) ; 118 119