1 //------------------------------------------------------------------------------
2 // GB_emult_01_phase1: # entries in C=A.*B or C<M or !M>=A.*B (C sparse/hyper)
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 // GB_emult_01_phase1 counts the number of entries in each vector of C, for
11 // C=A.*B, C<M>=A.*B, or C<!M>=A.*B and then does a cumulative sum to find Cp.
12 // GB_emult_01_phase1 is preceded by GB_emult_01_phase0, which finds the
13 // non-empty vectors of C. If the mask M is saprse, it is not complemented;
14 // only a bitmap or full M is complemented.
15
16 // C is sparse or hypersparse, as determined by GB_add_sparsity.
17 // M, A, and B can have any sparsity structure, but only a specific set of
18 // cases will be used (see GB_emult_sparsity for details).
19
20 // Cp is either freed by GB_emult_01_phase2, or transplanted into C.
21
22 #include "GB_emult.h"
23
GB_emult_01_phase1(int64_t ** Cp_handle,size_t * Cp_size_handle,int64_t * Cnvec_nonempty,GB_task_struct * restrict TaskList,const int C_ntasks,const int C_nthreads,const int64_t Cnvec,const int64_t * restrict Ch,const int64_t * restrict C_to_M,const int64_t * restrict C_to_A,const int64_t * restrict C_to_B,const GrB_Matrix M,const bool Mask_struct,const bool Mask_comp,const GrB_Matrix A,const GrB_Matrix B,GB_Context Context)24 GrB_Info GB_emult_01_phase1 // count nnz in each C(:,j)
25 (
26 // computed by phase1:
27 int64_t **Cp_handle, // output of size Cnvec+1
28 size_t *Cp_size_handle,
29 int64_t *Cnvec_nonempty, // # of non-empty vectors in C
30 // tasks from phase1a:
31 GB_task_struct *restrict TaskList, // array of structs
32 const int C_ntasks, // # of tasks
33 const int C_nthreads, // # of threads to use
34 // analysis from phase0:
35 const int64_t Cnvec,
36 const int64_t *restrict Ch, // Ch is NULL, or shallow pointer
37 const int64_t *restrict C_to_M,
38 const int64_t *restrict C_to_A,
39 const int64_t *restrict C_to_B,
40 // original input:
41 const GrB_Matrix M, // optional mask, may be NULL
42 const bool Mask_struct, // if true, use the only structure of M
43 const bool Mask_comp, // if true, use !M
44 const GrB_Matrix A,
45 const GrB_Matrix B,
46 GB_Context Context
47 )
48 {
49
50 //--------------------------------------------------------------------------
51 // check inputs
52 //--------------------------------------------------------------------------
53
54 ASSERT (Cp_handle != NULL) ;
55 ASSERT (Cp_size_handle != NULL) ;
56 ASSERT (Cnvec_nonempty != NULL) ;
57
58 ASSERT_MATRIX_OK_OR_NULL (M, "M for emult phase1", GB0) ;
59 ASSERT (!GB_ZOMBIES (M)) ;
60 ASSERT (!GB_JUMBLED (M)) ;
61 ASSERT (!GB_PENDING (M)) ;
62
63 ASSERT_MATRIX_OK (A, "A for emult phase1", GB0) ;
64 ASSERT (!GB_ZOMBIES (A)) ;
65 ASSERT (!GB_JUMBLED (A)) ;
66 ASSERT (!GB_PENDING (A)) ;
67
68 ASSERT_MATRIX_OK (B, "B for emult phase1", GB0) ;
69 ASSERT (!GB_ZOMBIES (B)) ;
70 ASSERT (!GB_JUMBLED (B)) ;
71 ASSERT (!GB_PENDING (B)) ;
72
73 ASSERT (A->vdim == B->vdim) ;
74
75 if (M == NULL)
76 {
77 ASSERT (GB_IS_SPARSE (A) || GB_IS_HYPERSPARSE (A)) ;
78 ASSERT (GB_IS_SPARSE (B) || GB_IS_HYPERSPARSE (B)) ;
79 }
80
81 //--------------------------------------------------------------------------
82 // allocate the result
83 //--------------------------------------------------------------------------
84
85 (*Cp_handle) = NULL ;
86 int64_t *restrict Cp = NULL ; size_t Cp_size = 0 ;
87 Cp = GB_CALLOC (GB_IMAX (2, Cnvec+1), int64_t, &Cp_size) ;
88 if (Cp == NULL)
89 {
90 // out of memory
91 return (GrB_OUT_OF_MEMORY) ;
92 }
93
94 //--------------------------------------------------------------------------
95 // count the entries in each vector of C
96 //--------------------------------------------------------------------------
97
98 #define GB_PHASE_1_OF_2
99 #include "GB_emult_01_meta.c"
100
101 //--------------------------------------------------------------------------
102 // cumulative sum of Cp and fine tasks in TaskList
103 //--------------------------------------------------------------------------
104
105 GB_task_cumsum (Cp, Cnvec, Cnvec_nonempty, TaskList, C_ntasks, C_nthreads,
106 Context) ;
107
108 //--------------------------------------------------------------------------
109 // return the result
110 //--------------------------------------------------------------------------
111
112 (*Cp_handle) = Cp ;
113 (*Cp_size_handle) = Cp_size ;
114 return (GrB_SUCCESS) ;
115 }
116
117