1 //------------------------------------------------------------------------------
2 // GB_dup2: make a deep copy of a sparse matrix
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 // C = A, making a deep copy.  The header for C may already exist.
11 
12 // if numeric is false, C->x is allocated but not initialized.
13 
14 // If *Chandle is not NULL, the header is reused.  It may be a static or
15 // dynamic header, depending on C->static_header.
16 
17 #include "GB.h"
18 #define GB_FREE_ALL ;
19 
GB_dup2(GrB_Matrix * Chandle,const GrB_Matrix A,const bool numeric,const GrB_Type ctype,GB_Context Context)20 GrB_Info GB_dup2            // make an exact copy of a matrix
21 (
22     GrB_Matrix *Chandle,    // output matrix, NULL or existing static/dynamic
23     const GrB_Matrix A,     // input matrix to copy
24     const bool numeric,     // if true, duplicate the numeric values
25     const GrB_Type ctype,   // type of C, if numeric is false
26     GB_Context Context
27 )
28 {
29 
30     //--------------------------------------------------------------------------
31     // check inputs
32     //--------------------------------------------------------------------------
33 
34     GrB_Info info ;
35     ASSERT (Chandle != NULL) ;
36     ASSERT (!GB_PENDING (A)) ;
37     ASSERT (GB_JUMBLED_OK (A)) ;
38     ASSERT (GB_ZOMBIES_OK (A)) ;
39 
40     //--------------------------------------------------------------------------
41     // determine the number of threads to use
42     //--------------------------------------------------------------------------
43 
44     GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
45 
46     //--------------------------------------------------------------------------
47     // get A
48     //--------------------------------------------------------------------------
49 
50     int64_t anz = GB_NNZ_HELD (A) ;
51     int64_t *Ap = A->p ;
52     int64_t *Ah = A->h ;
53     int64_t *Ai = A->i ;
54     int8_t  *Ab = A->b ;
55     GB_void *Ax = (GB_void *) A->x ;
56     int64_t anvec = A->nvec ;
57     int64_t anvals = A->nvals ;
58     int64_t anvec_nonempty = A->nvec_nonempty ;
59     int64_t A_nzombies = A->nzombies ;
60     bool A_jumbled = A->jumbled ;
61     int sparsity = A->sparsity ;
62     GrB_Type atype = A->type ;
63 
64     //--------------------------------------------------------------------------
65     // create C
66     //--------------------------------------------------------------------------
67 
68     // create C; allocate C->p and do not initialize it.
69     // C has the exact same sparsity structure as A.
70 
71     // allocate a new user header for C if (*Chandle) is NULL, or reuse the
72     // existing static or dynamic header if (*Chandle) is not NULL.
73     GrB_Matrix C = (*Chandle) ;
74     bool C_static_header = (C == NULL) ? false : C->static_header ;
75     GB_OK (GB_new_bix (Chandle, C_static_header, // new/old/static header
76         numeric ? atype : ctype, A->vlen, A->vdim, GB_Ap_malloc, A->is_csc,
77         GB_sparsity (A), false, A->hyper_switch, A->plen, anz, true, Context)) ;
78     C = (*Chandle) ;
79 
80     //--------------------------------------------------------------------------
81     // copy the contents of A into C
82     //--------------------------------------------------------------------------
83 
84     C->nvec = anvec ;
85     C->nvec_nonempty = anvec_nonempty ;
86     C->nvals = anvals ;             // for bitmap only
87     C->jumbled = A_jumbled ;        // C is jumbled if A is jumbled
88     C->nzombies = A_nzombies ;      // zombies can be duplicated
89     C->sparsity = sparsity ;        // copy in the sparsity control
90 
91     if (Ap != NULL)
92     {
93         GB_memcpy (C->p, Ap, (anvec+1) * sizeof (int64_t), nthreads_max) ;
94     }
95     if (Ah != NULL)
96     {
97         GB_memcpy (C->h, Ah, anvec * sizeof (int64_t), nthreads_max) ;
98     }
99     if (Ab != NULL)
100     {
101         GB_memcpy (C->b, Ab, anz * sizeof (int8_t), nthreads_max) ;
102     }
103     if (Ai != NULL)
104     {
105         GB_memcpy (C->i, Ai, anz * sizeof (int64_t), nthreads_max) ;
106     }
107     if (numeric)
108     {
109         GB_memcpy (C->x, Ax, anz * atype->size, nthreads_max) ;
110     }
111 
112     C->magic = GB_MAGIC ;      // C->p and C->h are now initialized
113     #ifdef GB_DEBUG
114     if (numeric) ASSERT_MATRIX_OK (C, "C duplicate of A", GB0) ;
115     #endif
116 
117     //--------------------------------------------------------------------------
118     // return the result
119     //--------------------------------------------------------------------------
120 
121     return (GrB_SUCCESS) ;
122 }
123 
124