1 //------------------------------------------------------------------------------
2 // GB_subassign_zombie: C(I,J)<!,repl> = empty ; using S
3 //------------------------------------------------------------------------------
4
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7
8 //------------------------------------------------------------------------------
9
10 // Method 00: C(I,J)<!,repl> = empty ; using S
11
12 // M: NULL
13 // Mask_comp: true
14 // C_replace: true
15 // accum: any (present or not; result is the same)
16 // A: any (scalar or matrix; result is the same)
17 // S: constructed
18
19 // C: not bitmap
20
21 #include "GB_subassign_methods.h"
22
23 #undef GB_FREE_ALL
24 #define GB_FREE_ALL GB_phbix_free (S) ;
25
GB_subassign_zombie(GrB_Matrix C,const GrB_Index * I,const int64_t ni,const int64_t nI,const int Ikind,const int64_t Icolon[3],const GrB_Index * J,const int64_t nj,const int64_t nJ,const int Jkind,const int64_t Jcolon[3],GB_Context Context)26 GrB_Info GB_subassign_zombie
27 (
28 GrB_Matrix C,
29 // input:
30 const GrB_Index *I,
31 const int64_t ni,
32 const int64_t nI,
33 const int Ikind,
34 const int64_t Icolon [3],
35 const GrB_Index *J,
36 const int64_t nj,
37 const int64_t nJ,
38 const int Jkind,
39 const int64_t Jcolon [3],
40 GB_Context Context
41 )
42 {
43
44 //--------------------------------------------------------------------------
45 // check inputs
46 //--------------------------------------------------------------------------
47
48 ASSERT (!GB_IS_BITMAP (C)) ; ASSERT (!GB_IS_FULL (C)) ;
49
50 //--------------------------------------------------------------------------
51 // S = C(I,J)
52 //--------------------------------------------------------------------------
53
54 GrB_Info info ;
55 struct GB_Matrix_opaque S_header ;
56 GrB_Matrix S = GB_clear_static_header (&S_header) ;
57 GB_OK (GB_subassign_symbolic (S, C, I, ni, J, nj, false, Context)) ;
58 ASSERT (GB_JUMBLED_OK (S)) ; // S can be returned as jumbled
59
60 //--------------------------------------------------------------------------
61 // get inputs
62 //--------------------------------------------------------------------------
63
64 const int64_t *restrict Sx = (int64_t *) S->x ;
65 int64_t *restrict Ci = C->i ;
66
67 //--------------------------------------------------------------------------
68 // Method 00: C(I,J)<!,repl> = empty ; using S
69 //--------------------------------------------------------------------------
70
71 // Time: Optimal, O(nnz(S)), assuming S has already been constructed.
72
73 //--------------------------------------------------------------------------
74 // Parallel: all entries in S can be processed entirely in parallel.
75 //--------------------------------------------------------------------------
76
77 // All entries in C(I,J) are deleted. The result does not depend on A or
78 // the scalar.
79
80 int64_t snz = GB_NNZ (S) ;
81
82 GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
83 int nthreads = GB_nthreads (snz, chunk, nthreads_max) ;
84
85 int64_t nzombies = C->nzombies ;
86
87 int64_t pS ;
88 #pragma omp parallel for num_threads(nthreads) schedule(static) \
89 reduction(+:nzombies)
90 for (pS = 0 ; pS < snz ; pS++)
91 {
92 // S (inew,jnew) is a pointer back into C (I(inew), J(jnew))
93 int64_t pC = Sx [pS] ;
94 int64_t i = Ci [pC] ;
95 // ----[X A 0] or [X . 0]-----------------------------------------------
96 // action: ( X ): still a zombie
97 // ----[C A 0] or [C . 0]-----------------------------------------------
98 // action: C_repl: ( delete ): becomes a zombie
99 if (!GB_IS_ZOMBIE (i))
100 {
101 nzombies++ ;
102 Ci [pC] = GB_FLIP (i) ;
103 }
104 }
105
106 //--------------------------------------------------------------------------
107 // free workspace and return result
108 //--------------------------------------------------------------------------
109
110 C->nzombies = nzombies ;
111 GB_FREE_ALL ;
112 return (GrB_SUCCESS) ;
113 }
114
115