File: GB_subassign.c

package info (click to toggle)
suitesparse 1%3A7.10.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 254,920 kB
  • sloc: ansic: 1,134,743; cpp: 46,133; makefile: 4,875; fortran: 2,087; java: 1,826; sh: 996; ruby: 725; python: 495; asm: 371; sed: 166; awk: 44
file content (143 lines) | stat: -rw-r--r-- 6,072 bytes parent folder | download | duplicates (2)
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)) ;
}