1 //------------------------------------------------------------------------------
2 // GB_mx_mxArray_to_Descriptor: get the contents of a GraphBLAS Descriptor
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 // get a GraphBLAS descriptor from a MATLAB struct.
11 // D.out, D.in0, D.in0, and D.mask must all be strings.
12 // Fields that are not present are left unchanged.
13
14 #include "GB_mex.h"
15
get_descriptor(GrB_Descriptor D,const mxArray * D_matlab,const char * fieldname,const GrB_Desc_Field field)16 static bool get_descriptor
17 (
18 GrB_Descriptor D, // GraphBLAS descriptor to modify
19 const mxArray *D_matlab, // MATLAB struct with D.output, etc
20 const char *fieldname, // fieldname to extract from D_matlab
21 const GrB_Desc_Field field // field to set in D
22 )
23 {
24
25 // A NULL means the descriptor is not in the list of input parameters.
26 // An empty Descriptor is OK. Both mean the GraphBLAS descriptor is NULL,
27 // which each method uses to denote default values for all parameters.
28 if (D_matlab == NULL || mxIsEmpty (D_matlab))
29 {
30 return (true) ;
31 }
32
33 // if present, the MATLAB D must be a struct
34 if (!mxIsStruct (D_matlab))
35 {
36 mexWarnMsgIdAndTxt ("GB:warn","descriptor must be a struct") ;
37 return (false) ;
38 }
39
40 // find the field in the MATLAB struct
41 int fieldnumber = mxGetFieldNumber (D_matlab, fieldname) ;
42 if (fieldnumber >= 0)
43 {
44 // the field is present
45 mxArray *value = mxGetFieldByNumber (D_matlab, 0, fieldnumber) ;
46
47 // its value must be a string
48 if (!mxIsChar (value))
49 {
50 mexWarnMsgIdAndTxt ("GB:warn","D.field must be a string") ;
51 return (false) ;
52 }
53
54 // get the string from the MATLAB field
55 #define LEN 100
56 char s [LEN] ;
57 mxGetString (value, s, LEN) ;
58
59 // convert the string to a Descriptor value, and set the value
60 GrB_Info info ;
61 if (MATCH (s, "default"))
62 {
63 info = GxB_Desc_set (D, field, GxB_DEFAULT) ;
64 }
65 else if (MATCH (s, "tran") || MATCH (s, "transpose"))
66 {
67 info = GxB_Desc_set (D, field, GrB_TRAN) ;
68 }
69 else if (MATCH (s, "complement"))
70 {
71 info = GxB_Desc_set (D, field, GrB_COMP) ;
72 }
73 else if (MATCH (s, "structure") || MATCH (s, "structural"))
74 {
75 info = GxB_Desc_set (D, field, GrB_STRUCTURE) ;
76 }
77 else if (MATCH (s, "structural complement"))
78 {
79 info = GxB_Desc_set (D, field, GrB_COMP + GrB_STRUCTURE) ;
80 }
81 else if (MATCH (s, "replace"))
82 {
83 info = GxB_Desc_set (D, field, GrB_REPLACE) ;
84 }
85 else if (MATCH (s, "saxpy"))
86 {
87 info = GxB_Desc_set (D, field, GxB_AxB_SAXPY) ;
88 }
89 else if (MATCH (s, "gustavson"))
90 {
91 info = GxB_Desc_set (D, field, GxB_AxB_GUSTAVSON) ;
92 }
93 else if (MATCH (s, "dot"))
94 {
95 info = GxB_Desc_set (D, field, GxB_AxB_DOT) ;
96 }
97 else if (MATCH (s, "hash"))
98 {
99 info = GxB_Desc_set (D, field, GxB_AxB_HASH) ;
100 }
101 else
102 {
103 // the string must be one of the four strings listed above
104 mexWarnMsgIdAndTxt ("GB:warn","unrecognized descriptor value") ;
105 return (false) ;
106 }
107
108 // make sure the Descriptor field was set OK
109 if (info != GrB_SUCCESS)
110 {
111 mexWarnMsgIdAndTxt ("GB:warn", "set D failed!") ;
112 return (false) ;
113 }
114 }
115 return (true) ;
116 }
117
118 //------------------------------------------------------------------------------
119
GB_mx_mxArray_to_Descriptor(GrB_Descriptor * handle,const mxArray * D_matlab,const char * name)120 bool GB_mx_mxArray_to_Descriptor // true if successful, false otherwise
121 (
122 GrB_Descriptor *handle, // descriptor to return
123 const mxArray *D_matlab, // MATLAB struct
124 const char *name // name of the descriptor
125 )
126 {
127 // a null descriptor is OK; the method will use defaults
128 (*handle) = NULL ;
129 if (D_matlab == NULL || mxIsEmpty (D_matlab))
130 {
131 return (true) ;
132 }
133
134 // the MATLAB desc is present and not empty, so create the GraphBLAS one
135 GrB_Descriptor D = NULL ;
136 GrB_Info info = GrB_Descriptor_new (&D) ;
137 if (info != GrB_SUCCESS)
138 {
139 GrB_Matrix_free_(&D) ;
140 mexWarnMsgIdAndTxt ("GB:warn", "new D failed") ;
141 return (false) ;
142 }
143
144 // get each component of the descriptor struct
145 if (!get_descriptor (D, D_matlab, "outp", GrB_OUTP) ||
146 !get_descriptor (D, D_matlab, "inp0", GrB_INP0) ||
147 !get_descriptor (D, D_matlab, "inp1", GrB_INP1) ||
148 !get_descriptor (D, D_matlab, "mask", GrB_MASK) ||
149 !get_descriptor (D, D_matlab, "axb", GxB_AxB_METHOD))
150 {
151 GrB_Matrix_free_(&D) ;
152 mexWarnMsgIdAndTxt ("GB:warn", "descriptor failed") ;
153 return (false) ;
154 }
155
156 // return the non-null Descriptor to the caller
157 ASSERT_DESCRIPTOR_OK (D, name, GB0) ;
158 (*handle) = D ;
159 return (true) ;
160 }
161
162