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