1 //------------------------------------------------------------------------------
2 // GB_printf.h: definitions for printing from GraphBLAS
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 #ifndef GB_PRINTF_H
11 #define GB_PRINTF_H
12 
13 #define GB_STRING_MATCH(s,t) (strcmp (s,t) == 0)
14 
15 //------------------------------------------------------------------------------
16 // printing control
17 //------------------------------------------------------------------------------
18 
19 // format strings, normally %llu and %lld, for GrB_Index values
20 #define GBu "%" PRIu64
21 #define GBd "%" PRId64
22 
23 // print to the standard output, and flush the result.  This function can
24 // print to the MATLAB command window.  No error check is done.  This function
25 // is used for the BURBLE, and for debugging output.
26 #define GBDUMP(...)                                                     \
27 {                                                                       \
28     GB_printf_function_t printf_func = GB_Global_printf_get ( ) ;       \
29     if (printf_func != NULL)                                            \
30     {                                                                   \
31         printf_func (__VA_ARGS__) ;                                     \
32     }                                                                   \
33     else                                                                \
34     {                                                                   \
35         printf (__VA_ARGS__) ;                                          \
36     }                                                                   \
37     GB_flush_function_t flush_func = GB_Global_flush_get ( ) ;          \
38     if (flush_func != NULL)                                             \
39     {                                                                   \
40         flush_func ( ) ;                                                \
41     }                                                                   \
42     else                                                                \
43     {                                                                   \
44         fflush (stdout) ;                                               \
45     }                                                                   \
46 }
47 
48 // print to a file f, or to stdout if f is NULL, and check the result.  This
49 // macro is used by all user-callable GxB_*print and GB_*check functions.
50 #define GBPR(...)                                                           \
51 {                                                                           \
52     int printf_result = 0 ;                                                 \
53     if (f == NULL)                                                          \
54     {                                                                       \
55         GB_printf_function_t printf_func = GB_Global_printf_get ( ) ;       \
56         if (printf_func != NULL)                                            \
57         {                                                                   \
58             printf_result = printf_func (__VA_ARGS__) ;                     \
59         }                                                                   \
60         else                                                                \
61         {                                                                   \
62             printf_result = printf (__VA_ARGS__) ;                          \
63         }                                                                   \
64         GB_flush_function_t flush_func = GB_Global_flush_get ( ) ;          \
65         if (flush_func != NULL)                                             \
66         {                                                                   \
67             flush_func ( ) ;                                                \
68         }                                                                   \
69         else                                                                \
70         {                                                                   \
71             fflush (stdout) ;                                               \
72         }                                                                   \
73     }                                                                       \
74     else                                                                    \
75     {                                                                       \
76         printf_result = fprintf (f, __VA_ARGS__)  ;                         \
77         fflush (f) ;                                                        \
78     }                                                                       \
79     if (printf_result < 0)                                                  \
80     {                                                                       \
81         int err = errno ;                                                   \
82         return (GrB_INVALID_VALUE) ;                                        \
83     }                                                                       \
84 }
85 
86 // print if the print level is greater than zero
87 #define GBPR0(...)                  \
88 {                                   \
89     if (pr != GxB_SILENT)           \
90     {                               \
91         GBPR (__VA_ARGS__) ;        \
92     }                               \
93 }
94 
95 // check object->magic and print an error if invalid
96 #define GB_CHECK_MAGIC(object,kind)                                     \
97 {                                                                       \
98     switch (object->magic)                                              \
99     {                                                                   \
100         case GB_MAGIC :                                                 \
101             /* the object is valid */                                   \
102             break ;                                                     \
103                                                                         \
104         case GB_FREED :                                                 \
105             /* dangling pointer! */                                     \
106             GBPR0 (" object already freed!\n") ;                        \
107             return (GrB_UNINITIALIZED_OBJECT) ;                         \
108                                                                         \
109         case GB_MAGIC2 :                                                \
110             /* invalid */                                               \
111             GBPR0 (" invalid object\n") ;                               \
112             return (GrB_INVALID_OBJECT) ;                               \
113                                                                         \
114         default :                                                       \
115             /* uninitialized */                                         \
116             GBPR0 (" uninititialized object\n") ;                       \
117             return (GrB_UNINITIALIZED_OBJECT) ;                         \
118     }                                                                   \
119 }
120 
121 //------------------------------------------------------------------------------
122 // burble
123 //------------------------------------------------------------------------------
124 
125 // GB_BURBLE provides diagnostic output.
126 // Use GxB_set (GxB_BURBLE, true) to turn it on
127 // and GxB_set (GxB_BURBLE, false) to turn it off.
128 
129 #if GB_BURBLE
130 
131 void GB_burble_assign
132 (
133     const bool C_replace,       // descriptor for C
134     const int Ikind,
135     const int Jkind,
136     const GrB_Matrix M,         // mask matrix, which is not NULL here
137     const bool Mask_comp,       // true for !M, false for M
138     const bool Mask_struct,     // true if M is structural, false if valued
139     const GrB_BinaryOp accum,   // present here
140     const GrB_Matrix A,         // input matrix, not transposed
141     const int assign_kind       // row assign, col assign, assign, or subassign
142 ) ;
143 
144 // define the function to use to burble
145 #define GBURBLE(...)                                \
146 {                                                   \
147     if (GB_Global_burble_get ( ))                   \
148     {                                               \
149         GBDUMP (__VA_ARGS__) ;                      \
150     }                                               \
151 }
152 
153 // burble if a matrix is dense or full
154 #define GB_BURBLE_DENSE(A,format)                               \
155 {                                                               \
156     if (GB_IS_FULL (A))                                         \
157     {                                                           \
158         GBURBLE (format, "full") ;                              \
159     }                                                           \
160     else if (GB_IS_BITMAP (A))                                  \
161     {                                                           \
162         GBURBLE (format, "bitmap") ;                            \
163     }                                                           \
164     else if (GB_is_dense (A) && !GB_PENDING_OR_ZOMBIES (A))     \
165     {                                                           \
166         GBURBLE (format, "dense") ;                             \
167     }                                                           \
168 }
169 
170 #if defined ( _OPENMP )
171 
172     // burble with timing
173     #define GB_BURBLE_START(func)                       \
174     double t_burble = 0 ;                               \
175     {                                                   \
176         if (GB_Global_burble_get ( ))                   \
177         {                                               \
178             GBURBLE (" [ " func " ") ;                  \
179             t_burble = GB_OPENMP_GET_WTIME ;            \
180         }                                               \
181     }
182 
183     #define GB_BURBLE_END                               \
184     {                                                   \
185         if (GB_Global_burble_get ( ))                   \
186         {                                               \
187             t_burble = GB_OPENMP_GET_WTIME - t_burble ; \
188             GBURBLE ("\n   %.3g sec ]\n", t_burble) ;   \
189         }                                               \
190     }
191 
192 #else
193 
194     // burble with no timing
195 
196     #define GB_BURBLE_START(func)                       \
197         GBURBLE (" [ " func " ")
198 
199     #define GB_BURBLE_END                               \
200         GBURBLE ("]\n")
201 
202 #endif
203 
204 #define GB_BURBLE_N(n,...)                              \
205 {                                                       \
206     if (n > 1) GBURBLE (__VA_ARGS__)                    \
207 }
208 
209 #define GB_BURBLE_MATRIX(A, ...)                                    \
210 {                                                                   \
211     if (!(A->vlen <= 1 && A->vdim <= 1)) GBURBLE (__VA_ARGS__)      \
212 }
213 
214 #else
215 
216 // no burble
217 #define GBURBLE(...)
218 #define GB_BURBLE_START(func)
219 #define GB_BURBLE_END
220 #define GB_BURBLE_N(n,...)
221 #define GB_BURBLE_MATRIX(A,...)
222 #define GB_BURBLE_DENSE(A,format)
223 
224 #endif
225 #endif
226 
227