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