1 //------------------------------------------------------------------------------
2 // GB_mex_edit: add/remove entries from a 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 #include "GB_mex.h"
11
12 #define USAGE "C = GB_mex_edit (C, I, J, X, Action)"
13
14 #define FREE_ALL \
15 { \
16 GrB_Matrix_free_(&C) ; \
17 GB_mx_put_global (true) ; \
18 }
19
20 #define OK(method) \
21 { \
22 info = method ; \
23 if (info != GrB_SUCCESS) \
24 { \
25 mexErrMsgTxt ("fail") ; \
26 } \
27 }
28
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])29 void mexFunction
30 (
31 int nargout,
32 mxArray *pargout [ ],
33 int nargin,
34 const mxArray *pargin [ ]
35 )
36 {
37
38 GrB_Matrix C = NULL ;
39 GrB_Index *I = NULL, ni = 0, I_range [3] ;
40 GrB_Index *J = NULL, nj = 0, J_range [3] ;
41 bool ignore ;
42 bool malloc_debug = false ;
43 GrB_Info info = GrB_SUCCESS ;
44 int64_t nwork = 0 ;
45
46 //--------------------------------------------------------------------------
47 // check inputs
48 //--------------------------------------------------------------------------
49
50 malloc_debug = GB_mx_get_global (true) ;
51 C = NULL ;
52
53 // check inputs
54 if (nargout > 1 || nargin != 5)
55 {
56 mexErrMsgTxt ("Usage: " USAGE) ;
57 }
58
59 //--------------------------------------------------------------------------
60 // get C (make a deep copy)
61 //--------------------------------------------------------------------------
62
63 C = GB_mx_mxArray_to_Matrix (pargin [0], "C input", true, true) ;
64 if (C == NULL)
65 {
66 FREE_ALL ;
67 mexErrMsgTxt ("C failed") ;
68 }
69
70 GrB_Index ncols ;
71 GxB_Format_Value fmt ;
72 bool is_hyper ;
73 OK (GrB_Matrix_ncols (&ncols, C)) ;
74 OK (GxB_Matrix_Option_get (C, GxB_FORMAT, &fmt)) ;
75 OK (GxB_Matrix_Option_get (C, GxB_IS_HYPER, &is_hyper)) ; // historical
76 bool is_vector = (fmt == GxB_BY_COL && !is_hyper && ncols == 1) ;
77
78 // get I
79 if (!GB_mx_mxArray_to_indices (&I, pargin [1], &ni, I_range, &ignore))
80 {
81 FREE_ALL ;
82 mexErrMsgTxt ("I failed") ;
83 }
84
85 // get J
86 if (!GB_mx_mxArray_to_indices (&J, pargin [2], &nj, J_range, &ignore))
87 {
88 FREE_ALL ;
89 mexErrMsgTxt ("J failed") ;
90 }
91
92 // get X; must be double
93 double *X = mxGetDoubles (pargin [3]) ;
94
95 // get Action: must be double
96 double *Action = mxGetDoubles (pargin [4]) ;
97
98 nwork = ni ;
99 if (nwork != nj ||
100 nwork != mxGetNumberOfElements (pargin [3]) ||
101 nwork != mxGetNumberOfElements (pargin [4]) ||
102 mxGetClassID (pargin [3]) != mxDOUBLE_CLASS ||
103 mxGetClassID (pargin [4]) != mxDOUBLE_CLASS)
104 {
105 mexErrMsgTxt ("Usage: " USAGE) ;
106 }
107
108 //--------------------------------------------------------------------------
109 // turn off malloc debugging
110 //--------------------------------------------------------------------------
111
112 bool save = GB_Global_malloc_debug_get ( ) ;
113 GB_Global_malloc_debug_set (false) ;
114
115 //--------------------------------------------------------------------------
116 // edit the matrix
117 //--------------------------------------------------------------------------
118
119 for (int64_t k = 0 ; k < nwork ; k++)
120 {
121 int64_t i = I [k] - 1 ;
122 int64_t j = J [k] - 1 ;
123 double x = X [k] ;
124 double action = Action [k] ;
125 if (action == 0)
126 {
127 // remove the (i,j) entry
128 if (is_vector)
129 {
130 OK (GrB_Vector_removeElement ((GrB_Vector) C, i)) ;
131 }
132 else
133 {
134 OK (GrB_Matrix_removeElement (C, i, j)) ;
135 }
136 }
137 else
138 {
139 // add the (i,j) entry
140 if (is_vector)
141 {
142 OK (GrB_Vector_setElement_FP64_ ((GrB_Vector) C, x, i)) ;
143 }
144 else
145 {
146 OK (GrB_Matrix_setElement_FP64_ (C, x, i, j)) ;
147 }
148 }
149 }
150
151 //--------------------------------------------------------------------------
152 // restore malloc debugging to test the method
153 //--------------------------------------------------------------------------
154
155 GB_Global_malloc_debug_set (save) ;
156
157 //--------------------------------------------------------------------------
158 // return C to MATLAB as a MATLAB sparse matrix
159 //--------------------------------------------------------------------------
160
161 pargout [0] = GB_mx_Matrix_to_mxArray (&C, "C mex_edit result", false) ;
162 FREE_ALL ;
163 }
164
165