1function R = GB_spec_mask (C, Mask, Z, C_replace, Mask_complement, identity)
2%GB_SPEC_MASK a pure MATLAB implementation of GrB_mask
3%
4% Computes C<Mask> = Z, in GraphBLAS notation.
5%
6% Usage:
7% C = GB_spec_mask (C, Mask, Z, C_replace, Mask_complement, identity)
8%
9% C and Z: matrices of the same size.
10%
11% optional inputs:
12% Mask: if empty or not present, Mask = ones (size (C))
13% C_replace: set C to zero first. Default is false.
14% Mask_complement: use ~Mask instead of Mask. Default is false.
15% Mask_struct: handled by GB_spec_mask.
16% identity: the additive identity of the semiring.  Default is zero.
17%   This is only needed because the GB_spec_* routines operate on dense
18%   matrices, and thus they need to know the value of the implicit 'zero'.
19%
20% This method operates on both plain matrices and on structs with
21% matrix, pattern, and class components.
22
23% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
24% SPDX-License-Identifier: Apache-2.0
25
26if (nargin < 6)
27    identity = 0 ;
28end
29if (nargin < 5)
30    Mask_complement = false ;
31end
32if (nargin < 4)
33    C_replace = false ;
34end
35
36if (isstruct (C))
37    % apply the mask to both the matrix and the pattern
38    R.matrix  = GB_spec_mask (C.matrix,  Mask, Z.matrix,  C_replace, ...
39        Mask_complement, identity) ;
40    R.pattern = GB_spec_mask (C.pattern, Mask, Z.pattern, C_replace, ...
41        Mask_complement, false) ;
42    R.class = C.class ;
43    return
44end
45
46% if (~isequal (size (C), size (Z)))
47if (~ ((size (C,1) == size (Z,1)) && (size (C,2) == size (Z,2))))
48    size (C)
49    size (Z)
50    error ('C and Z must have the same size') ;
51end
52if (~isempty (Mask))
53    % if (~isequal (size (C), size (Mask)))
54    if (~ ((size (C,1) == size (Mask,1)) && (size (C,2) == size (Mask,2))))
55        size (C)
56        size (Mask)
57        error ('C and Mask must have the same size') ;
58    end
59end
60
61% replace C if requested
62if (C_replace)
63    C (:,:) = identity ;
64end
65
66if (isempty (Mask))
67    % in GraphBLAS, this means Mask is NULL;
68    % implicitly, Mask = ones (size (C))
69    if (~Mask_complement)
70        R = Z ;
71    else
72        % note that Z need never have been computed
73        R = C ;
74    end
75else
76    % form the valued mask. For GraphBLAS, this does the
77    % right thing and ignores explicit zeros in Mask.
78    Mask = (Mask ~= 0) ;
79    if (~Mask_complement)
80        % R will equal C where Mask is false
81        R = C ;
82        % overwrite R with Z where Mask is true
83        R (Mask) = Z (Mask) ;
84    else
85        % Mask is complemented
86        % R will equal Z where Mask is false
87        R = Z ;
88        % overwrite R with C where Mask is true
89        R (Mask) = C (Mask) ;
90    end
91end
92
93