1function C = GB_spec_assign (C, Mask, accum, A, I, J, descriptor, scalar)
2%GB_SPEC_ASSIGN a MATLAB mimic of GrB_assign (but not Row or Col variants)
3%
4% Usage:
5% C = GB_spec_assign (C, Mask, accum, A, I, J, descriptor, scalar)
6%
7% Computes C<Mask>(I,J) = accum(C(I,J),A), in GraphBLAS notation.
8%
9% This function does the same thing as GrB_Matrix_assign, GrB_Vector_assign,
10% GrB_Matrix_assign_TYPE, and GrB_Vector_assign_TYPE.  For these uses, the Mask
11% must always be the same size as C.  All of C can be affected (if C_replace is
12% true, for example).
13%
14% This function does not mimic the GrB_Row_assign and GrB_Col_assign functions
15% since they behave differently; their Mask is a single row/column, and they do
16% not affect any part of C outside that row or column.  Those two functions
17% have their own GB_spec_Row_assign.m and GB_spec_Col_assign.m functions.
18
19% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
20% SPDX-License-Identifier: Apache-2.0
21
22%-------------------------------------------------------------------------------
23% get inputs
24%-------------------------------------------------------------------------------
25
26if (nargout > 1 || nargin ~= 8)
27    error ('usage: C = GB_spec_assign (C, Mask, accum, A, I, J, descriptor, scalar)') ;
28end
29
30% Convert inputs to dense matrices with explicit patterns and types,
31% and with where X(~X.pattern)==identity for all matrices A, B, and C.
32C = GB_spec_matrix (C) ;
33A = GB_spec_matrix (A) ;
34[C_replace Mask_comp Atrans Btrans Mask_struct] = ...
35    GB_spec_descriptor (descriptor) ;
36Mask = GB_spec_getmask (Mask, Mask_struct) ;
37
38%-------------------------------------------------------------------------------
39% do the work via a clean MATLAB interpretation of the entire GraphBLAS spec
40%-------------------------------------------------------------------------------
41
42% apply the descriptor to A
43if (Atrans)
44    A.matrix = A.matrix.' ;
45    A.pattern = A.pattern' ;
46end
47
48% expand I and J if empty
49if (ischar (I) & isempty (I))
50    % I = '' is treated as the empty list
51    I = [ ] ;
52elseif (isempty (I) || isequal (I, ':'))
53    % I = [ ] is treated as ":"
54    nrows = size (C.matrix, 1) ;
55    I = 1:nrows ;
56end
57if (ischar (J) & isempty (J))
58    % J = '' is treated as the empty list
59    J = [ ] ;
60elseif (isempty (J) || isequal (J, ':'))
61    % J = [ ] is treated as the ":"
62    ncols = size (C.matrix, 2) ;
63    J = 1:ncols ;
64end
65
66if (scalar)
67    % scalar expansion: remove duplicates and expand A into a matrix
68    I = unique (I) ;
69    J = unique (J) ;
70    ni = length (I) ;
71    nj = length (J) ;
72    A.matrix  (1:ni, 1:nj) = A.matrix (1,1) ;
73    A.pattern (1:ni, 1:nj) = true ;
74end
75
76%-------------------------------------------------------------------------------
77% compute the submatrix in Z, using accum
78%-------------------------------------------------------------------------------
79
80% initialize Z = C
81Z.matrix  = C.matrix ;
82Z.pattern = C.pattern ;
83Z.class   = C.class ;
84
85% extract the C(I,J) submatrix
86S.matrix  = C.matrix  (I,J) ;
87S.pattern = C.pattern (I,J) ;
88S.class   = C.class ;
89
90% apply the accum operator, ZIJ = accum (S, A)
91ZIJ = GB_spec_accum (accum, S, A) ;
92
93% assign the submatrix into Z
94Z.matrix  (I,J) = ZIJ.matrix ;
95Z.pattern (I,J) = ZIJ.pattern ;
96
97%-------------------------------------------------------------------------------
98% apply the Mask and C_replace
99%-------------------------------------------------------------------------------
100
101% C<Mask> = Z: apply the Mask and C_replace, and return the result
102C = GB_spec_mask (C, Mask, Z, C_replace, Mask_comp, 0) ;
103
104