1 //------------------------------------------------------------------------------
2 // GB_subref_phase1: find # of entries in C=A(I,J)
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_subref_phase1 counts the number of entries in each vector of C, for
11 // C=A(I,J) and then does a cumulative sum to find Cp.
12
13 // Cp is either freed by phase2, or transplanted into C.
14
15 #include "GB_subref.h"
16
GB_subref_phase1(int64_t ** Cp_handle,size_t * Cp_size_handle,int64_t * Cnvec_nonempty,GB_task_struct * restrict TaskList,const int ntasks,const int nthreads,const int64_t * Mark,const int64_t * Inext,const int64_t nduplicates,const int64_t * restrict Ap_start,const int64_t * restrict Ap_end,const int64_t Cnvec,const bool need_qsort,const int Ikind,const int64_t nI,const int64_t Icolon[3],const GrB_Matrix A,const GrB_Index * I,const bool symbolic,GB_Context Context)17 GrB_Info GB_subref_phase1 // count nnz in each C(:,j)
18 (
19 // computed by phase1:
20 int64_t **Cp_handle, // output of size Cnvec+1
21 size_t *Cp_size_handle,
22 int64_t *Cnvec_nonempty, // # of non-empty vectors in C
23 // tasks from phase0b:
24 GB_task_struct *restrict TaskList, // array of structs
25 const int ntasks, // # of tasks
26 const int nthreads, // # of threads to use
27 const int64_t *Mark, // for I inverse buckets, size A->vlen
28 const int64_t *Inext, // for I inverse buckets, size nI
29 const int64_t nduplicates, // # of duplicates, if I inverted
30 // analysis from phase0:
31 const int64_t *restrict Ap_start,
32 const int64_t *restrict Ap_end,
33 const int64_t Cnvec,
34 const bool need_qsort,
35 const int Ikind,
36 const int64_t nI,
37 const int64_t Icolon [3],
38 // original input:
39 const GrB_Matrix A,
40 const GrB_Index *I, // index list for C = A(I,J), or GrB_ALL, etc.
41 const bool symbolic,
42 GB_Context Context
43 )
44 {
45
46 //--------------------------------------------------------------------------
47 // check inputs
48 //--------------------------------------------------------------------------
49
50 ASSERT (Cp_handle != NULL) ;
51 ASSERT (Cp_size_handle != NULL) ;
52 ASSERT_MATRIX_OK (A, "A for subref phase1", GB0) ;
53 ASSERT (!GB_IS_BITMAP (A)) ; // GB_bitmap_subref is used instead
54
55 //--------------------------------------------------------------------------
56 // allocate the result
57 //--------------------------------------------------------------------------
58
59 (*Cp_handle) = NULL ;
60 (*Cp_size_handle) = 0 ;
61 int64_t *restrict Cp = NULL ; size_t Cp_size = 0 ;
62 Cp = GB_CALLOC (GB_IMAX (2, Cnvec+1), int64_t, &Cp_size) ;
63 if (Cp == NULL)
64 {
65 // out of memory
66 return (GrB_OUT_OF_MEMORY) ;
67 }
68
69 //--------------------------------------------------------------------------
70 // count the entries in each vector of C
71 //--------------------------------------------------------------------------
72
73 #define GB_PHASE_1_OF_2
74 if (symbolic)
75 {
76 #define GB_SYMBOLIC
77 #include "GB_subref_template.c"
78 #undef GB_SYMBOLIC
79 }
80 else
81 {
82 #define GB_NUMERIC
83 #include "GB_subref_template.c"
84 #undef GB_NUMERIC
85 }
86
87 //--------------------------------------------------------------------------
88 // cumulative sum of Cp and fine tasks in TaskList
89 //--------------------------------------------------------------------------
90
91 GB_task_cumsum (Cp, Cnvec, Cnvec_nonempty, TaskList, ntasks, nthreads,
92 Context) ;
93
94 //--------------------------------------------------------------------------
95 // return the result
96 //--------------------------------------------------------------------------
97
98 (*Cp_handle) = Cp ;
99 (*Cp_size_handle) = Cp_size ;
100 return (GrB_SUCCESS) ;
101 }
102
103