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