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