1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
//------------------------------------------------------------------------------
// GB_subassign: C(Rows,Cols)<M> = accum (C(Rows,Cols),A) or A'
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2025, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//------------------------------------------------------------------------------
// submatrix assignment: C(Rows,Cols)<M> = accum (C(Rows,Cols),A)
// All GxB_*_subassign operations rely on this function.
// With scalar_expansion = false, this method does the work for the standard
// GxB_*_subassign operations (GxB_Matrix_subassign, GxB_Vector_subassign,
// GxB_Row_subassign, and GxB_Col_subassign). If scalar_expansion is true, it
// performs scalar assignment (the GxB_*_subassign_TYPE functions) in which
// case the input matrix A is ignored (it is NULL), and the scalar is used
// instead.
// Compare with GB_assign, which uses M and C_replace differently
#include "assign/GB_subassign.h"
#include "assign/GB_bitmap_assign.h"
#define GB_FREE_ALL \
{ \
GB_Matrix_free (&Cwork) ; \
GB_Matrix_free (&Mwork) ; \
GB_Matrix_free (&Awork) ; \
GB_FREE_MEMORY (&I2, I2_size) ; \
GB_FREE_MEMORY (&J2, J2_size) ; \
}
GrB_Info GB_subassign // C(Rows,Cols)<M> += A or A'
(
GrB_Matrix C_in, // input/output matrix for results
bool C_replace, // descriptor for C
const GrB_Matrix M_in, // optional mask for C(Rows,Cols)
const bool Mask_comp, // true if mask is complemented
const bool Mask_struct, // if true, use the only structure of M
const bool M_transpose, // true if the mask should be transposed
const GrB_BinaryOp accum, // optional accum for accum(C,T)
const GrB_Matrix A_in, // input matrix
const bool A_transpose, // true if A is transposed
const void *Rows, // row indices
const bool Rows_is_32, // if true, Rows is 32-bit; else 64-bit
const uint64_t nRows_in, // number of row indices
const void *Cols, // column indices
const bool Cols_is_32, // if true, Cols is 32-bit; else 64-bit
const uint64_t nCols_in, // number of column indices
const bool scalar_expansion, // if true, expand scalar to A
const void *scalar, // scalar to be expanded
const GB_Type_code scalar_code, // type code of scalar to expand
GB_Werk Werk
)
{
//--------------------------------------------------------------------------
// check and prep inputs
//--------------------------------------------------------------------------
GrB_Info info ;
GrB_Matrix C = NULL ; // C_in or Cwork
GrB_Matrix M = NULL ; // M_in or Mwork
GrB_Matrix A = NULL ; // A_in or Awork
void *I = NULL ; // Rows, Cols, or I2
void *J = NULL ; // Rows, Cols, or J2
bool I_is_32, J_is_32 ;
// temporary matrices and arrays
GrB_Matrix Cwork = NULL ;
GrB_Matrix Mwork = NULL ;
GrB_Matrix Awork = NULL ;
struct GB_Matrix_opaque
Cwork_header, Mwork_header, Awork_header, MT_header, AT_header ;
void *I2 = NULL ; size_t I2_size = 0 ;
void *J2 = NULL ; size_t J2_size = 0 ;
GrB_Type scalar_type = NULL ;
int64_t ni, nj, nI, nJ, Icolon [3], Jcolon [3] ;
int Ikind, Jkind ;
int assign_kind = GB_SUBASSIGN ;
int subassign_method ;
GB_OK (GB_assign_prep (&C, &M, &A, &subassign_method,
&Cwork, &Mwork, &Awork,
&Cwork_header, &Mwork_header, &Awork_header, &MT_header, &AT_header,
&I, &I_is_32, &I2, &I2_size, &ni, &nI, &Ikind, Icolon,
&J, &J_is_32, &J2, &J2_size, &nj, &nJ, &Jkind, Jcolon,
&scalar_type, C_in, &C_replace, &assign_kind,
M_in, Mask_comp, Mask_struct, M_transpose, accum,
A_in, A_transpose,
Rows, Rows_is_32, nRows_in,
Cols, Cols_is_32, nCols_in,
scalar_expansion, scalar, scalar_code, Werk)) ;
// GxB_Row_subassign, GxB_Col_subassign, GxB_Matrix_subassign and
// GxB_Vector_subassign all use GB_SUBASSIGN.
ASSERT (assign_kind == GB_SUBASSIGN) ;
if (subassign_method == 0)
{
// GB_assign_prep has handled the entire assignment itself
ASSERT (C == C_in) ;
ASSERT_MATRIX_OK (C_in, "Final C for subassign", GB0) ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// C(I,J)<M> = A or accum (C(I,J),A) via GB_subassigner
//--------------------------------------------------------------------------
GB_OK (GB_subassigner (C, subassign_method, C_replace,
M, Mask_comp, Mask_struct, accum, A,
I, I_is_32, ni, nI, Ikind, Icolon,
J, J_is_32, nj, nJ, Jkind, Jcolon,
scalar_expansion, scalar, scalar_type, Werk)) ;
//--------------------------------------------------------------------------
// transplant C back into C_in
//--------------------------------------------------------------------------
if (C == Cwork)
{
// Transplant the content of Cwork into C_in and free Cwork. Zombies
// and pending tuples can be transplanted from Cwork into C_in, and if
// Cwork is jumbled, C_in becomes jumbled too.
ASSERT (Cwork->header_size == 0 || GBNSTATIC) ;
GB_OK (GB_transplant (C_in, C_in->type, &Cwork, Werk)) ;
}
//--------------------------------------------------------------------------
// free workspace, finalize C, and return result
//--------------------------------------------------------------------------
ASSERT_MATRIX_OK (C_in, "C for subassign before conform", GB0) ;
GB_OK (GB_conform (C_in, Werk)) ;
ASSERT_MATRIX_OK (C_in, "Final C for subassign", GB0) ;
GB_FREE_ALL ;
return (GB_block (C_in, Werk)) ;
}
|