1 //------------------------------------------------------------------------------
2 // GB_bitmap_assign_IxJ_template: iterate over all of C(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 // Iterate over all positions in the IxJ Cartesian product.  This is all
11 // entries C(i,j) where i is in the list I and j is in the list J.  This
12 // traversal occurs whether or not C(i,j) is an entry present in C.
13 
14 // The C matrix is accessed at C(I,J).  The A matrix is size |I|-by-|J|.
15 // For bitmap assignent, C(I,J)=A is being computed.  For bitmap extraction,
16 // C=A(I,J) so the roles of A and C are swapped (see GB_bitmap_subref.c).
17 
18 {
19 
20     //--------------------------------------------------------------------------
21     // create the tasks to iterate over IxJ
22     //--------------------------------------------------------------------------
23 
24     int ntasks = 0, nthreads ;
25     GB_task_struct *TaskList = NULL ; size_t TaskList_size = 0 ;
26     GB_OK (GB_subassign_IxJ_slice (&TaskList, &TaskList_size, &ntasks,
27         &nthreads, /* I, */ nI, /* Ikind, Icolon, J, */ nJ,
28         /* Jkind, Jcolon, */ Context)) ;
29 
30     //--------------------------------------------------------------------------
31     // iterate over all IxJ
32     //--------------------------------------------------------------------------
33 
34     int taskid ;
35     #pragma omp parallel for num_threads(nthreads) schedule(dynamic,1) \
36         reduction(+:cnvals)
37     for (taskid = 0 ; taskid < ntasks ; taskid++)
38     {
39 
40         //----------------------------------------------------------------------
41         // get the task descriptor
42         //----------------------------------------------------------------------
43 
44         int64_t kfirst = TaskList [taskid].kfirst ;
45         int64_t klast  = TaskList [taskid].klast ;
46         int64_t task_cnvals = 0 ;
47         bool fine_task = (klast == -1) ;
48         int64_t iA_start = 0, iA_end = nI ;
49         if (fine_task)
50         {
51             // a fine task operates on a slice of a single vector
52             klast = kfirst ;
53             iA_start = TaskList [taskid].pA ;
54             iA_end   = TaskList [taskid].pA_end ;
55         }
56 
57         //----------------------------------------------------------------------
58         // compute all vectors in this task
59         //----------------------------------------------------------------------
60 
61         for (int64_t jA = kfirst ; jA <= klast ; jA++)
62         {
63 
64             //------------------------------------------------------------------
65             // get jC, the corresponding vector of C
66             //------------------------------------------------------------------
67 
68             int64_t jC = GB_ijlist (J, jA, Jkind, Jcolon) ;
69             int64_t pC0 = jC * vlen ;       // first entry in C(:,jC)
70             int64_t pA0 = jA * nI ;         // first entry in A(:,jA)
71 
72             //------------------------------------------------------------------
73             // operate on C (I(iA_start,iA_end-1),jC)
74             //------------------------------------------------------------------
75 
76             for (int64_t iA = iA_start ; iA < iA_end ; iA++)
77             {
78                 int64_t iC = GB_ijlist (I, iA, Ikind, Icolon) ;
79                 int64_t pC = iC + pC0 ;
80                 int64_t pA = iA + pA0 ;
81                 // operate on C(iC,jC) at pC (if C is bitmap or full)
82                 // and A(iA,jA) or M(iA,jA) at pA, if A and/or M are
83                 // bitmap or full.  M(iA,jA) is accessed only for the
84                 // subassign method when M is bitmap or full.
85                 GB_IXJ_WORK (pC, pA) ;
86             }
87         }
88         cnvals += task_cnvals ;
89     }
90 
91     //--------------------------------------------------------------------------
92     // free workpace
93     //--------------------------------------------------------------------------
94 
95     GB_FREE_WERK (&TaskList, TaskList_size) ;
96 }
97 
98