1function C = GB_spec_transpose (C, Mask, accum, A, descriptor)
2%GB_SPEC_TRANSPOSE a MATLAB mimic of GrB_transpose
3%
4% Usage:
5% C = GB_spec_transpose (C, Mask, accum, A, descriptor)
6%
7% Computes C<Mask> = accum(C,A') or accum(C,A) depending on the descriptor.
8% This function and all GB_spec_* functions are not mean to be fast.  They
9% are meant to represent the GraphBLAS spec, for testing and illustration.
10%
11% The input matrices A, Mask, and C can be plain MATLAB matrices, sparse or
12% dense, where the class of the matrix is the same as the GraphBLAS type.
13% MATLAB sparse matrices can only handle 'logical', 'double', or 'double
14% compex' types, however.  To model this, the input matrices can also be
15% structs.  A.matrix is the matrix itself, and A.class is a string that the
16% matrix is supposed to represent ('logical', 'int8', ... 'single', 'double').
17%
18% accum can be a string with the name a valid binary operator (see
19% GB_spec_operator.m), or it can be a struct where accum.name is the name of
20% the operator and accum.class is the class.  If accum is empty, no accumulator
21% is used and C on input is ignored.
22%
23% Mask is a sparse or dense matrix, or an empty matrix ([ ]).  See
24% GB_spec_mask.m for a description.
25%
26% descriptor is a optional struct.  Defaults are used if empty or not present.
27%       descriptor.outp = 'replace' (clear C first) or 'default' (use C as-is)
28%       descriptor.inp0 = 'tran' (do C=A) or 'default' (do C=A')
29%       descriptor.mask =
30%               'default': use Mask
31%               'complement': use ~Mask
32%               'structural': use spones(Mask)
33%               'structural complement': use ~spones(Mask)
34%
35% GB_spec_transpose implements the entire specification of GrB_transpose, with
36% a few exceptions.
37%
38% (1) Internally it only works on dense matrices, since MATLAB supports logical
39% and double sparse matrices only.  As a result, the MATLAB GB_spec_* mimics
40% will be slow on large problems.
41%
42% (2) MATLAB does not allow explicit zeros in its sparse matrices. As a result,
43% the structural pattern of an input matrix A, sparse or dense, is assumed to
44% be GB_spones_mex(A).
45%
46% (3) Operations cannot be done purely in MATLAB because of the differences in
47% typecasting rules for integers.
48%
49% (4) Finally, this method assumes that the domains of x, y, and z for the
50% operator z=op(x,y) are all the same: optype.  This is true for all built-in
51% operators, but in GraphBLAS users can define their own operators with x, y
52% and z being all different domains.  That feature is not modeled by this
53% MATLAB function.
54%
55% Returns a struct with a dense matrix C.matrix with class C.class.
56%
57% Use an empty value ([ ] or '') to obtain the default value for optional
58% parameters.
59
60% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
61% SPDX-License-Identifier: Apache-2.0
62
63%-------------------------------------------------------------------------------
64% get inputs
65%-------------------------------------------------------------------------------
66
67if (nargout > 1 || nargin ~= 5)
68    error ('usage: C = GB_spec_transpose (C, Mask, accum, A, descriptor)') ;
69end
70
71C = GB_spec_matrix (C) ;
72A = GB_spec_matrix (A) ;
73[C_replace Mask_comp Atrans Btrans Mask_struct] = ...
74    GB_spec_descriptor (descriptor) ;
75Mask = GB_spec_getmask (Mask, Mask_struct) ;
76
77%-------------------------------------------------------------------------------
78% do the work via a clean MATLAB interpretation of the entire GraphBLAS spec
79%-------------------------------------------------------------------------------
80
81% apply the descriptor to A
82if (Atrans)
83    A.matrix = A.matrix.' ;
84    A.pattern = A.pattern' ;
85end
86
87% do the work
88
89% Yes, this is be a double-transpose if Atrans is true, which of course should
90% not be done in practice.  This just mimics the spec line-for-line.
91T.matrix = A.matrix' ;
92T.pattern = A.pattern' ;
93T.class = A.class ;
94
95% C<Mask> = accum (C,T): apply the accum, then Mask, and return the result
96C = GB_spec_accum_mask (C, Mask, accum, T, C_replace, Mask_comp, 0) ;
97
98